This commit is contained in:
alessandro bason 2026-03-05 16:45:29 +01:00
parent 507d635433
commit 1c13514a4d
45 changed files with 2615 additions and 2014 deletions

234
src/obj.c
View file

@ -5,7 +5,7 @@
#define CGLTF_IMPLEMENTATION
#include "libs/cgltf.h"
#include "vecmath.h"
#include "libs/handmademath.h"
typedef struct vertex_t vertex_t;
struct vertex_t {
@ -15,236 +15,12 @@ struct vertex_t {
vec2 lightmap;
};
typedef struct material_t material_t;
struct material_t {
// texture
vec3 ambient_color;
vec3 diff_color;
/*
* (*) -> unused
* Ka: ambient color
* Kd: diffuse color
* Ks*: specular color
* Ns*: specular exponent
* d*: dissolve (opacity)
* Ni*: optical density (???)
* Ke*: emissive color
* illum*: illumination mode:
0. Color on and Ambient off
1. Color on and Ambient on
2. Highlight on
3. Reflection on and Ray trace on
4. Transparency: Glass on, Reflection: Ray trace on
5. Reflection: Fresnel on and Ray trace on
6. Transparency: Refraction on, Reflection: Fresnel off and Ray trace on
7. Transparency: Refraction on, Reflection: Fresnel on and Ray trace on
8. Reflection on and Ray trace off
9. Transparency: Glass on, Reflection: Ray trace off
10. Casts shadows onto invisible surfaces
* */
};
typedef struct obj_t obj_t;
struct obj_t {
sg_bindings bindings;
u16 draw_count;
};
darr_define(f2_list_t, vec2);
darr_define(f3_list_t, vec3);
darr_define(i3_list_t, int3);
#define list_get(l, i) do { } while (0)
typedef struct {
f3_list_t *verts;
f3_list_t *norms;
f2_list_t *uvs;
i3_list_t *faces;
u32 vcount;
u32 ncount;
u32 tcount;
u32 fcount;
} obj_ctx_t;
#define READ_F2(arr, c) do { \
vec2 v = {0}; \
istr_skip_whitespace(in); istr_get_float(in, &v.x); \
istr_skip_whitespace(in); istr_get_float(in, &v.y); \
darr_push(arena, arr, v); \
++(c); \
} while (0)
#define READ_F3(arr, c) do { \
vec3 v = {0}; \
istr_skip_whitespace(in); istr_get_float(in, &v.x); \
istr_skip_whitespace(in); istr_get_float(in, &v.y); \
istr_skip_whitespace(in); istr_get_float(in, &v.z); \
darr_push(arena, arr, v); \
++(c); \
} while (0)
#define READ_I3(arr, c) do { \
int3 v = {0}; \
istr_skip_whitespace(in); istr_get_i32(in, &v.x); \
istr_skip_whitespace(in); istr_get_i32(in, &v.y); \
istr_skip_whitespace(in); istr_get_i32(in, &v.z); \
darr_push(arena, arr, v); \
++(c); \
} while (0)
void obj__parse_line(arena_t *arena, instream_t *in, obj_ctx_t *ctx) {
if (istr_peek(in) == '#') {
return;
}
switch (istr_peek(in)) {
// vertex stuff
case 'v':
istr_skip(in, 1);
switch (istr_get(in)) {
// vertex
case ' ':
READ_F3(ctx->verts, ctx->vcount);
break;
// normal
case 'n':
READ_F3(ctx->norms, ctx->ncount);
break;
// texture
case 't':
READ_F2(ctx->uvs, ctx->tcount);
break;
}
return;
// faces
case 'f':
READ_I3(ctx->faces, ctx->fcount);
return;
// smooth shading
case 's':
// not implemented
return;
// group
case 'g':
// not implemented
return;
// object
case 'o':
// not implemented
return;
case '#':
return;
}
strview_t word = istr_get_word(in);
if (strv_equals(word, strv("mtllib"))) {
// load mtl file
}
else if (strv_equals(word, strv("usemtl"))) {
// use material
}
}
obj_t obj_load(arena_t scratch, strview_t filename) {
obj_t out = {0};
str_t text = os_file_read_all_str(&scratch, filename);
instream_t in = istr_init(strv(text));
obj_ctx_t ctx = {0};
while (!istr_is_finished(&in)) {
instream_t line = istr_init(istr_get_line(&in));
obj__parse_line(&scratch, &line, &ctx);
}
debug("%u %u %u", ctx.vcount, ctx.ncount, ctx.tcount);
colla_assert(ctx.vcount == ctx.ncount && ctx.vcount == ctx.tcount);
// copy over vertex data
vertex_t *vertices = alloc(&scratch, vertex_t, ctx.vcount);
{
u32 i = 0;
for_each (v, ctx.verts) {
for (int k = 0; k < v->count; ++k) {
vertices[i++].pos = v->items[k];
}
}
}
{
u32 i = 0;
for_each (v, ctx.uvs) {
for (int k = 0; k < v->count; ++k) {
vertices[i++].tex = v->items[k];
}
}
}
{
u32 i = 0;
for_each (v, ctx.norms) {
for (int k = 0; k < v->count; ++k) {
vertices[i++].norm = v->items[k];
}
}
}
// copy over indices data
u32 icount = ctx.fcount * 3;
u16 *indices = alloc(&scratch, u16, icount);
{
u32 i = 0;
for_each (v, ctx.faces) {
for (int k = 0; k < v->count; ++k) {
indices[i++] = v->items[k].x - 1;
indices[i++] = v->items[k].y - 1;
indices[i++] = v->items[k].z - 1;
}
}
}
sg_buffer vertex_buffer = sg_make_buffer(&(sg_buffer_desc){
.data = {
.ptr = vertices,
.size = sizeof(vertex_t) * ctx.vcount,
},
.usage = {
.vertex_buffer = true,
.immutable = true,
},
});
sg_buffer index_buffer = sg_make_buffer(&(sg_buffer_desc){
.data = {
.ptr = indices,
.size = sizeof(u16) * ctx.fcount * 3,
},
.usage = {
.index_buffer = true,
.immutable = true,
},
});
return (obj_t){
.bindings = {
.vertex_buffers[0] = vertex_buffer,
.index_buffer = index_buffer,
// .views[0] = {0},
},
.draw_count = icount,
};
}
cgltf_result obj__cgltf_file_read_cb(
const cgltf_memory_options *m,
const cgltf_file_options *opt,
@ -466,25 +242,25 @@ scene_t obj_load_gltf(arena_t scratch, strview_t filename) {
case cgltf_attribute_type_position:
{
for (usize k = 0; k < acc->count; ++k) {
cgltf_accessor_read_float(acc, k, verts[k].pos.data, 3);
cgltf_accessor_read_float(acc, k, verts[k].pos.elements, 3);
}
break;
}
case cgltf_attribute_type_normal:
for (usize k = 0; k < acc->count; ++k) {
cgltf_accessor_read_float(acc, k, verts[k].norm.data, 3);
cgltf_accessor_read_float(acc, k, verts[k].norm.elements, 3);
}
break;
case cgltf_attribute_type_texcoord:
{
if (attr->index == 0) {
for (usize k = 0; k < acc->count; ++k) {
cgltf_accessor_read_float(acc, k, verts[k].tex.data, 2);
cgltf_accessor_read_float(acc, k, verts[k].tex.elements, 2);
}
}
else {
for (usize k = 0; k < acc->count; ++k) {
cgltf_accessor_read_float(acc, k, verts[k].lightmap.data, 2);
cgltf_accessor_read_float(acc, k, verts[k].lightmap.elements, 2);
}
}
break;