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 | |
parent | 2a733f3d513a7279c1df4efe88fc5386ced2ed14 (diff) |
.obj loading
Diffstat (limited to 'src')
-rw-r--r-- | src/graphics.c | 28 | ||||
-rw-r--r-- | src/graphics.h | 3 | ||||
-rw-r--r-- | src/main.c | 73 | ||||
-rw-r--r-- | src/objload.c | 219 | ||||
-rw-r--r-- | src/objload.h | 60 |
5 files changed, 359 insertions, 24 deletions
diff --git a/src/graphics.c b/src/graphics.c index e722abf..d603f68 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -643,7 +643,7 @@ static int create_pipeline(graphics_t graphics, struct graphics_info *info) // set up graphics pipeline stages VkVertexInputBindingDescription binding_description = {0}; - VkVertexInputAttributeDescription attribute_description[2] = {0}; + VkVertexInputAttributeDescription attribute_description[3] = {0}; vertex_populate_descriptions(&binding_description, attribute_description); VkPipelineVertexInputStateCreateInfo vertex_input = {0}; @@ -669,8 +669,13 @@ static int create_pipeline(graphics_t graphics, struct graphics_info *info) rasterizer.rasterizerDiscardEnable = VK_FALSE; rasterizer.polygonMode = VK_POLYGON_MODE_FILL; rasterizer.lineWidth = 1.0f; - rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; - rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + + // it is actually counter clocwise because + // the y axis was reversed + // but cull mode is NONE so both sides are shown + rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; + rasterizer.cullMode = VK_CULL_MODE_NONE; + rasterizer.depthBiasEnable = VK_FALSE; rasterizer.depthBiasConstantFactor = 0.0f; // Optional @@ -1275,9 +1280,13 @@ static int command_buffer_record(graphics_t graphics, u32 image_index) vkCmdBindDescriptorSets(CMND.buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, PPLN.layout, 0, 1, &UBOD.set, 0, NULL); - // 3 is the number of vertices + // 6 is the number of vertices // TODO: fix this - vkCmdDrawIndexed(CMND.buffer, 6, 1, 0, 0, 0); +// #ifndef MONKEY + // vkCmdDrawIndexed(CMND.buffer, 6, 1, 0, 0, 0); +// #else + vkCmdDraw(CMND.buffer, 8723, 1, 0, 0); // draw monkey +// #endif // Cleaning up vkCmdEndRenderPass(CMND.buffer); @@ -1317,13 +1326,18 @@ static int vertex_populate_descriptions(VkVertexInputBindingDescription *binding attribute_desc[0].binding = 0; attribute_desc[0].location = 0; - attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT; + attribute_desc[0].format = VK_FORMAT_R32G32B32_SFLOAT; attribute_desc[0].offset = offsetof(struct vertex, pos); attribute_desc[1].binding = 0; attribute_desc[1].location = 1; attribute_desc[1].format = VK_FORMAT_R32G32B32_SFLOAT; - attribute_desc[1].offset = offsetof(struct vertex, color); + attribute_desc[1].offset = offsetof(struct vertex, normal); + + attribute_desc[2].binding = 0; + attribute_desc[2].location = 2; + attribute_desc[2].format = VK_FORMAT_R32G32B32_SFLOAT; + attribute_desc[2].offset = offsetof(struct vertex, color); return 0; } diff --git a/src/graphics.h b/src/graphics.h index ff03e12..bac8300 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -15,7 +15,8 @@ typedef uint32_t u32; typedef struct vertex { - vec2 pos; + vec3 pos; + vec3 normal; vec3 color; } vertex_t; @@ -4,12 +4,15 @@ #include <cglm/cglm.h> #include <cglm/struct.h> +#include "objload.h" + +#define MONKEY #include "graphics.h" #include "window.h" #include "common.h" -#define SW 640 -#define SH 480 +u32 width = 640; +u32 height = 480; window_t window; graphics_t graphics; @@ -21,19 +24,24 @@ struct ubo { mat4 model; mat4 view; mat4 proj; -}; +}; + +#ifndef MONKEY vertex_t vertices[] = { - {{-0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}}, - {{0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}}, - {{0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}}, - {{-0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}} + {{-0.5f, -0.5f, 0.0f}, {0.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}}, + {{ 0.5f, -0.5f, -0.5f}, {0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}}, + {{ 0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}}, + {{-0.5f, 0.5f, -0.5f}, {0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}}, }; +#endif + u32 indices[] = { 0, 1, 2, 2, 3, 0 }; + int main(void) { int ret = 1; @@ -46,9 +54,9 @@ int main(void) // populate window info struct window_info win_info = {0}; win_info.title = "Test App"; - // win_info.flags = SDL_WINDOW_RESIZABLE; - win_info.w = SW; - win_info.h = SH; + win_info.flags = SDL_WINDOW_RESIZABLE; + win_info.w = width; + win_info.h = height; // create window window = window_create(&win_info); @@ -56,6 +64,33 @@ int main(void) err("window_create: failed"); goto f2; } + +#ifdef MONKEY + vertex_t *objvertices; + size_t nvertices = 0; + + // Load obj + FILE *fp = fopen("../files/monkey.obj", "r"); + + objload_t obj = {0}; + obj_load(fp, &obj); + + struct obj_struct_metadata obj_metadata = { + sizeof(vertex_t), + offsetof(vertex_t, pos), + offsetof(vertex_t, color), 0, + OBJ_STRUCT_VERT_EXISTS | + OBJ_STRUCT_NORM_EXISTS + }; + + obj_transfer_raw(obj, obj_metadata, &nvertices, NULL); + // leaks memory + objvertices = xcalloc(nvertices, sizeof(*objvertices)); + obj_transfer_raw(obj, obj_metadata, &nvertices, objvertices); + + obj_free(obj); + fclose(fp); +#endif // get extensions unsigned int ext_count = 0; @@ -71,11 +106,17 @@ int main(void) grph_info.ext_count = ext_count; grph_info.extensions = (const char * const *)extensions; - + +#ifndef MONKEY grph_info.vertices = vertices; grph_info.nvertices = ARR_SIZE(vertices); +#else + grph_info.vertices = objvertices; + grph_info.nvertices = nvertices; +#endif + grph_info.indices = indices; - grph_info.nindices = ARR_SIZE(indices); + grph_info.nindices = ARR_SIZE(indices); grph_info.ubo_size = sizeof(struct ubo); grph_info.update_ubo = update_ubo; @@ -120,12 +161,12 @@ int update_ubo(void *uniform_buffer) time += 0.01f; memcpy(ubo->model, glms_mat4_identity().raw, sizeof(ubo->model)); - glm_rotate(&ubo->model, time * glm_rad(90.0f), + glm_rotate(ubo->model, time * glm_rad(90.0f), (vec3){0.0f, 0.0f, 1.0f}); - glm_lookat((vec3){1.0f, 1.0f, 2.0f}, (vec3){0.0f, 0.0f, 0.0f}, (vec3){0.0f, 0.0f, 1.0f}, ubo->view); - - glm_perspective(glm_rad(45.0f), (float)SW/(float)SH, 0.1f, 10.0f, ubo->proj); + glm_lookat((vec3){2.0f, 2.0f, 2.0f}, (vec3){0.0f, 0.0f, 0.0f}, (vec3){0.0f, 0.0f, 1.0f}, ubo->view); + + glm_perspective(glm_rad(45.0f), (float)width/(float)height, 0.1f, 10.0f, ubo->proj); ubo->proj[1][1] *= -1; return 0; 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; +} diff --git a/src/objload.h b/src/objload.h new file mode 100644 index 0000000..8993f25 --- /dev/null +++ b/src/objload.h @@ -0,0 +1,60 @@ +#ifndef OBJLOAD_H +#define OBJLOAD_H + +#include <stdint.h> + +typedef enum OBJ_RESULT { + OBJ_SUCCESS = 0, + OBJ_LINE_UNKNOWN, + OBJ_NOT_SUPPORTED_LINE, + OBJ_NOT_SUPPORTED_UNKNOWN, + OBJ_ERROR_UNKNOWN, +} OBJRES; + +typedef struct objload { + size_t nvert; + float (*vertices)[3]; + + size_t nnorm; + float (*normals)[3]; + + size_t nuv; + float (*uvcoord)[2]; + + size_t nfaces; + struct face { + size_t vertidx; + size_t normidx; + size_t uvidx; + } (*faces)[3]; +} objload_t; + + +struct obj_struct_metadata { + size_t full_sz; + + size_t vert_off; + size_t norm_off; + size_t uvtx_off; + + enum { + OBJ_STRUCT_VERT_EXISTS = 1 << 0, + OBJ_STRUCT_NORM_EXISTS = 1 << 1, + OBJ_STRUCT_UVTX_EXISTS = 1 << 2, + OBJ_STRUCT_ALL_EXIST = 7, + } exist_flag; +}; + +typedef uint32_t obj_idx; + +OBJRES obj_load(FILE *fp, objload_t *obj); +void obj_free(objload_t obj); + +OBJRES obj_transfer_raw(objload_t obj, + struct obj_struct_metadata metadata, + size_t *nvbo, void *vbo); + +// OBJRES obj_transfer_indxed(objload_t obj, + // size_t *nvbo, obj_vbo vbo, + // size_t *nidx, obj_idx ibo); +#endif |