X-Git-Url: https://harrygodden.com/git/?p=csRadar.git;a=blobdiff_plain;f=vmf.h;h=ff3804d8c29691add5a67d82ba4f2eb64305f4e4;hp=9baa117510e54accfb98861f5647db90942fb136;hb=a53095e1511fecb8cc83c692e7ce7b23852fff16;hpb=a97099abba0a239e20929f04ece9d6839c96ac14 diff --git a/vmf.h b/vmf.h index 9baa117..ff3804d 100644 --- a/vmf.h +++ b/vmf.h @@ -1,12 +1,14 @@ -#include "csrTypes.h" -#include "csrComb.h" - #define SOLID_MAX_SIDES 512 +#define VMF_FLAG_IS_PROP 0x1 +#define VMF_FLAG_IS_INSTANCE 0x2 +#define VMF_FLAG_BRUSH_ENT 0x4 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,8 +51,41 @@ 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; + + m4x3f transform; + } + *cache; + + m4x3f transform; +}; + // IMPLEMENTATION +void solidgen_ctx_reset( vmf_solid *ctx ) +{ + csr_sb_clear( ctx->verts ); + csr_sb_clear( ctx->indices ); +} + void solidgen_ctx_init( vmf_solid *ctx ) { const u32 init_size = 128; @@ -66,27 +101,20 @@ void solidgen_ctx_free( vmf_solid *ctx ) } // Compute bounds of solid gen ctx -void solidgen_bounds( vmf_solid *ctx, u32 start, u32 end, v3f min, v3f max ) +void solidgen_bounds( vmf_solid *ctx, boxf box ) { v3f mine = { INFINITY, INFINITY, INFINITY }; v3f maxe = {-INFINITY,-INFINITY,-INFINITY }; - for( int i = start; i < end; i ++ ) + for( int i = 0; i < csr_sb_count( ctx->verts ); i ++ ) { vmf_vert *vert = ctx->verts + i; - float *co = vert->co; - - mine[0] = fminf( mine[0], co[0] ); - mine[1] = fminf( mine[1], co[1] ); - mine[2] = fminf( mine[2], co[2] ); - - maxe[0] = fmaxf( maxe[0], co[0] ); - maxe[1] = fmaxf( maxe[1], co[1] ); - maxe[2] = fmaxf( maxe[2], co[2] ); + v3_minv( mine, vert->co, mine ); + v3_maxv( maxe, vert->co, maxe ); } - v3_copy( mine, min ); - v3_copy( maxe, max ); + v3_copy( mine, box[0] ); + v3_copy( maxe, box[1] ); } struct @@ -260,6 +288,9 @@ ESolidResult solidgen_push( vmf_solid *ctx, vdf_node *node ) // TODO: What is this for again? surely it should be the other way around... i think... if( solid_has_displacement( node ) ) { + is_displacement = 1; + /* + printf( "solid_has_displacement\n" ); num_planes = vmf_api.bisectors; @@ -274,6 +305,7 @@ ESolidResult solidgen_push( vmf_solid *ctx, vdf_node *node ) } is_displacement = 1; + */ } int it = 0; @@ -534,6 +566,207 @@ 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; +} + +int vmf_class_is_prop( vdf_node *ent ) +{ + return !strncmp( kv_get( ent, "classname", "" ), "prop_", 5 ); +} + +void vmf_populate_models( vdf_node *vmf, vmf_map *map ) +{ + vdf_foreach( vmf, "entity", ent ) + { + // Use any class name with prop_ + if( vmf_class_is_prop( ent ) ) + { + // 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 = VMF_FLAG_IS_PROP; + ent->user1 = 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 )-1 ); + + u32 num_success = 0; + + // Load model data + // TODO: Make nice loading bar + for( int i = 1; i < csr_sb_count( map->models ); i ++ ) + { + struct vmf_model *mdl = &map->models[i]; + + if( mdl_from_find_files( mdl->str, &mdl->mdl ) ) + { + num_success ++; + } + else + { + fprintf( stderr, "Failed to load model: %s\n", mdl->str ); + } + } + + printf( "Done (%u of %u loaded)\n", num_success, csr_sb_count( map->models )-1 ); +} + +u32 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, "" ) ) + { + if( (ent->user1 = vmf_init_subvmf( map, path ))) + { + ent->user1 --; + ent->user = VMF_FLAG_IS_INSTANCE; + } + } + } + } +} + +// TODO: Merge this into above function.. doesnt need to be seperated +u32 vmf_init_subvmf( vmf_map *map, const char *subvmf ) +{ + u32 id; + u32 hash = djb2( (const unsigned char *)subvmf ); + + // Check if present + for( u32 i = 0; i < csr_sb_count( map->cache ); i ++ ) + { + if( hash == map->cache[i].hash ) + { + if( !strcmp( map->cache[i].name, subvmf ) ) + { + return i+1; + } + } + } + + printf( "Loading subvmf: %s\n", subvmf ); + + id = csr_sb_count( map->cache ); + map->cache = csr_sb_reserve( map->cache, 1, sizeof( struct vmf_instance )); + struct vmf_instance *inst = &map->cache[ id ]; + + 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 ); + + return id+1; + } + else + { + fprintf( stderr, "Failed to load instance file\n" ); + return 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 ); + + if( !map->root ) + { + free( map ); + return NULL; + } + + // 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" ); @@ -578,3 +811,60 @@ void solidgen_to_obj( vmf_solid *ctx, const char *path ) fprintf( stderr, "Could not open %s for writing\n", path ); } } + +void vmf_entity_transform( vdf_node *ent, m4x3f mat ) +{ + v3f angles = {0.f,0.f,0.f}; + v3f offset = {0.f,0.f,0.f}; + float scale; + + // Parse + scale = kv_get_float( ent, "uniformscale", 1.f ); + kv_float_array( ent, "angles", 3, angles ); + kv_float_array( ent, "origin", 3, offset ); + + // Translation + m4x3_translate( mat, offset ); + + // Make rotation ( Pitch yaw roll // YZX. Source->OpenGL ordering a lil messed up ) + m4x3_rotate_z( mat, csr_rad( angles[1] ) ); + m4x3_rotate_y( mat, csr_rad( angles[0] ) ); + m4x3_rotate_x( mat, csr_rad( angles[2] ) ); + + // Scale + m4x3_scale( mat, scale ); +} + +u32 vmf_visgroup_id( vdf_node *root, const char *name ) +{ + vdf_node *dict = vdf_next( root, "visgroups", NULL ); + + if( dict ) + { + vdf_foreach( dict, "visgroup", group ) + { + if( !strcmp( kv_get( group, "name", "" ), name ) ) + { + return kv_get_int( group, "visgroupid", 0 ); + } + } + } + + return 0; +} + +int vmf_visgroup_match( vdf_node *ent, u32 target ) +{ + vdf_node *editor = vdf_next( ent, "editor", NULL ); + + if( editor ) + { + kv_foreach( editor, "visgroupid", groupe ) + { + if( target == atoi( groupe ) ) + return 1; + } + } + + return 0; +}