diff options
| author | day <day@national.shitposting.agency> | 2026-03-14 05:21:43 +0100 |
|---|---|---|
| committer | day <day@national.shitposting.agency> | 2026-03-14 05:21:43 +0100 |
| commit | c2a4f7c2e6e4651dda6350a80a57e177f5ff2f55 (patch) | |
| tree | b5cd91a753257e026da0b2e3bc680f7f29ece59d | |
| parent | 59ca7ecafca84fa62ee8d54d0e48521b7e4c0a95 (diff) | |
starting obj parsing
| -rw-r--r-- | assets/obj/base.mtl | 32 | ||||
| -rw-r--r-- | assets/obj/base.obj | 38 | ||||
| -rw-r--r-- | src/game/assets.cpp | 2 | ||||
| -rw-r--r-- | src/game/player.cpp | 2 | ||||
| -rw-r--r-- | src/render/model.h | 239 | ||||
| -rw-r--r-- | src/util/file.h | 13 |
6 files changed, 319 insertions, 7 deletions
diff --git a/assets/obj/base.mtl b/assets/obj/base.mtl new file mode 100644 index 0000000..03942f4 --- /dev/null +++ b/assets/obj/base.mtl @@ -0,0 +1,32 @@ +# Blender 4.0.0 MTL File: 'None' +# www.blender.org + +newmtl floor +Ns 0.000000 +Ka 1.000000 1.000000 1.000000 +Kd 0.467821 0.307613 0.684474 +Ks 0.000000 0.000000 0.000000 +Ke 0.000000 0.000000 0.000000 +Ni 1.450000 +d 1.000000 +illum 1 + +newmtl roof +Ns 0.000000 +Ka 1.000000 1.000000 1.000000 +Kd 0.800204 0.447582 0.433705 +Ks 0.000000 0.000000 0.000000 +Ke 0.000000 0.000000 0.000000 +Ni 1.450000 +d 1.000000 +illum 1 + +newmtl wall +Ns 0.000000 +Ka 1.000000 1.000000 1.000000 +Kd 0.136969 0.317936 0.462675 +Ks 0.000000 0.000000 0.000000 +Ke 0.000000 0.000000 0.000000 +Ni 1.450000 +d 1.000000 +illum 1 diff --git a/assets/obj/base.obj b/assets/obj/base.obj new file mode 100644 index 0000000..093a98d --- /dev/null +++ b/assets/obj/base.obj @@ -0,0 +1,38 @@ +# Blender 4.0.0 +# www.blender.org +mtllib base.mtl +o Plane +v -25.415455 25.415455 0.000008 +v -25.415455 -25.415455 0.000008 +v 25.415455 25.415455 -0.000008 +v 25.415455 -25.415455 -0.000008 +v 20.117777 20.117769 18.003807 +v -20.117760 20.117769 18.003824 +v -20.117760 -20.117769 18.003824 +v 20.117777 -20.117769 18.003807 +vn -0.0000 -0.0000 -1.0000 +vn 0.9593 -0.0000 0.2823 +vn -0.9593 -0.0000 0.2823 +vn -0.0000 0.9593 0.2823 +vn -0.0000 -0.9593 0.2823 +vn -0.0000 -0.0000 1.0000 +vt 0.000000 1.000000 +vt 1.000000 0.000000 +vt 0.000000 0.000000 +vt 1.000000 1.000000 +s 0 +usemtl floor +f 3/1/1 2/2/1 1/3/1 +f 3/1/1 4/4/1 2/2/1 +usemtl wall +f 8/4/2 4/4/2 5/1/2 +f 6/3/3 1/3/3 7/2/3 +f 5/1/4 3/1/4 6/3/4 +f 7/2/5 2/2/5 8/4/5 +f 5/1/2 4/4/2 3/1/2 +f 6/3/4 3/1/4 1/3/4 +f 7/2/3 1/3/3 2/2/3 +f 8/4/5 2/2/5 4/4/5 +usemtl roof +f 5/1/6 6/3/6 8/4/6 +f 7/2/6 8/4/6 6/3/6 diff --git a/src/game/assets.cpp b/src/game/assets.cpp index 62663a9..2a73756 100644 --- a/src/game/assets.cpp +++ b/src/game/assets.cpp @@ -2,6 +2,7 @@ #include "../game.h" #include "../render/gl_2d_font.h" +#include "../render/model.h" #include "../util/stb_image.h" #include "../util/anim.h" @@ -9,6 +10,7 @@ void assets_init( GAME_DATA *game ) { game->assets.test = gl_texture_from_file( game->gl, "uvtest.png" ); game->assets.fonts_init = 0; + MODEL model = model_from_obj( "../assets/obj/", "base" ); } void assets_create_fonts( struct GAME_DATA *game ) { diff --git a/src/game/player.cpp b/src/game/player.cpp index e4c0390..8f418ac 100644 --- a/src/game/player.cpp +++ b/src/game/player.cpp @@ -58,7 +58,7 @@ void capture_move_keys( PLAYER* p ) { p->input.jump = input.keys[input.binds.jump]; if( input.keys[input.binds.fwd] ) { if( !p->input.fwd_held ) move->x = 1.f; - p->input.fwd_held = 1; + p->input.fwd_held = 1; } else { if( p->input.fwd_held ) { if( p->input.bk_held ) move->x = -1.f; diff --git a/src/render/model.h b/src/render/model.h new file mode 100644 index 0000000..c2db042 --- /dev/null +++ b/src/render/model.h @@ -0,0 +1,239 @@ +#include "../util/typedef.h" +#include "../util/string.h" +#include "../util/vector.h" +#include "../util/file.h" + +#include <assert.h> + +struct MODEL { + +}; + +namespace OBJ { + enum LINE_TYPES : U16 { + comment = ( '#' | ( ' ' << 8 ) ), + f = ( 'f' | ( ' ' << 8 ) ), + mtllib = ( 'm' | ( 't' << 8 ) ), + o = ( 'o' | ( ' ' << 8 ) ), + s = ( 's' | ( ' ' << 8 ) ), + v = ( 'v' | ( ' ' << 8 ) ), + vn = ( 'v' | ( 'n' << 8 ) ), + vt = ( 'v' | ( 't' << 8 ) ), + usemtl = ( 'u' | ( 's' << 8 ) ) + }; + + enum FACE_TYPES : U8 { + V = 0, + VVT = 1, + VVN = 2, + 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; + + static inline char* skip_space( char* s ) { + while( *s == ' ' || *s == '\t' ) ++s; + return s; + } + + static inline char* read_f32( char* s, F32* out ) { + *out = strtof( s, &s ); + return s; + } + + static inline char* read_u32( char* s, U32* out ) { + *out = strtoul( s, &s, 10 ); + return s; + } + + struct MTLDATA { + STR name; + }; + + struct OBJDATA { + LIST<VEC2> uvs; + LIST<VEC3> normals; + LIST<VEC3> vertices; + + LIST<MTLDATA> mtllib; + + struct UseMtl { + LIST<U32> indices; + LIST<STR> data; + } usemtl; + + struct Indices { + LIST<U32> data; + LIST<U32> counts; + LIST<FACE_TYPES> types; + } indices; + }; + + inline OBJDATA obj_from_file( const char* path, const char* name ) { + char* f_obj = nullptr; + STR obj_path( path ); + U64 obj_size = 0; + obj_path += name; + obj_path += ".obj"; + + f_obj = (char*)file_read( obj_path.data, &obj_size ); + if( !f_obj ) { + dlog( "obj_from_file() : failed to read obj file %s\n", obj_path.data ); + return {}; + } + dlog( "___modelfile___\n%s\n", f_obj ); + + OBJDATA obj; + for( U64 i = 0; i < obj_size - 1 && f_obj[i]; ++i ) { + if( f_obj[i] == (I32)'#' ) { + while( f_obj[i] && f_obj[i] != '\n' ) ++i; + continue; + } + + I32 c0 = f_obj[i]; + U16 c1 = f_obj[i + 1]; + I32 first_two = c0 | c1 << 8; + + switch( first_two ) { + case LINE_TYPES::f: { + FACE_TYPES type = FACE_TYPES::V; + char* s = f_obj + i + 2; + bool type_set = 0; + U32 count = 0; + + s = skip_space( s ); + + while( *s && *s != '\n' ) { + bool has_vt = 0, has_vn = 0; + U32 v = 0, vt = 0, vn = 0; + s = read_u32( s, &v ); + obj.indices.data.push( --v ); + + if( *s == '/' ) { + ++s; + + if( *s != '/' ) { + s = read_u32( s, &vt ); + obj.indices.data.push( --vt ); + has_vt = 1; + } + + if( *s == '/' ) { + s = read_u32( ++s, &vn ); + obj.indices.data.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; + } + + ++count; + + while( *s && *s != ' ' && *s != '\n' ) + ++s; + s = skip_space( s ); + } + obj.indices.counts.push( count ); + obj.indices.types.push( type ); + } break; + case LINE_TYPES::v: + case LINE_TYPES::vn: { + bool is_v = first_two == LINE_TYPES::v; + U32 start = i + ( is_v ? 2 : 3 ); + char* s = f_obj + start; + VEC3 temp{}; + s = skip_space( s ); + s = read_f32( s, &temp.x ); + s = skip_space( s ); + s = read_f32( s, &temp.y ); + s = skip_space( s ); + s = read_f32( s, &temp.z ); + if( is_v ) + obj.vertices.push( temp ); + else + obj.normals.push( temp ); + } break; + case LINE_TYPES::vt: { + char* s = f_obj + i + 3; + VEC2 temp{}; + s = skip_space( s ); + s = read_f32( s, &temp.x ); + s = skip_space( s ); + s = read_f32( s, &temp.y ); + obj.uvs.push( temp ); + } break; + case LINE_TYPES::mtllib: + case LINE_TYPES::usemtl: { + bool is_mtllib = first_two == LINE_TYPES::mtllib; + char* start = f_obj + i + 7; + char* end = start; + while( *end && *end != '\n' ) ++end; + U32 len = end - start; + STR temp; + temp.reserve( len + 1 ); + memcpy( temp, start, len ); + temp.data[len] = 0; + if( !is_mtllib ) { + obj.usemtl.data.push( temp ); + obj.usemtl.indices.push( obj.indices.data.size ); + } + else { + U64 mtl_size = 0; + STR mtl_path( path ); + mtl_path += temp.data; + char* f_mtl = (char*)file_read( mtl_path.data, &mtl_size ); + if( !f_mtl ) { + dlog( "obj_from_file() : failed to read mtl file %s\n", mtl_path.data ); + return {}; + } + dlog( "___mtlfile___\n%s\n", f_mtl ); + + // TODO: finish mtl parsing here into obj.mtllib + + obj.mtllib.push({ temp }); + free( (void*)f_mtl ); + } + } break; + case LINE_TYPES::comment: + case LINE_TYPES::o: + case LINE_TYPES::s: break; + default: dlog( "unhandled char combo %c%c\n", c0, c1 ); break; + } + + while( f_obj[i] && f_obj[i] != '\n' ) ++i; + } + free( (void*)f_obj ); + return obj; + } + + inline MODEL obj_to_model( OBJDATA obj ) { + MODEL model; + + return model; + } +}; + +inline MODEL model_from_obj( const I8* path, const I8* name ) { + OBJ::OBJDATA obj = OBJ::obj_from_file( path, name ); + return OBJ::obj_to_model( obj ); +} diff --git a/src/util/file.h b/src/util/file.h index e19a390..7e4d413 100644 --- a/src/util/file.h +++ b/src/util/file.h @@ -8,7 +8,7 @@ #include "typedef.h" #include "allocator.h" -inline void* file_read( const char* file ) { +inline void* file_read( const char* file, U64* size = nullptr ) { FILE* f = fopen( file, "rb" ); if( !f ) return 0; @@ -16,15 +16,16 @@ inline void* file_read( const char* file ) { defer( fclose( f ) ); fseek( f, 0, SEEK_END ); - U64 size = ftell( f ); + U64 fsize = ftell( f ); rewind( f ); - if( !size ) + if( !fsize ) return 0; - void* block = malloc( size + 1 ); - fread( block, size, 1, f ); + void* block = malloc( fsize + 1 ); + fread( block, fsize, 1, f ); - ( (U8*)block )[size] = 0; + ( (U8*)block )[fsize] = 0; + if ( size ) *size = fsize; return block; } |
