diff options
author | jvech <jmvalenciae@unal.edu.co> | 2022-10-03 11:38:07 -0500 |
---|---|---|
committer | jvech <jmvalenciae@unal.edu.co> | 2022-10-03 11:38:07 -0500 |
commit | 8fad4fc153d162598e432ca5740c5ec401b46696 (patch) | |
tree | 32cdf567cb433397db9594202c7b15358e002eb2 | |
parent | fc8d7fed3ccdf0998a7b9809aa825f2d14876b29 (diff) |
feat: obj file reading and rendering implemented
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | TODO | 11 | ||||
-rw-r--r-- | shaders/dummy.fsh | 7 | ||||
-rw-r--r-- | shaders/dummy.vsh | 20 | ||||
-rw-r--r-- | src/main.c | 287 | ||||
-rw-r--r-- | src/obj.c | 293 | ||||
-rw-r--r-- | src/obj.h | 26 | ||||
-rw-r--r-- | src/shader.c | 4 |
9 files changed, 443 insertions, 213 deletions
@@ -1,3 +1,5 @@ objs/ mverse tags +models +textures @@ -4,10 +4,10 @@ DLIBS := -lm $(shell pkg-config --libs glfw3 opengl glew) INCLUDE := $(addprefix -I,./include) OBJDIR = objs SRCDIR = src -OBJS = $(addprefix objs/,main.o shader.o linear.o) +OBJS = $(addprefix objs/,main.o shader.o linear.o obj.o) BIN = mverse -all: build run +all: build $(OBJS): | $(OBJDIR) @@ -15,7 +15,7 @@ $(OBJDIR): mkdir ${OBJDIR} $(OBJDIR)/%.o: $(SRCDIR)/%.c - ${CC} -c $< -o $@ ${CFLAGS} ${INCLUDE} + ${CC} -g -c $< -o $@ ${CFLAGS} ${INCLUDE} build: $(OBJS) ${CC} $^ -o ${BIN} ${DLIBS} @@ -3,12 +3,13 @@ General ? Try to implement it without external libraries - Make a PNG image reader -- Add 3D objects - - define a format for 3D objects - - Implement a function to load objects from a file - - Render a set of vertices loaded from a file +Obj +- Load obj files + * Vertex coordinates, normals and textures + - read faces with more than 4 vertices +- Render a set of vertices loaded from a file + - Add normal Support -* Implement Camera movement Linear - Implement the Inverse function of mat4 diff --git a/shaders/dummy.fsh b/shaders/dummy.fsh new file mode 100644 index 0000000..7d94f22 --- /dev/null +++ b/shaders/dummy.fsh @@ -0,0 +1,7 @@ +#version 330 core +out vec4 FragColor; + +void main() +{ + FragColor = vec4(0.0f); +} diff --git a/shaders/dummy.vsh b/shaders/dummy.vsh new file mode 100644 index 0000000..ab57a50 --- /dev/null +++ b/shaders/dummy.vsh @@ -0,0 +1,20 @@ +# version 330 core + +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoords; + +uniform mat4 model, view, proj; +uniform mat4 rotNormals; + +out vec3 FragPos; +out vec3 Normal; +out vec2 TexCoords; + +void main() +{ + gl_Position = proj * view * model * vec4(aPos, 1.0f); + //FragPos = vec3(model * vec4(aPos, 1.0)); + //Normal = vec3(rotNormals * vec4(aNormal, 1.0)); + //TexCoords = aTexCoords; +} @@ -10,11 +10,12 @@ #include <GLFW/glfw3.h> #define STB_IMAGE_IMPLEMENTATION -#include <stb_image.h> +#include "../include/stb_image.h" #include "main.h" #include "linear.h" #include "shader.h" +#include "obj.h" struct Camera { Vec3 position; @@ -22,55 +23,15 @@ struct Camera { Vec3 up; }; -float vertices[] = { - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, - - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f -}; - static void userError(const char *msg, const char *detail); static void glfw_size_callback(GLFWwindow *window, int width, int height); static void processInput(GLFWwindow *window); static Mat4 processCameraInput(GLFWwindow *window, struct Camera *cameraObj, float deltaTime); static unsigned int loadTexture(char const *path); +static void meshSetUp(Mesh *mesh); +static void meshDraw(unsigned int shader, Mesh mesh); + +static float cameraSpeed = 2.0; void userError(const char *msg, const char *detail) @@ -107,7 +68,11 @@ processCameraInput(GLFWwindow *window, struct Camera *camObj, float deltaTime) * Keyboard Input */ Vec3 tmp; - float speed = 2.0f * deltaTime; + float speed = cameraSpeed * deltaTime; + + if (glfwGetKey(window, GLFW_KEY_K)) cameraSpeed += 0.2; + if (glfwGetKey(window, GLFW_KEY_J)) cameraSpeed -= 0.2; + if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { // pos = pos + front * speed tmp = linearVec3ScalarMulp(camObj->front, speed); @@ -213,11 +178,57 @@ loadTexture(char const *path) return textureID; } -int main() + +void +meshSetUp(Mesh *mesh) { + glGenVertexArrays(1, &(mesh->VAO)); + glGenBuffers(1, &(mesh->VBO)); + glGenBuffers(1, &(mesh->EBO)); + + glBindVertexArray(mesh->VAO); + + glBindBuffer(GL_ARRAY_BUFFER, mesh->VBO); + glBufferData(GL_ARRAY_BUFFER, mesh->vertexSize * sizeof(Vertex), mesh->vertices, GL_STATIC_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->EBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh->indexSize * sizeof(int), mesh->indices, GL_STATIC_DRAW); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)0); + + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)offsetof(Vertex, normal)); + + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)offsetof(Vertex, texCoords)); + + glBindVertexArray(0); +} + +void +meshDraw(unsigned int shader, Mesh mesh) +{ + glBindVertexArray(mesh.VAO); + glDrawElements(GL_TRIANGLES, mesh.indexSize, GL_UNSIGNED_INT, 0); + glBindVertexArray(0); +} + +int main(int argc, char *argv[]) +{ + Mesh *mesh; GLFWwindow *window; const char *glfwErrno; + if (argc == 2) mesh = objCreateMesh(argv[1]); + else if (argc == 1) mesh = objCreateMesh("-"); + else return 1; + + if (mesh == NULL) { + glfwTerminate(); + userError("objCreateMesh Error", "NULL mesh returned"); + } + if (!glfwInit()) { glfwGetError(&glfwErrno); glfwTerminate(); @@ -227,7 +238,7 @@ int main() window = glfwCreateWindow(640, 480, "Mverse", NULL, NULL); if (!window) { glfwTerminate(); - userError("glfwCreateWindow() failed", "Can't create window"); + userError("glfwCreateWindow() Error", "Can't create window"); } glfwSetFramebufferSizeCallback(window, glfw_size_callback); @@ -237,189 +248,59 @@ int main() GLubyte glewErrno = glewInit(); if (glewErrno != GLEW_OK) { glfwTerminate(); - userError("glewInit() failed", (const char *)glewGetErrorString(glewErrno)); + userError("glewInit Error", (const char *)glewGetErrorString(glewErrno)); } - glEnable(GL_DEPTH_TEST); - stbi_set_flip_vertically_on_load(1); - - unsigned int programColor = shaderCreateProgram("shaders/color.vsh", - "shaders/color.fsh"); - unsigned int programLight = shaderCreateProgram("shaders/lightsource.vsh", - "shaders/lightsource.fsh"); - unsigned int VBO, VAO, lightVAO; - int vertexSize = 8; - - glGenVertexArrays(1, &VAO); - glGenBuffers(1, &VBO); - - glBindBuffer(GL_ARRAY_BUFFER, VBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - - glBindVertexArray(VAO); - - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertexSize * sizeof(float), (void *)0); - glEnableVertexAttribArray(0); - - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertexSize * sizeof(float), (void *)(3 * sizeof(float))); - glEnableVertexAttribArray(1); - - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, vertexSize * sizeof(float), (void *)(6 * sizeof(float))); - glEnableVertexAttribArray(2); - - glBindVertexArray(lightVAO); - - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertexSize * sizeof(float), (void *)0); - glEnableVertexAttribArray(0); - - unsigned int diffuseMap = loadTexture("textures/container2.png"); - unsigned int specularMap = loadTexture("textures/container2_specular.png"); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); + unsigned int shader = shaderCreateProgram("shaders/dummy.vsh", "shaders/dummy.fsh"); - /*============ Initializations ===============*/ - - Vec3 cubePositions[] = { - linearVec3( 0.5f, 0.0f, 0.0f), - linearVec3( 2.0f, 5.0f, -15.0f), - linearVec3(-1.5f, -2.2f, -2.5f), - linearVec3(-3.8f, -2.0f, -12.3f), - linearVec3( 2.4f, -0.4f, -3.5f), - linearVec3(-1.7f, 3.0f, -7.5f), - linearVec3( 1.3f, -2.0f, -2.5f), - linearVec3( 1.5f, 2.0f, -2.5f), - linearVec3( 1.5f, 0.2f, -1.5f), - linearVec3(-1.3f, 1.0f, -1.5f) - }; - - Vec3 pointLightsPos[4] = { - linearVec3(0.7f, 0.2f, 2.0f), - linearVec3(2.3f, -3.3f, -4.0f), - linearVec3(-4.0f, 2.0f, -12.0f), - linearVec3(0.0f, 0.0f, -3.0f), - }; + meshSetUp(mesh); struct Camera mainCamera; - mainCamera.position = linearVec3(0.0, 0.0, 3.0); + mainCamera.position = linearVec3(0.0, 0.0, 10.0); mainCamera.front = linearVec3(0.0, 0.0, -1.0); mainCamera.up = linearVec3(0.0, 1.0, 0.0); Mat4 model, view, proj; Mat4 T, S, R; - - Vec3 dirLight = linearVec3(-0.2, -1.0, 0.3); - Vec3 ambient = linearVec3(0.0, 0.0, 0.0); - Vec3 diffuse = linearVec3(0.5, 0.5, 0.5); - Vec3 specular = linearVec3(1.0, 1.0, 1.0); - float dt, t, t0; + float t, t0, dt; int width, height; t0 = 0; + + glEnable(GL_DEPTH_TEST); while (!glfwWindowShouldClose(window)) { processInput(window); - - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glfwGetWindowSize(window, &width, &height); - /* ------------------- - * frame calculations - * ------------------*/ t = (float)glfwGetTime(); dt = t - t0; t0 = t; - view = processCameraInput(window, &mainCamera, dt); - glfwGetWindowSize(window, &width, &height); proj = linearPerspective(35, (float)width / height, 0.1, 100); + T = linearTranslate(0.0, 0.0, 0.0); + R = linearRotate(0, 1.0, 0.0, 0.0); + S = linearScale(0.6, 0.6, 0.6); + model = linearMat4Muln(3, T, R, S); - glUseProgram(programColor); - - float constant = 1.0; - float linear = 0.09; - float quadratic = 0.032f; - - shaderSetfv(programColor, "dirLight.direction", dirLight.vector, glUniform3fv); - shaderSetfv(programColor, "dirLight.ambient", ambient.vector, glUniform3fv); - shaderSetfv(programColor, "dirLight.diffuse", diffuse.vector, glUniform3fv); - shaderSetfv(programColor, "dirLight.specular", vec3(1.0, 1.0, 1.0), glUniform3fv); - - char varNames[7][50]; - for (int i = 0; i < 4; i++) { - sprintf(varNames[0], "pointLight[%d].position", i); - sprintf(varNames[1], "pointLight[%d].ambient", i); - sprintf(varNames[2], "pointLight[%d].diffuse", i); - sprintf(varNames[3], "pointLight[%d].specular", i); - sprintf(varNames[4], "pointLight[%d].constant", i); - sprintf(varNames[5], "pointLight[%d].linear", i); - sprintf(varNames[6], "pointLight[%d].quadratic", i); - - shaderSetfv(programColor, varNames[0], pointLightsPos[i].vector, glUniform3fv); - shaderSetfv(programColor, varNames[1], ambient.vector, glUniform3fv); - shaderSetfv(programColor, varNames[2], diffuse.vector, glUniform3fv); - shaderSetfv(programColor, varNames[3], specular.vector, glUniform3fv); - shaderSet1f(programColor, varNames[4], constant); - shaderSet1f(programColor, varNames[5], linear); - shaderSet1f(programColor, varNames[6], quadratic); - } - - shaderSetfv(programColor, "flashLight.position", mainCamera.position.vector, glUniform3fv); - shaderSetfv(programColor, "flashLight.direction", mainCamera.front.vector, glUniform3fv); - shaderSetfv(programColor, "flashLight.ambient", ambient.vector, glUniform3fv); - shaderSetfv(programColor, "flashLight.diffuse", vec3(0.8, 0.5, 0.5), glUniform3fv); - shaderSetfv(programColor, "flashLight.specular", vec3(1.0, 0.0, 0.0), glUniform3fv); - shaderSet1f(programColor, "flashLight.constant", constant); - shaderSet1f(programColor, "flashLight.linear", linear); - shaderSet1f(programColor, "flashLight.quadratic", quadratic); - shaderSet1f(programColor, "flashLight.cutOff", cosf(12.5f * M_PI / 180)); - shaderSet1f(programColor, "flashLight.outerCutOff", cosf(17.5f * M_PI / 180)); - - shaderSetfv(programColor, "viewPos", mainCamera.position.vector, glUniform3fv); - shaderSetfv(programColor, "material.specular", vec3(0.5, 0.5, 0.5), glUniform3fv); - shaderSet1f(programColor, "material.shininess", 64.0f); - shaderSet1i(programColor, "material.diffuse", 0); - shaderSet1i(programColor, "material.specular", 1); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, diffuseMap); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, specularMap); - - shaderSetMatrixfv(programColor, "view", view.matrix[0], glUniformMatrix4fv); - shaderSetMatrixfv(programColor, "proj", proj.matrix[0], glUniformMatrix4fv); - for (int i = 0; i < 10; i++) { - // World Transformation - // -------------------- - T = linearTranslatev(cubePositions[i]); - R = linearRotate(180 * i / M_PI, 1.0, 0.3, 0.5); - S = linearScale(1.0, 1.0, 1.0); - model = linearMat4Muln(3, T, R, S); - shaderSetMatrixfv(programColor, "model", model.matrix[0], glUniformMatrix4fv); - shaderSetMatrixfv(programColor, "rotNormals", R.matrix[0], glUniformMatrix4fv); - - glBindVertexArray(VAO); - glDrawArrays(GL_TRIANGLES, 0, sizeof(vertices) / sizeof(float)); - } - - /* ----------------- - * Light Source - * -----------------*/ - for (int i = 0; i < 4; i++) { - model = linearMat4Mul(linearTranslatev(pointLightsPos[i]), - linearScale(0.2, 0.2, 0.2)); - glUseProgram(programLight); - glBindVertexArray(lightVAO); - - shaderSetMatrixfv(programColor, "model", model.matrix[0], glUniformMatrix4fv); - shaderSetMatrixfv(programColor, "view", view.matrix[0], glUniformMatrix4fv); - shaderSetMatrixfv(programColor, "proj", proj.matrix[0], glUniformMatrix4fv); - glDrawArrays(GL_TRIANGLES, 0, sizeof(vertices) / sizeof(float)); - } + glUseProgram(shader); + + shaderSetMatrixfv(shader, "model", model.matrix[0], glUniformMatrix4fv); + shaderSetMatrixfv(shader, "proj", proj.matrix[0], glUniformMatrix4fv); + shaderSetMatrixfv(shader, "view", view.matrix[0], glUniformMatrix4fv); + shaderSetMatrixfv(shader, "rotNormals", R.matrix[0], glUniformMatrix4fv); + + meshDraw(shader, mesh[0]); glfwSwapBuffers(window); glfwPollEvents(); } glfwTerminate(); + + free(mesh->vertices); + free(mesh->indices); + free(mesh); return 0; } diff --git a/src/obj.c b/src/obj.c new file mode 100644 index 0000000..0f13fb4 --- /dev/null +++ b/src/obj.c @@ -0,0 +1,293 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include "obj.h" + +enum ObjVertexType { + OBJ_V, + OBJ_VN, + OBJ_VT, + OBJ_F, + OBJ_OTHER +}; + +struct Setv3 { + float data[3]; +}; + +struct Setv2 { + float data[2]; +}; + +struct Seti { + int v, vn, vt; +}; + +static void readV3(char *line, struct Setv3 **v, int vIndex); +static void readV2(char *line, struct Setv2 **vn, int vtIndex); +static void readF(char *line, Mesh *mesh, struct Setv3 *v, struct Setv2 *vt, struct Setv3 *vn); +static void vertexCount(FILE *, int *vSize, int *vtSize, int *vnSize); + +// ---------------------------------------------------------------------------- +static int readIndices(char *line, struct Seti *f); +static Vertex createVertex(struct Seti f, struct Setv3 *v, struct Setv2 *vt, struct Setv3 *vn); +static int vertexInVertices(Vertex vertex, Vertex *vertices, int nVertices); +static void vertexAdd(Mesh *mesh, Vertex vertex); +static int vertexGetIndex(Vertex *vertices, Vertex vertex, int nVertices); +static void indexAdd(Mesh *mesh, int index); + +Mesh * +objCreateMesh(const char *filename) +{ + Mesh *mesh; + char lineBuffer[OBJ_LINE_MAX_SIZE]; + FILE *fi; + + struct Setv3 *v, *vn; + struct Setv2 *vt; + int vSize, vtSize, vnSize; + vSize = vtSize = vnSize = 0; + + fi = (!strcmp(filename, "-")) ? stdin : fopen(filename, "r"); + mesh = (Mesh *)calloc(1, sizeof(Mesh)); + + // On error return NULL + if (fi == NULL || mesh == NULL) { + fprintf(stderr, "objCreateMesh() Error: %s\n", strerror(errno)); + fclose(fi); + return NULL; + } + + //vertexCount(fi, &vSize, &vtSize, &vnSize); + v = (struct Setv3 *)calloc(1, vSize * sizeof(struct Setv3)); + vt = (struct Setv2 *)calloc(1, vtSize * sizeof(struct Setv2)); + vn = (struct Setv3 *)calloc(1, vnSize * sizeof(struct Setv3)); + + /* + if (vSize == 0) { + fprintf(stderr, "objCreateMesh() Error: v components not found\n"); + exit(1); + } else if (v == NULL) { + fprintf(stderr, "objCreateMesh() Error: %s\n", strerror(errno)); + exit(1); + } + */ + + int vIndex, vtIndex, vnIndex; + vIndex = vtIndex = vnIndex = 0; + while (fgets(lineBuffer, OBJ_LINE_MAX_SIZE, fi)) { + if (!strncmp("f", lineBuffer, 1)) readF (lineBuffer + 1, mesh, v, vt, vn); + else if (!strncmp("vt", lineBuffer, 2)) readV2(lineBuffer + 2, &vt, vtIndex++); + else if (!strncmp("vn", lineBuffer, 2)) readV3(lineBuffer + 2, &vn, vnIndex++); + else if (!strncmp("v", lineBuffer, 1)) readV3(lineBuffer + 1, &v, vIndex++); + + /* + if (vIndex > vSize) { + fprintf(stderr, "objCreateMesh() Error: v components exceeded the expected size\n"); + exit(1); + } else if (vtIndex > vtSize) { + fprintf(stderr, "objCreateMesh() Error: vt components exceeded the expected size\n"); + exit(1); + } else if (vtIndex > vnSize) { + fprintf(stderr, "objCreateMesh() Error: vn components exceeded the expected size\n"); + exit(1); + } + */ + } + + free(v); + free(vt); + free(vn); + fclose(fi); + + return mesh; +} + +void +vertexCount(FILE *fi, int *vSize, int *vtSize, int *vnSize) +{ + char line[OBJ_LINE_MAX_SIZE]; + while (fgets(line, OBJ_LINE_MAX_SIZE, fi)) { + if (!strncmp("vt", line, 2)) (*vtSize)++; + else if (!strncmp("vn", line, 2)) (*vnSize)++; + else if (!strncmp("v", line, 1)) (*vSize)++; + } + fseek(fi, 0L, SEEK_SET); +} + +void +readF(char *line, Mesh *mesh, struct Setv3 *v, struct Setv2 *vt, struct Setv3 *vn) +{ + Vertex vertexBuffer; + struct Seti f[6]; + int i, nIndices, vi; + nIndices = readIndices(line, f); + + for (i = 0; i < nIndices; i++) { + vertexBuffer = createVertex(f[i], v, vt, vn); + if (!vertexInVertices(vertexBuffer, mesh->vertices, mesh->vertexSize)) + vertexAdd(mesh, vertexBuffer); + vi = vertexGetIndex(mesh->vertices, vertexBuffer, mesh->vertexSize); + indexAdd(mesh, vi); + } +} + +void +readV3(char *line, struct Setv3 **v, int vIndex) +{ + int i, n; + char *ptr; + struct Setv3 *vptr; + + if (vIndex > 0) + *v = (struct Setv3 *)realloc(*v, (vIndex + 1) * sizeof(struct Setv3)); + + vptr = *v; + for (i = 0, ptr = line, n = 0; i < 3; i++, ptr += n) + sscanf(ptr, " %f%n", vptr[vIndex].data + i, &n); +} + +void +readV2(char *line, struct Setv2 **v, int vIndex) +{ + int i, n; + char *ptr; + struct Setv2 *vptr; + + if (vIndex > 0) + *v = (struct Setv2 *)realloc(*v, (vIndex + 1) * sizeof(struct Setv2)); + + vptr = *v; + for (i = 0, ptr = line, n = 0; i < 2; i++, ptr += n) + sscanf(line, " %f%n", vptr[vIndex].data + i, &n); +} + +int +readIndices(char *line, struct Seti *f) +{ + int i, n, fSize; + char *ptr; + + for (ptr = line, i = n = fSize = 0; *ptr != '\n'; fSize++, ptr += n, i++) { + f[i].v = f[i].vt = f[i].vn = -1; + if ((sscanf(ptr, " %d/%d/%d%n", &f[i].v, &f[i].vn, &f[i].vt, &n) >= 3)) continue; + + f[i].v = f[i].vt = f[i].vn = -1; + if ((sscanf(ptr, " %d//%d%n", &f[i].v, &f[i].vn, &n) >= 2)) continue; + + f[i].v = f[i].vt = f[i].vn = -1; + if ((sscanf(ptr, " %d/%d%n", &f[i].v, &f[i].vt, &n) >= 2)) continue; + + f[i].v = f[i].vt = f[i].vn = -1; + if ((sscanf(ptr, " %d%n", &f[i].v, &n) >= 1)) continue; + + fprintf(stderr, "readIndices() Error: bad format on line '%s'\n", line - 1); + exit(1); + } + + for (i = 0; i < fSize; i++) { + if (f[i].v > 0) f[i].v--; + if (f[i].vn > 0) f[i].vn--; + if (f[i].vt > 0 && i < 2) f[i].vt--; + } + + if (fSize == 4) { + f[4].v = f[2].v; + f[4].vt = f[2].vt; + f[4].vn = f[2].vn; + + f[5].v = f[0].v; + f[5].vt = f[0].vt; + f[5].vn = f[0].vn; + fSize += 2; + } + return fSize; +} + +Vertex +createVertex(struct Seti f, struct Setv3 *v, struct Setv2 *vt, struct Setv3 *vn) +{ + int i; + Vertex out = {.position = {0, 0, 0}, .normal = {0, 0, 0}, .texCoords = {0, 0}}; + for (i = 0; i < 3; i++) { + if (f.v != -1) out.position[i] = v[f.v].data[i]; + if (f.vn != -1) out.normal[i] = vn[f.vn].data[i]; + if (f.vt != -1 && i < 2) out.texCoords[i] = vt[f.vt].data[i]; + } + return out; +} + +int +vertexInVertices(Vertex vertex, Vertex *vertices, int nVertices) +{ + return vertexGetIndex(vertices, vertex, nVertices) + 1; +} + +int +vertexGetIndex(Vertex *vertices, Vertex vertex, int nVertices) { + int i, j, n; + for (i = 0; i < nVertices; i++) { + n = 0; + for (j = 0; j < 3; j++) { + if (vertices[i].position[j] == vertex.position[j]) n++; + if (vertices[i].normal[j] == vertex.normal[j]) n++; + } + for (j = 0; j < 2; j++) { + if (vertices[i].texCoords[j] == vertex.texCoords[j]) n++; + } + + if (n == 8) return i; + } + return -1; +} + +void +vertexAdd(Mesh *mesh, Vertex vertex) +{ + Vertex *v; + int i; + unsigned int vSize; + + v = mesh->vertices; + vSize = mesh->vertexSize; + + if (!vSize) v = (Vertex *)calloc(1, sizeof(Vertex)); + else v = (Vertex *)realloc(v, (vSize + 1) * sizeof(Vertex)); + + if (v == NULL) { + fprintf(stderr, "vertexAdd() Error: %s\n", strerror(errno)); + exit(1); + } + + for (i = 0; i < 3; i++) { + v[vSize].position[i] = vertex.position[i]; + v[vSize].normal[i] = vertex.normal[i]; + if (i < 2) + v[vSize].texCoords[i] = vertex.texCoords[i]; + } + mesh->vertices = v; + mesh->vertexSize++; +} + +void +indexAdd(Mesh *mesh, int index) +{ + unsigned int *iv, iSize; + + iv = mesh->indices; + iSize = mesh->indexSize; + + if (!iSize) iv = (unsigned int *)calloc(1, sizeof(int)); + else iv = (unsigned int *)realloc(iv, (iSize + 1) * sizeof(int)); + + if (iv == NULL) { + fprintf(stderr, "vertexAdd() Error: %s\n", strerror(errno)); + exit(1); + } + + iv[iSize] = index; + mesh->indices = iv; + mesh->indexSize++; +} diff --git a/src/obj.h b/src/obj.h new file mode 100644 index 0000000..864910f --- /dev/null +++ b/src/obj.h @@ -0,0 +1,26 @@ +# ifndef __OBJ__ +#define __OBJ__ + +#define OBJ_LINE_MAX_SIZE 1024 + +typedef struct { + float position[3]; + float normal[3]; + float texCoords[2]; +} Vertex; + +typedef struct { + unsigned int id; + char type[50]; +} Texture; + +typedef struct { + Vertex *vertices; + Texture *textures; + unsigned int *indices; + unsigned int indexSize, vertexSize; + unsigned int VAO, EBO, VBO; +} Mesh; + +Mesh * objCreateMesh(const char *filename); +# endif diff --git a/src/shader.c b/src/shader.c index efc4844..2156490 100644 --- a/src/shader.c +++ b/src/shader.c @@ -7,8 +7,8 @@ static char *getShaderSource(const char *shaderPath); static void checkShaderCompile(unsigned int shader, const char *shaderPath); static void checkProgramLink(unsigned int shader); -char -*getShaderSource(const char *shaderPath) +char * +getShaderSource(const char *shaderPath) { long fileSize; char *shaderSource; |