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

View File

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

View File

@ -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);
}
}
/**

View File

@ -1,12 +1,8 @@
#include "objectHandler.h"
#include "wavefrontobj.h"
#include <GL/glew.h>
#include <stdlib.h>
typedef struct {
GLuint vao;
GLuint vbo;
ParsedObjFile object;
} ObjectData;
#include <stdio.h>
/**
* 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);
}

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));
}
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);
}

View File

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