X-Git-Url: https://harrygodden.com/git/?p=csRadar.git;a=blobdiff_plain;f=vmf.h;h=887fe849b9da5e684a0286ee7d2b4a754ca8684b;hp=9baa117510e54accfb98861f5647db90942fb136;hb=0399aad1d7374badf037a2696d9e276d71b7a297;hpb=a97099abba0a239e20929f04ece9d6839c96ac14 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" );