From: hgn Date: Fri, 9 Jul 2021 21:30:15 +0000 (+0100) Subject: vpk loading/models X-Git-Url: https://harrygodden.com/git/?p=csRadar.git;a=commitdiff_plain;h=0399aad1d7374badf037a2696d9e276d71b7a297 vpk loading/models --- diff --git a/csRadar.c b/csRadar.c index ae383f7..de19eba 100644 --- a/csRadar.c +++ b/csRadar.c @@ -3,6 +3,7 @@ #include #include #include +#include // CSR lib #include "csrTypes.h" @@ -14,10 +15,11 @@ // Valve formats #include "vdf.h" #include "vpk.h" +#include "vfilesys.h" + #include "vmdl.h" #include "vmf.h" -#include "vfilesys.h" // CSR main #include "csrDraw.h" @@ -28,29 +30,19 @@ int main( int argc, char *argv[] ) { - vmf_vert *triangles = NULL; - vmf_vert oh_yeah_yeah = {0}; - - for( int i = 0; i < 22; i ++ ) - { - triangles = csr_sb_reserve( triangles, 3, sizeof( vmf_vert ) ); - - vmf_vert *tri = triangles + csr_sb_count( triangles ); - - tri[0] = oh_yeah_yeah; - tri[1] = oh_yeah_yeah; - tri[2] = oh_yeah_yeah; - - csr_sb_inc( triangles, 3 ); - } - if( argc == 2 ) { + fs_set_gameinfo( "/home/harry/SteamLibrary/steamapps/common/Counter-Strike Global Offensive/csgo/gameinfo.txt" ); printf( "read: %s\n", argv[1] ); - vdf_node *node = vdf_open_file( argv[1] ); + //vdf_node *node = vdf_open_file( argv[1] ); + vmf_map *map = vmf_init( argv[1], 1 ); + vmf_free( map ); + fs_exit(); + + /* vmf_solid solid_main; @@ -62,26 +54,31 @@ int main( int argc, char *argv[] ) { solidgen_push( &solid_main, brush ); } - - vmf_vert *triangles = NULL; + + clock_t t; + t = clock(); + printf("Timer starts\n"); + + csr_frag *image = (csr_frag *)csr_malloc( 1024*1024*sizeof(csr_frag) ); + clear_depth( image, 1024, 1024 ); for( int i = 0; i < csr_sb_count( solid_main.indices )/3; i ++ ) { u32 * base = solid_main.indices + i*3; - triangles = csr_sb_reserve( triangles, 3, sizeof( vmf_vert ) ); - - vmf_vert *tri = triangles + csr_sb_count( triangles ); + vmf_vert tri[3]; tri[0] = solid_main.verts[ base[0] ]; tri[1] = solid_main.verts[ base[1] ]; tri[2] = solid_main.verts[ base[2] ]; - - csr_sb_inc( triangles, 3 ); + + draw_buffers( image, 1024, 1024, (v4f){ -1000.f, -1000.f, 1000.f, 1000.f }, tri, 1 ); } - csr_frag *image = (csr_frag *)csr_malloc( 1024*1024*sizeof(csr_frag) ); - draw_buffers( image, 1024, 1024, (v4f){ -1000.f, -1000.f, 1000.f, 1000.f }, triangles, csr_sb_count( triangles )/3 ); + printf("Timer ends \n"); + t = clock() - t; + double time_taken = ((double)t)/CLOCKS_PER_SEC; // calculate the elapsed time + printf("Tracing took %f seconds to execute\n", time_taken); float *rgba_test = (float *)csr_malloc( 1024*1024*sizeof(float)*3 ); @@ -96,10 +93,10 @@ int main( int argc, char *argv[] ) free( rgba_test ); free( image ); - csr_sb_free( triangles ); solidgen_to_obj( &solid_main, "hello.obj" ); vdf_free_r( node ); + */ } } diff --git a/csrDraw.h b/csrDraw.h index e0635bb..e0d125e 100644 --- a/csrDraw.h +++ b/csrDraw.h @@ -1,5 +1,3 @@ -#include - typedef struct csr_frag csr_frag; struct csr_frag @@ -69,20 +67,9 @@ void simple_raster( csr_frag fragments[], u32 x, u32 y, v4f cam_bounds, vmf_vert // First pass 'fragmentize' void draw_buffers( csr_frag fragments[], u32 x, u32 y, v4f cam_bounds, vmf_vert *triangles, u32 triangle_count ) { - clock_t t; - t = clock(); - printf("Timer starts\n"); - - clear_depth( fragments, x, y ); - for( u32 i = 0; i < triangle_count; i ++ ) { vmf_vert *triangle = triangles + i*3; simple_raster( fragments, x, y, cam_bounds, triangle, i ); } - - printf("Timer ends \n"); - t = clock() - t; - double time_taken = ((double)t)/CLOCKS_PER_SEC; // calculate the elapsed time - printf("Tracing took %f seconds to execute\n", time_taken); } diff --git a/csrMap.h b/csrMap.h new file mode 100644 index 0000000..e69de29 diff --git a/csrMem.h b/csrMem.h index dbcc942..b2be8e8 100644 --- a/csrMem.h +++ b/csrMem.h @@ -11,6 +11,14 @@ void *csr_malloc( size_t size ) return ret; } +void *csr_calloc( size_t size ) +{ + void *ret = calloc( 1, size ); + if( !ret ) + exit(1); + return ret; +} + void *csr_sb_raw( void *arr ) { return ((u32 *)arr)-3; diff --git a/vdf.h b/vdf.h index ddfc2d3..2b77a7a 100644 --- a/vdf.h +++ b/vdf.h @@ -103,6 +103,8 @@ struct vdf_node vdf_node **nodes; vdf_kv *pairs; + + u32 user; }; vdf_node *vdf_next( vdf_node *node, const char *name, int *it ) @@ -112,7 +114,7 @@ vdf_node *vdf_next( vdf_node *node, const char *name, int *it ) for( int i = it? *it: 0; i < csr_sb_count( node->nodes ); i ++ ) { - if( !strcmp( name, node->nodes[i]->name )) + if( !name || !strcmp( name, node->nodes[i]->name )) { if( it ) *it = i+1; return node->nodes[i]; @@ -534,24 +536,38 @@ void vdf_parse_feedbuffer( vdf_ctx *ctx, char *buf ) } } -vdf_node *vdf_open_file( const char *fn ) -{ +int vdf_load_into( const char *fn, vdf_node *node ) +{ char *text_src = csr_textasset_read( fn ); if( !text_src ) { fprintf( stderr, "vdf open failed\n" ); - return NULL; + return 0; } vdf_ctx ctx = {0}; - ctx.root = ctx.st.pnode = vdf_create_node( NULL, NULL ); + ctx.root = ctx.st.pnode = node; vdf_newln( &ctx ); vdf_parse_feedbuffer( &ctx, text_src ); - free( text_src ); - return ctx.root; + + return 1; +} + +vdf_node *vdf_open_file( const char *fn ) +{ + vdf_node *root = vdf_create_node( NULL, NULL ); + if( vdf_load_into( fn, root ) ) + { + return root; + } + else + { + vdf_free_r( root ); + return NULL; + } } // OUTPUT diff --git a/vfilesys.h b/vfilesys.h index 2f33f83..5206d57 100644 --- a/vfilesys.h +++ b/vfilesys.h @@ -68,7 +68,7 @@ void fs_set_gameinfo( const char *path ) strcpy( pack_path, fs->searchpaths[i] ); strcat( pack_path, "pak01_dir.vpk" ); - if( (fs->vpk = (VPKHeader *)csr_asset_read( path )) ) + if( (fs->vpk = (VPKHeader *)csr_asset_read( pack_path )) ) { break; } diff --git a/vmdl.h b/vmdl.h index 51b8f05..7b5bb07 100644 --- a/vmdl.h +++ b/vmdl.h @@ -469,6 +469,14 @@ void mdl_free( mdl_mesh_t *m ) free( m->vertices ); } +void mdl_error( mdl_mesh_t *m ) +{ + m->num_indices = 0; + m->num_vertices = 0; + m->indices = NULL; + m->vertices = NULL; +} + int mdl_from_find_files( const char *mdlname, mdl_mesh_t *ctx ) { // Read entire files into memory (inline functions map memory) @@ -477,20 +485,24 @@ int mdl_from_find_files( const char *mdlname, mdl_mesh_t *ctx ) strcpy( path, mdlname ); csr_stripext( path ); strcat( path, ".dx90.vtx" ); - VTXFileHeader_t *pVtxHdr = (VTXFileHeader_t *)csr_asset_read( path ); + VTXFileHeader_t *pVtxHdr = (VTXFileHeader_t *)valve_fs_get( path ); - if( !pVtxHdr ) + if( !pVtxHdr ) + { + mdl_error( ctx ); return 0; + } // .VVD strcpy( path, mdlname ); csr_stripext( path ); strcat( path, ".vvd" ); - vertexFileHeader_t *pVvdHdr = (vertexFileHeader_t *)csr_asset_read( path ); + vertexFileHeader_t *pVvdHdr = (vertexFileHeader_t *)valve_fs_get( path ); if( !pVvdHdr ) { free( pVtxHdr ); + mdl_error( ctx ); return 0; } @@ -498,12 +510,13 @@ int mdl_from_find_files( const char *mdlname, mdl_mesh_t *ctx ) strcpy( path, mdlname ); csr_stripext( path ); strcat( path, ".mdl" ); - studiohdr_t *pMdl = (studiohdr_t *)csr_asset_read( path ); + studiohdr_t *pMdl = (studiohdr_t *)valve_fs_get( path ); if( !pMdl ) { free( pVtxHdr ); free( pVvdHdr ); + mdl_error( ctx ); return 0; } diff --git a/vmf.h b/vmf.h index 9baa117..887fe84 100644 --- a/vmf.h +++ b/vmf.h @@ -1,12 +1,11 @@ -#include "csrTypes.h" -#include "csrComb.h" - #define SOLID_MAX_SIDES 512 typedef struct vmf_solid vmf_solid; typedef struct vmf_vert vmf_vert; typedef struct vmf_mat vmf_mat; typedef struct vmf_face vmf_face; +typedef struct vmf_userdata vmf_userdata; +typedef struct vmf_map vmf_map; typedef enum ESolidResult ESolidResult; @@ -49,6 +48,29 @@ struct vmf_mat u32 hash; }; +struct vmf_map +{ + vdf_node *root; + + struct vmf_model + { + char *str; + u32 hash; + + mdl_mesh_t mdl; + } + *models; + + struct vmf_instance + { + char *name; + u32 hash; + + vdf_node *root; + } + *cache; +}; + // IMPLEMENTATION void solidgen_ctx_init( vmf_solid *ctx ) @@ -534,6 +556,185 @@ ESolidResult solidgen_push( vmf_solid *ctx, vdf_node *node ) return flag; } +u32 vmf_get_mdl( vmf_map *map, const char *mdl ) +{ + u32 hash = djb2( (const unsigned char *)mdl ); + + for( u32 i = 0; i < csr_sb_count( map->models ); i ++ ) + { + if( hash == map->models[i].hash && !strcmp( map->models[i].str, mdl ) ) + { + return i; + } + } + + return 0; +} + +void vmf_populate_models( vdf_node *vmf, vmf_map *map ) +{ + vdf_foreach( vmf, "entity", ent ) + { + // Use any class name with prop_ + if( !strncmp( kv_get( ent, "classname", "" ), "prop_", 5 )) + { + // Check if it exists + const char *model_path = kv_get( ent, "model", "" ); + u32 mdl_id = vmf_get_mdl( map, model_path ); + + if( !mdl_id ) + { + map->models = csr_sb_reserve( map->models, 1, sizeof( struct vmf_model )); + + struct vmf_model *entry = &map->models[ csr_sb_count( map->models ) ]; + entry->str = csr_malloc( strlen( model_path ) +1 ); + strcpy( entry->str, model_path ); + entry->hash = djb2( (const unsigned char *)model_path ); + + mdl_id = csr_sb_count( map->models ); + csr_sb_use( map->models ); + } + + // Assign prop-ID for later use + ent->user = mdl_id; + } + } +} + +// Load all models +void vmf_load_models( vmf_map *map ) +{ + printf( "Loading all models\n" ); + + // Error model. TODO: Maybe don't have this be junk data. + map->models = csr_sb_reserve( map->models, 1, sizeof( struct vmf_model )); + csr_sb_use( map->models ); + mdl_error( &map->models[0].mdl ); + + // Create listings for each model + vmf_populate_models( map->root, map ); + + for( int i = 0; i < csr_sb_count( map->cache ); i ++ ) + { + vmf_populate_models( map->cache[i].root, map ); + } + + printf( "Indexed (%u) models\n", csr_sb_count( map->models ) ); + + u32 num_success = 0; + + // Load model data + // TODO: Make nice loading bar + for( int i = 1; i < csr_sb_count( map->models ); i ++ ) + { + printf( "Load model (%d)\n", i ); + + struct vmf_model *mdl = &map->models[i]; + + if( mdl_from_find_files( mdl->str, &mdl->mdl ) ) + { + num_success ++; + } + } + + printf( "Done (%u of %u loaded)\n", num_success, csr_sb_count( map->models ) ); +} + +void vmf_init_subvmf( vmf_map *map, const char *subvmf ); + +void vmf_load_all_instances( vmf_map *map, vdf_node *vmf ) +{ + vdf_foreach( vmf, "entity", ent ) + { + if( !strcmp( kv_get( ent, "classname", "" ), "func_instance" )) + { + // Entity is in use if file is specified, if not just ignore the entity. + const char *path = kv_get( ent, "file", "" ); + if( strcmp( path, "" ) ) + { + vmf_init_subvmf( map, path ); + } + } + } +} + +void vmf_init_subvmf( vmf_map *map, const char *subvmf ) +{ + printf( "Loading subvmf: %s\n", subvmf ); + + u32 hash = djb2( (const unsigned char *)subvmf ); + + // Check if present + for( int i = 0; i < csr_sb_count( map->cache ); i ++ ) + { + if( hash == map->cache[i].hash ) + { + if( !strcmp( map->cache[i].name, subvmf ) ) + { + return; + } + } + } + + map->cache = csr_sb_reserve( map->cache, 1, sizeof( struct vmf_instance )); + struct vmf_instance *inst = &map->cache[ csr_sb_count( map->cache ) ]; + + if( (inst->root = vdf_open_file( subvmf )) ) + { + csr_sb_use( map->cache ); + + inst->hash = hash; + inst->name = csr_malloc( strlen( subvmf )+1 ); + strcpy( inst->name, subvmf ); + + // Recursive load other instances + vmf_load_all_instances( map, inst->root ); + } + else + { + // TODO: Don't die here? + fprintf( stderr, "Failed to load instance file\n" ); + exit(0); + } +} + +vmf_map *vmf_init( const char *path, int load_models ) +{ + vmf_map *map = csr_calloc( sizeof( vmf_map ) ); + map->root = vdf_open_file( path ); + + // Prepare instances + vmf_load_all_instances( map, map->root ); + + // Other resources + if( load_models ) + { + vmf_load_models( map ); + } + + return map; +} + +void vmf_free( vmf_map *map ) +{ + for( int i = 0; i < csr_sb_count( map->cache ); i ++ ) + { + vdf_free_r( map->cache[i].root ); + free( map->cache[i].name ); + } + + for( int i = 1; i < csr_sb_count( map->models ); i ++ ) + { + free( map->models[i].str ); + mdl_free( &map->models[i].mdl ); + } + + vdf_free_r( map->root ); + csr_sb_free( map->models ); + csr_sb_free( map->cache ); + free( map ); +} + void solidgen_to_obj( vmf_solid *ctx, const char *path ) { FILE *fp = fopen( path, "w" ); diff --git a/vpk.h b/vpk.h index 73ff7cb..b6bd69d 100644 --- a/vpk.h +++ b/vpk.h @@ -50,8 +50,8 @@ VPKDirectoryEntry *vpk_find( VPKHeader *self, const char *asset ) while( 1 ) { if( !*pCur ) break; - - int bExt = !strcmp( ext, pCur ); + + int bExt = !strcmp( ext, pCur ); while( *( pCur ++ ) ) {}; while( 1 )