Compare commits

..

4 Commits

Author SHA1 Message Date
Luca Conte 63c44f9f7a go back I want to be monkey 2025-05-15 15:33:51 +02:00
Luca Conte dd201108e6 load obj files 2025-05-15 15:28:30 +02:00
Luca Conte 6ccfb7e818 fix projection 2025-04-23 17:20:35 +02:00
Luca Conte cced3c5c83 include string.h for memcpy 2025-04-23 11:59:55 +02:00
17 changed files with 2052435 additions and 427 deletions

View File

@ -1,33 +1,33 @@
# Detect OS
OS := $(shell uname)
GLEW_LIBS := $(shell pkgconf --libs glew)
GLFW_LIBS := $(shell pkgconf --libs glfw3)
# Set libraries for Linux
ifeq ($(OS), Linux)
OPENGL_LIB := -lGL
# Set libraries for Windows (MSYS2)
else
OPENGL_LIB := -lopengl32
endif
# Source files
SRC := src/main.c src/log.c src/shader.c src/matrix-math.c
# Output binary
OUT := cg1
# Compiler
CC := gcc
# Build target
$(OUT): $(SRC)
$(CC) -o $(OUT) $(SRC) $(GLEW_LIBS) $(GLFW_LIBS) $(OPENGL_LIB)
# Clean target
clean:
rm -f $(OUT)
# mark phony targets
# Detect OS
OS := $(shell uname)
GLEW_LIBS := $(shell pkgconf --libs glew)
GLFW_LIBS := $(shell pkgconf --libs glfw3)
# Set libraries for Linux
ifeq ($(OS), Linux)
OPENGL_LIB := -lGL
# Set libraries for Windows (MSYS2)
else
OPENGL_LIB := -lopengl32
endif
# Source files
SRC := src/main.c src/log.c src/shader.c
# Output binary
OUT := cg1
# Compiler
CC := gcc
# Build target
$(OUT): $(SRC)
$(CC) -o $(OUT) $(SRC) $(GLEW_LIBS) $(GLFW_LIBS) $(OPENGL_LIB)
# Clean target
clean:
rm -f $(OUT)
# mark phony targets
.PHONY: clean

View File

