From 14626a5bd575ed1ad651fde5f40809598faed9dc Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Wed, 19 Jun 2024 10:51:37 +0200 Subject: [PATCH] scene graph logic --- src/Makefile | 4 +- src/fragmentShader.glsl | 17 +---- src/main.c | 162 +++++++++++++++++----------------------- src/objectHandler.c | 30 +++----- src/objectHandler.h | 17 +++++ src/sceneGraph.c | 51 +++++++++++++ src/sceneGraph.h | 30 ++++++++ src/wavefrontobj.c | 13 +++- src/wavefrontobj.h | 4 +- 9 files changed, 195 insertions(+), 133 deletions(-) create mode 100644 src/objectHandler.h create mode 100644 src/sceneGraph.c create mode 100644 src/sceneGraph.h diff --git a/src/Makefile b/src/Makefile index 1ea898c..17e08fb 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,7 +4,7 @@ OTHER_LIBS = -lm ALL_LIBS = $(GLEW_LIBS) $(GLFW_LIBS) $(OTHER_LIBS) -OBJ = matrixMath.o transformation.o wavefrontobj.o +OBJ = matrixMath.o transformation.o wavefrontobj.o sceneGraph.o objectHandler.o SHADERS = fragmentShader.c vertexShader.c cg1.out: test.out main.o $(OBJ) $(SHADERS) @@ -17,7 +17,7 @@ test.out: test.o $(OBJ) %Shader.c: %Shader.glsl xxd -i $? > $@ -main.o: $(SHADERS) matrixMath.h transformation.h wavefrontobj.h +main.o: $(SHADERS) matrixMath.h transformation.h wavefrontobj.h sceneGraph.h objectHandler.h test.o: matrixMath.h transformation.h wavefrontobj.h diff --git a/src/fragmentShader.glsl b/src/fragmentShader.glsl index 79e05d1..bf7c06a 100644 --- a/src/fragmentShader.glsl +++ b/src/fragmentShader.glsl @@ -13,10 +13,7 @@ uniform vec4 ambientLight; uniform vec3 lightPosition; uniform vec4 lightColor; -uniform sampler2D day; -uniform sampler2D night; -uniform sampler2D clouds; -uniform sampler2D ocean; +uniform sampler2D textureSampler; uniform sampler2D normalMap; @@ -24,13 +21,7 @@ float emissionStrength = 0.0; void main() { - vec4 color = vec4(texture(day, textureCoordinate).rgb, 1.0); - - float nightBrightness = texture(night, textureCoordinate).r; - vec4 nightColor = vec4(nightBrightness, nightBrightness * 0.7, nightBrightness * 0.5, 1.0); - float shininessMultiplier = texture(ocean, textureCoordinate).r; - - vec4 cloudColor = texture(clouds, textureCoordinate).rgba; + vec4 color = vec4(texture(textureSampler, textureCoordinate).rgb, 1.0); vec3 norm = normalize(normal); @@ -40,7 +31,7 @@ void main() { float diff = max(dot(norm, lightDir), 0.0); vec3 halfway = (lightDir + eyeDir) / length(lightDir + eyeDir); - float specular = pow(max(dot(halfway, norm), 0.0), shininess) * shininessMultiplier; + float specular = pow(max(dot(halfway, norm), 0.0), shininess); gl_FragColor = @@ -51,7 +42,7 @@ void main() { ambientLight * color + // DIFFUSION - mix(nightColor * (vec4(1,1,1,1) - cloudColor) + (cloudColor * ambientLight), color + cloudColor, diff) + + color * diff + // SPECULAR specular * lightColor * color; diff --git a/src/main.c b/src/main.c index 59ff4c2..7f1d2b7 100644 --- a/src/main.c +++ b/src/main.c @@ -5,10 +5,12 @@ #include "vertexShader.c" #include "fragmentShader.c" -#include "objectHandler.c" + +#include "objectHandler.h" #include "matrixMath.h" #include "transformation.h" #include "wavefrontobj.h" +#include "sceneGraph.h" #define STB_IMAGE_IMPLEMENTATION #include "../lib/stb_image.h" @@ -58,6 +60,11 @@ 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; +mat4 viewingTransformation; + +// Define a global scene graph root node +SceneNode* rootNode; + int numModels = 0; char* models[] = { @@ -150,9 +157,39 @@ void loadTexture(char* textureFile, GLuint* texture) { stbi_image_free(image); } -//TODO -void drawObject() { +void renderNode(SceneNode* node) { + mat4 modelView; + identity(&modelView); + multiply(&modelView, &node->worldTransformation, &modelView); + multiply(&modelView, &viewingTransformation, &modelView); + // 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); + + // SET MATERIAL DATA + glUniform1f(glGetUniformLocation(program, "shininess"), 60.0f * 4.0f); + + + // BIND TEXTURES + GLuint textureLocation; + textureLocation = glGetUniformLocation(program, "textureSampler"); + glUniform1i(textureLocation, 0); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, textures[DAY]); + + textureLocation = glGetUniformLocation(program, "normalMap"); + glUniform1i(textureLocation, 4); + glActiveTexture(GL_TEXTURE4); + glBindTexture(GL_TEXTURE_2D, textures[NORMAL]); + + draw_object(node->objectData); } void init(void) { @@ -227,32 +264,7 @@ void init(void) { //objectData = readObjFiles(&models, numModels); char* c = "../obj/new/Window.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++) { - - 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); - - 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); - - glBindVertexArray(0); - - objectData[i] = objData; - } - */ + objectData = readSingleObjFile(&c); stbi_set_flip_vertically_on_load(flipFlag); // -------------- READ TEXTURE FILES @@ -260,6 +272,19 @@ void init(void) { loadTexture(textureFiles[i], &textures[i]); } + setNodeRenderFunction(&renderNode); + + // Create the root scene node + rootNode = createSceneNode(); + + // Create a child node (e.g., for the model) + SceneNode* modelNode = createSceneNode(); + modelNode->objectData = objectData; + addChild(rootNode, modelNode); + + // Set transformations for the modelNode (example) + rotateY(&modelNode->transformation, &modelNode->transformation, pi / 4); + // ENABLE BACKFACE CULLING glFrontFace(GL_CCW); glEnable(GL_CULL_FACE); @@ -312,7 +337,6 @@ void draw(void) { vec3 origin = {0.0f, 0.0f, 0.0f}; vec3 up = {0.0f, 1.0f, 0.0f}; - mat4 viewingTransformation; lookAt(&viewingTransformation, &cameraPosition, &origin, &up); // -------------- PROJECTION TRANSFORMATION ---------------- @@ -331,75 +355,27 @@ void draw(void) { multiply(&projection, &projectionTransformation, &projection); multiply(&projection, &normalisationTransformation, &projection); - // ------------- DRAW EACH OBJECT SEPARATELY ---------------- - for (int i = 0; i < numModels; i++) { - // Reset model transformation for each object - mat4 modelTransformation; - identity(&modelTransformation); + glUniformMatrix4fv(glGetUniformLocation(program, "projection"), 1, GL_FALSE, (GLfloat*)&projection); - // Apply object-specific transformations - vec3 v = { - (GLfloat)i*2+objectPosition.x, - 0.0f+objectPosition.y, - 0.0f+objectPosition.z - }; - translate(&modelTransformation, &modelTransformation, &v); - + // 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); - mat4 modelView; - identity(&modelView); - multiply(&modelView, &modelTransformation, &modelView); - multiply(&modelView, &viewingTransformation, &modelView); + // BIND TEXTURES + GLuint textureLocation; + textureLocation = glGetUniformLocation(program, "textureSampler"); + glUniform1i(textureLocation, 0); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, textures[DAY]); - // calculate matrix for normals - mat3 normalModelView; - mat3From4(&normalModelView, &modelView); - mat3Inverse(&normalModelView, &normalModelView); - mat3Transpose(&normalModelView, &normalModelView); + textureLocation = glGetUniformLocation(program, "normalMap"); + glUniform1i(textureLocation, 4); + glActiveTexture(GL_TEXTURE4); + glBindTexture(GL_TEXTURE_2D, textures[NORMAL]); - // 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); + renderSceneNode(rootNode); - // 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 each object separately - glBindVertexArray(objectData[i].vao); - glDrawArrays(GL_TRIANGLES, 0, objectData[i].object.length * 3); - } } /** diff --git a/src/objectHandler.c b/src/objectHandler.c index ba4a504..7178283 100644 --- a/src/objectHandler.c +++ b/src/objectHandler.c @@ -1,12 +1,8 @@ +#include "objectHandler.h" #include "wavefrontobj.h" #include #include - -typedef struct { - GLuint vao; - GLuint vbo; - ParsedObjFile object; -} ObjectData; +#include /** * Loads an object. @@ -17,7 +13,7 @@ void load_object(ObjectData* objectData) { //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); + glBufferData(GL_ARRAY_BUFFER, objectData->object->length * sizeof(face), objectData->object->faces, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); @@ -98,23 +94,19 @@ ObjectData* readObjFiles(char** path, int numModels, int* count) { * 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; +ObjectData* readSingleObjFile(char** path) { + ObjectData* objectData = (ObjectData*) malloc(sizeof(ObjectData)); - if (!objects) { + if (!objectData) { 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; + objectData->object = readObjFile(*path); + load_object(objectData); + + return objectData; } /** @@ -123,6 +115,6 @@ ObjectData* readSingleObjFile(char** path, int numModels, int* count) { */ void draw_object(ObjectData* objectData) { glBindVertexArray(objectData->vao); - glDrawArrays(GL_TRIANGLES, 0, objectData->object.length * 3); // Annahme: Jedes face hat 3 vertices + glDrawArrays(GL_TRIANGLES, 0, objectData->object->length * 3); // Annahme: Jedes face hat 3 vertices glBindVertexArray(0); } \ No newline at end of file diff --git a/src/objectHandler.h b/src/objectHandler.h new file mode 100644 index 0000000..2f7d46c --- /dev/null +++ b/src/objectHandler.h @@ -0,0 +1,17 @@ +#ifndef OBJECTHANDLER_H +#define OBJECTHANDLER_H + +#include "wavefrontobj.h" + +typedef struct { + GLuint vao; + GLuint vbo; + ParsedObjFile* object; +} ObjectData; + +extern void load_object(ObjectData* objectData); +extern ObjectData* readObjFiles(char** path, int numModels, int* count); +extern ObjectData* readSingleObjFile(char** path); +extern void draw_object(ObjectData* objectData); + +#endif \ No newline at end of file diff --git a/src/sceneGraph.c b/src/sceneGraph.c new file mode 100644 index 0000000..36a00d7 --- /dev/null +++ b/src/sceneGraph.c @@ -0,0 +1,51 @@ +// sceneGraph.c + +#include "sceneGraph.h" +#include "objectHandler.h" +#include + +void (*renderFunction)(SceneNode*); + +void setNodeRenderFunction(void (*newRenderFunction)(SceneNode*)) { + renderFunction = newRenderFunction; +} + +SceneNode* createSceneNode() { + SceneNode* node = (SceneNode*)malloc(sizeof(SceneNode)); + identity(&node->transformation); + identity(&node->worldTransformation); + node->children = NULL; + node->numChildren = 0; + node->objectData = NULL; + return node; +} + +void addChild(SceneNode* parent, SceneNode* child) { + parent->children = (SceneNode**)realloc(parent->children, sizeof(SceneNode*) * (parent->numChildren + 1)); + parent->children[parent->numChildren] = child; + parent->numChildren++; +} + +void updateSceneNode(SceneNode* node, mat4* parentTransformation) { + multiply(&node->worldTransformation, parentTransformation, &node->transformation); + for (int i = 0; i < node->numChildren; i++) { + updateSceneNode(node->children[i], &node->worldTransformation); + } +} + +void renderSceneNode(SceneNode* node) { + if (node->objectData) { + renderFunction(node); + } + for (int i = 0; i < node->numChildren; i++) { + renderSceneNode(node->children[i]); + } +} + +void freeSceneNode(SceneNode* node) { + for (int i = 0; i < node->numChildren; i++) { + freeSceneNode(node->children[i]); + } + free(node->children); + free(node); +} \ No newline at end of file diff --git a/src/sceneGraph.h b/src/sceneGraph.h new file mode 100644 index 0000000..066977f --- /dev/null +++ b/src/sceneGraph.h @@ -0,0 +1,30 @@ +// sceneGraph.h + +#ifndef SCENE_GRAPH_H +#define SCENE_GRAPH_H + +#include +#include "matrixMath.h" +#include "wavefrontobj.h" +#include "objectHandler.h" + + +typedef struct SceneNode SceneNode; + +struct SceneNode { + mat4 transformation; // Local transformation matrix + mat4 worldTransformation; // World transformation matrix + SceneNode** children; // Array of pointers to child nodes + int numChildren; // Number of child nodes + ObjectData* objectData; + +}; + +void setNodeRenderFunction(void (*newRenderFunction)(SceneNode*)); +extern SceneNode* createSceneNode(); +extern void addChild(SceneNode* parent, SceneNode* child); +extern void updateSceneNode(SceneNode* node, mat4* parentTransformation); +extern void renderSceneNode(SceneNode* node); +extern void freeSceneNode(SceneNode* node); + +#endif \ No newline at end of file diff --git a/src/wavefrontobj.c b/src/wavefrontobj.c index 3b755eb..7c99811 100644 --- a/src/wavefrontobj.c +++ b/src/wavefrontobj.c @@ -71,7 +71,7 @@ void storeTB(face* f, memcpy(&f->v3.tangent, &tangent, sizeof(vec3)); } -ParsedObjFile readObjFile(char* path) { +ParsedObjFile* readObjFile(char* path) { ParsedObjFile parsedFile; FILE* fp = fopen(path, "r"); @@ -235,9 +235,14 @@ ParsedObjFile readObjFile(char* path) { free(normals); fclose(fp); - return parsedFile; + // copy parsed file into allocated memory and return pointer to it + ParsedObjFile* ptr = (ParsedObjFile*) malloc(sizeof(ParsedObjFile)); + memcpy(ptr, &parsedFile, sizeof(ParsedObjFile)); + + return ptr; } -void clearParsedFile(ParsedObjFile file) { - free(file.faces); +void clearParsedFile(ParsedObjFile* file) { + free(file->faces); + free(file); } \ No newline at end of file diff --git a/src/wavefrontobj.h b/src/wavefrontobj.h index 950c4d1..61e6873 100644 --- a/src/wavefrontobj.h +++ b/src/wavefrontobj.h @@ -23,8 +23,8 @@ typedef struct { } ParsedObjFile; -extern ParsedObjFile readObjFile(char* path); -extern void clearParsedFile(ParsedObjFile file); +extern ParsedObjFile* readObjFile(char* path); +extern void clearParsedFile(ParsedObjFile* file); #endif \ No newline at end of file