diff options
| author | day <day@national.shitposting.agency> | 2026-03-17 00:20:45 +0100 |
|---|---|---|
| committer | day <day@national.shitposting.agency> | 2026-03-17 00:20:45 +0100 |
| commit | 7cc07134a9759ed196b0fe5ea26c18d76e232952 (patch) | |
| tree | 0468db0f07cfc27769075a902d9c752fb7b779e0 /src/render/model.h | |
| parent | 7f85c9fc75bd62ac09ea4457d3b17f85988fca66 (diff) | |
set MODEL formatting for rendering
Diffstat (limited to 'src/render/model.h')
| -rw-r--r-- | src/render/model.h | 160 |
1 files changed, 119 insertions, 41 deletions
diff --git a/src/render/model.h b/src/render/model.h index 63b053c..83a85bb 100644 --- a/src/render/model.h +++ b/src/render/model.h @@ -5,8 +5,15 @@ #include <assert.h> -struct MODEL { +struct MODEL_DATA { + VEC3 position; + VEC2 uv; + VEC3 normal; +}; +struct MODEL { + LIST<MODEL_DATA> vertices; + LIST<U32> indices; }; static inline char* skip_space( char* s ) { @@ -176,18 +183,13 @@ namespace OBJ { VVTVN = 3 }; - static inline U32 face_stride( FACE_TYPES t ) { - switch( t ) { - case FACE_TYPES::V: return 1; - case FACE_TYPES::VVT: return 2; - case FACE_TYPES::VVN: return 2; - case FACE_TYPES::VVTVN: return 3; - } - return 0; - } - constexpr U32 STR_LEN = 0x40; + struct OBJFACE { + OBJ::FACE_TYPES type; + LIST<U32> indices; + }; + struct OBJDATA { LIST<VEC2> uvs; LIST<VEC3> normals; @@ -196,17 +198,23 @@ namespace OBJ { LIST<MTL::MTLLIB> mtllib; struct UseMtl { - LIST<U32> indices; - LIST<STR> data; + LIST<U32> face_start; + LIST<STR> mtl_name; } usemtl; - struct Indices { - LIST<U32> data; - LIST<U32> counts; - LIST<FACE_TYPES> types; - } indices; + LIST<OBJFACE> faces; }; + static inline U32 face_stride( FACE_TYPES t ) { + switch( t ) { + case FACE_TYPES::V: return 1; + case FACE_TYPES::VVT: return 2; + case FACE_TYPES::VVN: return 2; + case FACE_TYPES::VVTVN: return 3; + } + return 0; + } + inline OBJDATA obj_from_file( const char* path, const char* name ) { char* f_obj = nullptr; STR obj_path( path ); @@ -233,55 +241,66 @@ namespace OBJ { switch( first_two ) { case LINE_TYPES::f: { - FACE_TYPES type = FACE_TYPES::V; + FACE_TYPES type = (FACE_TYPES)0; char* s = f_obj + i + 2; bool type_set = 0; - U32 count = 0; + OBJFACE temp{}; s = skip_space( s ); - while( *s && *s != '\n' ) { - bool has_vt = 0, has_vn = 0; + bool has_vt = 0; + bool has_vn = 0; + U32 v = strtoul( s, &s, 10 ); - obj.indices.data.push( --v ); + temp.indices.push( --v ); if( *s == '/' ) { ++s; if( *s != '/' ) { U32 vt = strtoul( s, &s, 10 ); - obj.indices.data.push( --vt ); + temp.indices.push( --vt ); has_vt = 1; } if( *s == '/' ) { ++s; U32 vn = strtoul( s, &s, 10 ); - obj.indices.data.push( --vn ); + temp.indices.push( --vn ); has_vn = 1; } } if( !type_set ) { - if( has_vt && has_vn ) - type = FACE_TYPES::VVTVN; - else if( has_vt ) - type = FACE_TYPES::VVT; - else if( has_vn ) - type = FACE_TYPES::VVN; - else - type = FACE_TYPES::V; type_set = 1; + if( has_vt && has_vn ) type = FACE_TYPES::VVTVN; + else if( has_vt ) type = FACE_TYPES::VVT; + else if( has_vn ) type = FACE_TYPES::VVN; + else type = FACE_TYPES::V; } - ++count; - - while( *s && *s != ' ' && *s != '\n' ) - ++s; + while( *s && *s != ' ' && *s != '\n' ) ++s; s = skip_space( s ); } - obj.indices.counts.push( count ); - obj.indices.types.push( type ); + temp.type = type; + U32 stride = face_stride( type ); + U32 count = temp.indices.size / stride; + if ( count <= 3 ) + obj.faces.push( temp ); + else { + for( U32 idx = 1; idx < count - 1; ++idx ) { + OBJFACE tri{}; + tri.type = type; + + for( U32 ind = 0; ind < stride; ++ind ) + tri.indices.push( temp.indices.data[ind] ); + for( U32 ind = 0; ind < stride; ++ind ) + tri.indices.push( temp.indices.data[idx * stride + ind] ); + for( U32 ind = 0; ind < stride; ++ind ) + tri.indices.push( temp.indices.data[( idx + 1 ) * stride + ind] ); + obj.faces.push( tri ); + } + } } break; case LINE_TYPES::v: case LINE_TYPES::vn: { @@ -314,8 +333,9 @@ namespace OBJ { memcpy( temp, start, len ); temp.data[len] = 0; if( !is_mtllib ) { - obj.usemtl.data.push( temp ); - obj.usemtl.indices.push( obj.indices.data.size ); + if( obj.usemtl.mtl_name.size ) + obj.usemtl.face_start.push( obj.faces.size ); + obj.usemtl.mtl_name.push( temp.data ); } else obj.mtllib.push( MTL::mtl_from_file( path, temp.data ) ); } break; @@ -327,13 +347,71 @@ namespace OBJ { while( f_obj[i] && f_obj[i] != '\n' ) ++i; } + obj.usemtl.face_start.push( obj.faces.size ); + if ( !obj.usemtl.mtl_name.size ) + obj.usemtl.mtl_name.push( "default" ); free( (void*)f_obj ); return obj; } inline MODEL obj_to_model( OBJDATA obj ) { + struct KEY { U32 v, vt, vn; }; + struct ENTRY { KEY key; U32 idx; }; + MODEL model; + LIST<ENTRY> table; + table.reserve( obj.faces.size * 3 ); + for( U32 f = 0; f < obj.faces.size; ++f ) { + OBJFACE& face = obj.faces.data[f]; + U32 stride = face_stride( face.type ); + U32 count = face.indices.size / stride; + + for( U32 v = 0; v < count; ++v ) { + KEY key = { + 0xFFFFFFFF, + 0xFFFFFFFF, + 0xFFFFFFFF + }; + U32 base = v * stride; + key.v = face.indices.data[base + 0]; + if( face.type == FACE_TYPES::VVT || face.type == FACE_TYPES::VVTVN ) + key.vt = face.indices.data[base + 1]; + if( face.type == FACE_TYPES::VVN ) + key.vn = face.indices.data[base + 1]; + if( face.type == FACE_TYPES::VVTVN ) + key.vn = face.indices.data[base + 2]; + + U32 idx = 0; + bool found = 0; + // this should be fine until ~1m triangles, right? + for( U32 i = 0; i < table.size; ++i ) { + ENTRY& e = table.data[i]; + if( e.key.vn != key.vn + || e.key.vt != key.vt + || e.key.v != key.v + ) continue; + + idx = e.idx; + found = 1; + break; + } + if( !found ) { + MODEL_DATA data{}; + data.position = obj.vertices.data[key.v]; + if( face.type == FACE_TYPES::VVTVN + || face.type == FACE_TYPES::VVT ) + data.uv = obj.uvs.data[key.vt]; + if( face.type == FACE_TYPES::VVTVN + || face.type == FACE_TYPES::VVN ) + data.normal = obj.normals.data[key.vn]; + idx = model.vertices.size; + model.vertices.push( data ); + table.push({ key, idx }); + } + model.indices.push( idx ); + } + } return model; } }; |