@ -7,7 +7,8 @@ src_files = [
'./src/main.c',
'./src/shader.c',
'./src/log.c',
'./src/matrix-math.c'
'./src/matrix-math.c',
'./src/wavefrontobj.c'
]
executable('cg1',

34
obj/cube.obj Normal file
View File

@ -0,0 +1,34 @@
# Blender 4.4.3
# www.blender.org
o Cube
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
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 1.000000 0.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 1.000000
s 0
f 5/1/1 3/2/1 1/3/1
f 3/1/2 8/2/2 4/3/2
f 7/1/3 6/2/3 8/3/3
f 2/1/4 8/2/4 6/3/4
f 1/1/5 4/2/5 2/3/5
f 5/1/6 2/2/6 6/3/6
f 5/1/1 7/4/1 3/2/1
f 3/1/2 7/4/2 8/2/2
f 7/1/3 5/4/3 6/2/3
f 2/1/4 4/4/4 8/2/4
f 1/1/5 3/4/5 4/2/5
f 5/1/6 1/4/6 2/2/6

2066
obj/monkey.obj Normal file

File diff suppressed because it is too large Load Diff

2033859
obj/smooth_monkey.obj Normal file

File diff suppressed because it is too large Load Diff

16109
obj/teapot.obj Normal file

File diff suppressed because it is too large Load Diff

View File

@ -11,31 +11,21 @@
#include "log.h"
#include "shader.h"
#include "matrix-math.h"
#include "wavefrontobj.h"
#define STATUS_INTERVAL 0.5
#define PI 3.14159f
GLFWwindow* window;
GLuint program;
GLuint originProgram;
GLuint floorProgram;
GLuint vertexArrayObject;
GLuint originVAO;
GLuint indexBuffer;
GLuint lineIndexBuffer;
GLuint floorIndexBuffer;
GLuint numVertices;
GLuint initialWindowWidth = 800;
GLuint initialWindowHeight = 600;
GLfloat aspect;
mat4 realProjectionMatrix;
GLfloat currentTime = 0.0f;
mat4 projectionMatrix;
int frameCount = 0;
struct timespec last_time, current_time;
@ -87,19 +77,19 @@ void updateStatusDisplay() {
double fps = frameCount / elapsed;
frameCount = 0;
last_time = current_time;
printf("\rFPS: %5.2f - currentTime: %5.2f", fps, currentTime);
printf("\rFPS: %.2f ", fps);
fflush(stdout);
}
}
void recalculateProjectionMatrix() {
mat4BuildPerspective(realProjectionMatrix, 90 * M_PI / 180, aspect, 0.1, 50);
mat4BuildPerspective(projectionMatrix, 60 * M_PI / 180, aspect, 0.1, 10);
DEBUG("Recalculating Projection Matrix");
}
void init(void) {
INFO("Building main program...");
INFO("Building Programs...");
ProgramLinkResult linkResult = buildShaderProgram("src/shaders/vertex.glsl", "src/shaders/fragment.glsl");
if (!linkResult.success) {
FATAL("Failed to link Program");
@ -108,25 +98,6 @@ void init(void) {
program = linkResult.program;
INFO("Building origin program...");
linkResult = buildShaderProgram("src/shaders/origin-vertex.glsl", "src/shaders/origin-fragment.glsl");
if (!linkResult.success) {
FATAL("Failed to link Program");
exit(1);
}
originProgram = linkResult.program;
INFO("Building floor program...");
linkResult = buildShaderProgram("src/shaders/floor-vertex.glsl", "src/shaders/floor-fragment.glsl");
if (!linkResult.success) {
FATAL("Failed to link Program");
exit(1);
}
floorProgram = linkResult.program;
INFO("Shader Program Done.");
// create triangle buffer
@ -151,73 +122,15 @@ void init(void) {
*
*/
GLfloat vertices[] = {
// X // Y
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
};
GLuint restart = 128;
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(restart);
GLuint indices[] = {
1, 0, 2,
1, 2, 3,
4, 0, 1,
5, 4, 1,
5, 1, 7,
1, 3, 7,
5, 7, 6,
4, 5, 6,
0, 4, 6,
2, 0, 6,
3, 2, 6,
7, 3, 6
};
GLuint lineIndices[] = {
0, 1,
0, 2,
0, 4,
1, 3,
1, 5,
2, 3,
2, 6,
3, 7,
4, 5,
4, 6,
5, 7,
6, 7
};
GLuint floorIndices[] = {
2, 3, 6,
3, 7, 6
};
DEBUG("Loading OBJ File");
ParsedObjFile f = readObjFile("obj/smooth_monkey.obj");
numVertices = f.length * sizeof(face) / sizeof(vertex);
DEBUG("Creating vertext buffer");
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, f.length * sizeof(face), f.faces, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
DEBUG("Creating vertex array object");
@ -232,83 +145,32 @@ void init(void) {
3, // number of values to read
GL_FLOAT, // type of value
GL_FALSE, // if values are normalised
3 * sizeof(GLfloat), // stride - distance between vertices
sizeof(vertex), // stride - distance between vertices
0 // start offset
);
glEnableVertexAttribArray(0);
glVertexAttribPointer(
1, // shader location
3, // number of values to read
GL_FLOAT, // type of value
GL_FALSE, // if values are normalised
3 * sizeof(GLfloat), // stride - distance between vertices
0 // start offset
1,
3,
GL_FLOAT,
GL_FALSE,
sizeof(vertex),
(void*)offsetof(vertex, normal)
);
glEnableVertexAttribArray(1);
DEBUG("Creating index buffers");
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glGenBuffers(1, &lineIndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lineIndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(lineIndices), lineIndices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glGenBuffers(1, &floorIndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, floorIndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(floorIndices), floorIndices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glClearColor(0.3f, 0.3f, 0.4f, 1.0f);
glClearColor(0.0f, 0.0f, 0.0f, 0.3f);
glViewport(0, 0, initialWindowWidth, initialWindowHeight);
// glEnable(GL_CULL_FACE);
glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
DEBUG("Creating origin vertex buffer");
GLfloat originVertices[] = {
// X Y Z R G B
0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f
};
GLuint originVBO;
glGenBuffers(1, &originVBO);
glBindBuffer(GL_ARRAY_BUFFER, originVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(originVertices), originVertices, GL_STATIC_DRAW);
glGenVertexArrays(1, &originVAO);
glBindVertexArray(originVAO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
initialiseStatusDisplay();
recalculateProjectionMatrix();
@ -316,213 +178,48 @@ void init(void) {
INFO("--- Initialisation done ---");
}
void drawCube(mat4 modelMatrix, mat4 viewMatrix) {
mat4 modelViewMatrix;
mat4Multiply(modelViewMatrix, viewMatrix, modelMatrix);
// send modelView and projection matrix to shader
GLuint modelViewLocation = glGetUniformLocation(program, "uModelView");
glUniformMatrix4fv(modelViewLocation, 1, GL_FALSE, modelViewMatrix);
// draw cube
glBindVertexArray(vertexArrayObject);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glDrawElements(GL_TRIANGLES, 48, GL_UNSIGNED_INT, 0);
}
GLfloat clamp(GLfloat d, GLfloat min, GLfloat max) {
const GLfloat t = d < min ? min : d;
return t > max ? max : t;
}
GLfloat mapTo01(GLfloat d, GLfloat min, GLfloat max) {
return (clamp(d, min, max) - min) * (1 / (max - min));
}
GLfloat currentHue = 0.0f;
void draw(void) {
// 0.0: virtual view
// 0.1 transition to real view
// 0.15 done
// 0.3 start view transformation
// 0.35 done
// 0.4 start projection
// 0.45 done
// 0.55 - repeat
updateStatusDisplay();
mat4 identity;
mat4Identity(identity);
mat4 projectionMatrix;
// mat4Interpolate(projectionMatrix, identity, projectionMatrix, mapTo01(currentHue, 0.0f, 0.1f));
// counter for animation
currentTime += 0.0001f;
int state = glfwGetKey(window, GLFW_KEY_SPACE);
if (state == GLFW_PRESS)
{
currentTime += 0.001f;
}
if (currentTime > 0.55f) currentTime = 0.0f;
currentHue += 0.005f;
if (currentHue > 1.0) currentHue = 0.0f;
// clear colour and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// select program
glUseProgram(program);
// build view matrix
mat4 viewMatrix;
// mat4Identity(viewMatrix);
vec3 cameraPos = {cos(currentTime * 6 * M_PI) * 3.0f, 3.0f + sin(currentTime * 12 * M_PI) * 0.5, sin(currentTime * 6 * M_PI) * 3.0f};
vec3 cameraLookAt = {0.0f, 0.0f, 0.0f};
vec3 cameraPos = {cos(currentHue * M_PI * 2), 0.0f, sin(currentHue * M_PI * 2)};
vec3 cameraLookAt = {0.0f, 0.2f, 0.0f};
vec3 cameraUp = {0.0f, 1.0f, 0.0f};
mat4BuildLookAt(viewMatrix, cameraPos, cameraLookAt, cameraUp);
vec3 virtualCameraPosition = {1.5f, 1.0f, 1.0f};
vec3 virtualCameraLookAt = {0.0f, 0.0f, -1.0f};
// calculate virtual lookAt and projection
mat4 virtualViewMatrix;
mat4 virtualProjectionMatrix;
mat4BuildLookAt(virtualViewMatrix, virtualCameraPosition, virtualCameraLookAt, cameraUp);
mat4BuildPerspective(virtualProjectionMatrix, 60 * M_PI / 180, aspect, 1, 4);
mat4 inverseVirtualView;
mat4Inverse(inverseVirtualView, virtualViewMatrix);
mat4Interpolate(inverseVirtualView, inverseVirtualView, identity, mapTo01(currentTime, 0.3f, 0.35f));
mat4 inverseVirtualProjection;
mat4Inverse(inverseVirtualProjection, virtualProjectionMatrix);
mat4 viewFrustumModelView;
mat4Multiply(viewFrustumModelView, inverseVirtualView, inverseVirtualProjection);
mat3 mat3CameraRotationMatrix;
mat3From4(mat3CameraRotationMatrix, virtualViewMatrix);
mat3Inverse(mat3CameraRotationMatrix, mat3CameraRotationMatrix);
mat4 cameraRotationMatrix;
mat4From3(cameraRotationMatrix, mat3CameraRotationMatrix);
mat4Interpolate(projectionMatrix, virtualProjectionMatrix, realProjectionMatrix, mapTo01(currentTime, 0.1f, 0.15f));
mat4Interpolate(viewMatrix, virtualViewMatrix, viewMatrix, mapTo01(currentTime, 0.1f, 0.15f));
mat4Interpolate(virtualViewMatrix, identity, virtualViewMatrix, mapTo01(currentTime, 0.3f, 0.35f));
mat4Interpolate(virtualProjectionMatrix, identity, virtualProjectionMatrix, mapTo01(currentTime, 0.4f, 0.45f) * mapTo01(currentTime, 0.4f, 0.45f));
glUseProgram(program);
GLuint brightnessLocation = glGetUniformLocation(program, "uBrightness");
GLuint projectionLocation = glGetUniformLocation(program, "uProjection");
glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, projectionMatrix);
// cubes.
// build model Matrix
mat4 modelMatrix;
vec3 scale;
vec3 position;
mat4 modelViewMatrix;
vec3 scale = {0.2f, 0.2f, 0.2f};
// cube 1
mat4Identity(modelMatrix);
vec3Set(scale, 0.5f, 0.5f, 0.5f);
mat4Scale(modelMatrix, modelMatrix, scale);
mat4Multiply(modelViewMatrix, viewMatrix, modelMatrix);
mat4RotateY(modelMatrix, modelMatrix, 0.5f);
glUniformMatrix4fv(glGetUniformLocation(program, "uModelView"), 1, GL_FALSE, modelViewMatrix);
vec3Set(position, -0.3f, 0.5f, -0.4f);
mat4Translate(modelMatrix, modelMatrix, position);
mat4Multiply(modelMatrix, virtualViewMatrix, modelMatrix);
mat4Multiply(modelMatrix, virtualProjectionMatrix, modelMatrix);
glUniform1f(brightnessLocation, 1.0f);
drawCube(modelMatrix, viewMatrix);
// cube 2
mat4Identity(modelMatrix);
vec3Set(scale, 0.3f, 0.3f, 0.3f);
mat4Scale(modelMatrix, modelMatrix, scale);
mat4RotateY(modelMatrix, modelMatrix, 0.5f);
vec3Set(position, -0.9f, 0.3f, -3.8f);
mat4Translate(modelMatrix, modelMatrix, position);
mat4Multiply(modelMatrix, virtualViewMatrix, modelMatrix);
mat4Multiply(modelMatrix, virtualProjectionMatrix, modelMatrix);
glUniform1f(brightnessLocation, 1.0f);
drawCube(modelMatrix, viewMatrix);
// draw virtual camera
mat4Identity(modelMatrix);
vec3Set(scale, 0.2f, 0.15f, 0.05f);
mat4Scale(modelMatrix, modelMatrix, scale);
// apply rotations to camera
mat4Multiply(modelMatrix, cameraRotationMatrix, modelMatrix);
mat4Translate(modelMatrix, modelMatrix, virtualCameraPosition);
mat4Multiply(modelMatrix, virtualViewMatrix, modelMatrix);
glUniform1f(brightnessLocation, 0.0f);
if (currentTime < 0.37f) {
drawCube(modelMatrix, viewMatrix);
}
glUseProgram(originProgram);
projectionLocation = glGetUniformLocation(originProgram, "uProjection");
glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, projectionMatrix);
GLuint modelViewLocation = glGetUniformLocation(originProgram, "uModelView");
glUniformMatrix4fv(modelViewLocation, 1, GL_FALSE, viewMatrix);
glBindVertexArray(originVAO);
glLineWidth(5.0f);
glDrawArrays(GL_LINES, 0, 6);
if (currentTime < 0.65) {
mat4Multiply(viewFrustumModelView, virtualProjectionMatrix, viewFrustumModelView);
mat4Multiply(viewFrustumModelView, viewMatrix, viewFrustumModelView);
glUniformMatrix4fv(modelViewLocation, 1, GL_FALSE, viewFrustumModelView);
glBindVertexArray(vertexArrayObject);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lineIndexBuffer);
glDrawElements(GL_LINES, 24, GL_UNSIGNED_INT, 0);
}
// draw floor
glUseProgram(floorProgram);
glBindVertexArray(vertexArrayObject);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, floorIndexBuffer);
glUniformMatrix4fv(glGetUniformLocation(floorProgram, "uView"), 1, GL_FALSE, viewMatrix);
glUniformMatrix4fv(glGetUniformLocation(floorProgram, "uProjection"), 1, GL_FALSE, projectionMatrix);
mat4 floorModelMatrix;
vec3 floorScale;
mat4Identity(floorModelMatrix);
vec3Set(floorScale, 10.0f, 0.01f, 10.0f);
mat4Scale(floorModelMatrix, floorModelMatrix, floorScale);
glUniformMatrix4fv(glGetUniformLocation(floorProgram, "uModel"), 1, GL_FALSE, floorModelMatrix);
glDepthMask(GL_FALSE);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glDepthMask(GL_TRUE);
glDrawArrays(GL_TRIANGLES, 0, numVertices);
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
@ -551,7 +248,9 @@ int main(int argc, char const *argv[])
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(initialWindowWidth, initialWindowHeight, "CG1", NULL, NULL);
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER , GLFW_TRUE);
GLFWwindow* window = glfwCreateWindow(initialWindowWidth, initialWindowHeight, "CG1", NULL, NULL);
aspect = (float)initialWindowWidth / initialWindowHeight;
if (!window) {

View File

@ -422,6 +422,18 @@ void vec3Set(vec3 out, GLfloat x, GLfloat y, GLfloat z) {
out[2] = z;
}
void vec3Multiply(vec3 out, vec3 in, GLfloat x) {
out[0] = in[0] * x;
out[1] = in[1] * x;
out[2] = in[2] * x;
}
void vec2Subtract(vec2 out, vec2 a, vec2 b) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
}
void mat3Copy(mat3 src, mat3 dst) {
for (int i = 0; i < 9; i++) {

View File

@ -9,10 +9,12 @@
typedef GLfloat vec4[4];
typedef GLfloat vec3[3];
typedef GLfloat vec2[2];
typedef GLfloat mat4[16];
typedef GLfloat mat3[9];
extern void mat4Identity(mat4 mat);
extern void mat4Copy(mat4 src, mat4 dst);
extern void mat4Empty(mat4 mat);
@ -36,6 +38,9 @@ extern void vec3Normalise(vec3 out, vec3 in);
extern GLfloat vec3Length(vec3 in);
extern GLfloat vec3DotProduct(vec3 a, vec3 b);
extern void vec3Set(vec3 out, GLfloat x, GLfloat y, GLfloat z);
extern void vec3Multiply(vec3 out, vec3 in, GLfloat x);
extern void vec2Subtract(vec2 out, vec2 a, vec2 b);
extern void mat3Copy(mat3 src, mat3 dst);
extern void mat3Inverse(mat3 out, mat3 in);

View File

@ -1,8 +0,0 @@
#version 330 core
in vec4 vPosition;
void main() {
gl_FragColor = mix(vec4(1,1,1,0.5), vec4(0.8,0.8,0.8,0.5), step(0, sin(vPosition.x * 3.14159) * sin(vPosition.z * 3.14159)));
// gl_FragColor = vec4(1,0,0,1);
}

View File

@ -1,14 +0,0 @@
#version 330 core
layout (location = 0) in vec3 aPosition;
uniform mat4 uModel;
uniform mat4 uView;
uniform mat4 uProjection;
out vec4 vPosition;
void main() {
vPosition = uModel * vec4(aPosition, 1);
gl_Position = uProjection * uView * vPosition;
}

View File

@ -1,17 +1,6 @@
#version 330 core
vec3 colors[6] = vec3[6](
vec3(1.0, 0.5, 0.5),
vec3(0.5, 1.0, 0.5),
vec3(0.5, 0.5, 1.0),
vec3(1.0, 1.0, 0.5),
vec3(1.0, 0.5, 1.0),
vec3(0.5, 1.0, 1.0)
);
uniform float uBrightness;
in vec3 vNormal;
void main() {
// hacky solution to give each side a different colour
int side = gl_PrimitiveID / 2;
gl_FragColor = vec4(colors[side] * uBrightness, 1.0);
gl_FragColor = vec4(vNormal * 0.5 + vec3(0.5), 1.0);
}

View File

@ -1,7 +0,0 @@
#version 330 core
in vec3 vertexColor;
void main() {
gl_FragColor = vec4(vertexColor, 1.0);
}

View File

@ -1,13 +0,0 @@
#version 330 core
layout (location = 0) in vec3 aPosition;
layout (location = 1) in vec3 aColor;
uniform mat4 uModelView;
uniform mat4 uProjection;
out vec3 vertexColor;
void main() {
vertexColor = aColor;
gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);
}

View File

@ -1,8 +1,12 @@
#version 330 core
layout (location = 0) in vec3 aPosition;
layout (location = 1) in vec3 aNormal;
uniform mat4 uModelView;
uniform mat4 uProjection;
out vec3 vNormal;
void main() {
vNormal = aNormal;
gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);
}

242
src/wavefrontobj.c Normal file
View File

@ -0,0 +1,242 @@
#include <GL/glew.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wavefrontobj.h"
#define OBJ_LINE_BUFFER_SIZE 256
/**
*
* ADJUSTMENT NEEDED FOR
* - Face Definitions other than vertex/texture/normal
* - Vertex positions including w
* - Any faces using vertices yet to be defined
* (File is read top to bottom. A face using a vertex
* defined underneath it in the file will not work)
*
*/
void storeFace(
face* f,
vec3 v1, vec2 vt1, vec3 vn1,
vec3 v2, vec2 vt2, vec3 vn2,
vec3 v3, vec2 vt3, vec3 vn3
) {
memcpy(&f->v1.position, v1, sizeof(vec3));
memcpy(&f->v2.position, v2, sizeof(vec3));
memcpy(&f->v3.position, v3, sizeof(vec3));
memcpy(&f->v1.normal, vn1, sizeof(vec3));
memcpy(&f->v2.normal, vn2, sizeof(vec3));
memcpy(&f->v3.normal, vn3, sizeof(vec3));
memcpy(&f->v1.texture, vt1, sizeof(vec2));
memcpy(&f->v2.texture, vt2, sizeof(vec2));
memcpy(&f->v3.texture, vt3, sizeof(vec2));
}
// void storeTB(face* f,
// vec3 v1, vec2 vt1, vec3 vn1,
// vec3 v2, vec2 vt2, vec3 vn2,
// vec3 v3, vec2 vt3, vec3 vn3
// ) {
// // https://www.opengl-tutorial.org/intermediate-tutorials/tutorial-13-normal-mapping/
// vec3 deltaPos1;
// vec3 deltaPos2;
// vec3Subtract(deltaPos1, v2, v1);
// vec3Subtract(deltaPos1, v3, v1);
// vec2 deltaTex1;
// vec2 deltaTex2;
// vec2Subtract(deltaTex1, vt2, vt1);
// vec2Subtract(deltaTex2, vt3, vt1);
// GLfloat r = 1.0f / (deltaTex1[0] * deltaTex2[1] - deltaTex1[1] * deltaTex2[0]);
// vec3Multiply(deltaPos1, deltaPos1, deltaTex2[1]);
// vec3Multiply(deltaPos2, deltaPos2, deltaTex1[1]);
// vec3 tangent;
// vec3Subtract(tangent, deltaPos1, deltaPos2);
// vec3Multiply(tangent, tangent, r);
// memcpy(&f->v1.tangent, &tangent, sizeof(vec3));
// memcpy(&f->v2.tangent, &tangent, sizeof(vec3));
// memcpy(&f->v3.tangent, &tangent, sizeof(vec3));
// }
ParsedObjFile readObjFile(char* path) {
ParsedObjFile parsedFile;
FILE* fp = fopen(path, "r");
if (fp == NULL) {
fprintf(stderr, "File could not be opened: %s", path);
parsedFile.faces = NULL;
parsedFile.length = 0;
}
uint numVertices = 0;
uint numVertexNormals = 0;
uint numFaces = 0;
uint numTextureCoords = 0;
char buf[OBJ_LINE_BUFFER_SIZE];
while (fgets(buf, OBJ_LINE_BUFFER_SIZE, fp)) {
if (buf[0] == 'v') {
if (buf[1] == ' ') {
numVertices++;
} else if (buf[1] == 't') {
numTextureCoords++;
} else if (buf[1] == 'n') {
numVertexNormals++;
}
}
if (buf[0] == 'f') {
int numSpaces = 0;
for (int i = 0; i < strlen(buf); i++) {
if (buf[i] == ' ') {
numSpaces++;
}
}
numFaces += numSpaces - 2;
}
}
// printf("Vertices: %d\nFaces: %d\nNormals:%d\nTextures:%d\n", numVertices, numFaces, numVertexNormals, numTextureCoords);
vec3* vertices = (vec3*) malloc(sizeof(vec3) * numVertices);
vec3* normals = (vec3*) malloc(sizeof(vec3) * numVertexNormals);
vec2* textures = (vec2*) malloc(sizeof(vec2) * numTextureCoords);
face* faces = (face*) malloc(sizeof(face) * numFaces);
parsedFile.faces = faces;
parsedFile.length = numFaces;
rewind(fp);
uint curVertex = 0;
uint curNormal = 0;
uint curFace = 0;
uint curTexture = 0;
while (fgets(buf, OBJ_LINE_BUFFER_SIZE, fp)) {
if (buf[0] == 'v') {
if (buf[1] == ' ') {
sscanf(buf,
"v %f %f %f",
&vertices[curVertex][0],
&vertices[curVertex][1],
&vertices[curVertex][2]
);
curVertex++;
} else if (buf[1] == 't') {
int readValues = sscanf(buf,
"vt %f %f",
&textures[curTexture][0],
&textures[curTexture][1]
);
if (readValues != 2) {
textures[curTexture][1] = 0;
}
curTexture++;
} else if (buf[1] == 'n') {
sscanf(buf,
"vn %f %f %f",
&normals[curNormal][0],
&normals[curNormal][1],
&normals[curNormal][2]
);
curNormal++;
}
}
if (buf[0] == 'f') {
int v1, v2, v3;
int vt1, vt2, vt3;
int vn1, vn2, vn3;
sscanf(buf,
"f %d/%d/%d %d/%d/%d %d/%d/%d",
&v1, &vt1, &vn1,
&v2, &vt2, &vn2,
&v3, &vt3, &vn3
);
storeFace(&faces[curFace],
vertices[v1 - 1], textures[vt1 - 1], normals[vn1 - 1],
vertices[v2 - 1], textures[vt2 - 1], normals[vn2 - 1],
vertices[v3 - 1], textures[vt3 - 1], normals[vn3 - 1]
);
// storeTB(&faces[curFace],
// vertices[v1 - 1], textures[vt1 - 1], normals[vn1 - 1],
// vertices[v2 - 1], textures[vt2 - 1], normals[vn2 - 1],
// vertices[v3 - 1], textures[vt3 - 1], normals[vn3 - 1]
// );
curFace++;
int numSpaces = 0;
for (int i = 0; i < strlen(buf); i++) {
if (buf[i] == ' ') {
numSpaces++;
}
}
if (numSpaces == 4) {
// storeTB(&faces[curFace],
// vertices[v1 - 1], textures[vt1 - 1], normals[vn1 - 1],
// vertices[v2 - 1], textures[vt2 - 1], normals[vn2 - 1],
// vertices[v3 - 1], textures[vt3 - 1], normals[vn3 - 1]
// );
sscanf(buf,
"f %d/%d/%d %*d/%*d/%*d %d/%d/%d %d/%d/%d",
&v1, &vt1, &vn1,
&v2, &vt2, &vn2,
&v3, &vt3, &vn3
);
storeFace(&faces[curFace],
vertices[v1 - 1], textures[vt1 - 1], normals[vn1 - 1],
vertices[v2 - 1], textures[vt2 - 1], normals[vn2 - 1],
vertices[v3 - 1], textures[vt3 - 1], normals[vn3 - 1]
);
curFace++;
}
// TODO: textures
}
}
free(vertices);
free(normals);
fclose(fp);
return parsedFile;
}
void clearParsedFile(ParsedObjFile file) {
free(file.faces);
}

30
src/wavefrontobj.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef WAVEFRONTOBJ_H
#define WAVEFRONTOBJ_H
#include <GL/glew.h>
#include "matrix-math.h"
typedef struct {
vec3 position;
vec3 normal;
vec2 texture;
// vec3 tangent;
} vertex;
typedef struct {
vertex v1;
vertex v2;
vertex v3;
} face;
typedef struct {
face* faces;
GLuint length;
} ParsedObjFile;
extern ParsedObjFile readObjFile(char* path);
extern void clearParsedFile(ParsedObjFile file);
#endif