Merge branch 'multiple-objects'

This commit is contained in:
Luca Conte 2024-06-10 11:13:34 +02:00
commit 3db8817187
6 changed files with 605 additions and 333 deletions

40
obj/Xblock.obj Normal file
View File

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

40
obj/Yblock.obj Normal file
View File

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

40
obj/Yblock_rotated.obj Normal file
View File

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

40
obj/Zblock.obj Normal file
View File

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

View File

@ -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 <stdbool.h>
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);
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);
}
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
if (!status) {
printf("Error validating program: ");
GLchar infoLog[1024];
glGetProgramInfoLog(program, 1024, NULL, infoLog);
printf("%s",infoLog);
exit(1);
}
//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++) {
glGenVertexArrays(1, &objData->vao);
glGenBuffers(1, &objData->vbo);
// --------------- READ MODEL FILE
ParsedObjFile teapot = readObjFile(model);
numFaces = teapot.length;
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);
// 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);
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);
stbi_set_flip_vertically_on_load(flipFlag);
// -------------- READ TEXTURE FILES
for (int i = 0; i < NUM_TEXTURES; i++) {
loadTexture(textureFiles[i], &textures[i]);
}
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]);
}
// create vertex array object
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, triangleVertexBufferObject);
// ENABLE BACKFACE CULLING
glFrontFace(GL_CCW);
glEnable(GL_CULL_FACE);
// vertex positions
glVertexAttribPointer(
0,
3,
GL_FLOAT,
GL_FALSE,
sizeof(vertex),
0
);
glEnableVertexAttribArray(0);
// ENABLE DEPTH BUFFER
glEnable(GL_DEPTH_TEST);
// 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};
mat4 viewingTransformation;
lookAt(&viewingTransformation, &cameraPosition, &origin, &up);
// -------------- PROJECTION TRANSFORMATION ----------------
mat4 projectionTransformation;
GLfloat near = 0.1f;
GLfloat far = 20.0f;
perspectiveProjection(&projectionTransformation, near, far);
// -------------- NORMALISATION TRANSFORMATION -------------
mat4 normalisationTransformation;
GLfloat fovy = pi / 2;
normalisedDeviceCoordinatesFov(&normalisationTransformation, fovy, aspectRatio, near, far);
mat4 projection;
identity(&projection);
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);
// ------------- MODEL TRANSFORMATION ---------------------
// SCALE -> ROTATE -> TRANSLATE
mat4 modelView;
identity(&modelView);
multiply(&modelView, &modelTransformation, &modelView);
multiply(&modelView, &viewingTransformation, &modelView);
mat4 modelTransformation;
identity(&modelTransformation);
// calculate matrix for normals
mat3 normalModelView;
mat3From4(&normalModelView, &modelView);
mat3Inverse(&normalModelView, &normalModelView);
mat3Transpose(&normalModelView, &normalModelView);
rotateY(&modelTransformation, &modelTransformation, stepi * 2);
rotateZ(&modelTransformation, &modelTransformation, -23.5f / 180 * pi);
// 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);
// ------------- VIEWING TRANSFORMATION -------------------
vec3 origin = {0.0f, 0.0f, 0.0f};
vec3 up = {0.0f, 1.0f, 0.0f};
// SET MATERIAL DATA
glUniform1f(glGetUniformLocation(program, "shininess"), 60.0f * 4.0f);
mat4 viewingTransformation;
lookAt(&viewingTransformation, &cameraPosition, &origin, &up);
// 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]);
// -------------- PROJECTION TRANSFORMATION ----------------
mat4 projectionTransformation;
GLfloat near = 0.1f;
GLfloat far = 20.0f;
perspectiveProjection(&projectionTransformation, near, far);
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]);
// -------------- NORMALISATION TRANSFORMATION -------------
mat4 normalisationTransformation;
GLfloat fovy = pi / 2;
normalisedDeviceCoordinatesFov(&normalisationTransformation, fovy, aspectRatio, near, far);
mat4 modelView;
identity(&modelView);
multiply(&modelView, &modelTransformation, &modelView);
multiply(&modelView, &viewingTransformation, &modelView);
mat4 projection;
identity(&projection);
multiply(&projection, &projectionTransformation, &projection);
multiply(&projection, &normalisationTransformation, &projection);
// 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);
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;
return 0;
}

128
src/objectHandler.c Normal file
View File

@ -0,0 +1,128 @@
#include "wavefrontobj.h"
#include <GL/glew.h>
#include <stdlib.h>
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);
}