diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | README.md | 14 | ||||
-rw-r--r-- | shaders/dummy.fsh | 12 | ||||
-rw-r--r-- | shaders/dummy.vsh | 2 | ||||
-rw-r--r-- | src/main.c | 40 | ||||
-rw-r--r-- | src/obj.c | 176 | ||||
-rw-r--r-- | src/obj.h | 17 |
8 files changed, 222 insertions, 42 deletions
@@ -1,4 +1,5 @@ objs/ +docs/ mverse tags models @@ -1,5 +1,5 @@ CC := cc -CFLAGS := -Wall -pedantic -pedantic-errors -std=c11 +CFLAGS := -Wall -pedantic -pedantic-errors -std=c99 DLIBS := -lm $(shell pkg-config --libs glfw3 opengl glew) INCLUDE := $(addprefix -I,./include) OBJDIR = objs @@ -2,3 +2,17 @@ The goal of this project is learning Opengl through a project, which consists in making a convincing world with mountains and lands, this will take a while 🥲. + +# Installation + +```shell +$ cd mverse +$ make +``` + +# Usage + +``` +$ ./mverse <FILE> +``` + diff --git a/shaders/dummy.fsh b/shaders/dummy.fsh index 7d94f22..472bb26 100644 --- a/shaders/dummy.fsh +++ b/shaders/dummy.fsh @@ -1,7 +1,17 @@ #version 330 core + +struct Material { + vec3 ambient; + vec3 diffuse; + vec3 specular; + int illum; + float Ns; +}; + +uniform Material mtl; out vec4 FragColor; void main() { - FragColor = vec4(0.0f); + FragColor = vec4(mtl.diffuse, 1.0); } diff --git a/shaders/dummy.vsh b/shaders/dummy.vsh index ab57a50..bd540ab 100644 --- a/shaders/dummy.vsh +++ b/shaders/dummy.vsh @@ -14,7 +14,7 @@ out vec2 TexCoords; void main() { gl_Position = proj * view * model * vec4(aPos, 1.0f); - //FragPos = vec3(model * vec4(aPos, 1.0)); + FragPos = vec3(model * vec4(aPos, 1.0)); //Normal = vec3(rotNormals * vec4(aNormal, 1.0)); //TexCoords = aTexCoords; } @@ -30,6 +30,8 @@ static Mat4 processCameraInput(GLFWwindow *window, struct Camera *cameraObj, flo static unsigned int loadTexture(char const *path); static void meshSetUp(Mesh *mesh); static void meshDraw(unsigned int shader, Mesh mesh); +static void objSetUp(Obj obj); +static void objDraw(unsigned int shader, Obj obj); static float cameraSpeed = 2.0; @@ -214,17 +216,38 @@ meshDraw(unsigned int shader, Mesh mesh) glBindVertexArray(0); } +void +objSetUp(Obj obj) +{ + int i; + for (i = 0; i < obj.size; i++) + meshSetUp(obj.mesh + i); +} + +void +objDraw(unsigned int shader, Obj obj) +{ + int i; + for (i = 0; i < obj.size; i++) { + shaderSetfv(shader, "mtl.ambient", obj.mesh[i].material.ka, glUniform3fv); + shaderSetfv(shader, "mtl.diffuse", obj.mesh[i].material.kd, glUniform3fv); + shaderSetfv(shader, "mtl.specular", obj.mesh[i].material.ks, glUniform3fv); + meshDraw(shader, obj.mesh[i]); + } +} + + int main(int argc, char *argv[]) { - Mesh *mesh; + Obj obj; GLFWwindow *window; const char *glfwErrno; - if (argc == 2) mesh = objCreateMesh(argv[1]); - else if (argc == 1) mesh = objCreateMesh("-"); + if (argc == 2) obj = objCreate(argv[1]); + else if (argc == 1) obj = objCreate("-"); else return 1; - if (mesh == NULL) { + if (obj.mesh == NULL) { glfwTerminate(); userError("objCreateMesh Error", "NULL mesh returned"); } @@ -254,7 +277,7 @@ int main(int argc, char *argv[]) unsigned int shader = shaderCreateProgram("shaders/dummy.vsh", "shaders/dummy.fsh"); - meshSetUp(mesh); + objSetUp(obj); struct Camera mainCamera; mainCamera.position = linearVec3(0.0, 0.0, 10.0); @@ -270,7 +293,7 @@ int main(int argc, char *argv[]) glEnable(GL_DEPTH_TEST); while (!glfwWindowShouldClose(window)) { processInput(window); - glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glClearColor(0.5f, 0.5f, 0.5f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glfwGetWindowSize(window, &width, &height); @@ -292,15 +315,12 @@ int main(int argc, char *argv[]) shaderSetMatrixfv(shader, "view", view.matrix[0], glUniformMatrix4fv); shaderSetMatrixfv(shader, "rotNormals", R.matrix[0], glUniformMatrix4fv); - meshDraw(shader, mesh[0]); + objDraw(shader, obj); glfwSwapBuffers(window); glfwPollEvents(); } glfwTerminate(); - free(mesh->vertices); - free(mesh->indices); - free(mesh); return 0; } @@ -5,14 +5,6 @@ #include "obj.h" -enum ObjVertexType { - OBJ_V, - OBJ_VN, - OBJ_VT, - OBJ_F, - OBJ_OTHER -}; - struct Setv3 { float data[3]; }; @@ -27,9 +19,13 @@ struct Seti { 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 readF(char *line, Mesh *mesh, int meshIndex, struct Setv3 *v, struct Setv2 *vt, struct Setv3 *vn); + +static Material * readMtl(char *line, const char *path, int *size); +static unsigned int useMtl(char *line, Material *mtl, unsigned int size); + +/* -------------------------------------------------------------------------- */ -// ---------------------------------------------------------------------------- struct Seti * readIndices(char *line, int *nIndices); static int readIndex(char *line, struct Seti *f); static Vertex createVertex(struct Seti f, struct Setv3 *v, struct Setv2 *vt, struct Setv3 *vn); @@ -38,10 +34,18 @@ 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) +/* -------------------------------------------------------------------------- */ +static void getDir(char *filepath); +static void appendMtl(char *line, Material **mtl, int index); +static void readColor(char *line, float *k); + + +Obj +objCreate(const char *filename) { + Obj o; Mesh *mesh; + Material *mtl; char lineBuffer[OBJ_LINE_MAX_SIZE]; FILE *fi; @@ -57,30 +61,48 @@ objCreateMesh(const char *filename) if (fi == NULL || mesh == NULL) { fprintf(stderr, "objCreateMesh() Error: %s\n", strerror(errno)); fclose(fi); - return NULL; + exit(1); } 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) { + if (v == NULL) { fprintf(stderr, "objCreateMesh() Error: %s\n", strerror(errno)); exit(1); } - */ + int n; + char key[500]; int vIndex, vtIndex, vnIndex; - vIndex = vtIndex = vnIndex = 0; + int mtlSize, mtlIndex, meshIndex; + vIndex = vtIndex = vnIndex = meshIndex = 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++); + + sscanf(lineBuffer, "%s%n", key, &n); + + if (!strcmp("f" , key)) readF (lineBuffer + n, mesh, meshIndex, v, vt, vn); + else if (!strcmp("vt", key)) readV2(lineBuffer + n, &vt, vtIndex++); + else if (!strcmp("vn", key)) readV3(lineBuffer + n, &vn, vnIndex++); + else if (!strcmp("v" , key)) readV3(lineBuffer + n, &v, vIndex++); + + else if (!strcmp("mtllib", key)) mtl = readMtl(lineBuffer + n, filename, &mtlSize); + else if (!strcmp("usemtl", key)) { + mtlIndex = useMtl (lineBuffer + n, mtl, mtlSize); + mesh = (Mesh *)realloc(mesh, (++meshIndex + 1) * sizeof(Mesh)); + memset(mesh + meshIndex, 0, sizeof(Mesh)); + mesh[meshIndex].material = mtl[mtlIndex]; + mesh[meshIndex].indexSize = 0; + } + } + + o.mesh = mesh; + o.size = meshIndex + 1; + for (int i = 1; i < o.size; i++) { + o.mesh[i].vertices = o.mesh[0].vertices; + o.mesh[i].vertexSize = o.mesh[0].vertexSize; } free(v); @@ -88,11 +110,11 @@ objCreateMesh(const char *filename) free(vn); fclose(fi); - return mesh; + return o; } void -readF(char *line, Mesh *mesh, struct Setv3 *v, struct Setv2 *vt, struct Setv3 *vn) +readF(char *line, Mesh *mesh, int meshIndex, struct Setv3 *v, struct Setv2 *vt, struct Setv3 *vn) { Vertex vertexBuffer; struct Seti *f; @@ -104,7 +126,7 @@ readF(char *line, Mesh *mesh, struct Setv3 *v, struct Setv2 *vt, struct Setv3 *v if (!vertexInVertices(vertexBuffer, mesh->vertices, mesh->vertexSize)) vertexAdd(mesh, vertexBuffer); vi = vertexGetIndex(mesh->vertices, vertexBuffer, mesh->vertexSize); - indexAdd(mesh, vi); + indexAdd(mesh + meshIndex, vi); } free(f); } @@ -305,3 +327,103 @@ indexAdd(Mesh *mesh, int index) mesh->indices = iv; mesh->indexSize++; } + +Material * +readMtl(char *line, const char *objFile, int *size) +{ + Material *out; + char buffer[OBJ_LINE_MAX_SIZE], mtlFilename[OBJ_LINE_MAX_SIZE], key[500]; + char path[512], fileName[512]; + FILE *fin; + int i, n; + + strncpy(path, objFile, 512); + getDir(path); + sscanf(line, " ./%s", fileName); + sprintf(mtlFilename, "%s/%s", path, fileName); + + fin = fopen(mtlFilename, "r"); + i = 0; + while(fgets(buffer, OBJ_LINE_MAX_SIZE, fin)) { + sscanf(buffer, "%s%n", key, &n); + if (!strcmp(key, "newmtl")) appendMtl(buffer + n, &out, i++); + if (i > 0) { + if (!strcmp(key, "Ka")) readColor(buffer + n, out[i - 1].ka); + else if (!strcmp(key, "Kd")) readColor(buffer + n, out[i - 1].kd); + else if (!strcmp(key, "Ks")) readColor(buffer + n, out[i - 1].ks); + else if (!strcmp(key, "illum")) sscanf(buffer + n, "%u", &out[i - 1].illum); + else if (!strcmp(key, "Ns")) sscanf(buffer + n, "%f", &out[i - 1].ns); + } + } + + if (size) *size = i; + fclose(fin); + return out; +} + +void +appendMtl(char *line, Material **mtl, int index) +{ + char name[OBJ_LINE_MAX_SIZE]; + + if (index == 0) + *mtl = (Material *)calloc(1, sizeof(Material)); + else + *mtl = (Material *)realloc(*mtl, (index + 1) * sizeof(Material)); + + sscanf(line, "%s", name); + strncpy((*mtl + index)->name, name, OBJ_LINE_MAX_SIZE); + + if (mtl == NULL) { + fprintf(stderr, "appendMtl() Error: %s\n", strerror(errno)); + exit(1); + } +} + +void +readColor(char *line, float *k) +{ + int ret; + ret = sscanf(line, "%f %f %f", k, k + 1, k + 2); + switch (ret) { + case 1: + k[1] = k[2] = k[0]; + break; + case 3: + break; + default: + fprintf(stderr, "readColor() Error: line '%s' invalid format", line - 2); + exit(1); + break; + } +} + +unsigned int +useMtl(char *line, Material *mtl, unsigned int size) +{ + int i; + char name[OBJ_LINE_MAX_SIZE]; + for (i = 0; i < size; i++) { + sscanf(line, "%s", name); + if (!strcmp(name, mtl[i].name)) + return i; + } + return 0; +} + +void +getDir(char *filepath) +{ + int i; + for (i = strlen(filepath) - 1; i >= 0; i--) { + switch (filepath[i]) { + case '/': + case '\\': + filepath[i] = '\0'; + return; + default: + break; + } + } + strcpy(filepath, "."); +} @@ -2,6 +2,7 @@ #define __OBJ__ #define OBJ_LINE_MAX_SIZE 1024 +#define OBJ_MAX_NAME 512 typedef struct { float position[3]; @@ -15,12 +16,24 @@ typedef struct { } Texture; typedef struct { + char name[OBJ_LINE_MAX_SIZE]; + float ka[3], kd[3], ks[3]; + unsigned int illum; + float ns; +} Material; + +typedef struct { Vertex *vertices; - Texture *textures; + Material material; unsigned int *indices; unsigned int indexSize, vertexSize; unsigned int VAO, EBO, VBO; } Mesh; -Mesh * objCreateMesh(const char *filename); +typedef struct { + Mesh *mesh; + unsigned int size; +} Obj; + +Obj objCreate(const char *filename); # endif |