scene graph logic
This commit is contained in:
parent
2632068106
commit
14626a5bd5
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
140
src/main.c
140
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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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");
|
||||
textureLocation = glGetUniformLocation(program, "textureSampler");
|
||||
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);
|
||||
}
|
||||
|
||||
renderSceneNode(rootNode);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
objectData->object = readObjFile(*path);
|
||||
load_object(objectData);
|
||||
|
||||
return objects;
|
||||
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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue