scene graph logic

This commit is contained in:
Luca Conte 2024-06-19 10:51:37 +02:00
parent 2632068106
commit 14626a5bd5
9 changed files with 195 additions and 133 deletions

View File

@ -4,7 +4,7 @@ OTHER_LIBS = -lm
ALL_LIBS = $(GLEW_LIBS) $(GLFW_LIBS) $(OTHER_LIBS) 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 SHADERS = fragmentShader.c vertexShader.c
cg1.out: test.out main.o $(OBJ) $(SHADERS) cg1.out: test.out main.o $(OBJ) $(SHADERS)
@ -17,7 +17,7 @@ test.out: test.o $(OBJ)
%Shader.c: %Shader.glsl %Shader.c: %Shader.glsl
xxd -i $? > $@ 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 test.o: matrixMath.h transformation.h wavefrontobj.h

View File

@ -13,10 +13,7 @@ uniform vec4 ambientLight;
uniform vec3 lightPosition; uniform vec3 lightPosition;
uniform vec4 lightColor; uniform vec4 lightColor;
uniform sampler2D day; uniform sampler2D textureSampler;
uniform sampler2D night;
uniform sampler2D clouds;
uniform sampler2D ocean;
uniform sampler2D normalMap; uniform sampler2D normalMap;
@ -24,13 +21,7 @@ float emissionStrength = 0.0;
void main() { void main() {
vec4 color = vec4(texture(day, textureCoordinate).rgb, 1.0); vec4 color = vec4(texture(textureSampler, 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;
vec3 norm = normalize(normal); vec3 norm = normalize(normal);
@ -40,7 +31,7 @@ void main() {
float diff = max(dot(norm, lightDir), 0.0); float diff = max(dot(norm, lightDir), 0.0);
vec3 halfway = (lightDir + eyeDir) / length(lightDir + eyeDir); 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 = gl_FragColor =
@ -51,7 +42,7 @@ void main() {
ambientLight * color + ambientLight * color +
// DIFFUSION // DIFFUSION
mix(nightColor * (vec4(1,1,1,1) - cloudColor) + (cloudColor * ambientLight), color + cloudColor, diff) + color * diff +
// SPECULAR // SPECULAR
specular * lightColor * color; specular * lightColor * color;

View File

@ -5,10 +5,12 @@
#include "vertexShader.c" #include "vertexShader.c"
#include "fragmentShader.c" #include "fragmentShader.c"
#include "objectHandler.c"
#include "objectHandler.h"
#include "matrixMath.h" #include "matrixMath.h"
#include "transformation.h" #include "transformation.h"
#include "wavefrontobj.h" #include "wavefrontobj.h"
#include "sceneGraph.h"
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#include "../lib/stb_image.h" #include "../lib/stb_image.h"
@ -58,6 +60,11 @@ const GLfloat pi = 3.14159f;
vec3 cameraPosition = {0.0f, 3.0f, 5.5f}; vec3 cameraPosition = {0.0f, 3.0f, 5.5f};
vec3 objectPosition = {0.0f, 0.0f, 0.0f}; vec3 objectPosition = {0.0f, 0.0f, 0.0f};
GLfloat radius = 1.0f; GLfloat radius = 1.0f;
mat4 viewingTransformation;
// Define a global scene graph root node
SceneNode* rootNode;
int numModels = 0; int numModels = 0;
char* models[] = { char* models[] = {
@ -150,9 +157,39 @@ void loadTexture(char* textureFile, GLuint* texture) {
stbi_image_free(image); stbi_image_free(image);
} }
//TODO void renderNode(SceneNode* node) {
void drawObject() { 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) { void init(void) {
@ -227,32 +264,7 @@ void init(void) {
//objectData = readObjFiles(&models, numModels); //objectData = readObjFiles(&models, numModels);
char* c = "../obj/new/Window.obj"; char* c = "../obj/new/Window.obj";
objectData = readSingleObjFile(&c, 10, &numModels); objectData = readSingleObjFile(&c);
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;
}
*/
stbi_set_flip_vertically_on_load(flipFlag); stbi_set_flip_vertically_on_load(flipFlag);
// -------------- READ TEXTURE FILES // -------------- READ TEXTURE FILES
@ -260,6 +272,19 @@ void init(void) {
loadTexture(textureFiles[i], &textures[i]); 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 // ENABLE BACKFACE CULLING
glFrontFace(GL_CCW); glFrontFace(GL_CCW);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
@ -312,7 +337,6 @@ void draw(void) {
vec3 origin = {0.0f, 0.0f, 0.0f}; vec3 origin = {0.0f, 0.0f, 0.0f};
vec3 up = {0.0f, 1.0f, 0.0f}; vec3 up = {0.0f, 1.0f, 0.0f};
mat4 viewingTransformation;
lookAt(&viewingTransformation, &cameraPosition, &origin, &up); lookAt(&viewingTransformation, &cameraPosition, &origin, &up);
// -------------- PROJECTION TRANSFORMATION ---------------- // -------------- PROJECTION TRANSFORMATION ----------------
@ -331,75 +355,27 @@ void draw(void) {
multiply(&projection, &projectionTransformation, &projection); multiply(&projection, &projectionTransformation, &projection);
multiply(&projection, &normalisationTransformation, &projection); multiply(&projection, &normalisationTransformation, &projection);
// ------------- DRAW EACH OBJECT SEPARATELY ---------------- glUniformMatrix4fv(glGetUniformLocation(program, "projection"), 1, GL_FALSE, (GLfloat*)&projection);
for (int i = 0; i < numModels; i++) {
// Reset model transformation for each object
mat4 modelTransformation;
identity(&modelTransformation);
// Apply object-specific transformations // SET LIGHT DATA
vec3 v = { glUniform4f(glGetUniformLocation(program, "lightColor"), 1.0f, 1.0f, 1.0f, 1.0f);
(GLfloat)i*2+objectPosition.x, glUniform4f(glGetUniformLocation(program, "ambientLight"), 0.05f, 0.05f, 0.05f, 1.0f);
0.0f+objectPosition.y,
0.0f+objectPosition.z // BIND TEXTURES
}; GLuint textureLocation;
translate(&modelTransformation, &modelTransformation, &v); 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]);
mat4 modelView; renderSceneNode(rootNode);
identity(&modelView);
multiply(&modelView, &modelTransformation, &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);
glUniformMatrix4fv(glGetUniformLocation(program, "projection"), 1, GL_FALSE, (GLfloat*)&projection);
// 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 each object separately
glBindVertexArray(objectData[i].vao);
glDrawArrays(GL_TRIANGLES, 0, objectData[i].object.length * 3);
}
} }
/** /**

View File

@ -1,12 +1,8 @@
#include "objectHandler.h"
#include "wavefrontobj.h" #include "wavefrontobj.h"
#include <GL/glew.h> #include <GL/glew.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
typedef struct {
GLuint vao;
GLuint vbo;
ParsedObjFile object;
} ObjectData;
/** /**
* Loads an object. * Loads an object.
@ -17,7 +13,7 @@ void load_object(ObjectData* objectData) {
//GLuint triangleVertexBufferObject; //GLuint triangleVertexBufferObject;
glGenBuffers(1, &objectData->vbo); glGenBuffers(1, &objectData->vbo);
glBindBuffer(GL_ARRAY_BUFFER, 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); 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. * Takes a single object and reads it a certain number of times.
* Returns an array of objects. * Returns an array of objects.
*/ */
ObjectData* readSingleObjFile(char** path, int numModels, int* count) { ObjectData* readSingleObjFile(char** path) {
ObjectData* objects = (ObjectData*) malloc(sizeof(ObjectData) * numModels); ObjectData* objectData = (ObjectData*) malloc(sizeof(ObjectData));
*count += numModels;
if (!objects) { if (!objectData) {
printf("ERROR in objectHandler: Failed to allocate memory for objects\n"); printf("ERROR in objectHandler: Failed to allocate memory for objects\n");
fflush(stdout); fflush(stdout);
return NULL; return NULL;
} }
for (int i = 0; i < numModels; ++i) { objectData->object = readObjFile(*path);
objects[i].object = readObjFile(*path); load_object(objectData);
load_object(&objects[i]);
*count++;
}
return objects; return objectData;
} }
/** /**
@ -123,6 +115,6 @@ ObjectData* readSingleObjFile(char** path, int numModels, int* count) {
*/ */
void draw_object(ObjectData* objectData) { void draw_object(ObjectData* objectData) {
glBindVertexArray(objectData->vao); 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); glBindVertexArray(0);
} }

17
src/objectHandler.h Normal file
View File

@ -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

51
src/sceneGraph.c Normal file
View File

@ -0,0 +1,51 @@
// sceneGraph.c
#include "sceneGraph.h"
#include "objectHandler.h"
#include <stdlib.h>
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);
}

30
src/sceneGraph.h Normal file
View File

@ -0,0 +1,30 @@
// sceneGraph.h
#ifndef SCENE_GRAPH_H
#define SCENE_GRAPH_H
#include <GL/glew.h>
#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

View File

@ -71,7 +71,7 @@ void storeTB(face* f,
memcpy(&f->v3.tangent, &tangent, sizeof(vec3)); memcpy(&f->v3.tangent, &tangent, sizeof(vec3));
} }
ParsedObjFile readObjFile(char* path) { ParsedObjFile* readObjFile(char* path) {
ParsedObjFile parsedFile; ParsedObjFile parsedFile;
FILE* fp = fopen(path, "r"); FILE* fp = fopen(path, "r");
@ -235,9 +235,14 @@ ParsedObjFile readObjFile(char* path) {
free(normals); free(normals);
fclose(fp); 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) { void clearParsedFile(ParsedObjFile* file) {
free(file.faces); free(file->faces);
free(file);
} }

View File

@ -23,8 +23,8 @@ typedef struct {
} ParsedObjFile; } ParsedObjFile;
extern ParsedObjFile readObjFile(char* path); extern ParsedObjFile* readObjFile(char* path);
extern void clearParsedFile(ParsedObjFile file); extern void clearParsedFile(ParsedObjFile* file);
#endif #endif