-#define SOLID_MAX_SIDES 512
-#define VMF_FLAG_IS_PROP 0x1
-#define VMF_FLAG_IS_INSTANCE 0x2
-#define VMF_FLAG_BRUSH_ENT 0x4
+// This software is not affiliated with Valve Corporation
+// We are not affiliated, associated, authorized, endorsed by, or in any way officially
+// connected with Valve Corporation, or any of its subsidiaries or its affiliates.
+//
+// All trademarks are property of their respective owners
typedef struct vmf_solid vmf_solid;
typedef struct vmf_vert vmf_vert;
typedef enum ESolidResult ESolidResult;
+// API
+//=======================================================================================================================
+
+// Load vmf from disk
+vmf_map *vmf_init( const char *path );
+void vmf_free( vmf_map *map );
+
+// Solidgen API ~ Converting brushes into meshes
+// ---------------------------------------------
+void solidgen_ctx_init( vmf_solid *ctx );
+void solidgen_ctx_reset( vmf_solid *ctx );
+void solidgen_ctx_free( vmf_solid *ctx );
+void solidgen_bounds( vmf_solid *ctx, boxf box );
+
+ESolidResult solidgen_push( vmf_solid *ctx, vdf_node *node );
+
+// General VMF
+// -----------
+int solid_has_displacement( vdf_node *node );
+int vmf_class_is_prop( vdf_node *ent );
+
+// Build the list of all models used in this map, including instances
+void vmf_index_models( vmf_map *map );
+
+// Loads all models that have the resource flagged with need_load
+void vmf_load_models( vmf_map *map );
+
+// Create matrix describing this entities transform
+void vmf_entity_transform( vdf_node *ent, m4x3f mat );
+
+int vmf_visgroup_id( vdf_node *root, const char *name );
+int vmf_visgroup_match( vdf_node *ent, u32 target );
+
+// Currently unused
+//void vmf_addbisector( double p[4] );
+//void vmf_clearbisectors( void );
+//void vmf_ignore_mat( const char *material );
+//void vmf_clearignore( void );
+
+// Implementation
+//=======================================================================================================================
+
+#define SOLID_MAX_SIDES 512
+#define VMF_FLAG_IS_PROP 0x1
+#define VMF_FLAG_IS_INSTANCE 0x2
+#define VMF_FLAG_BRUSH_ENT 0x4
+
enum ESolidResult
{
k_ESolidResult_valid,
{
v3f co;
v3f nrm;
- v2f xy;
+ v3f origin;
};
struct vmf_face
u32 hash;
mdl_mesh_t mdl;
+
+ int need_load;
}
*models;
m4x3f transform;
};
-// IMPLEMENTATION
+#ifdef VALVE_IMPLEMENTATION
void solidgen_ctx_reset( vmf_solid *ctx )
{
if( num_planes >= SOLID_MAX_SIDES )
{
flag = k_ESolidResult_maxsides;
- fprintf( stderr, "Solid over maxsides limit (%i)\n", SOLID_MAX_SIDES );
+ log_error( "Solid over maxsides limit (%i)\n", SOLID_MAX_SIDES );
break;
}
v3_divs( center, (float)numpoints, center );
for( ; vert_start < csr_sb_count( ctx->verts ); vert_start ++ )
{
- v2_copy( center, ctx->verts[ vert_start ].xy );
+ v3_copy( center, ctx->verts[ vert_start ].origin );
}
// Sort each faces and trianglulalate them
if( csr_sb_count( face->indices ) < 3 )
{
flag = k_ESolidResult_degenerate;
- fprintf( stderr, "Skipping degenerate face\n" );
+ log_error( "Skipping degenerate face\n" );
continue;
}
if( csr_sb_count( face->indices ) != 4 )
{
flag = k_ESolidResult_degenerate;
- fprintf( stderr, "Skipping degenerate displacement\n" );
+ log_error( "Skipping degenerate displacement\n" );
continue;
}
// Todo, put correct normal
v3_copy( (v3f){ 0.f, 0.f, 1.f }, vert->nrm );
+
+ // Todo: use real bounds of displaced vertices
+ v3_copy( center, vert->origin );
}
}
map->models = csr_sb_reserve( map->models, 1, sizeof( struct vmf_model ));
struct vmf_model *entry = &map->models[ csr_sb_count( map->models ) ];
+ entry->need_load = 0;
+ mdl_error( &entry->mdl ); // (just setting arrays to 0)
+
entry->str = csr_malloc( strlen( model_path ) +1 );
strcpy( entry->str, model_path );
entry->hash = djb2( (const unsigned char *)model_path );
}
// Load all models
-void vmf_load_models( vmf_map *map )
+void vmf_index_models( vmf_map *map )
{
- printf( "Loading all models\n" );
+ log_info( "Indexing all models\n" );
- // Error model. TODO: Maybe don't have this be junk data.
+ // Error model == blank
map->models = csr_sb_reserve( map->models, 1, sizeof( struct vmf_model ));
csr_sb_use( map->models );
mdl_error( &map->models[0].mdl );
vmf_populate_models( map->cache[i].root, map );
}
- printf( "Indexed (%u) models\n", csr_sb_count( map->models )-1 );
-
+ log_info( "Indexed (%u) models\n", csr_sb_count( map->models )-1 );
+}
+
+void vmf_load_models( vmf_map *map )
+{
u32 num_success = 0;
+ u32 num_reqs = 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
+ if( mdl->need_load )
{
- fprintf( stderr, "Failed to load model: %s\n", mdl->str );
+ num_reqs ++;
+
+ if( mdl_from_find_files( mdl->str, &mdl->mdl ) )
+ {
+ num_success ++;
+ }
+ else
+ {
+ log_warn( "Failed to load model: %s\n", mdl->str );
+ }
}
}
- printf( "Done (%u of %u loaded)\n", num_success, csr_sb_count( map->models )-1 );
+ log_info( "Done (%u of %u loaded)\n", num_success, num_reqs );
}
u32 vmf_init_subvmf( vmf_map *map, const char *subvmf );
{
if( !strcmp( map->cache[i].name, subvmf ) )
{
- return i+1;
+ if( map->cache[i].root )
+ return i+1;
+ else
+ return 0;
}
}
}
- 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 ];
+ csr_sb_use( map->cache );
+ inst->hash = hash;
+ inst->name = csr_malloc( strlen( subvmf )+1 );
+ strcpy( inst->name, subvmf );
+
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 );
-
+ vmf_load_all_instances( map, inst->root );
return id+1;
}
else
{
- fprintf( stderr, "Failed to load instance file\n" );
+ log_error( "Failed to load instance file: %s\n", subvmf );
return 0;
}
}
-vmf_map *vmf_init( const char *path, int load_models )
+vmf_map *vmf_init( const char *path )
{
vmf_map *map = csr_calloc( sizeof( vmf_map ) );
map->root = vdf_open_file( path );
vmf_load_all_instances( map, map->root );
// Other resources
- if( load_models )
- {
- vmf_load_models( map );
- }
-
+ vmf_index_models( map );
return map;
}
{
for( int i = 0; i < csr_sb_count( map->cache ); i ++ )
{
- vdf_free_r( map->cache[i].root );
+ if( map->cache[i].root )
+ vdf_free_r( map->cache[i].root );
+
free( map->cache[i].name );
}
free( map );
}
-void solidgen_to_obj( vmf_solid *ctx, const char *path )
-{
- FILE *fp = fopen( path, "w" );
-
- if( fp )
- {
- fprintf( fp, "o vmf_export\n" );
-
- vmf_vert *vert;
-
- // Write vertex block
- for( int i = 0; i < csr_sb_count( ctx->verts ); i ++ )
- {
- vert = &ctx->verts[i];
- fprintf( fp, "v %f %f %f\n", vert->co[0], vert->co[1], vert->co[2] );
- }
-
- // Write normals block
- for( int i = 0; i < csr_sb_count( ctx->verts ); i ++ )
- {
- vert = &ctx->verts[i];
- fprintf( fp, "vn %f %f %f\n", vert->nrm[0], vert->nrm[1], vert->nrm[2] );
- }
-
- fprintf( fp, "s off\n" );
-
- // Indices
- for( int i = 0; i < csr_sb_count( ctx->indices )/3; i ++ )
- {
- u32 * base = ctx->indices + i*3;
- fprintf( fp, "f %u//%u %u//%u %u//%u\n",
- base[2]+1, base[2]+1,
- base[1]+1, base[1]+1,
- base[0]+1, base[0]+1
- );
- }
-
- fclose( fp );
- }
- else
- {
- 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};
m4x3_scale( mat, scale );
}
-u32 vmf_visgroup_id( vdf_node *root, const char *name )
+int vmf_visgroup_id( vdf_node *root, const char *name )
{
vdf_node *dict = vdf_next( root, "visgroups", NULL );
}
}
- return 0;
+ return -1;
}
int vmf_visgroup_match( vdf_node *ent, u32 target )
return 0;
}
+
+#endif