summaryrefslogtreecommitdiff
path: root/src
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
parent2a733f3d513a7279c1df4efe88fc5386ced2ed14 (diff)
.obj loading
Diffstat (limited to 'src')
-rw-r--r--src/graphics.c28
-rw-r--r--src/graphics.h3
-rw-r--r--src/main.c73
-rw-r--r--src/objload.c219
-rw-r--r--src/objload.h60
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;
diff --git a/src/main.c b/src/main.c
index c4bf2c3..edaf8a3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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