Merge branch 'master' of github.com:Faerbit/swp

Conflicts:
	camera.cc
	graphics.cc
This commit is contained in:
Fabian Klemp 2014-11-17 13:31:01 +01:00
commit 0a0dcd90f8
22 changed files with 10110 additions and 157 deletions

2
.gitignore vendored
View File

@ -1,3 +1,5 @@
binaries
build
Makefile
CMakeLists.txt.user
*.cbp

2069
Geometry/Sphere.obj Normal file

File diff suppressed because it is too large Load Diff

BIN
Geometry/stoneTexture.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@ -4,8 +4,8 @@ uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
in vec3 aNormal;
in vec3 aPosition;
in vec3 aNormal;
in vec2 aTexCoord;
out vec3 vNormal;

View File

@ -33,6 +33,30 @@ void Camera::setRotation(glm::vec2 rotation) {
void Camera::updateRotation(glm::vec2 rotation) {
this->rotation += rotation;
if((this->rotation.x + rotation.x) >= 1.57f) {
this->rotation.x = 1.57;
this->rotation.y += rotation.y;
}
else if ((this->rotation.x + rotation.x) <= -1.57f) {
this->rotation.x = -1.57f;
this->rotation.y += rotation.y;
}
else {
this-> rotation += rotation;
}
updatePosition();
}
void Camera:: updateDistance(float distance) {
if (this->distance + distance <= 1.0f) {
this->distance = 1.0f;
}
else if (this->distance + distance >= 30.0f) {
this->distance = 30.f;
}
else {
this->distance += distance;
}
updatePosition();
}

View File

@ -10,6 +10,7 @@ class Camera {
~Camera();
float getDistance();
void setDistance(float distance);
void updateDistance(float distance); //adds to current distance
glm::vec2 getRotation();
void setRotation(glm::vec2 rotation);
void updateRotation(glm::vec2 rotation); //adds to current rotation

View File

@ -1,6 +1,11 @@
#include "entity.hh"
Entity::Entity(glm::vec3 position, glm::vec3 rotation) {
this->position = position;
setRotation(rotation);
}
Entity::Entity(glm::vec3 position, glm::mat4 rotation) {
this->position = position;
this->rotation = rotation;
}
@ -15,7 +20,7 @@ glm::vec3 Entity::getPosition() {
return position;
}
glm::vec3 Entity::getRotation() {
glm::mat4 Entity::getRotation() {
return rotation;
}
@ -24,5 +29,11 @@ void Entity::setPosition(glm::vec3 position) {
}
void Entity::setRotation(glm::vec3 rotation) {
this->rotation = glm::rotate(rotation.x, glm::vec3(1.0f, 0.0f, 0.0f))
* glm::rotate(rotation.y, glm::vec3(0.0f, 1.0f, 0.0f))
* glm::rotate(rotation.z, glm::vec3(0.0f, 0.0f, 1.0f));
}
void Entity::setRotation(glm::mat4 rotation) {
this->rotation = rotation;
}

View File

@ -6,15 +6,17 @@
class Entity {
public:
Entity(glm::vec3 position, glm::vec3 rotation);
Entity(glm::vec3 position, glm::mat4 rotation);
Entity();
~Entity();
void setPosition(glm::vec3 positon);
void setRotation(glm::vec3 rotation);
void setRotation(glm::mat4 rotation);
glm::vec3 getPosition();
glm::vec3 getRotation();
glm::mat4 getRotation();
private:
glm::vec3 position;
glm::vec3 rotation;
glm::mat4 rotation;
};
#endif

View File

@ -17,6 +17,8 @@ subject to the following restrictions:
#ifndef BT_OBJECT_ARRAY__
#define BT_OBJECT_ARRAY__
#pragma GCC diagnostic ignored "-Wunused-variable"
#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
#include "btAlignedAllocator.h"

View File

@ -68,7 +68,7 @@ bool Graphics::createWindow()
glfwWindowHint( GLFW_OPENGL_DEBUG_CONTEXT, true );
// define whether the window can get resized:
glfwWindowHint(GLFW_RESIZABLE, false);
glfwWindowHint(GLFW_RESIZABLE, true);
// non-decorated windows can be used as splash screens:
//glfwWindowHint( GLFW_DECORATED, false );
@ -142,13 +142,6 @@ void Graphics::setWindowSize(glm::uvec2 windowSize) {
this->windowSize = windowSize;
}
void resizeCallback(Graphics* graphics, int newWidth, int newHeight)
{
// store the new window size and adjust the viewport:
graphics->setWindowSize(glm::uvec2( newWidth, newHeight));
glViewport( 0, 0, newWidth, newHeight);
}
glm::mat4 Graphics::buildFrustum( float phiInDegree, float _near, float _far, float aspectRatio) {
float phiHalfInRadians = 0.5*phiInDegree * (M_PI/180.0);

View File

@ -11,8 +11,6 @@ class Graphics {
Graphics(glm::uvec2 windowSize, float nearPlane, float farPlane);
Graphics();
void render(Level* level, ACGL::OpenGL::SharedShaderProgram shader);
// gets called at window resize:
void resizeCallback( GLFWwindow *, int newWidth, int newHeight );
// to build the projection matrix:
glm::mat4 buildFrustum( float phiInDegree, float near, float far, float aspectRatio);
glm::mat4 buildViewMatrix(Level* level);
@ -28,6 +26,4 @@ class Graphics {
GLFWwindow* window;
};
void resizeCallback(Graphics* graphics, int newWidth, int newHeight);
#endif

View File

@ -1,5 +1,7 @@
#include "level.hh"
Level::Level(std::string filePath){
this->filePath = filePath;
this->terrain = Terrain(filePath + "/terrain");
@ -12,31 +14,40 @@ Level::~Level() {
}
void Level::load(ACGL::OpenGL::SharedShaderProgram shader) {
this->physics = Physics();
this->physics.init();
// currently hard coded should later read this stuff out of a file
this->camera = Camera(glm::vec2(-0.8f, 0.0f), 3.0f);
// load the geometry of the stanford bunny and build a VAO:
Model model = Model("Bunny.obj", 0.25f);
Model model = Model("Sphere.obj", 0.75f);
// load a texture:
Material material = Material("clownfishBunny.png", 0.1f, 0.5f, 0.5f, 3.0f);
Material material = Material("stoneTexture.png", 0.1f, 0.5f, 0.5f, 3.0f);
//Create object
Object object = Object(model, material, glm::vec3(0.0f, 0.0f, -2.0f),
Object object = Object(model, material, glm::vec3(0.0f, 5.0f, 0.0f),
glm::vec3(0.0f, 1.0472f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 0.0f, 0.0f), shader);
//add player to phy
this->physics.addPlayer(0.75f,0.0f,5.0f,0.0f,1.0f,0);
physics.addStaticGroundPlane();
//set lighting parameters
ambientLight = glm::vec3(1.0f, 1.0f, 1.0f);
Light light = Light(glm::vec3(-3.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), 2.0f);
Light light = Light(glm::vec3(-3.0f, 6.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), 10.0f);
lights.push_back(light);
Light light2 = Light(glm::vec3(3.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), 2.0f);
Light light2 = Light(glm::vec3(3.0f, 6.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f), 10.0f);
lights.push_back(light2);
// load terrain
this->terrain.load();
Model terrainModel = this->terrain.getModel();
Model terrainModel = Model(this->terrain.getModel());
// load a texture:
Material terrainMaterial = Material("clownfishBunny.png", 0.1f, 0.7f, 0.3f, 1.0f);
Material terrainMaterial = Material("terrainTexture.png", 0.1f, 0.8f, 0.2f, 3.0f);
//Create object
Object terrainObject = Object(terrainModel, terrainMaterial,
glm::vec3(-0.5f*(float)this->terrain.getHeightmapHeight(), 0.0f, -0.5f*(float)this->terrain.getHeightmapWidth()),
@ -51,13 +62,30 @@ void Level::render() {
for(unsigned int i = 0; i<objects.size(); i++) {
objects[i].render();
}
// this->terrain.render();
}
void Level::update(float runTime, glm::vec2 mouseDelta) {
void Level::update(float runTime, glm::vec2 mouseDelta, bool wPressed, bool aPressed, bool dPressed, bool sPressed) {
// rotate bunny
//cameraCenter->setRotation(glm::vec3(0.0f, 1.0472f * runTime, 0.0f));
camera.updateRotation(mouseDelta/50.0f);
// Ignore first two mouse updates, because they are incorrect
static int i = 0;
if (i <2) {
i++;
}
else {
camera.updateRotation(mouseDelta/100.0f);
}
if(wPressed)
{
//physics.rollForward(camera.getRotation);
}
physics.takeUpdateStep(runTime);
objects[0].setPosition(physics.getPos(0));
}
glm::vec3 Level::getAmbientLight() {

View File

@ -8,6 +8,7 @@
#include "terrain.hh"
#include "material.hh"
#include "camera.hh"
#include "physics.hh"
class Level {
public:
@ -15,7 +16,7 @@ class Level {
Level();
~Level();
void load(ACGL::OpenGL::SharedShaderProgram shader); // Shader is necessary for correct texture assigning
void update(float runTime, glm::vec2 mouseDelta);
void update(float runTime, glm::vec2 mouseDelta,bool wPressed, bool aPressed,bool sPressed, bool dPressed);
void render();
glm::vec3 getAmbientLight();
std::vector<Light> getLights();
@ -27,6 +28,7 @@ class Level {
std::vector<Light> lights;
glm::vec3 ambientLight;
Object* cameraCenter;
Physics physics;
Camera camera;
Terrain terrain;
};

6096
lodepng.cpp Normal file

File diff suppressed because it is too large Load Diff

1702
lodepng.h Normal file

File diff suppressed because it is too large Load Diff

67
main.cc
View File

@ -16,13 +16,6 @@
#include <ACGL/OpenGL/glloaders/extensions.hh>
#include <ACGL/Base/Settings.hh>
#include "model.hh"
using namespace std;
using namespace ACGL::OpenGL;
using namespace ACGL::Base;
using namespace ACGL::Utils;
Application::Application() {
graphics = Graphics(glm::uvec2(1024, 786), 0.1f, 100.0f);
}
@ -47,13 +40,17 @@ void Application::init()
ACGL::Base::Settings::the()->setTexturePath("Geometry/");
ACGL::Base::Settings::the()->setGeometryPath("Geometry/");
// load Model to give shader correct Attribute locations
// TODO look up if this is really necessary, since this looks really stupid.
Model model = Model("Bunny.obj");
// construct VAO to give shader correct Attribute locations
ACGL::OpenGL::SharedArrayBuffer ab = std::make_shared<ACGL::OpenGL::ArrayBuffer>();
ab->defineAttribute("aPosition", GL_FLOAT, 3);
ab->defineAttribute("aTexCoord", GL_FLOAT, 2);
ab->defineAttribute("aNormal", GL_FLOAT, 3);
ACGL::OpenGL::SharedVertexArrayObject vao = std::make_shared<ACGL::OpenGL::VertexArrayObject>();
vao->attachAllAttributes(ab);
// look up all shader files starting with 'phong' and build a ShaderProgram from it:
shader = ACGL::OpenGL::ShaderProgramCreator("phong").attributeLocations(
model.getReference()->getAttributeLocations()).create();
vao->getAttributeLocations()).create();
shader->use();
// load Level
@ -63,10 +60,12 @@ void Application::init()
openGLCriticalError();
}
/**********************************************************************************************************************
* Returns true if a window with the desired context could get created.
* Requested OpenGL version gets set by ACGL defines.
*/
void resizeCallback(GLFWwindow* window, int newWidth, int newHeight)
{
// store the new window size and adjust the viewport:
app.getGraphics()->setWindowSize(glm::uvec2( newWidth, newHeight));
glViewport( 0, 0, newWidth, newHeight);
}
static void keyCallback(GLFWwindow* _window, int _key, int, int _action, int)
{
@ -75,10 +74,14 @@ static void keyCallback(GLFWwindow* _window, int _key, int, int _action, int)
}
}
static void scrollCallback(GLFWwindow* window, double xoffset, double yoffset) {
app.getLevel()->getCamera()->updateDistance(-(float)yoffset);
}
int main( int argc, char *argv[] )
{
Application app = Application();
//Application app = Application();
/////////////////////////////////////////////////////////////////////////////////////
// Create OpenGL capable window:
@ -91,12 +94,15 @@ int main( int argc, char *argv[] )
/////////////////////////////////////////////////////////////////////////////////////
// Set window title to binary name (without the path):
//
std::vector<std::string> tmp = StringHelpers::split( std::string( argv[0] ), '/' );
std::vector<std::string> tmp = ACGL::Utils::StringHelpers::split( std::string( argv[0] ), '/' );
glfwSetWindowTitle(app.getGraphics()->getWindow(), tmp[tmp.size()-1].c_str() );
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(app.getGraphics()->getWindow(), GLFW_STICKY_KEYS, 1 );
//glfwSetWindowSizeCallback(app.getGraphics(), resizeCallback);
glfwSetInputMode(app.getGraphics()->getWindow(), GLFW_STICKY_KEYS, 1);
// Hide mouse cursor
glfwSetInputMode(app.getGraphics()->getWindow(), GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
glfwSetWindowSizeCallback(app.getGraphics()->getWindow(), resizeCallback);
glfwSetKeyCallback(app.getGraphics()->getWindow(), keyCallback );
glfwSetScrollCallback(app.getGraphics()->getWindow(), scrollCallback );
// Enable vertical sync (on cards that support it) with parameter 1 - 0 means off
glfwSwapInterval( 0 );
@ -113,13 +119,21 @@ int main( int argc, char *argv[] )
const double FPSdelay = 2.0;
double startTimeInSeconds = glfwGetTime();
double showNextFPS = startTimeInSeconds + FPSdelay;
double lastUpdate=0.0f;
int stateW = glfwGetKey(app.getGraphics()->getWindow(), GLFW_KEY_W);
int stateA = glfwGetKey(app.getGraphics()->getWindow(), GLFW_KEY_A);
int stateS = glfwGetKey(app.getGraphics()->getWindow(), GLFW_KEY_S);
int stateD = glfwGetKey(app.getGraphics()->getWindow(), GLFW_KEY_D);
do {
double now = glfwGetTime();
double now = glfwGetTime()- startTimeInSeconds;
if (showNextFPS <= now) {
stringstream sstream (stringstream::in | stringstream::out);
sstream << setprecision(1) << std::fixed
std::stringstream sstream (std::stringstream::in | std::stringstream::out);
sstream << std::setprecision(1) << std::fixed
<< tmp[tmp.size()-1] << " - FPS: " << frameCount / (now-showNextFPS + FPSdelay) << " " << 1000 * (now-showNextFPS + FPSdelay)/frameCount << " msec";
glfwSetWindowTitle(app.getGraphics()->getWindow(), sstream.str().c_str() );
showNextFPS = now + FPSdelay;
@ -130,10 +144,13 @@ int main( int argc, char *argv[] )
glfwGetCursorPos(app.getGraphics()->getWindow(), &xpos, &ypos);
glfwSetCursorPos(app.getGraphics()->getWindow(), app.getGraphics()->getWindowSize().x/2, app.getGraphics()->getWindowSize().y/2);
app.getLevel()->update(now - startTimeInSeconds, glm::vec2((float)ypos-app.getGraphics()->getWindowSize().y/2,
(float)xpos-app.getGraphics()->getWindowSize().x/2));
app.getLevel()->update(now - lastUpdate,
glm::vec2((float)ypos-app.getGraphics()->getWindowSize().y/2,
(float)xpos-app.getGraphics()->getWindowSize().x/2),
stateW == GLFW_PRESS,stateA == GLFW_PRESS,stateS == GLFW_PRESS,stateD == GLFW_PRESS);
lastUpdate = now;
app.getGraphics()->render(app.getLevel(), app.getShader());
openGLCriticalError();
// MacOS X will not swap correctly is another FBO is bound:

View File

@ -25,4 +25,5 @@ class Application {
ACGL::OpenGL::SharedShaderProgram shader;
};
Application app;
#endif

View File

@ -24,9 +24,7 @@ void Object::render() {
shader->setUniform("shininess", material.getShininess());
shader->setTexture("uTexture", material.getReference(), 0);
// set model matrix
glm::mat4 rotationMatrix = glm::rotate<float>(this->getRotation()[0], glm::vec3(1.0f, 0.0f, 0.0f)) *
glm::rotate<float>(this->getRotation()[1], glm::vec3(0.0f, 1.0f, 0.0f)) * glm::rotate<float>(this->getRotation()[2], glm::vec3(0.0f, 0.0f, 1.0f));
glm::mat4 modelMatrix = glm::translate(this->getPosition()) * rotationMatrix * glm::scale<float>(glm::vec3(model.getScale()));
glm::mat4 modelMatrix = glm::translate(getPosition()) * getRotation() * glm::scale<float>(glm::vec3(model.getScale()));
shader->setUniform( "modelMatrix", modelMatrix);
// draw
model.getReference()->render();

View File

@ -1,7 +1,5 @@
#include "physics.hh"
#include <vector>
btDynamicsWorld* world; //contains physical attributes of the world.
btDispatcher* dispatcher; //
@ -12,8 +10,16 @@ btConstraintSolver* solver; //solver for forces and impulses.
std::vector<btRigidBody*> bodies; //list of all bodies. bodies are also in world, but save again to ease cleaning up process.
btRigidBody* playerBall;
btRigidBody* terrainBody;
btRigidBody* staticGroundBody;
void init()
Physics::Physics() {
}
Physics::~Physics() {
}
void Physics::init()
{
colConfig = new btDefaultCollisionConfiguration();
dispatcher = new btCollisionDispatcher(colConfig);
@ -21,17 +27,15 @@ void init()
solver = new btSequentialImpulseConstraintSolver();
world = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,colConfig);
world->setGravity(btVector3(0,-10,-0));
world->setGravity(btVector3(0,-10,-0));
}
void takeUpdateStep(float timeDiff)
void Physics::takeUpdateStep(float timeDiff)
{
world->stepSimulation(timeDiff);
}
void addTerrain(int width, int length, float** heightData)
void Physics::addTerrain(int width, int length, float** heightData)
{
float* heightfield = new float[width * length];
int highest = -999999, j = 0, i = 0;
@ -70,7 +74,17 @@ void addTerrain(int width, int length, float** heightData)
}
void addPlayer(float rad, float x, float y, float z, float mass, unsigned indice)
void Physics::addStaticGroundPlane()
{
btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0, 1, 0), 0);
btDefaultMotionState* groundMotionState = new btDefaultMotionState(btTransform(btQuaternion(0, 0, 0, 1), btVector3(0, 0, 0)));
btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI(0, groundMotionState, groundShape, btVector3(0, 0, 0));
staticGroundBody = new btRigidBody(groundRigidBodyCI);
world->addRigidBody(staticGroundBody);
}
void Physics::addPlayer(float rad, float x, float y, float z, float mass, unsigned indice)
{
if(bodies.size() != indice)
throw std::invalid_argument( "Bodies out of Sync" );
@ -98,7 +112,7 @@ void addPlayer(float rad, float x, float y, float z, float mass, unsigned indice
}
void addSphere(float rad, float x, float y, float z, float mass, unsigned indice)
void Physics::addSphere(float rad, float x, float y, float z, float mass, unsigned indice)
{
if(bodies.size() != indice)
throw std::invalid_argument( "Bodies out of Sync" );
@ -126,30 +140,34 @@ void addSphere(float rad, float x, float y, float z, float mass, unsigned indice
}
glm::vec3 getPos(int i)
glm::vec3 Physics::getPos(int i)
{
btVector3 origin = bodies[i]->getCenterOfMassPosition();
glm::vec3 save(origin.getX(),origin.getY(),origin.getZ());
return save;
}
glm::mat4 getRotation(int i)
glm::mat4 Physics::getRotation(int i)
{
btQuaternion quat = bodies[i]->getOrientation();
glm::mat4 matrix = glm::rotate(
matrix,
quat.getAngle(),
glm::vec3(quat.getAxis().getX(), quat.getAxis().getY(), quat.getAxis().getZ())
);
return matrix;
}
void rollForward(glm::mat3 rotCamera)
void Physics::rollForward(glm::vec3 camPos)
{
glm::vec3 saveVector= glm::vec3(1,0,0) * rotCamera;
btVector3 pos(camPos.x,camPos.y,camPos.z);
pos -= playerBody->getCenterOfMassPosition();
pos.cross(btVector3(0,1,0));
playerBall->applyTorque(pos);
/* glm::vec3 saveVector= glm::vec3(1,0,0) * rotCamera;
saveVector = glm::cross(glm::vec3(0,1,0),saveVector);
playerBall->applyTorque(btVector3(saveVector[0],saveVector[1],saveVector[2]));
playerBall->applyTorque(btVector3(saveVector[0],saveVector[1],saveVector[2]));*/
}
/*

View File

@ -11,6 +11,7 @@
#include "extern/bullet/src/BulletCollision/CollisionShapes/btSphereShape.h"
#include "extern/bullet/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h"
#include "extern/bullet/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h"
#include "extern/bullet/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h"
#include "extern/bullet/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"//YAY!
@ -31,14 +32,15 @@
class Physics {
public:
Physics();
Physics();
~Physics();
void init();
void takeUpdateStep(float timeDiff);
void rollForward(glm::vec3 camPos, float strength);
glm::vec3 getPos(int i);
glm::mat4 getRotation(int i);
void rollForward(glm::mat3 rotCamera);
void rollForward(glm::vec3 camPos);
void addStaticGroundPlane();
void addTerrain(int width, int length, float** heightData);
void addPlayer(float rad, float x, float y, float z, float mass, unsigned indice);
void addSphere(float rad, float x, float y, float z, float mass, unsigned indice);
@ -47,6 +49,7 @@ class Physics {
btRigidBody* playerBody;
btRigidBody* terrainBody;
std::vector<btRigidBody*> bodies; //list of all bodies. bodies are also in world, but save again to ease cleaning up process.
btRigidBody* staticGroundBody;
btDynamicsWorld* world; //contains physical attributes of the world.

View File

@ -1,4 +1,5 @@
#include "terrain.hh"
#include "lodepng.h"
Terrain::Terrain(std::string filePath){
this->filePath = filePath;
@ -12,28 +13,21 @@ Terrain::~Terrain() {
void Terrain::load() {
this->filePath = "../Levels/LevelTest/terrain"; //TODO remove this, its only for testing
filePath = "../Levels/LevelTest/terrain/"; //TODO remove this, its only for testing
std::ifstream terrain_png(this->filePath + "/heightmap.png");
unsigned int rowNum, columnNum, heightmapValue;
terrain_png.seekg(16); //skip part of the header
char temp[4];
terrain_png.read(temp, 4); //read width
this->heightmapWidth = (temp[3]<<0) | (temp[2]<<8) | (temp[1]<<16) | (temp[0]<<24); //convert from network to host byte order
terrain_png.read(temp, 4); //read height
this->heightmapHeight = (temp[3]<<0) | (temp[2]<<8) | (temp[1]<<16) | (temp[0]<<24); //convert from network to host byte order
heightmap = new float*[this->heightmapHeight]; //initialize the heightmap
for(rowNum = 0; rowNum < this->heightmapHeight; rowNum++){ //read in the heightmap
heightmap[rowNum] = new float[this->heightmapWidth];
for(columnNum = 0; columnNum < this->heightmapWidth; columnNum++){
terrain_png.read((char *)&heightmapValue, 1);
heightmap[rowNum][columnNum] = (float)heightmapValue / 256;
std::vector<unsigned char> image; //the raw pixels
unsigned error = lodepng::decode(image, heightmapWidth, heightmapHeight, filePath + "heightmap.png");
if (error) {
std::cout << "decoder error " << error << ": " << lodepng_error_text(error) << std::endl;
}
this->heightmap = new float*[this->heightmapHeight]; //initialize the heightmap
for(unsigned int rowNum = 0; rowNum < this->heightmapHeight; rowNum++){ //read in the heightmap
this->heightmap[rowNum] = new float[this->heightmapWidth];
for(unsigned int columnNum = 0; columnNum < this->heightmapWidth; columnNum++){
this->heightmap[rowNum][columnNum] = (float)(image[(rowNum*heightmapWidth+columnNum)*4]) / 32;
}
}
this->makeTriangleMesh();
heightmapChanged = false; //no need to make a TriangleMesh again before rendering
@ -42,48 +36,53 @@ void Terrain::load() {
void Terrain::makeTriangleMesh(){
ACGL::OpenGL::SharedArrayBuffer ab = std::make_shared<ACGL::OpenGL::ArrayBuffer>();
ab->defineAttribute("aPosition", GL_FLOAT, 3); //TODO: ArrayBuffer for the texture coordinates
ab->defineAttribute("aNormal", GL_FLOAT, 3);
// Do NOT change the order of this!
ab->defineAttribute("aPosition", GL_FLOAT, 3);
ab->defineAttribute("aTexCoord", GL_FLOAT, 2);
ab->defineAttribute("aNormal", GL_FLOAT, 3);
unsigned int rowNum=0, columnNum=0, dataCount=0, abNumFloats=8; //initializing:
bool movingRight = true, isUp = true;
int numVertices = (this->heightmapHeight - 1) * (this->heightmapWidth * 2 + 1) + 1;
float* abData = new float[numVertices * abNumFloats];
float* abData = new float[numVertices * floatsPerVertex];
while(rowNum < this->heightmapHeight){ //traversing the Triangle Strip!
set_abData(abData, dataCount, rowNum, columnNum);
dataCount += abNumFloats;
dataCount += floatsPerVertex;
if (isUp){
rowNum = rowNum + 1;
isUp = false;
}else if (movingRight){
if (columnNum == this->heightmapWidth - 1){
set_abData(abData, dataCount, rowNum, columnNum);
dataCount += abNumFloats;
set_abData(abData, dataCount, rowNum, columnNum);
dataCount += abNumFloats;
movingRight = false;
rowNum = rowNum + 1;
} else{
rowNum = rowNum - 1;
columnNum = columnNum + 1;
isUp = true;
}
}else{
if (columnNum == 0){
set_abData(abData, dataCount, rowNum, columnNum);
dataCount += abNumFloats;
set_abData(abData, dataCount, rowNum, columnNum);
dataCount += abNumFloats;
movingRight = true;
rowNum = rowNum + 1;
}else{
rowNum = rowNum - 1;
columnNum = columnNum - 1;
isUp = true;
}
}
else if (movingRight) {
if (columnNum == this->heightmapWidth - 1) {
set_abData(abData, dataCount, rowNum, columnNum);
dataCount += abNumFloats;
set_abData(abData, dataCount, rowNum, columnNum);
dataCount += abNumFloats;
movingRight = false;
rowNum = rowNum + 1;
}
else {
rowNum = rowNum - 1;
columnNum = columnNum + 1;
isUp = true;
}
}
else {
if (columnNum == 0){
set_abData(abData, dataCount, rowNum, columnNum);
dataCount += abNumFloats;
set_abData(abData, dataCount, rowNum, columnNum);
dataCount += abNumFloats;
movingRight = true;
rowNum = rowNum + 1;
}
else {
rowNum = rowNum - 1;
columnNum = columnNum - 1;
isUp = true;
}
}
}
ab->setDataElements(numVertices, abData);
@ -101,33 +100,34 @@ void Terrain::set_abData(float* abData, unsigned int dataCount, unsigned int row
abData[dataCount+1] = heightmap[rowNum][columnNum];
abData[dataCount+2] = (float)columnNum;
//set Texture Coordinate
abData[dataCount+3] = (float)(rowNum % 2);
abData[dataCount+4] = (float)(columnNum % 2);
//setNormal
if (rowNum==0 || rowNum==(this->heightmapHeight-1) || columnNum==0 || columnNum==(this->heightmapWidth-1)){
abData[dataCount+3] = 0.0;
abData[dataCount+4] = 1.0;
abData[dataCount+5] = 0.0;
}else{
glm::vec3 sumNormals;
for (int i=-1; i<2; i+=1){
for (int j=-1; j<2; j+=1){
glm::vec3 vecA, vecB, normal;
vecA = glm::vec3((float)i, (heightmap[rowNum+i][columnNum] - heightmap[rowNum][columnNum]), 0.0f);
vecB = glm::vec3(0.0f, (heightmap[rowNum][columnNum+j] - heightmap[rowNum][columnNum]), (float)j);
normal = glm::normalize(glm::cross(vecA, vecB));
if(i+j==0)
normal = normal*(-1.0f);
sumNormals += normal;
}
}
sumNormals = sumNormals*0.111f;
abData[dataCount+3] = sumNormals[0];
abData[dataCount+4] = sumNormals[1];
abData[dataCount+5] = sumNormals[2];
abData[dataCount+6] = 1.0;
abData[dataCount+7] = 0.0;
}
else {
glm::vec3 sumNormals = glm::vec3(0.0f, 0.0f, 0.0f);
for (int i=-1; i<2; i+=2) {
for (int j=-1; j<2; j+=2) {
glm::vec3 vecA, vecB, normal;
vecA = glm::vec3((float)i, (heightmap[rowNum+i][columnNum] - heightmap[rowNum][columnNum]), 0.0f);
vecB = glm::vec3(0.0f, (heightmap[rowNum][columnNum+j] - heightmap[rowNum][columnNum]), (float)j);
normal = glm::normalize(glm::cross(vecA, vecB));
if(i+j!=0)
normal = normal*(-1.0f);
sumNormals += normal;
}
}
sumNormals = glm::normalize(sumNormals);
abData[dataCount+5] = sumNormals[0];
abData[dataCount+6] = sumNormals[1];
abData[dataCount+7] = sumNormals[2];
}
//set Texture Coordinate
abData[dataCount+6] = (float)(rowNum % 2);
abData[dataCount+7] = (float)(columnNum % 2);
}
Model Terrain::getModel(){
@ -145,14 +145,3 @@ unsigned int Terrain::getHeightmapHeight(){
unsigned int Terrain::getHeightmapWidth(){
return this->heightmapWidth;
}

View File

@ -3,7 +3,6 @@
#include <string>
#include "material.hh"
#include <fstream>
#include <ACGL/OpenGL/Objects/VertexArrayObject.hh>
#include "model.hh"
class Terrain {