diff options
author | kartofen <mladenovnasko0@gmail.com> | 2023-11-11 19:00:10 +0200 |
---|---|---|
committer | kartofen <mladenovnasko0@gmail.com> | 2023-11-11 19:00:10 +0200 |
commit | 1e436946514f3a0e9fe3d091394db6b86e06f033 (patch) | |
tree | cddf3bb618ade66fd5bd4eacd028a7d54a760e37 /src/objload.c | |
parent | 2a733f3d513a7279c1df4efe88fc5386ced2ed14 (diff) |
.obj loading
Diffstat (limited to 'src/objload.c')
-rw-r--r-- | src/objload.c | 219 |
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; +} |