summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorday <day@national.shitposting.agency>2026-03-17 00:20:45 +0100
committerday <day@national.shitposting.agency>2026-03-17 00:20:45 +0100
commit7cc07134a9759ed196b0fe5ea26c18d76e232952 (patch)
tree0468db0f07cfc27769075a902d9c752fb7b779e0
parent7f85c9fc75bd62ac09ea4457d3b17f85988fca66 (diff)
set MODEL formatting for rendering
-rw-r--r--src/render/model.h160
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;
}
};