Compare commits
23 Commits
Author | SHA1 | Date |
---|---|---|
|
63c44f9f7a | |
|
dd201108e6 | |
|
6ccfb7e818 | |
|
cced3c5c83 | |
|
daa584842c | |
|
f695d0bb39 | |
|
76d8f1d58f | |
|
1e2adcfe37 | |
|
1db1b9378b | |
|
c5f7407199 | |
|
b798a9a26e | |
|
1a84ed5ab6 | |
|
5046266906 | |
|
0aeec51093 | |
|
cbc94e8459 | |
|
5fc371cded | |
|
548b167968 | |
|
e0f3c7d2ff | |
|
40979a9a31 | |
|
e2771c9f36 | |
|
e054627c25 | |
|
e8b713db85 | |
|
4cc7e98998 |
|
@ -6,7 +6,9 @@ m_dep = cc.find_library('m', required : false)
|
|||
src_files = [
|
||||
'./src/main.c',
|
||||
'./src/shader.c',
|
||||
'./src/log.c'
|
||||
'./src/log.c',
|
||||
'./src/matrix-math.c',
|
||||
'./src/wavefrontobj.c'
|
||||
]
|
||||
|
||||
executable('cg1',
|
||||
|
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
10
src/log.h
10
src/log.h
|
@ -22,10 +22,10 @@ extern unsigned int logLevel;
|
|||
#define DEBUG_COL "\x1B[90m"
|
||||
#define NORMAL_COL "\x1B[0m"
|
||||
|
||||
#define FATAL(...) if (logLevel >= LOG_LEVEL_FATAL) { printf("| %sFATAL%s | ", FATAL_COL, NORMAL_COL); printf(__VA_ARGS__); printf("\n"); }
|
||||
#define ERROR(...) if (logLevel >= LOG_LEVEL_ERROR) { printf("| %sERROR%s | ", ERROR_COL, NORMAL_COL); printf(__VA_ARGS__); printf("\n"); }
|
||||
#define WARN(...) if (logLevel >= LOG_LEVEL_WARN) { printf("| %sWARN%s | ", WARN_COL, NORMAL_COL); printf(__VA_ARGS__); printf("\n"); }
|
||||
#define INFO(...) if (logLevel >= LOG_LEVEL_INFO) { printf("| %sINFO%s | ", INFO_COL, NORMAL_COL); printf(__VA_ARGS__); printf("\n"); }
|
||||
#define DEBUG(...) if (logLevel >= LOG_LEVEL_DEBUG) { printf("| %sDEBUG%s | ", DEBUG_COL, NORMAL_COL); printf(__VA_ARGS__); printf("\n"); }
|
||||
#define FATAL(...) if (logLevel >= LOG_LEVEL_FATAL) { fprintf(stderr, "| %sFATAL%s | ", FATAL_COL, NORMAL_COL); fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); }
|
||||
#define ERROR(...) if (logLevel >= LOG_LEVEL_ERROR) { fprintf(stderr, "| %sERROR%s | ", ERROR_COL, NORMAL_COL); fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); }
|
||||
#define WARN(...) if (logLevel >= LOG_LEVEL_WARN) { fprintf(stderr, "| %sWARN%s | ", WARN_COL, NORMAL_COL); fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); }
|
||||
#define INFO(...) if (logLevel >= LOG_LEVEL_INFO) { fprintf(stderr, "| %sINFO%s | ", INFO_COL, NORMAL_COL); fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); }
|
||||
#define DEBUG(...) if (logLevel >= LOG_LEVEL_DEBUG) { fprintf(stderr, "| %sDEBUG%s | ", DEBUG_COL, NORMAL_COL); fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); }
|
||||
|
||||
#endif // LOG_H
|
209
src/main.c
209
src/main.c
|
@ -1,4 +1,5 @@
|
|||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
@ -9,16 +10,23 @@
|
|||
#include "shader.h"
|
||||
#include "log.h"
|
||||
#include "shader.h"
|
||||
#include "matrix-math.h"
|
||||
#include "wavefrontobj.h"
|
||||
|
||||
#define STATUS_INTERVAL 0.5
|
||||
#define PI 3.14159f
|
||||
|
||||
GLuint program;
|
||||
|
||||
GLuint vertexArrayObject;
|
||||
GLuint numVertices;
|
||||
|
||||
GLuint initialWindowWidth = 800;
|
||||
GLuint initialWindowHeight = 600;
|
||||
|
||||
GLfloat aspect;
|
||||
mat4 projectionMatrix;
|
||||
|
||||
int frameCount = 0;
|
||||
struct timespec last_time, current_time;
|
||||
|
||||
|
@ -39,7 +47,7 @@ GLfloat hueToRgb(GLfloat p, GLfloat q, GLfloat t) {
|
|||
return p;
|
||||
}
|
||||
|
||||
// Color Conversion Functions by Copilot
|
||||
// Color Conversion Functions from https://gist.github.com/ciembor/1494530
|
||||
ColorRGB hslToRgb(GLfloat h, GLfloat s, GLfloat l) {
|
||||
ColorRGB result = {0, 0, 0};
|
||||
|
||||
|
@ -74,29 +82,15 @@ void updateStatusDisplay() {
|
|||
}
|
||||
}
|
||||
|
||||
void recalculateProjectionMatrix() {
|
||||
mat4BuildPerspective(projectionMatrix, 60 * M_PI / 180, aspect, 0.1, 10);
|
||||
DEBUG("Recalculating Projection Matrix");
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
INFO("Compiling Shaders...");
|
||||
|
||||
// create and compile vertex shader
|
||||
INFO("Compiling Vertex Shader...");
|
||||
ShaderCompileResult vertexShader = readAndCompileShaderFromFile("src/shaders/vertex.glsl", GL_VERTEX_SHADER);
|
||||
|
||||
if (!vertexShader.success) {
|
||||
FATAL("Failed to compile Vertex Shader");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// create and compile fragment shader
|
||||
INFO("Compiling Fragment Shader...");
|
||||
ShaderCompileResult fragmentShader = readAndCompileShaderFromFile("src/shaders/fragment.glsl", GL_FRAGMENT_SHADER);
|
||||
if (!fragmentShader.success) {
|
||||
FATAL("Failed to compile Vertex Shader");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// create and link shader program
|
||||
INFO("Linking Shader Program...");
|
||||
ProgramLinkResult linkResult = linkShaderProgram(vertexShader.shader, fragmentShader.shader);
|
||||
INFO("Building Programs...");
|
||||
ProgramLinkResult linkResult = buildShaderProgram("src/shaders/vertex.glsl", "src/shaders/fragment.glsl");
|
||||
if (!linkResult.success) {
|
||||
FATAL("Failed to link Program");
|
||||
exit(1);
|
||||
|
@ -112,112 +106,31 @@ void init(void) {
|
|||
* | -0.2 0.2 |
|
||||
* | | | |
|
||||
*
|
||||
* +----+ +----+ --- 0.6
|
||||
* 0----1 4----5 --- 0.6
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | +--------+ | --- 0.1
|
||||
* | 2--------3 | --- 0.1
|
||||
* | |
|
||||
* | +--------+ | --- -0.1
|
||||
* | 9--------8 | --- -0.1
|
||||
* | | | |
|
||||
* | | | |
|
||||
* +----+ +----+ --- -0.6
|
||||
* 11---10 7----6 --- -0.6
|
||||
*
|
||||
* +------------------+ --- -0.7
|
||||
* 12-----------------13 --- -0.7
|
||||
* | |
|
||||
* +------------------+ --- -0.9
|
||||
* 15-----------------14 --- -0.9
|
||||
*
|
||||
*/
|
||||
|
||||
GLfloat vertices[] = {
|
||||
// X // Y
|
||||
|
||||
// left vertical bar
|
||||
-0.35f, -0.6f,
|
||||
-0.35f, 0.6f,
|
||||
-0.2f, 0.6f,
|
||||
|
||||
-0.35f, -0.6f,
|
||||
-0.2f, 0.6f,
|
||||
-0.2f, -0.6f,
|
||||
|
||||
// right vertical bar
|
||||
0.35f, -0.6f,
|
||||
0.35f, 0.6f,
|
||||
0.2f, 0.6f,
|
||||
|
||||
0.35f, -0.6f,
|
||||
0.2f, 0.6f,
|
||||
0.2f, -0.6f,
|
||||
|
||||
// middle bar
|
||||
-0.2f, -0.1f,
|
||||
-0.2f, 0.1f,
|
||||
0.2f, 0.1f,
|
||||
|
||||
-0.2f, -0.1f,
|
||||
0.2f, 0.1f,
|
||||
0.2f, -0.1f,
|
||||
|
||||
// bottom bar
|
||||
-0.35f, -0.7f,
|
||||
-0.35f, -0.9f,
|
||||
0.35f, -0.9f,
|
||||
|
||||
-0.35f, -0.7f,
|
||||
0.35f, -0.9f,
|
||||
0.35f, -0.7f
|
||||
};
|
||||
|
||||
GLfloat colors[] = {
|
||||
// R // G // B
|
||||
1.0f, 0.0f, 0.0f,
|
||||
1.0f, 0.0f, 0.3f,
|
||||
1.0f, 0.3f, 0.0f,
|
||||
|
||||
1.0f, 0.3f, 0.3f,
|
||||
1.0f, 0.3f, 0.6f,
|
||||
1.0f, 0.6f, 0.3f,
|
||||
|
||||
|
||||
0.0f, 1.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.3f,
|
||||
0.3f, 1.0f, 0.0f,
|
||||
|
||||
0.3f, 1.0f, 0.3f,
|
||||
0.3f, 1.0f, 0.6f,
|
||||
0.6f, 1.0f, 0.3f,
|
||||
|
||||
|
||||
0.3f, 0.3f, 1.0f,
|
||||
0.3f, 0.6f, 1.0f,
|
||||
0.6f, 0.3f, 1.0f,
|
||||
|
||||
0.3f, 0.3f, 1.0f,
|
||||
0.3f, 0.6f, 1.0f,
|
||||
0.6f, 0.3f, 1.0f,
|
||||
|
||||
|
||||
1.0f, 1.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.1f,
|
||||
1.0f, 1.0f, 0.2f,
|
||||
|
||||
1.0f, 1.0f, 0.7f,
|
||||
1.0f, 1.0f, 0.8f,
|
||||
1.0f, 1.0f, 0.9f
|
||||
};
|
||||
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);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
DEBUG("Creating colour buffer");
|
||||
GLuint colorBuffer;
|
||||
glGenBuffers(1, &colorBuffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, 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");
|
||||
|
@ -229,28 +142,39 @@ void init(void) {
|
|||
// vertex position data
|
||||
glVertexAttribPointer(
|
||||
0, // shader location
|
||||
2, // number of values to read
|
||||
3, // number of values to read
|
||||
GL_FLOAT, // type of value
|
||||
GL_FALSE, // if values are normalised
|
||||
2 * sizeof(GLfloat), // stride - distance between vertices
|
||||
sizeof(vertex), // stride - distance between vertices
|
||||
0 // start offset
|
||||
);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
// vertex color data
|
||||
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);
|
||||
glVertexAttribPointer(
|
||||
1,
|
||||
3,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
sizeof(vertex),
|
||||
(void*)offsetof(vertex, normal)
|
||||
);
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.3f);
|
||||
glViewport(0, 0, initialWindowWidth, initialWindowHeight);
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
glFrontFace(GL_CCW);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
initialiseStatusDisplay();
|
||||
|
||||
recalculateProjectionMatrix();
|
||||
|
||||
INFO("--- Initialisation done ---");
|
||||
}
|
||||
|
||||
|
@ -259,21 +183,50 @@ GLfloat currentHue = 0.0f;
|
|||
void draw(void) {
|
||||
updateStatusDisplay();
|
||||
|
||||
currentHue += 0.001f;
|
||||
// counter for animation
|
||||
currentHue += 0.005f;
|
||||
if (currentHue > 1.0) currentHue = 0.0f;
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
// clear colour and depth buffer
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// select program
|
||||
glUseProgram(program);
|
||||
|
||||
GLuint positionLocation = glGetUniformLocation(program, "uPosition");
|
||||
glUniform2f(positionLocation, cos(currentHue * 2 * M_PI) * 0.2f, sin(currentHue * 2 * M_PI) * 0.2f);
|
||||
// build view matrix
|
||||
mat4 viewMatrix;
|
||||
|
||||
// mat4Identity(viewMatrix);
|
||||
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);
|
||||
|
||||
GLuint projectionLocation = glGetUniformLocation(program, "uProjection");
|
||||
glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, projectionMatrix);
|
||||
|
||||
|
||||
// build model Matrix
|
||||
mat4 modelMatrix;
|
||||
mat4 modelViewMatrix;
|
||||
|
||||
vec3 scale = {0.2f, 0.2f, 0.2f};
|
||||
|
||||
mat4Identity(modelMatrix);
|
||||
mat4Scale(modelMatrix, modelMatrix, scale);
|
||||
mat4Multiply(modelViewMatrix, viewMatrix, modelMatrix);
|
||||
|
||||
glUniformMatrix4fv(glGetUniformLocation(program, "uModelView"), 1, GL_FALSE, modelViewMatrix);
|
||||
|
||||
glBindVertexArray(vertexArrayObject);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 48);
|
||||
glDrawArrays(GL_TRIANGLES, 0, numVertices);
|
||||
}
|
||||
|
||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
|
||||
glViewport(0, 0, width, height);
|
||||
aspect = (float)width / height;
|
||||
|
||||
recalculateProjectionMatrix();
|
||||
}
|
||||
|
||||
int main(int argc, char const *argv[])
|
||||
|
@ -295,7 +248,11 @@ int main(int argc, char const *argv[])
|
|||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
GLFWwindow *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) {
|
||||
FATAL("Failed to open window");
|
||||
glfwTerminate();
|
||||
|
|
|
@ -0,0 +1,518 @@
|
|||
#include "matrix-math.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* overwrites a 4x4 matrix with the identity matrix
|
||||
*/
|
||||
void mat4Identity(mat4 mat) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
mat[i] = (i % 4 == i / 4) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* copies a mat4 from src to dst
|
||||
*/
|
||||
void mat4Copy(mat4 src, mat4 dst) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
dst[i] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sets all the values in a mat4 to zero
|
||||
*/
|
||||
void mat4Empty(mat4 mat) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
mat[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mutliplies A with B and stores the result in result
|
||||
*/
|
||||
void mat4Multiply(mat4 result, mat4 A, mat4 B) {
|
||||
// if result is one of the arguments, modify copy instead of result directly
|
||||
if (result == A || result == B) {
|
||||
mat4 tempResult;
|
||||
mat4Multiply(tempResult, A, B);
|
||||
mat4Copy(tempResult, result);
|
||||
return;
|
||||
}
|
||||
|
||||
// loops over cells of the result matrix
|
||||
for (int i = 0; i < 16; i++) {
|
||||
int col = i / 4;
|
||||
int row = i % 4;
|
||||
|
||||
// pointer to the current cell
|
||||
GLfloat* curr = &(result[i]);
|
||||
|
||||
// initialise current cell with 0
|
||||
*curr = 0;
|
||||
|
||||
// loop over the row of A and column of B
|
||||
// continuously adding the multiplication of the two values to the result cell
|
||||
for (int j = 0; j < 4; j++) {
|
||||
*curr += A[row + j * 4] * B[j + col * 4];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* prints a mat4 to the screen
|
||||
*/
|
||||
void mat4Print(mat4 m) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
printf("%.2f ", m[j * 4 + i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* translates by the vector v
|
||||
*/
|
||||
void mat4Translate(mat4 out, mat4 in, vec3 v) {
|
||||
mat4 T;
|
||||
mat4Identity(T);
|
||||
|
||||
T[12] = v[0];
|
||||
T[13] = v[1];
|
||||
T[14] = v[2];
|
||||
|
||||
mat4Multiply(out, T, in);
|
||||
}
|
||||
|
||||
/**
|
||||
* scales by the vector v
|
||||
*/
|
||||
void mat4Scale(mat4 out, mat4 in, vec3 v) {
|
||||
mat4 T;
|
||||
mat4Identity(T);
|
||||
|
||||
T[0] = v[0];
|
||||
T[5] = v[1];
|
||||
T[10] = v[2];
|
||||
|
||||
mat4Multiply(out, T, in);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* rotates around the X axis by the angle a (in radians)
|
||||
*/
|
||||
void mat4RotateX(mat4 out, mat4 in, GLfloat a) {
|
||||
mat4 T;
|
||||
mat4Identity(T);
|
||||
|
||||
T[5] = cos(a);
|
||||
T[6] = sin(a);
|
||||
T[9] = -sin(a);
|
||||
T[10] = cos(a);
|
||||
|
||||
mat4Multiply(out, T, in);
|
||||
}
|
||||
|
||||
/**
|
||||
* rotates around the Y axis by the angle a (in radians)
|
||||
*/
|
||||
void mat4RotateY(mat4 out, mat4 in, GLfloat a) {
|
||||
mat4 T;
|
||||
mat4Identity(T);
|
||||
|
||||
T[0] = cos(a);
|
||||
T[2] = -sin(a);
|
||||
T[8] = sin(a);
|
||||
T[10] = cos(a);
|
||||
|
||||
mat4Multiply(out, T, in);
|
||||
}
|
||||
|
||||
/**
|
||||
* rotates around the Z axis by the angle a (in radians)
|
||||
*/
|
||||
void mat4RotateZ(mat4 out, mat4 in, GLfloat a) {
|
||||
mat4 T;
|
||||
mat4Identity(T);
|
||||
|
||||
T[0] = cos(a);
|
||||
T[1] = sin(a);
|
||||
T[4] = -sin(a);
|
||||
T[5] = cos(a);
|
||||
|
||||
mat4Multiply(out, T, in);
|
||||
}
|
||||
|
||||
/**
|
||||
* builds a look-at matrix, overwriting out
|
||||
* eye is the position of the camera
|
||||
* look is the position of the target to be looked at
|
||||
* up is the up vector
|
||||
*/
|
||||
void mat4BuildLookAt(mat4 out, vec3 eye, vec3 look, vec3 up) {
|
||||
vec3 n;
|
||||
vec3 u;
|
||||
vec3 v;
|
||||
vec3 t;
|
||||
|
||||
vec3Subtract(n, eye, look);
|
||||
|
||||
vec3CrossProduct(u, up, n);
|
||||
|
||||
vec3CrossProduct(v, n, u);
|
||||
|
||||
vec3Normalise(n, n);
|
||||
vec3Normalise(u, u);
|
||||
vec3Normalise(v, v);
|
||||
|
||||
t[0] = - vec3DotProduct(u, eye);
|
||||
t[1] = - vec3DotProduct(v, eye);
|
||||
t[2] = - vec3DotProduct(n, eye);
|
||||
|
||||
out[0] = u[0]; out[4] = u[1]; out[8] = u[2]; out[12] = t[0];
|
||||
out[1] = v[0]; out[5] = v[1]; out[9] = v[2]; out[13] = t[1];
|
||||
out[2] = n[0]; out[6] = n[1]; out[10] = n[2]; out[14] = t[2];
|
||||
out[3] = 0; out[7] = 0; out[11] = 0; out[15] = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* builds a projection matrix, overwriting out
|
||||
* r, l, t, b are the right, left, top and bottom of the frustum
|
||||
* n and f are the distance of the near and far planes from the camera
|
||||
*/
|
||||
void mat4BuildProjection(mat4 out, GLfloat r, GLfloat l, GLfloat t, GLfloat b, GLfloat n, GLfloat f) {
|
||||
mat4Identity(out);
|
||||
|
||||
out[0] = 2.0f / (r - l);
|
||||
out[5] = 2.0f / (t - b);
|
||||
|
||||
out[8] = 1.0f / n * (r + l) / (r - l);
|
||||
out[9] = 1.0f / n * (t + b) / (t - b);
|
||||
out[10] = -1.0f / n * (f + n) / (f - n);
|
||||
out[11] = -1.0f / n;
|
||||
|
||||
out[14] = - 2.0f * f / (f - n);
|
||||
out[15] = 0.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* builds a perspective projection matrix, overwriting out
|
||||
* fovy is the field of view in the y direction
|
||||
* aspect is the aspect ratio
|
||||
* n and f are the distance of the near and far planes from the camera
|
||||
*/
|
||||
void mat4BuildPerspective(mat4 out, GLfloat fovy, GLfloat aspect, GLfloat n, GLfloat f) {
|
||||
GLfloat t = n * tan(0.5f * fovy);
|
||||
GLfloat b = -t;
|
||||
|
||||
GLfloat r = aspect * t;
|
||||
GLfloat l = -r;
|
||||
|
||||
mat4BuildProjection(out, r, l, t, b, n, f);
|
||||
}
|
||||
|
||||
/**
|
||||
* linearly interpolates between a and b, storing the result in out
|
||||
*/
|
||||
void mat4Interpolate(mat4 out, mat4 a, mat4 b, GLfloat f) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
out[i] = (1 - f) * a[i] + f * b[i];
|
||||
}
|
||||
}
|
||||
|
||||
void mat4From3(mat4 out, mat3 in) {
|
||||
mat4Identity(out);
|
||||
memcpy(&out[0], &in[0], sizeof(GLfloat) * 3);
|
||||
memcpy(&out[4], &in[3], sizeof(GLfloat) * 3);
|
||||
memcpy(&out[8], &in[6], sizeof(GLfloat) * 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* https://stackoverflow.com/questions/1148309/inverting-a-4x4-matrix
|
||||
*/
|
||||
void mat4Inverse(mat4 out, mat4 m) {
|
||||
GLfloat inv[16], det;
|
||||
int i;
|
||||
|
||||
inv[0] = m[5] * m[10] * m[15] -
|
||||
m[5] * m[11] * m[14] -
|
||||
m[9] * m[6] * m[15] +
|
||||
m[9] * m[7] * m[14] +
|
||||
m[13] * m[6] * m[11] -
|
||||
m[13] * m[7] * m[10];
|
||||
|
||||
inv[4] = -m[4] * m[10] * m[15] +
|
||||
m[4] * m[11] * m[14] +
|
||||
m[8] * m[6] * m[15] -
|
||||
m[8] * m[7] * m[14] -
|
||||
m[12] * m[6] * m[11] +
|
||||
m[12] * m[7] * m[10];
|
||||
|
||||
inv[8] = m[4] * m[9] * m[15] -
|
||||
m[4] * m[11] * m[13] -
|
||||
m[8] * m[5] * m[15] +
|
||||
m[8] * m[7] * m[13] +
|
||||
m[12] * m[5] * m[11] -
|
||||
m[12] * m[7] * m[9];
|
||||
|
||||
inv[12] = -m[4] * m[9] * m[14] +
|
||||
m[4] * m[10] * m[13] +
|
||||
m[8] * m[5] * m[14] -
|
||||
m[8] * m[6] * m[13] -
|
||||
m[12] * m[5] * m[10] +
|
||||
m[12] * m[6] * m[9];
|
||||
|
||||
inv[1] = -m[1] * m[10] * m[15] +
|
||||
m[1] * m[11] * m[14] +
|
||||
m[9] * m[2] * m[15] -
|
||||
m[9] * m[3] * m[14] -
|
||||
m[13] * m[2] * m[11] +
|
||||
m[13] * m[3] * m[10];
|
||||
|
||||
inv[5] = m[0] * m[10] * m[15] -
|
||||
m[0] * m[11] * m[14] -
|
||||
m[8] * m[2] * m[15] +
|
||||
m[8] * m[3] * m[14] +
|
||||
m[12] * m[2] * m[11] -
|
||||
m[12] * m[3] * m[10];
|
||||
|
||||
inv[9] = -m[0] * m[9] * m[15] +
|
||||
m[0] * m[11] * m[13] +
|
||||
m[8] * m[1] * m[15] -
|
||||
m[8] * m[3] * m[13] -
|
||||
m[12] * m[1] * m[11] +
|
||||
m[12] * m[3] * m[9];
|
||||
|
||||
inv[13] = m[0] * m[9] * m[14] -
|
||||
m[0] * m[10] * m[13] -
|
||||
m[8] * m[1] * m[14] +
|
||||
m[8] * m[2] * m[13] +
|
||||
m[12] * m[1] * m[10] -
|
||||
m[12] * m[2] * m[9];
|
||||
|
||||
inv[2] = m[1] * m[6] * m[15] -
|
||||
m[1] * m[7] * m[14] -
|
||||
m[5] * m[2] * m[15] +
|
||||
m[5] * m[3] * m[14] +
|
||||
m[13] * m[2] * m[7] -
|
||||
m[13] * m[3] * m[6];
|
||||
|
||||
inv[6] = -m[0] * m[6] * m[15] +
|
||||
m[0] * m[7] * m[14] +
|
||||
m[4] * m[2] * m[15] -
|
||||
m[4] * m[3] * m[14] -
|
||||
m[12] * m[2] * m[7] +
|
||||
m[12] * m[3] * m[6];
|
||||
|
||||
inv[10] = m[0] * m[5] * m[15] -
|
||||
m[0] * m[7] * m[13] -
|
||||
m[4] * m[1] * m[15] +
|
||||
m[4] * m[3] * m[13] +
|
||||
m[12] * m[1] * m[7] -
|
||||
m[12] * m[3] * m[5];
|
||||
|
||||
inv[14] = -m[0] * m[5] * m[14] +
|
||||
m[0] * m[6] * m[13] +
|
||||
m[4] * m[1] * m[14] -
|
||||
m[4] * m[2] * m[13] -
|
||||
m[12] * m[1] * m[6] +
|
||||
m[12] * m[2] * m[5];
|
||||
|
||||
inv[3] = -m[1] * m[6] * m[11] +
|
||||
m[1] * m[7] * m[10] +
|
||||
m[5] * m[2] * m[11] -
|
||||
m[5] * m[3] * m[10] -
|
||||
m[9] * m[2] * m[7] +
|
||||
m[9] * m[3] * m[6];
|
||||
|
||||
inv[7] = m[0] * m[6] * m[11] -
|
||||
m[0] * m[7] * m[10] -
|
||||
m[4] * m[2] * m[11] +
|
||||
m[4] * m[3] * m[10] +
|
||||
m[8] * m[2] * m[7] -
|
||||
m[8] * m[3] * m[6];
|
||||
|
||||
inv[11] = -m[0] * m[5] * m[11] +
|
||||
m[0] * m[7] * m[9] +
|
||||
m[4] * m[1] * m[11] -
|
||||
m[4] * m[3] * m[9] -
|
||||
m[8] * m[1] * m[7] +
|
||||
m[8] * m[3] * m[5];
|
||||
|
||||
inv[15] = m[0] * m[5] * m[10] -
|
||||
m[0] * m[6] * m[9] -
|
||||
m[4] * m[1] * m[10] +
|
||||
m[4] * m[2] * m[9] +
|
||||
m[8] * m[1] * m[6] -
|
||||
m[8] * m[2] * m[5];
|
||||
|
||||
det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
|
||||
|
||||
if (det == 0) {
|
||||
mat4Copy(m, out); // singular matrix, can't invert
|
||||
return;
|
||||
}
|
||||
|
||||
det = 1.0 / det;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
out[i] = inv[i] * det;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* subtracts b from a, storing the result in out
|
||||
*/
|
||||
void vec3Subtract(vec3 out, vec3 a, vec3 b) {
|
||||
out[0] = a[0] - b[0];
|
||||
out[1] = a[1] - b[1];
|
||||
out[2] = a[2] - b[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* calculates the cross product of a and b, storing the result in out
|
||||
*/
|
||||
void vec3CrossProduct(vec3 out, vec3 a, vec3 b) {
|
||||
vec3 result;
|
||||
result[0] = a[1] * b[2] - a[2] * b[1];
|
||||
result[1] = a[2] * b[0] - a[0] * b[2];
|
||||
result[2] = a[0] * b[1] - a[1] * b[0];
|
||||
|
||||
out[0] = result[0];
|
||||
out[1] = result[1];
|
||||
out[2] = result[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* normalizes in storing the result in out
|
||||
*/
|
||||
void vec3Normalise(vec3 out, vec3 in) {
|
||||
GLfloat length = vec3Length(in);
|
||||
out[0] = in[0] / length;
|
||||
out[1] = in[1] / length;
|
||||
out[2] = in[2] / length;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the length of the vector in
|
||||
*/
|
||||
GLfloat vec3Length(vec3 in) {
|
||||
return sqrt(in[0] * in[0] + in[1] * in[1] + in[2] * in[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the dot product of the vectors a and b
|
||||
*/
|
||||
GLfloat vec3DotProduct(vec3 a, vec3 b) {
|
||||
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the values of out to x, y and z
|
||||
*/
|
||||
void vec3Set(vec3 out, GLfloat x, GLfloat y, GLfloat z) {
|
||||
out[0] = x;
|
||||
out[1] = y;
|
||||
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++) {
|
||||
dst[i] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
void mat3From4(mat3 out, mat4 in) {
|
||||
memcpy(&out[0], &in[0], sizeof(GLfloat) * 3);
|
||||
memcpy(&out[3], &in[4], sizeof(GLfloat) * 3);
|
||||
memcpy(&out[6], &in[8], sizeof(GLfloat) * 3);
|
||||
}
|
||||
|
||||
void mat3Transpose(mat3 out, mat3 in) {
|
||||
mat3 result;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
result[i * 3 + j] = in[j * 3 + i];
|
||||
}
|
||||
}
|
||||
|
||||
mat3Copy(result, out);
|
||||
}
|
||||
|
||||
void mat3Minor(mat3 out, mat3 in) {
|
||||
mat3 result;
|
||||
|
||||
// TODO: check if this is correct
|
||||
result[0] = in[4] * in[8] - in[5] * in[7];
|
||||
result[1] = in[3] * in[8] - in[5] * in[6];
|
||||
result[2] = in[3] * in[7] - in[4] * in[6];
|
||||
|
||||
result[3] = in[1] * in[8] - in[2] * in[7];
|
||||
result[4] = in[0] * in[8] - in[2] * in[6];
|
||||
result[5] = in[0] * in[7] - in[1] * in[6];
|
||||
|
||||
result[6] = in[1] * in[5] - in[2] * in[4];
|
||||
result[7] = in[0] * in[5] - in[2] * in[3];
|
||||
result[8] = in[0] * in[4] - in[1] * in[3];
|
||||
|
||||
mat3Copy(result, out);
|
||||
}
|
||||
|
||||
void mat3Cofactor(mat3 out, mat3 in) {
|
||||
mat3Minor(out, in);
|
||||
|
||||
out[1] *= -1;
|
||||
out[3] *= -1;
|
||||
out[5] *= -1;
|
||||
out[7] *= -1;
|
||||
}
|
||||
|
||||
void mat3Adjoint(mat3 out, mat3 in) {
|
||||
mat3Cofactor(out, in);
|
||||
mat3Transpose(out, in);
|
||||
}
|
||||
|
||||
void mat3MultiplyScalar(mat3 out, mat3 in, GLfloat x) {
|
||||
for (int i = 0; i < 9; i++) {
|
||||
out[i] = in[i] * x;
|
||||
}
|
||||
}
|
||||
|
||||
GLfloat mat3Determinant(mat3 M) {
|
||||
return
|
||||
+ M[0] * M[4] * M[8]
|
||||
+ M[3] * M[7] * M[2]
|
||||
+ M[6] * M[1] * M[5]
|
||||
|
||||
- M[2] * M[4] * M[6]
|
||||
- M[5] * M[7] * M[0]
|
||||
- M[8] * M[1] * M[3]
|
||||
;
|
||||
}
|
||||
|
||||
void mat3Inverse(mat3 out, mat3 in) {
|
||||
mat3 result;
|
||||
mat3Adjoint(result, in);
|
||||
mat3MultiplyScalar(result, result, 1 / mat3Determinant(in));
|
||||
mat3Copy(result, out);
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef MATRIX_MATH_H
|
||||
#define MATRIX_MATH_H
|
||||
|
||||
#include <GL/gl.h>
|
||||
|
||||
/**
|
||||
* !!! ALL matrices are in column major
|
||||
*/
|
||||
|
||||
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);
|
||||
extern void mat4Multiply(mat4 result, mat4 A, mat4 B);
|
||||
extern void mat4Print(mat4 m);
|
||||
extern void mat4Translate(mat4 out, mat4 in, vec3 v);
|
||||
extern void mat4Scale(mat4 out, mat4 in, vec3 v);
|
||||
extern void mat4RotateX(mat4 out, mat4 in, GLfloat a);
|
||||
extern void mat4RotateY(mat4 out, mat4 in, GLfloat a);
|
||||
extern void mat4RotateZ(mat4 out, mat4 in, GLfloat a);
|
||||
extern void mat4BuildLookAt(mat4 out, vec3 eye, vec3 center, vec3 up);
|
||||
extern void mat4BuildProjection(mat4 out, GLfloat r, GLfloat l, GLfloat t, GLfloat b, GLfloat n, GLfloat f);
|
||||
extern void mat4BuildPerspective(mat4 out, GLfloat fovy, GLfloat aspect, GLfloat n, GLfloat f);
|
||||
extern void mat4Interpolate(mat4 out, mat4 a, mat4 b, GLfloat f);
|
||||
extern void mat4From3(mat4 out, mat3 in);
|
||||
extern void mat4Inverse(mat4 m, mat4 out);
|
||||
|
||||
extern void vec3Subtract(vec3 out, vec3 a, vec3 b);
|
||||
extern void vec3CrossProduct(vec3 out, vec3 a, vec3 b);
|
||||
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);
|
||||
extern GLfloat mat3Determinant(mat3 m);
|
||||
extern void mat3MultiplyScalar(mat3 out, mat3 in, GLfloat x);
|
||||
extern void mat3Adjoint(mat3 out, mat3 in);
|
||||
extern void mat3Cofactor(mat3 out, mat3 in);
|
||||
extern void mat3Minor(mat3 out, mat3 in);
|
||||
extern void mat3Transpose(mat3 out, mat3 in);
|
||||
extern void mat3From4(mat3 out, mat4 in);
|
||||
|
||||
#endif
|
25
src/shader.c
25
src/shader.c
|
@ -116,4 +116,27 @@ ProgramLinkResult linkShaderProgram(GLuint vertexShader, GLuint fragmentShader)
|
|||
|
||||
result.success = true;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
ProgramLinkResult buildShaderProgram(const char* vertexShaderPath, const char* fragmentShaderPath) {
|
||||
ProgramLinkResult result = { .success = false, .program = 0 };
|
||||
|
||||
ShaderCompileResult vertexShader = readAndCompileShaderFromFile(vertexShaderPath, GL_VERTEX_SHADER);
|
||||
if (!vertexShader.success) {
|
||||
FATAL("Failed to compile vertex shader");
|
||||
return result;
|
||||
}
|
||||
|
||||
ShaderCompileResult fragmentShader = readAndCompileShaderFromFile(fragmentShaderPath, GL_FRAGMENT_SHADER);
|
||||
if (!fragmentShader.success) {
|
||||
FATAL("Failed to compile fragment shader");
|
||||
return result;
|
||||
}
|
||||
|
||||
result = linkShaderProgram(vertexShader.shader, fragmentShader.shader);
|
||||
|
||||
glDeleteShader(vertexShader.shader);
|
||||
glDeleteShader(fragmentShader.shader);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -17,5 +17,6 @@ typedef struct {
|
|||
extern const char* readFileToMemory(const char* filepath);
|
||||
extern ShaderCompileResult readAndCompileShaderFromFile(const char* filepath, GLenum shaderType);
|
||||
extern ProgramLinkResult linkShaderProgram(GLuint vertexShader, GLuint fragmentShader);
|
||||
extern ProgramLinkResult buildShaderProgram(const char* vertexShaderPath, const char* fragmentShaderPath);
|
||||
|
||||
#endif // SHADER_H
|
|
@ -1,5 +1,6 @@
|
|||
#version 330 core
|
||||
in vec3 vertexColor;
|
||||
in vec3 vNormal;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = vec4(vertexColor, 1.0);
|
||||
gl_FragColor = vec4(vNormal * 0.5 + vec3(0.5), 1.0);
|
||||
}
|
|
@ -1,11 +1,12 @@
|
|||
#version 330 core
|
||||
layout (location = 0) in vec2 aPosition;
|
||||
layout (location = 1) in vec3 aColor;
|
||||
uniform vec2 uPosition;
|
||||
layout (location = 0) in vec3 aPosition;
|
||||
layout (location = 1) in vec3 aNormal;
|
||||
uniform mat4 uModelView;
|
||||
uniform mat4 uProjection;
|
||||
|
||||
out vec3 vertexColor;
|
||||
out vec3 vNormal;
|
||||
|
||||
void main() {
|
||||
vertexColor = aColor;
|
||||
gl_Position = vec4(uPosition + aPosition, 0.0, 1.0);
|
||||
vNormal = aNormal;
|
||||
gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue