summaryrefslogtreecommitdiff
path: root/src/objload.c
diff options
context:
space:
mode:
authorkartofen <mladenovnasko0@gmail.com>2023-11-11 19:00:10 +0200
committerkartofen <mladenovnasko0@gmail.com>2023-11-11 19:00:10 +0200
commit1e436946514f3a0e9fe3d091394db6b86e06f033 (patch)
treecddf3bb618ade66fd5bd4eacd028a7d54a760e37 /src/objload.c
parent2a733f3d513a7279c1df4efe88fc5386ced2ed14 (diff)
.obj loading
Diffstat (limited to 'src/objload.c')
-rw-r--r--src/objload.c219
1 files changed, 219 insertions, 0 deletions
diff --git a/src/objload.c b/src/objload.c
new file mode 100644
index 0000000..7cc12ab
--- /dev/null
+++ b/src/objload.c
@@ -0,0 +1,219 @@
+#include <stdio.h>
+#include <stdlib.h>
+#define _BSD_SOURCE
+#include <string.h>
+
+#include "objload.h"
+
+// TODO: !! vert_idx, norm_idx and uv_idx currently
+// must be present for all faces
+// TODO: face vertices is hard-coded to 3
+
+
+#define OBJ_CHECK(x) do { \
+ OBJRES res = x; \
+ if(res != OBJ_SUCCESS) return res; \
+ } while(0)
+
+static OBJRES data_allocate(FILE *fp, objload_t *obj);
+static OBJRES data_load(FILE *fp, objload_t *obj);
+
+static OBJRES data_load_vert(char *line, float vertex[3]);
+static OBJRES data_load_norm(char *line, float normal[3]);
+static OBJRES data_load_uv(char *line, float uvcoord[2]);
+
+static OBJRES data_load_face(char *line, struct face face[3]);
+static OBJRES data_load_face_entry(char *entry, struct face *face);
+
+OBJRES obj_load(FILE *fp, objload_t *obj)
+{
+ fseek(fp, 0, SEEK_SET);
+ OBJ_CHECK(data_allocate(fp, obj));
+
+ fseek(fp, 0, SEEK_SET);
+ OBJ_CHECK(data_load(fp, obj));
+
+ return OBJ_SUCCESS;
+}
+
+void obj_free(objload_t obj)
+{
+ if(obj.nvert) free(obj.vertices);
+ if(obj.nnorm) free(obj.normals);
+ if(obj.nuv) free(obj.uvcoord);
+ if(obj.nfaces) free(obj.faces);
+}
+
+OBJRES obj_transfer_raw(objload_t obj, struct obj_struct_metadata metadata, size_t *nvbo, void *vbo)
+{
+ if(vbo == NULL) {
+ *nvbo = obj.nfaces * 3;
+ return OBJ_SUCCESS;
+ }
+
+ for(size_t i = 0; i < *nvbo; i++)
+ {
+ if(metadata.exist_flag & OBJ_STRUCT_VERT_EXISTS) {
+ memcpy(vbo + metadata.vert_off,
+ obj.vertices[obj.faces[i/3][i%3].vertidx -1],
+ sizeof(*obj.vertices));
+ }
+ if(metadata.exist_flag & OBJ_STRUCT_NORM_EXISTS) {
+ memcpy(vbo + metadata.norm_off,
+ obj.normals[obj.faces[i/3][i%3].normidx -1],
+ sizeof(*obj.normals));
+ }
+ if(metadata.exist_flag & OBJ_STRUCT_UVTX_EXISTS) {
+ memcpy(vbo + metadata.uvtx_off,
+ obj.uvcoord[obj.faces[i/3][i%3].uvidx -1],
+ sizeof(*obj.uvcoord));
+ }
+
+ vbo += metadata.full_sz;
+ }
+
+ return OBJ_SUCCESS;
+}
+
+static OBJRES data_allocate(FILE *fp, objload_t *obj)
+{
+ char line[256] = {0};
+ while(fgets(line, sizeof(line), fp))
+ {
+ // printf("%s\n", line);
+ switch(line[0]) {
+ case 'o':
+ break;
+ case 'v':
+ switch(line[1]) {
+ case ' ':
+ obj->nvert++;
+ break;
+ case 'n':
+ obj->nnorm++;
+ break;
+ case 't':
+ obj->nuv++;
+ break;
+ default:
+ return OBJ_LINE_UNKNOWN;
+ }
+ break;
+ case 'f':
+ obj->nfaces++;
+ break;
+ case 'l': case 'm':
+ case 's': case 'u':
+ break; // temporary
+ return OBJ_NOT_SUPPORTED_LINE;
+ case '#': case EOF:
+ break;
+ default:
+ return OBJ_LINE_UNKNOWN;
+ }
+ }
+
+ obj->vertices = calloc(obj->nvert, sizeof(*obj->vertices));
+ obj->normals = calloc(obj->nnorm, sizeof(*obj->normals));
+ obj->uvcoord = calloc(obj->nuv, sizeof(*obj->uvcoord));
+ obj->faces = calloc(obj->nfaces, sizeof(*obj->faces));
+
+ return OBJ_SUCCESS;
+}
+
+static OBJRES data_load(FILE *fp, objload_t *obj)
+{
+ size_t vert_idx = 0;
+ size_t norm_idx = 0;
+ size_t uv_idx = 0;
+ size_t face_idx = 0;
+
+ char line[256] = {0};
+ while(fgets(line, sizeof(line), fp))
+ {
+ switch(line[0]) {
+ case 'v':
+ switch(line[1]) {
+ case ' ':
+ data_load_vert(line, obj->vertices[vert_idx++]);
+ break;
+ case 'n':
+ data_load_norm(line, obj->normals[norm_idx++]);
+ break;
+ case 't':
+ data_load_uv(line, obj->uvcoord[uv_idx++]);
+ break;
+ default:
+ break;
+ }
+ break;
+ case 'f':
+ data_load_face(line, obj->faces[face_idx++]);
+ break;
+ case '#':
+ break;
+ default:
+ break;
+ }
+ }
+
+ return OBJ_SUCCESS;
+}
+
+static OBJRES data_load_vert(char *line, float vertex[3])
+{
+ char *saveptr;
+ strtok_r(line, " ", &saveptr);
+
+ vertex[0] = strtof(strtok_r(NULL, " ", &saveptr), NULL);
+ vertex[1] = strtof(strtok_r(NULL, " ", &saveptr), NULL);
+ vertex[2] = strtof(strtok_r(NULL, " ", &saveptr), NULL);
+
+ return OBJ_SUCCESS;
+}
+
+static OBJRES data_load_norm(char *line, float normal[3])
+{
+ char *saveptr;
+ strtok_r(line, " ", &saveptr);
+
+ normal[0] = strtof(strtok_r(NULL, " ", &saveptr), NULL);
+ normal[1] = strtof(strtok_r(NULL, " ", &saveptr), NULL);
+ normal[2] = strtof(strtok_r(NULL, " ", &saveptr), NULL);
+
+ return OBJ_SUCCESS;
+}
+
+static OBJRES data_load_uv(char *line, float uvcoord[2])
+{
+ char *saveptr;
+ strtok_r(line, " ", &saveptr);
+
+ uvcoord[0] = strtof(strtok_r(NULL, " ", &saveptr), NULL);
+ uvcoord[1] = strtof(strtok_r(NULL, " ", &saveptr), NULL);
+
+ return OBJ_SUCCESS;
+}
+
+static OBJRES data_load_face(char *line, struct face face[3])
+{
+ char *saveptr;
+ strtok_r(line, " ", &saveptr);
+
+ data_load_face_entry(strtok_r(NULL, " ", &saveptr), &face[0]);
+ data_load_face_entry(strtok_r(NULL, " ", &saveptr), &face[1]);
+ data_load_face_entry(strtok_r(NULL, " ", &saveptr), &face[2]);
+
+ return OBJ_SUCCESS;
+}
+
+static OBJRES data_load_face_entry(char *entry, struct face *face)
+{
+ char *saveptr;
+
+ face->vertidx = strtoull(strtok_r(entry, "/", &saveptr), NULL, 10);
+ face->uvidx = strtoull(strtok_r(NULL, "/", &saveptr), NULL, 10);
+ face->normidx = strtoull(strtok_r(NULL, "/", &saveptr), NULL, 10);
+
+ return OBJ_SUCCESS;
+}