vpk loading/models
authorhgn <hgodden00@gmail.com>
Fri, 9 Jul 2021 21:30:15 +0000 (22:30 +0100)
committerhgn <hgodden00@gmail.com>
Fri, 9 Jul 2021 21:30:15 +0000 (22:30 +0100)
csRadar.c
csrDraw.h
csrMap.h [new file with mode: 0644]
csrMem.h
vdf.h
vfilesys.h
vmdl.h
vmf.h
vpk.h

index ae383f77e756ac7f5c32c998d7dfcbeab5d6e00f..de19eba919c9411a9f523d53fd010ececf517b82 100644 (file)
--- a/csRadar.c
+++ b/csRadar.c
@@ -3,6 +3,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <math.h>
+#include <time.h>
 
 // CSR lib
 #include "csrTypes.h"
 // 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"
 
 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 );
+               */
        }
 }
index e0635bbdafabb5d93b2297eb965394d1345bde33..e0d125e7482b0334a156b6c0f33516a99f98f892 100644 (file)
--- a/csrDraw.h
+++ b/csrDraw.h
@@ -1,5 +1,3 @@
-#include <time.h>
-
 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 (file)
index 0000000..e69de29
index dbcc942566e3e5420290cf773f80978709f101d3..b2be8e8bcb576d9c68dd3a5895da8b3ae172703b 100644 (file)
--- 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 ddfc2d34300cc87751183c45dc64bec543439a95..2b77a7a4f3bf65fc87aa0b7c54bc7978d8e1a782 100644 (file)
--- 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
index 2f33f8312e09809b118f1055197ab0fa784d5cf4..5206d57c4bf5af76829d9982838c1f28e5bd73a8 100644 (file)
@@ -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 51b8f05c19264dff7ae28991fb4ad08c7a1154f8..7b5bb07263dec764036883064c23158afffbf29f 100644 (file)
--- 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 9baa117510e54accfb98861f5647db90942fb136..887fe849b9da5e684a0286ee7d2b4a754ca8684b 100644 (file)
--- 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 73ff7cb75f9126aee4aeb8192f00519ab9cb0af8..b6bd69daf272e69cf8997e18c1330a8b9e54bde7 100644 (file)
--- 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 )