/// Inlcudes #define MAIN #include "MicroGlut.h" #include "GL_utilities.h" #include "VectorUtils4.h" #include "LittleOBJLoader.h" #include "LoadTGA.h" /// Globals GLuint program; mat4 projection; Model * terrain; GLuint tex; /// Generate terrain Model * GenerateTerrain(const char * filename) { TextureData textureData; if (!LoadTGATextureData(filename, &textureData)) return nullptr; int vertexCount = textureData.width * textureData.height; int triangleCount = (textureData.width-1) * (textureData.height-1) * 2; vec3 * position = (vec3 *) malloc(sizeof(GLfloat) * 3 * vertexCount); vec3 * normal = (vec3 *) malloc(sizeof(GLfloat) * 3 * vertexCount); vec2 * texCoord = (vec2 *) malloc(sizeof(GLfloat) * 2 * vertexCount); GLuint * indices = (GLuint *)malloc(sizeof(GLuint) * 3 * triangleCount); int bytesPerPixel = textureData.bpp / 8; for (unsigned int x = 0; x < textureData.width; ++x) for (unsigned int z = 0; z < textureData.height; ++z) { int indexBase = (x + z * textureData.width); // Vertex array. You need to scale this properly. GLubyte data = textureData.imageData[indexBase * bytesPerPixel]; position[indexBase].x = x / 1.0; position[indexBase].y = data / 100.0; position[indexBase].z = z / 1.0; // Normal vectors. You need to calculate these. normal[indexBase].x = 0.0; normal[indexBase].y = 1.0; normal[indexBase].z = 0.0; // Texture coordinates. You may want to scale them. texCoord[indexBase].x = x; // (float)x / textureData.width; texCoord[indexBase].y = z; // (float)z / textureData.height; } for (unsigned int x = 0; x < textureData.width-1; ++x) for (unsigned int z = 0; z < textureData.height-1; ++z) { int indexBase = (x + z * (textureData.width-1))*6; // Triangle 1 indices[indexBase + 0] = (x+0) + (z+0) * textureData.width; indices[indexBase + 1] = (x+0) + (z+1) * textureData.width; indices[indexBase + 2] = (x+1) + (z+0) * textureData.width; // Triangle 2 indices[indexBase + 3] = (x+1) + (z+0) * textureData.width; indices[indexBase + 4] = (x+0) + (z+1) * textureData.width; indices[indexBase + 5] = (x+1) + (z+1) * textureData.width; } // Create Model and upload to GPU: Model * model = LoadDataToModel( position, normal, texCoord, nullptr, indices, vertexCount, triangleCount * 3 ); free(textureData.imageData); return model; } /// Init void init(void) { // GL inits. glClearColor(0.2, 0.2, 0.5, 0.0); glEnable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); printError("init GL"); // Load and compile shader. program = loadShaders("terrain.vert", "terrain.frag"); glUseProgram(program); printError("init shader"); // Matrices. projection = frustum(-0.1, 0.1, -0.1, 0.1, 0.2, 50.0); glUniformMatrix4fv(glGetUniformLocation(program, "projection"), 1, GL_TRUE, projection.m); printError("init matrices"); // Textures. LoadTGATextureSimple("../assets/terrain/dandelion.tga", &tex); glBindTexture(GL_TEXTURE_2D, tex); glUniform1i(glGetUniformLocation(program, "tex"), 0); printError("init textures"); // Generate terrain. terrain = GenerateTerrain("../assets/terrain/simple-4.tga"); printError("init terrain"); } /// Display void display(void) { // Clear the screen. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Uniforms. mat4 view = lookAt( vec3(0, 5, 8), // Position. vec3(2, 0, 2), // Target. vec3(0, 1, 0) // Up. ); mat4 model = IdentityMatrix(); mat4 modelView = view * model; glUniformMatrix4fv(glGetUniformLocation(program, "modelView"), 1, GL_TRUE, modelView.m); printError("display uniforms"); // Draw. DrawModel(terrain, program, "inPosition", nullptr, "inTexCoord"); printError("display draw"); // Show on the screen. glutSwapBuffers(); } /// Mouse void mouse(int x, int y) { // This function is included in case you want some hints about using // passive mouse movement. Uncomment to see mouse coordinates: // printf("%d %d\n", x, y); } /// Main int main(int argc, char * argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH); glutInitContextVersion(3, 2); glutInitWindowSize(600, 600); glutCreateWindow("TSBK07"); glutRepeatingTimer(20); glutDisplayFunc(display); glutPassiveMotionFunc(mouse); dumpInfo(); init(); glutMainLoop(); }