diff --git a/obj/Xblock.obj b/obj/Xblock.obj new file mode 100644 index 0000000..531e1a2 --- /dev/null +++ b/obj/Xblock.obj @@ -0,0 +1,40 @@ +# Blender 4.1.1 +# www.blender.org +mtllib Xblock.mtl +o Cube +v 1.740000 0.130000 -0.150000 +v 1.740000 -0.130000 -0.150000 +v 1.740000 0.130000 0.150000 +v 1.740000 -0.130000 0.150000 +v -1.740000 0.130000 -0.150000 +v -1.740000 -0.130000 -0.150000 +v -1.740000 0.130000 0.150000 +v -1.740000 -0.130000 0.150000 +vn -0.0000 1.0000 -0.0000 +vn -0.0000 -0.0000 1.0000 +vn -1.0000 -0.0000 -0.0000 +vn -0.0000 -1.0000 -0.0000 +vn 1.0000 -0.0000 -0.0000 +vn -0.0000 -0.0000 -1.0000 +vt 0.625000 0.500000 +vt 0.875000 0.500000 +vt 0.875000 0.750000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 1.000000 +vt 0.375000 1.000000 +vt 0.375000 0.000000 +vt 0.625000 0.000000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.125000 0.500000 +vt 0.375000 0.500000 +vt 0.125000 0.750000 +s 0 +usemtl Material +f 1/1/1 5/2/1 7/3/1 3/4/1 +f 4/5/2 3/4/2 7/6/2 8/7/2 +f 8/8/3 7/9/3 5/10/3 6/11/3 +f 6/12/4 2/13/4 4/5/4 8/14/4 +f 2/13/5 1/1/5 3/4/5 4/5/5 +f 6/11/6 5/10/6 1/1/6 2/13/6 diff --git a/obj/Yblock.obj b/obj/Yblock.obj new file mode 100644 index 0000000..845b7b9 --- /dev/null +++ b/obj/Yblock.obj @@ -0,0 +1,40 @@ +# Blender 4.1.1 +# www.blender.org +mtllib Yblock.mtl +o Cube +v 0.230000 0.130000 -1.230000 +v 0.230000 -0.130000 -1.230000 +v 0.230000 0.130000 1.230000 +v 0.230000 -0.130000 1.230000 +v -0.230000 0.130000 -1.230000 +v -0.230000 -0.130000 -1.230000 +v -0.230000 0.130000 1.230000 +v -0.230000 -0.130000 1.230000 +vn -0.0000 1.0000 -0.0000 +vn -0.0000 -0.0000 1.0000 +vn -1.0000 -0.0000 -0.0000 +vn -0.0000 -1.0000 -0.0000 +vn 1.0000 -0.0000 -0.0000 +vn -0.0000 -0.0000 -1.0000 +vt 0.625000 0.500000 +vt 0.875000 0.500000 +vt 0.875000 0.750000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 1.000000 +vt 0.375000 1.000000 +vt 0.375000 0.000000 +vt 0.625000 0.000000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.125000 0.500000 +vt 0.375000 0.500000 +vt 0.125000 0.750000 +s 0 +usemtl Material +f 1/1/1 5/2/1 7/3/1 3/4/1 +f 4/5/2 3/4/2 7/6/2 8/7/2 +f 8/8/3 7/9/3 5/10/3 6/11/3 +f 6/12/4 2/13/4 4/5/4 8/14/4 +f 2/13/5 1/1/5 3/4/5 4/5/5 +f 6/11/6 5/10/6 1/1/6 2/13/6 diff --git a/obj/Yblock_rotated.obj b/obj/Yblock_rotated.obj new file mode 100644 index 0000000..83b122b --- /dev/null +++ b/obj/Yblock_rotated.obj @@ -0,0 +1,40 @@ +# Blender 4.1.1 +# www.blender.org +mtllib Yblock_rotated.mtl +o Cube +v 1.231565 1.164580 -0.150000 +v 1.395188 0.962522 -0.150000 +v 1.231565 1.164580 0.150000 +v 1.395188 0.962522 0.150000 +v -1.395188 -0.962522 -0.150000 +v -1.231565 -1.164580 -0.150000 +v -1.395188 -0.962522 0.150000 +v -1.231565 -1.164580 0.150000 +vn -0.6293 0.7771 -0.0000 +vn -0.0000 -0.0000 1.0000 +vn -0.7771 -0.6293 -0.0000 +vn 0.6293 -0.7771 -0.0000 +vn 0.7771 0.6293 -0.0000 +vn -0.0000 -0.0000 -1.0000 +vt 0.625000 0.500000 +vt 0.875000 0.500000 +vt 0.875000 0.750000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 1.000000 +vt 0.375000 1.000000 +vt 0.375000 0.000000 +vt 0.625000 0.000000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.125000 0.500000 +vt 0.375000 0.500000 +vt 0.125000 0.750000 +s 0 +usemtl Material +f 1/1/1 5/2/1 7/3/1 3/4/1 +f 4/5/2 3/4/2 7/6/2 8/7/2 +f 8/8/3 7/9/3 5/10/3 6/11/3 +f 6/12/4 2/13/4 4/5/4 8/14/4 +f 2/13/5 1/1/5 3/4/5 4/5/5 +f 6/11/6 5/10/6 1/1/6 2/13/6 diff --git a/obj/Zblock.obj b/obj/Zblock.obj new file mode 100644 index 0000000..4db8bb1 --- /dev/null +++ b/obj/Zblock.obj @@ -0,0 +1,40 @@ +# Blender 4.1.1 +# www.blender.org +mtllib Zblock.mtl +o Cube +v 0.280000 1.000000 -0.170000 +v 0.280000 -1.000000 -0.170000 +v 0.280000 1.000000 0.170000 +v 0.280000 -1.000000 0.170000 +v -0.280000 1.000000 -0.170000 +v -0.280000 -1.000000 -0.170000 +v -0.280000 1.000000 0.170000 +v -0.280000 -1.000000 0.170000 +vn -0.0000 1.0000 -0.0000 +vn -0.0000 -0.0000 1.0000 +vn -1.0000 -0.0000 -0.0000 +vn -0.0000 -1.0000 -0.0000 +vn 1.0000 -0.0000 -0.0000 +vn -0.0000 -0.0000 -1.0000 +vt 0.625000 0.500000 +vt 0.875000 0.500000 +vt 0.875000 0.750000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 1.000000 +vt 0.375000 1.000000 +vt 0.375000 0.000000 +vt 0.625000 0.000000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.125000 0.500000 +vt 0.375000 0.500000 +vt 0.125000 0.750000 +s 0 +usemtl Material +f 1/1/1 5/2/1 7/3/1 3/4/1 +f 4/5/2 3/4/2 7/6/2 8/7/2 +f 8/8/3 7/9/3 5/10/3 6/11/3 +f 6/12/4 2/13/4 4/5/4 8/14/4 +f 2/13/5 1/1/5 3/4/5 4/5/5 +f 6/11/6 5/10/6 1/1/6 2/13/6 diff --git a/src/main.c b/src/main.c index f877312..8a694d6 100644 --- a/src/main.c +++ b/src/main.c @@ -5,7 +5,7 @@ #include "vertexShader.c" #include "fragmentShader.c" - +#include "objectHandler.c" #include "matrixMath.h" #include "transformation.h" #include "wavefrontobj.h" @@ -19,7 +19,6 @@ #include GLuint program; -GLuint vao; #define NUM_TEXTURES 5 @@ -33,14 +32,14 @@ int flipFlag = 1; GLuint textures[NUM_TEXTURES]; char* textureFiles[NUM_TEXTURES] = { - "../texture/earth/day.png", - "../texture/earth/night.png", - "../texture/earth/clouds.png", - "../texture/earth/ocean_mask.png", - "../texture/earth/normal.png" + "../texture/earth/day.png", + "../texture/earth/night.png", + "../texture/earth/clouds.png", + "../texture/earth/ocean_mask.png", + "../texture/earth/normal.png" }; -int numFaces = 0; +ObjectData* objectData; bool exitRequested = false; @@ -57,412 +56,397 @@ GLfloat step = 0.0f; const GLfloat pi = 3.14159f; vec3 cameraPosition = {0.0f, 3.0f, 5.5f}; +vec3 objectPosition = {0.0f, 0.0f, 0.0f}; +GLfloat radius = 1.0f; -char* defaultModel = "../obj/monkey.obj"; -char* model; +int numModels = 0; +char* models[] = { + "../obj/Xblock.obj", + "../obj/Yblock.obj", + "../obj/Yblock_rotated.obj", + "../obj/Zblock.obj", +}; -// input handler for camera movement +/** + * Input handler for camera movement. + * */ void handleInputs(double deltaTime) { - if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { - cameraPosition.z += deltaTime * 10; - } - if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { - cameraPosition.z -= deltaTime * 10; - } - if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { - cameraPosition.x += deltaTime * 10; - } - if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { - cameraPosition.x -= deltaTime * 10; - } - if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) { - cameraPosition.y += deltaTime * 10; - } - if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) { - cameraPosition.y -= deltaTime * 10; - } + if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { + cameraPosition.z += deltaTime * 10; + } + if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { + cameraPosition.z -= deltaTime * 10; + } + if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { + cameraPosition.x += deltaTime * 10; + } + if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { + cameraPosition.x -= deltaTime * 10; + } + if (glfwGetKey(window, GLFW_KEY_F) == GLFW_PRESS) { + cameraPosition.y += deltaTime * 10; + } + if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS) { + cameraPosition.y -= deltaTime * 10; + } + + if (glfwGetKey(window, GLFW_KEY_L) == GLFW_PRESS) { + objectPosition.x += deltaTime * 10; + } + if (glfwGetKey(window, GLFW_KEY_J) == GLFW_PRESS) { + objectPosition.x -= deltaTime * 10; + } + if (glfwGetKey(window, GLFW_KEY_I) == GLFW_PRESS) { + objectPosition.z += deltaTime * 10; + } + if (glfwGetKey(window, GLFW_KEY_K) == GLFW_PRESS) { + objectPosition.z -= deltaTime * 10; + } + if (glfwGetKey(window, GLFW_KEY_O) == GLFW_PRESS) { + radius += deltaTime * 10; + } + if (glfwGetKey(window, GLFW_KEY_U) == GLFW_PRESS) { + radius -= deltaTime * 10; + } } // input handler to quit with ESC void keyboardHandler(GLFWwindow* window, int key, int scancode, int action, int mods) { - if (action == GLFW_PRESS) { - if (key == GLFW_KEY_ESCAPE) { - exitRequested = true; - } - } + if (action == GLFW_PRESS) { + if (key == GLFW_KEY_ESCAPE) { + exitRequested = true; + } + } } +/** + * Loads textures. + */ void loadTexture(char* textureFile, GLuint* texture) { - int width, height, nrChannels; - unsigned char* image = stbi_load(textureFile, &width, &height, &nrChannels, 0); + int width, height, nrChannels; + unsigned char* image = stbi_load(textureFile, &width, &height, &nrChannels, 0); - // default: 3 channels, RGB + // default: 3 channels, RGB - GLenum channelFormats[] = { - 0, - GL_RED, - GL_RG, - GL_RGB, - GL_RGBA - }; - GLenum format = channelFormats[nrChannels]; + GLenum channelFormats[] = { + 0, + GL_RED, + GL_RG, + GL_RGB, + GL_RGBA + }; + GLenum format = channelFormats[nrChannels]; - glGenTextures(1, texture); - glBindTexture(GL_TEXTURE_2D, *texture); + glGenTextures(1, texture); + glBindTexture(GL_TEXTURE_2D, *texture); - printf("%s - %d\n", textureFile, nrChannels); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, format, GL_UNSIGNED_BYTE, image); - // load texture using previously determined format ----- ^^^^^^ + printf("%s - %d\n", textureFile, nrChannels); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, format, GL_UNSIGNED_BYTE, image); + // load texture using previously determined format ----- ^^^^^^ - glGenerateMipmap(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, 0); + glGenerateMipmap(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); - stbi_image_free(image); + stbi_image_free(image); } void init(void) { - // create and compile vertex shader - const GLchar *vertexTextConst = vertexShader_glsl; + // create and compile vertex shader + const GLchar *vertexTextConst = vertexShader_glsl; - GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(vertexShader, 1, &vertexTextConst, &vertexShader_glsl_len); - glCompileShader(vertexShader); + GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertexShader, 1, &vertexTextConst, &vertexShader_glsl_len); + glCompileShader(vertexShader); - GLint status; - glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status); - - if (!status) { - printf("Error compiling vertex shader: "); - GLchar infoLog[1024]; - glGetShaderInfoLog(vertexShader, 1024, NULL, infoLog); - printf("%s",infoLog); - exit(1); - } + GLint status; + glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status); + + if (!status) { + printf("Error compiling vertex shader: "); + GLchar infoLog[1024]; + glGetShaderInfoLog(vertexShader, 1024, NULL, infoLog); + printf("%s",infoLog); + exit(1); + } - vertexTextConst = NULL; + vertexTextConst = NULL; + + // create and compile fragment shader + const GLchar *fragmentTextConst = fragmentShader_glsl; + + GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragmentShader, 1, &fragmentTextConst, &fragmentShader_glsl_len); + glCompileShader(fragmentShader); + + glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status); + + if (!status) { + printf("Error compiling fragment shader: "); + GLchar infoLog[1024]; + glGetShaderInfoLog(fragmentShader, 1024, NULL, infoLog); + printf("%s",infoLog); + exit(1); + } + + // create and link shader program + program = glCreateProgram(); + glAttachShader(program, vertexShader); + glAttachShader(program, fragmentShader); + glLinkProgram(program); + + glGetProgramiv(program, GL_LINK_STATUS, &status); + + if (!status) { + printf("Error linking program: "); + GLchar infoLog[1024]; + glGetProgramInfoLog(program, 1024, NULL, infoLog); + printf("%s",infoLog); + exit(1); + } + glValidateProgram(program); + glGetProgramiv(program, GL_VALIDATE_STATUS, &status); - // create and compile fragment shader - - const GLchar *fragmentTextConst = fragmentShader_glsl; - - GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(fragmentShader, 1, &fragmentTextConst, &fragmentShader_glsl_len); - glCompileShader(fragmentShader); - - glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status); - - if (!status) { - printf("Error compiling fragment shader: "); - GLchar infoLog[1024]; - glGetShaderInfoLog(fragmentShader, 1024, NULL, infoLog); - printf("%s",infoLog); - exit(1); - } - - // create and link shader program - program = glCreateProgram(); - glAttachShader(program, vertexShader); - glAttachShader(program, fragmentShader); - glLinkProgram(program); - - glGetProgramiv(program, GL_LINK_STATUS, &status); - - if (!status) { - printf("Error linking program: "); - GLchar infoLog[1024]; - glGetProgramInfoLog(program, 1024, NULL, infoLog); - printf("%s",infoLog); - exit(1); - } - glValidateProgram(program); + if (!status) { + printf("Error validating program: "); + GLchar infoLog[1024]; + glGetProgramInfoLog(program, 1024, NULL, infoLog); + printf("%s",infoLog); + exit(1); + } - glGetProgramiv(program, GL_VALIDATE_STATUS, &status); + // --------------- READ MODEL FILES + + //objectData = readObjFiles(&models, numModels); + char* c = "../obj/Yblock.obj"; + objectData = readSingleObjFile(&c, 10, &numModels); + printf("\nAmount %d\n", numModels); + fflush(stdout); + /* + objectData = malloc(numModels * sizeof(ObjectData)); + for (int i = 0; i < numModels; i++) { - if (!status) { - printf("Error validating program: "); - GLchar infoLog[1024]; - glGetProgramInfoLog(program, 1024, NULL, infoLog); - printf("%s",infoLog); - exit(1); - } + glGenVertexArrays(1, &objData->vao); + glGenBuffers(1, &objData->vbo); + glBindVertexArray(objData->vao); + glBindBuffer(GL_ARRAY_BUFFER, objData->vbo); + glBufferData(GL_ARRAY_BUFFER, objData->object.numFaces * 3 * sizeof(Vertex), objData->object.vertices, GL_STATIC_DRAW); - // --------------- READ MODEL FILE - ParsedObjFile teapot = readObjFile(model); - numFaces = teapot.length; + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)0); + glEnableVertexAttribArray(0); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(3 * sizeof(GLfloat))); + glEnableVertexAttribArray(1); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(6 * sizeof(GLfloat))); + glEnableVertexAttribArray(2); - // write faces to buffer - GLuint triangleVertexBufferObject; - glGenBuffers(1, &triangleVertexBufferObject); - glBindBuffer(GL_ARRAY_BUFFER, triangleVertexBufferObject); - glBufferData(GL_ARRAY_BUFFER, teapot.length * sizeof(face), teapot.faces, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + objectData[i] = objData; + } + */ - stbi_set_flip_vertically_on_load(flipFlag); - // -------------- READ TEXTURE FILES - for (int i = 0; i < NUM_TEXTURES; i++) { - loadTexture(textureFiles[i], &textures[i]); - } + stbi_set_flip_vertically_on_load(flipFlag); + // -------------- READ TEXTURE FILES + for (int i = 0; i < NUM_TEXTURES; i++) { + loadTexture(textureFiles[i], &textures[i]); + } + // ENABLE BACKFACE CULLING + glFrontFace(GL_CCW); + glEnable(GL_CULL_FACE); - // create vertex array object - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); - glBindBuffer(GL_ARRAY_BUFFER, triangleVertexBufferObject); + // ENABLE DEPTH BUFFER + glEnable(GL_DEPTH_TEST); - // vertex positions - glVertexAttribPointer( - 0, - 3, - GL_FLOAT, - GL_FALSE, - sizeof(vertex), - 0 - ); - glEnableVertexAttribArray(0); - - // vertex normals - glVertexAttribPointer( - 1, - 3, - GL_FLOAT, - GL_FALSE, - sizeof(vertex), - (void*) offsetof(vertex, normal) - ); - glEnableVertexAttribArray(1); - - // vertex texture coordinates - glVertexAttribPointer( - 2, - 2, - GL_FLOAT, - GL_FALSE, - sizeof(vertex), - (void*) offsetof(vertex, texture) - ); - glEnableVertexAttribArray(2); - - // face tangents - glVertexAttribPointer( - 3, - 3, - GL_FLOAT, - GL_FALSE, - sizeof(vertex), - (void*) offsetof(vertex, tangent) - ); - glEnableVertexAttribArray(3); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - - - // ENABLE BACKFACE CULLING - glFrontFace(GL_CCW); - glEnable(GL_CULL_FACE); - - // ENABLE DEPTH BUFFER - glEnable(GL_DEPTH_TEST); - - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); } void updateStats() { - printf("\rFPS: %.1f", framesSinceUpdate / timeSinceUpdate); - printf(" - Camera Position: [%f, %f, %f]", cameraPosition.x, cameraPosition.y, cameraPosition.z); - fflush(stdout); + printf("\rFPS: %.1f", framesSinceUpdate / timeSinceUpdate); + printf(" - Camera Position: [%f, %f, %f]", cameraPosition.x, cameraPosition.y, cameraPosition.z); + fflush(stdout); } +/** + * Main draw function. + */ void draw(void) { - // FPS Counter - framesSinceUpdate++; - double deltaTime = glfwGetTime(); - timeSinceUpdate += deltaTime; - glfwSetTime(0.0f); + // FPS Counter + framesSinceUpdate++; + double deltaTime = glfwGetTime(); + timeSinceUpdate += deltaTime; + glfwSetTime(0.0f); - if (timeSinceUpdate >= timeBetweenUpdates) { - updateStats(); - timeSinceUpdate = 0.0f; - framesSinceUpdate = 0; - } + if (timeSinceUpdate >= timeBetweenUpdates) { + updateStats(); + timeSinceUpdate = 0.0f; + framesSinceUpdate = 0; + } - // camera movement - handleInputs(deltaTime); + // camera movement + handleInputs(deltaTime); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glUseProgram(program); - glBindVertexArray(vao); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glUseProgram(program); - // step for rotations - // counts up to 1.0 and then resets back to 0.0 forever - step += deltaTime / 15; - if (step > 1.0f) step -= 1.0f; - if (step < 0.0f) step += 1.0f; + // step for rotations + // counts up to 1.0 and then resets back to 0.0 forever + step += deltaTime / 15; + if (step > 1.0f) step -= 1.0f; + if (step < 0.0f) step += 1.0f; - // step multiplied by pi * 2 for use in rotation and trig functions - GLfloat stepi = step * pi * 2; + // step multiplied by pi * 2 for use in rotation and trig functions + GLfloat stepi = step * pi * 2; + // ------------- VIEWING TRANSFORMATION ------------------- + vec3 origin = {0.0f, 0.0f, 0.0f}; + vec3 up = {0.0f, 1.0f, 0.0f}; - // ------------- MODEL TRANSFORMATION --------------------- - // SCALE -> ROTATE -> TRANSLATE + mat4 viewingTransformation; + lookAt(&viewingTransformation, &cameraPosition, &origin, &up); - mat4 modelTransformation; - identity(&modelTransformation); + // -------------- PROJECTION TRANSFORMATION ---------------- + mat4 projectionTransformation; + GLfloat near = 0.1f; + GLfloat far = 20.0f; + perspectiveProjection(&projectionTransformation, near, far); - rotateY(&modelTransformation, &modelTransformation, stepi * 2); - rotateZ(&modelTransformation, &modelTransformation, -23.5f / 180 * pi); + // -------------- NORMALISATION TRANSFORMATION ------------- + mat4 normalisationTransformation; + GLfloat fovy = pi / 2; + normalisedDeviceCoordinatesFov(&normalisationTransformation, fovy, aspectRatio, near, far); - // ------------- VIEWING TRANSFORMATION ------------------- - vec3 origin = {0.0f, 0.0f, 0.0f}; - vec3 up = {0.0f, 1.0f, 0.0f}; + mat4 projection; + identity(&projection); + multiply(&projection, &projectionTransformation, &projection); + multiply(&projection, &normalisationTransformation, &projection); - mat4 viewingTransformation; - lookAt(&viewingTransformation, &cameraPosition, &origin, &up); + // ------------- DRAW EACH OBJECT SEPARATELY ---------------- + for (int i = 0; i < numModels; i++) { + // Reset model transformation for each object + mat4 modelTransformation; + identity(&modelTransformation); + // Apply object-specific transformations + vec3 v = { + (GLfloat)i*2+objectPosition.x, + 0.0f+objectPosition.y, + 0.0f+objectPosition.z + }; + translate(&modelTransformation, &modelTransformation, &v); + + mat4 modelView; + identity(&modelView); + multiply(&modelView, &modelTransformation, &modelView); + multiply(&modelView, &viewingTransformation, &modelView); - // -------------- PROJECTION TRANSFORMATION ---------------- - mat4 projectionTransformation; - GLfloat near = 0.1f; - GLfloat far = 20.0f; - perspectiveProjection(&projectionTransformation, near, far); + // calculate matrix for normals + mat3 normalModelView; + mat3From4(&normalModelView, &modelView); + mat3Inverse(&normalModelView, &normalModelView); + mat3Transpose(&normalModelView, &normalModelView); + // send transformation matrix to shader + glUniformMatrix4fv(glGetUniformLocation(program, "modelView"), 1, GL_FALSE, (GLfloat*)&modelView); + glUniformMatrix3fv(glGetUniformLocation(program, "normalModelView"), 1, GL_FALSE, (GLfloat*)&normalModelView); + glUniformMatrix4fv(glGetUniformLocation(program, "projection"), 1, GL_FALSE, (GLfloat*)&projection); + // SET MATERIAL DATA + glUniform1f(glGetUniformLocation(program, "shininess"), 60.0f * 4.0f); - // -------------- NORMALISATION TRANSFORMATION ------------- - mat4 normalisationTransformation; - GLfloat fovy = pi / 2; - normalisedDeviceCoordinatesFov(&normalisationTransformation, fovy, aspectRatio, near, far); + // SET LIGHT DATA + glUniform4f(glGetUniformLocation(program, "lightColor"), 1.0f, 1.0f, 1.0f, 1.0f); + glUniform4f(glGetUniformLocation(program, "ambientLight"), 0.05f, 0.05f, 0.05f, 1.0f); + // BIND TEXTURES + GLuint textureLocation; + textureLocation = glGetUniformLocation(program, "day"); + glUniform1i(textureLocation, 0); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, textures[DAY]); - mat4 modelView; - identity(&modelView); - multiply(&modelView, &modelTransformation, &modelView); - multiply(&modelView, &viewingTransformation, &modelView); + textureLocation = glGetUniformLocation(program, "night"); + glUniform1i(textureLocation, 1); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, textures[NIGHT]); - mat4 projection; - identity(&projection); - multiply(&projection, &projectionTransformation, &projection); - multiply(&projection, &normalisationTransformation, &projection); + textureLocation = glGetUniformLocation(program, "clouds"); + glUniform1i(textureLocation, 2); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, textures[CLOUDS]); - // calculate matrix for normals - mat3 normalModelView; - mat3From4(&normalModelView, &modelView); - mat3Inverse(&normalModelView, &normalModelView); - mat3Transpose(&normalModelView, &normalModelView); + textureLocation = glGetUniformLocation(program, "ocean"); + glUniform1i(textureLocation, 3); + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D, textures[OCEAN]); - // send transformation matrix to shader - glUniformMatrix4fv(glGetUniformLocation(program, "modelView"), 1, GL_FALSE, (GLfloat*)&modelView); - glUniformMatrix3fv(glGetUniformLocation(program, "normalModelView"), 1, GL_FALSE, (GLfloat*)&normalModelView); - glUniformMatrix4fv(glGetUniformLocation(program, "projection"), 1, GL_FALSE, (GLfloat*)&projection); + textureLocation = glGetUniformLocation(program, "normalMap"); + glUniform1i(textureLocation, 4); + glActiveTexture(GL_TEXTURE4); + glBindTexture(GL_TEXTURE_2D, textures[NORMAL]); - - vec4 lightPosition = {cos(stepi) * 1000.0f, 0.0f, sin(stepi) * 1000.0f, 1.0f}; - multiplyAny((GLfloat *)&lightPosition, (GLfloat *)&viewingTransformation, (GLfloat *)&lightPosition, 4, 4, 1); - - glUniform3f(glGetUniformLocation(program, "lightPosition"), lightPosition.x, lightPosition.y, lightPosition.z); - - - // SET MATERIAL DATA - glUniform1f(glGetUniformLocation(program, "shininess"), 60.0f * 4.0f); - - // SET LIGHT DATA - glUniform4f(glGetUniformLocation(program, "lightColor"), 1.0f, 1.0f, 1.0f, 1.0f); - glUniform4f(glGetUniformLocation(program, "ambientLight"), 0.05f, 0.05f, 0.05f, 1.0f); - - - // BIND TEXTURES - GLuint textureLocation; - textureLocation = glGetUniformLocation(program, "day"); - glUniform1i(textureLocation, 0); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, textures[DAY]); - - textureLocation = glGetUniformLocation(program, "night"); - glUniform1i(textureLocation, 1); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, textures[NIGHT]); - - textureLocation = glGetUniformLocation(program, "clouds"); - glUniform1i(textureLocation, 2); - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, textures[CLOUDS]); - - textureLocation = glGetUniformLocation(program, "ocean"); - glUniform1i(textureLocation, 3); - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, textures[OCEAN]); - - textureLocation = glGetUniformLocation(program, "normalMap"); - glUniform1i(textureLocation, 4); - glActiveTexture(GL_TEXTURE4); - glBindTexture(GL_TEXTURE_2D, textures[NORMAL]); - - - // draw!!1 - glDrawArrays(GL_TRIANGLES, 0, numFaces * 3); + // draw each object separately + glBindVertexArray(objectData[i].vao); + glDrawArrays(GL_TRIANGLES, 0, objectData[i].object.length * 3); + } } -// change viewport size and adjust aspect ratio when changing window size +/** + * Changes viewport size and adjust aspect ratio when changing window size + */ void framebuffer_size_callback(GLFWwindow *window, int width, int height) { - glViewport(0, 0, width, height); - aspectRatio = (float)width / height; + glViewport(0, 0, width, height); + aspectRatio = (float)width / height; } +/** + * Main function. + */ int main(int argc, char **argv) { + // initialise window + glfwInit(); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - if (argc >= 2) { - model = argv[1]; - } else { - model = defaultModel; - } - // initialise window - glfwInit(); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + window = glfwCreateWindow(700, 700, "Computergrafik 1", NULL, NULL); - window = glfwCreateWindow(700, 700, "Computergrafik 1", NULL, NULL); + if (!window) { + printf("Failed to create window\n"); + glfwTerminate(); + return -1; + } - if (!window) { - printf("Failed to create window\n"); - glfwTerminate(); - return -1; - } + glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); + glfwMakeContextCurrent(window); + // disable framerate cap + glfwSwapInterval(0); - glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); - glfwMakeContextCurrent(window); + // register keyboard event handler + glfwSetKeyCallback(window, keyboardHandler); - // disable framerate cap - glfwSwapInterval(0); + // initialise glew + glewInit(); - // register keyboard event handler - glfwSetKeyCallback(window, keyboardHandler); + printf("OpenGL version supported by this platform (%s):\n", glGetString(GL_VERSION)); - // initialise glew - glewInit(); + init(); + // exit when window should close or exit is requested (ESC) + while (!glfwWindowShouldClose(window) && !exitRequested) { + draw(); - printf("OpenGL version supported by this platform (%s):\n", glGetString(GL_VERSION)); + glfwSwapBuffers(window); + glfwPollEvents(); + } - init(); + glfwTerminate(); - // exit when window should close or exit is requested (ESC) - while (!glfwWindowShouldClose(window) && !exitRequested) { - draw(); - - glfwSwapBuffers(window); - glfwPollEvents(); - } - - glfwTerminate(); - - return 0; -} \ No newline at end of file + return 0; +} diff --git a/src/objectHandler.c b/src/objectHandler.c new file mode 100644 index 0000000..ba4a504 --- /dev/null +++ b/src/objectHandler.c @@ -0,0 +1,128 @@ +#include "wavefrontobj.h" +#include +#include + +typedef struct { + GLuint vao; + GLuint vbo; + ParsedObjFile object; +} ObjectData; + +/** + * Loads an object. + * Basically generates vbo and vao for an object and saving them in the ObjectData struct. + */ +void load_object(ObjectData* objectData) { + // write faces to buffer + //GLuint triangleVertexBufferObject; + glGenBuffers(1, &objectData->vbo); + glBindBuffer(GL_ARRAY_BUFFER, objectData->vbo); + glBufferData(GL_ARRAY_BUFFER, objectData->object.length * sizeof(face), objectData->object.faces, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + + // create vertex array object + glGenVertexArrays(1, &objectData->vao); + glBindVertexArray(objectData->vao); + glBindBuffer(GL_ARRAY_BUFFER, objectData->vao); + + // vertex positions + glVertexAttribPointer( + 0, + 3, + GL_FLOAT, + GL_FALSE, + sizeof(vertex), + 0 + ); + glEnableVertexAttribArray(0); + + // vertex normals + glVertexAttribPointer( + 1, + 3, + GL_FLOAT, + GL_FALSE, + sizeof(vertex), + (void*) offsetof(vertex, normal) + ); + glEnableVertexAttribArray(1); + + // vertex texture coordinates + glVertexAttribPointer( + 2, + 2, + GL_FLOAT, + GL_FALSE, + sizeof(vertex), + (void*) offsetof(vertex, texture) + ); + glEnableVertexAttribArray(2); + + // face tangents + glVertexAttribPointer( + 3, + 3, + GL_FLOAT, + GL_FALSE, + sizeof(vertex), + (void*) offsetof(vertex, tangent) + ); + glEnableVertexAttribArray(3); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); +} + +/** + * Takes a string-pointer, a number of files to read and a number to store the added objects to + * Returns an array of objects. +*/ +ObjectData* readObjFiles(char** path, int numModels, int* count) { + ObjectData* objects = (ObjectData*) malloc(sizeof(ObjectData) * numModels); + *count += numModels; + if (!objects) { + printf("ERROR in objectHandler: Failed to allocate memory for objects\n"); + return NULL; + } + + for (int i = 0; i < numModels; ++i) { + objects[i].object = readObjFile(path[i]); + load_object(&objects[i]); + } + + return objects; +} + +/** + * Takes a single object and reads it a certain number of times. + * Returns an array of objects. + */ +ObjectData* readSingleObjFile(char** path, int numModels, int* count) { + ObjectData* objects = (ObjectData*) malloc(sizeof(ObjectData) * numModels); + *count += numModels; + + if (!objects) { + printf("ERROR in objectHandler: Failed to allocate memory for objects\n"); + fflush(stdout); + return NULL; + } + + for (int i = 0; i < numModels; ++i) { + objects[i].object = readObjFile(*path); + load_object(&objects[i]); + *count++; + } + + return objects; +} + +/** + * Draw call for a single object. + * Used to clean up the draw calls in Main(). + */ +void draw_object(ObjectData* objectData) { + glBindVertexArray(objectData->vao); + glDrawArrays(GL_TRIANGLES, 0, objectData->object.length * 3); // Annahme: Jedes face hat 3 vertices + glBindVertexArray(0); +} \ No newline at end of file