finish up plugin architecture
authorhgn <hgodden00@gmail.com>
Fri, 16 Jul 2021 10:42:05 +0000 (11:42 +0100)
committerhgn <hgodden00@gmail.com>
Fri, 16 Jul 2021 10:42:05 +0000 (11:42 +0100)
19 files changed:
build.sh [new file with mode: 0755]
csRadar.c
csRadar.h [new file with mode: 0644]
csrComb.h
csrDraw.h
csrIO.h
csrLog.h
csrMap.h [deleted file]
csrMath.h
csrMem.h
csrOpt.h
csrPlatform.h [new file with mode: 0644]
ext_csr_free.c [new file with mode: 0644]
plugins/geometry_buffers.c [deleted file]
vdf.h
vfilesys.h
vmdl.h
vmf.h
vpk.h

diff --git a/build.sh b/build.sh
new file mode 100755 (executable)
index 0000000..33bbae0
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,6 @@
+mkdir -p ext
+echo gcc -ggdb3 -Wall -fsanitize=address -rdynamic csRadar.c -o csRadar -lm -ldl
+gcc -ggdb3 -Wall -fsanitize=address -rdynamic csRadar.c -o csRadar -lm -ldl
+
+echo -ggdb3 -Wall -fsanitize=address -fpic -shared -o ext/csRadarFree.so ext_csr_free.c -lm
+gcc -ggdb3 -Wall -fsanitize=address -fpic -shared -o ext/csRadarFree.so ext_csr_free.c -lm
index 5347d751021634e7b31c04ac7eb90d1fd4c00022..9af5cdad09b9ed2b9853338c3312982ab01113a0 100644 (file)
--- a/csRadar.c
+++ b/csRadar.c
@@ -1,70 +1,41 @@
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-#include <time.h>
-#include <stdarg.h>
-
-
-#include <unistd.h>
-
-// CSR lib
-#include "csrLog.h"
-#include "csrOpt.h"
-#include "csrTypes.h"
-#include "csrMath.h"
-#include "csrMem.h"
-#include "csrIO.h"
-#include "csrComb.h"
-
-// Valve formats
-#include "vdf.h"
-#include "vpk.h"
-#include "vfilesys.h"
-
-#include "vmdl.h"
-#include "vmf.h"
-
-// CSR main
-#include "csr32f.h"
-#include "csrDraw.h"
-
-#define CSR_VERSION "0.0.1"
+#define VALVE_IMPLEMENTATION
+#define CSR_EXECUTABLE
+#include "csRadar.h"
 
 // gcc -Wall -fsanitize=address csRadar.c -o csRadar -lm
 
 int main( int argc, char *argv[] )
 {
-       char *arg;
-       char *strings[ 20 ];
-       int num_strings = 0;
-       
-       float padding = 128.f;
-       u32 resolution = 1024;
-       int write_txt = 1;
-       char output_path[ 512 ];                // Full path eg. /home/harry/my_map.vmf
-       char vmf_name[ 128 ];                   // Just the base name eg. my_map
+       csr_api api = 
+       {
+               .padding = 128.f,
+               .resolution = 1024,
+               .write_txt = 1,
+               .api_version = csr_api_version,
+               .sampling_mode = k_EMSAA_RGSS
+       };
+
        int output_set = 0;
-       EMSAA sampling_mode = k_EMSAA_RGSS;
+       char *extension = NULL;
 
+       char *arg;
        while( csr_argp( argc, argv ) )
        {
                if( (arg = csr_arg()) )
                {
-                       if( num_strings == 20 )
+                       if( api.num_strings == 20 )
                        {
                                log_error( "Too many arguments! Max 20\n" );
                                goto IL_CSR_EXIT;
                        }
                        
-                       strings[ num_strings ++ ] = arg;
+                       api.strings[ api.num_strings ++ ] = arg;
                }
                
                if( (arg = csr_opt_arg( 'o' )) )
                {
-                       strcpy( output_path, arg );
-                       csr_path_winunix( output_path );
+                       strcpy( api.output_path, arg );
+                       csr_path_winunix( api.output_path );
                        
                        output_set = 1;
                }
@@ -76,31 +47,31 @@ int main( int argc, char *argv[] )
                
                if( (arg = csr_opt_arg( 'r' )) )
                {
-                       resolution = atoi( arg );
+                       api.resolution = atoi( arg );
                }
                
                if( (arg = csr_long_opt_arg( "padding" )) )
                {
-                       padding = atof( arg );
+                       api.padding = atof( arg );
                }
                
                if( (arg = csr_long_opt_arg( "multi-sample" )) )
                {
                        if( !strcmp( arg, "none" ))
                        {
-                               sampling_mode = k_EMSAA_none;
+                               api.sampling_mode = k_EMSAA_none;
                        }
                        else if( !strcmp( arg, "rgss" ))
                        {
-                               sampling_mode = k_EMSAA_RGSS;
+                               api.sampling_mode = k_EMSAA_RGSS;
                        }
                        else if( !strcmp( arg, "2x" ))
                        {
-                               sampling_mode = k_EMSAA_2x2;
+                               api.sampling_mode = k_EMSAA_2x2;
                        }
                        else if( !strcmp( arg, "8r" ))
                        {
-                               sampling_mode = k_EMSAA_8R;
+                               api.sampling_mode = k_EMSAA_8R;
                        }
                        else
                        {
@@ -108,10 +79,15 @@ int main( int argc, char *argv[] )
                                goto IL_CSR_EXIT;
                        }
                }
+               
+               if( (arg = csr_long_opt_arg( "extension" )) )
+               {
+                       extension = arg;
+               }
 
                if( csr_opt( 'v' ) || csr_long_opt( "version" ) )
                {
-                       printf( "csRadar version: " CSR_VERSION "\n" );
+                       printf( "csRadar build: %u, api_version: %u\n", csr_build, csr_api_version );
                        goto IL_CSR_EXIT;
                }
                
@@ -133,6 +109,8 @@ int main( int argc, char *argv[] )
                                "   -o <output>                    Specify output name/path\n"
                                "   --padding=128                  When cropping radar, add padding units to border\n"
                                //"   --standard-layers              Use standard TAR layers/groups\n"
+                               "   --write-normals                Enable normals as an output stream\n"
+                               "   --write-origins                Enable entity origins as an output stream\n"
                                "   --no-txt                       Don't create matching radar txt\n"
                                "   --multi-sample=RGSS            [ none, 2x, rgss, 8r ]\n"
                                "   --extension=TAR                Use an extension binary instead\n"
@@ -145,106 +123,63 @@ int main( int argc, char *argv[] )
                }
        }
        
-       if( num_strings )
+       if( api.num_strings )
        {
-               vmf_map *map = vmf_init( strings[0] );
-       
-               if( map )
+               // Path handling
+               if( !output_set )
                {
-                       // Path handling
-                       if( !output_set )
-                       {
-                               strcpy( output_path, strings[0] );
-                               csr_stripext( output_path );
-                       }
-                       
-                       char *base_name;
-                       if( !(base_name = csr_findext( output_path, '/' ) ))
-                       {
-                               base_name = output_path;
-                       }
-                       
-                       strcpy( vmf_name, base_name );
-                       
-                       log_info( "output_path: '%s'\n", output_path );
-                       log_info( "vmf_name: '%s'\n", vmf_name );
-                       
-                       // Main                 
-                       csr_target target;
-                       
-                       csr_create_target( &target, resolution, resolution, sampling_mode );
-                       csr_rt_clear( &target );
-                       
-                       csr_use_program( &target, frag_gbuffer );
-                       
-                       // Compute bounds
-                       csr_filter filter = 
-                       {
-                               .classname = NULL,
-                               .visgroup = NULL,
-                               .compute_bounds_only = 1
-                       };
+                       strcpy( api.output_path, api.strings[0] );
+                       csr_stripext( api.output_path );
+               }
+               
+               char *base_name;
+               if( !(base_name = csr_findext( api.output_path, '/' ) ))
+               {
+                       base_name = api.output_path;
+               }
+               
+               strcpy( api.vmf_name, base_name );
+               
+               log_info( "output_path: '%s'\n", api.output_path );
+               log_info( "vmf_name: '%s'\n", api.vmf_name );
+
+               api.map = vmf_init( api.strings[0] );
+               if( api.map )
+               {
+                       if( !extension )
+                               extension = "csRadarFree";
+               
+                       csr_so ext = csr_libopen( extension );
                        
-                       // One pass for fitting, second pass for drawing
-                       for( int i = 0; i < 2; i ++ )
+                       if( ext )
                        {
-                               if( num_strings == 1 )
-                               {
-                                       // Draw everything
-                                       draw_vmf_group( &target, map, map->root, &filter, NULL, NULL );
-                                       csr_rt_save_buffers( &target, output_path, "all" );
-                               }
-                               else
-                               {
-                                       // Draw groups
-                                       for( int i = 1; i < num_strings; i ++ )
-                                       {
-                                               filter.visgroup = strings[ i ];
-                                               
-                                               draw_vmf_group( &target, map, map->root, &filter, NULL, NULL );
-                                               csr_rt_save_buffers( &target, output_path, strings[i] );
-                                               
-                                               csr_rt_clear( &target );
-                                       }
-                               }
+                               void (*csr_ext_main)(csr_api *);
+                               void (*csr_ext_exit)(csr_api *);
                                
-                               if( i == 0 )
+                               csr_ext_main = csr_get_proc( ext, "csr_ext_main" );
+                               csr_ext_exit = csr_get_proc( ext, "csr_ext_exit" );
+                                       
+                               if( csr_ext_main && csr_ext_exit )
                                {
-                                       filter.compute_bounds_only = 0;
-                                       csr_auto_fit( &target, padding );
-                                       vmf_load_models( map );
+                                       csr_ext_main( &api );
+                                       
+                                       // Do other
+                                       
+                                       csr_ext_exit( &api );
                                }
                                else
                                {
-                                       float prog = 0.f;
-                                       csr_prog_begin( "Rendering" );
-                                       for(;;)
-                                       {
-                                               if( prog > 1.f )
-                                                       break;
-                                               
-                                               csr_prog_update( prog );
-                                               usleep( 20000 );
-
-                                               prog += 0.01f;
-                                       }
-
-                                       csr_prog_end();
+                                       csr_liberr();
                                }
+                               
+                               csr_libclose( ext );
                        }
-                       
-                       if( write_txt )
+                       else
                        {
-                               char txt_path[ 512 ];
-                               
-                               strcpy( txt_path, output_path );
-                               strcat( txt_path, ".txt" );
-                               
-                               csr_write_txt( txt_path, vmf_name, &target );
+                               csr_liberr();
                        }
                        
-                       csr_rt_free( &target );
-                       vmf_free( map );
+                       vmf_free( api.map );
                }
                else
                {
diff --git a/csRadar.h b/csRadar.h
new file mode 100644 (file)
index 0000000..95e1048
--- /dev/null
+++ b/csRadar.h
@@ -0,0 +1,70 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+#include <stdarg.h>
+
+// CSR lib
+#include "csrLog.h"                    // Y
+#include "csrOpt.h"                    // Y
+#include "csrTypes.h"          // Y
+#include "csrMath.h"                   // Y
+#include "csrMem.h"                    // Y
+#include "csrIO.h"                     // Y
+#include "csrComb.h"                   // Y
+#include "csrPlatform.h"       // Y
+
+// Valve formats
+#include "vdf.h"                               // Y
+#include "vpk.h"                               // Y
+#include "vfilesys.h"          // Y
+
+#include "vmdl.h"                              // Y
+#include "vmf.h"                               // Y
+
+// Drawing
+#ifdef CSR_EXECUTABLE
+ #include "csr32f.h"
+//#include "csrTga.h"
+#endif
+
+#include "csrDraw.h"                   // Y
+
+static const u32 csr_build = 3;
+static const u32 csr_api_version = 1;
+
+typedef struct csr_api csr_api;
+struct csr_api
+{
+       // Floating arguments from main's argv
+       char *strings[ 20 ];
+       int num_strings;
+       
+       float padding;
+       u32 resolution;
+       int write_txt;
+       char output_path[ 512 ];                // Full path eg. /home/harry/my_map.vmf
+       char vmf_name[ 128 ];                   // Just the base name eg. my_map
+       EMSAA sampling_mode;
+       
+       // Main API interface
+       vmf_map *map;
+       csr_target target;
+       
+       u32 api_version;
+};
+
+#ifndef CSR_EXECUTABLE
+static int csr_init( csr_api *api )
+{
+       if( api->api_version > csr_api_version )
+       {
+               log_warn( "API Version out of date. Host: %u, Plugin: %u\n", api->api_version, csr_api_version );
+               return 0;
+       }
+       
+       return 1;
+}
+#endif
index 1a549d48e4228968499cf0bd2ac20f25ef568eed..92a1e0d2fe0bf1c47428b53cd624ea4da824c361 100644 (file)
--- a/csrComb.h
+++ b/csrComb.h
@@ -1,3 +1,39 @@
+// Copyright (C) 2021 Harry Godden (hgn)
+
+// API
+//=======================================================================================================================
+
+// Algorithm 1: Generate non-repeating combinations of size M in set of N
+// Usage:
+//   int p[3];
+//   hgn_comb_init( 3, p );
+//   
+//   do
+//   {
+//      something with p[0], p[1], p[2]
+//   }
+//   while( hgn_comb( 3, 5, p ) );
+//
+//   Output of p each iteration:
+//     0 1 2
+//     0 1 3
+//     0 1 4
+//     0 2 3
+//     0 2 4
+//     0 3 4
+//     1 2 3
+//     1 2 4
+//     1 3 4
+//     2 3 4
+
+void csr_comb_init( int const M, int p[] );
+int csr_comb( int M, int N, int p[] );
+
+// Implementation
+//=======================================================================================================================
+
+#ifdef CSR_EXECUTABLE
+
 void csr_comb_init( int const M, int p[] )
 {
        for( int i = 0; i < M; i ++ )
@@ -22,3 +58,5 @@ int csr_comb( int M, int N, int p[] )
        }
        return 0;
 }
+
+#endif
index 00346e444491d36e736ec116242787d3613b25c9..97fd8a54553966b80b7f94ac210c6e4001ef5857 100644 (file)
--- a/csrDraw.h
+++ b/csrDraw.h
@@ -1,9 +1,95 @@
-typedef struct csr_frag csr_frag;
+// Copyright (C) 2021 Harry Godden (hgn)
+
+// Extremely simple software renderer. Only supports orthographic
+//=======================================================================================================================
+
 typedef struct csr_target csr_target;
 typedef struct csr_filter csr_filter;
+typedef struct csr_shader csr_shader;
 typedef enum EMSAA EMSAA;
 
-typedef void (* csr_frag_shader)( v4f, vmf_vert[3], float, float, float );
+typedef void (* csr_frag_program)( void *, vmf_vert[3], float, float, float );
+typedef void (* csr_frag_clear)( void * );
+
+// API
+//=======================================================================================================================
+
+// Create a render target. Resolution, msaa, and shader must be known at this point!
+void csr_create_target( csr_target *rt, u32 x, u32 y, EMSAA aa, csr_shader *shader );
+void csr_rt_clear( csr_target *rt );
+void csr_rt_free( csr_target *rt );
+
+// Refit bounds so that it is square, and crops to center with padding
+void csr_auto_fit( csr_target *rt, float padding );
+
+// Run this after bounds have been adjusted on the RT to update the size of the msaa
+// Auto fit will call this.
+void csr_update_subsamples( csr_target *rt );
+
+// Write CS:GO radar txt
+void csr_write_txt( char const *path, const char *name, csr_target *rt  );
+
+// Render calls
+// ------------
+
+// Render a finalzied triangle into target. Coordinates are world space
+void simple_raster( csr_target *rt, vmf_vert tri[3] );
+
+// Draw a batch of triangles with an affine world transformation
+void csr_draw( csr_target *rt, vmf_vert *triangles, u32 triangle_count, m4x3f transform );
+
+// Draw VMF with filtering options. Will automatically branch into instances
+// You should call this with the last two recursive arguments (prev,inst), set to NULL
+//
+// Filter is optional, it can be st to NULL to just render everything.
+void csr_vmf_render( csr_target *rt, vmf_map *map, vdf_node *root, csr_filter *filter, m4x3f prev, m4x3f inst );
+
+// Obsolete
+void csr_rt_save_buffers( csr_target *rt, const char *basename, const char *subname );
+
+// Implementation
+//=======================================================================================================================
+
+struct csr_shader
+{
+       u32 stride;
+       csr_frag_program frag;
+       csr_frag_clear clear;
+};
+
+struct csr_target
+{
+       void  *colour;
+       float *depth;
+       
+       u32 x, y; 
+       boxf bounds;
+       float scale;
+       
+       v2f subsamples[ 8 ];
+       int num_samples;
+       v2f *sample_src;
+       
+       csr_shader *shader;
+};
+
+struct csr_filter
+{
+       const char *visgroup;           // Limit to this visgroup only
+       const char *classname;          // Limit to this exact classname. will not draw world
+       
+       int compute_bounds_only;
+};
+
+enum EMSAA
+{
+       k_EMSAA_none,
+       k_EMSAA_2x2,
+       k_EMSAA_RGSS,
+       k_EMSAA_8R
+};
+
+#ifdef CSR_EXECUTABLE
 
 // MSAA patterns
 v2f csr_msaa_1[] =
@@ -53,49 +139,8 @@ v2f csr_msaa_8rook[] =
        { -0x0.3p0f,  0x0.5p0f }
 };
 
-struct csr_frag
-{      
-       v4f colour;
-       float depth;
-};
-
-struct csr_target
-{
-       csr_frag *fragments;
-       
-       u32 x, y; 
-       boxf bounds;
-       float scale;
-       
-       v2f subsamples[ 8 ];
-       int num_samples;
-       v2f *sample_src;
-       
-       csr_frag_shader shader;
-};
-
-void csr_use_program( csr_target *rt, csr_frag_shader shader )
-{
-       rt->shader = shader;
-}
 
-struct csr_filter
-{
-       const char *visgroup;           // Limit to this visgroup only
-       const char *classname;          // Limit to this exact classname. will not draw world
-       
-       int compute_bounds_only;
-};
-
-enum EMSAA
-{
-       k_EMSAA_none,
-       k_EMSAA_2x2,
-       k_EMSAA_RGSS,
-       k_EMSAA_8R
-};
-
-void csr_create_target( csr_target *rt, u32 x, u32 y, EMSAA aa )
+void csr_create_target( csr_target *rt, u32 x, u32 y, EMSAA aa, csr_shader *shader )
 {
        rt->x = x;
        rt->y = y;
@@ -124,7 +169,9 @@ void csr_create_target( csr_target *rt, u32 x, u32 y, EMSAA aa )
                        break;
        }
        
-       rt->fragments = (csr_frag *)csr_malloc( x*y*sizeof(csr_frag)*rt->num_samples );
+       rt->shader = shader;
+       rt->depth = (float *)csr_malloc( x*y*rt->num_samples * sizeof(float) );
+       rt->colour = csr_malloc( x * y * rt->shader->stride * rt->num_samples );
        
        v3_fill( rt->bounds[0], INFINITY );
        v3_fill( rt->bounds[1], -INFINITY );
@@ -145,15 +192,16 @@ void csr_update_subsamples( csr_target *rt )
 
 void csr_rt_free( csr_target *rt )
 {
-       free( rt->fragments );
+       free( rt->depth );
+       free( rt->colour );
 }
 
 void csr_rt_clear( csr_target *rt )
 {
        for( u32 i = 0; i < rt->x*rt->y*rt->num_samples; i ++ )
        {
-               v4_zero( rt->fragments[ i ].colour );
-               rt->fragments[i].depth = 0.f;
+               rt->shader->clear( rt->colour + i * rt->shader->stride );       
+               rt->depth[i] = 0.f;
        }
 }
 
@@ -161,6 +209,7 @@ void csr_auto_fit( csr_target *rt, float padding )
 {
        // Correct aspect ratio to be square
        float dx, dy, l, cx, cy;
+
        dx = rt->bounds[1][0] - rt->bounds[0][0];
        dy = rt->bounds[1][1] - rt->bounds[0][1];
        
@@ -195,13 +244,6 @@ void csr_write_txt( char const *path, const char *name, csr_target *rt  )
        fclose( write_ptr );
 }
 
-void frag_gbuffer( v4f frag_colour, vmf_vert tri[3], float bca, float bcb, float bcc )
-{
-       v3_muls( tri[0].co, bca, frag_colour );
-       v3_muladds( frag_colour, tri[1].co, bcb, frag_colour );
-       v3_muladds( frag_colour, tri[2].co, bcc, frag_colour );
-}
-
 void simple_raster( csr_target *rt, vmf_vert tri[3] )
 {
        // Very very simplified rasterizing algorithm
@@ -242,7 +284,10 @@ void simple_raster( csr_target *rt, vmf_vert tri[3] )
                
                for( u32 px = start_x; px <= end_x; px ++ )
                {
-                       csr_frag *frag = &rt->fragments[ (py * rt->y + px) * rt->num_samples ];
+                       u32 sample_index = (py * rt->y + px) * rt->num_samples;
+               
+                       void *frag = rt->colour + sample_index*rt->shader->stride;
+                       float *depth = &rt->depth[ sample_index ];
 
                        trace_origin[0] = csr_lerpf( rt->bounds[0][0], rt->bounds[1][0], (float)px/(float)rt->x );
                        
@@ -271,10 +316,10 @@ void simple_raster( csr_target *rt, vmf_vert tri[3] )
                                
                                float hit = (tri[0].co[2] * bca + tri[1].co[2] * bcb + tri[2].co[2] * bcc) +16385.f;
                                
-                               if( hit > frag[i].depth )
+                               if( hit > depth[i] )
                                {
-                                       frag[i].depth = hit;
-                                       rt->shader( frag[i].colour, tri, bca, bcb, bcc );
+                                       depth[i] = hit;
+                                       rt->shader->frag( frag+i*rt->shader->stride, tri, bca, bcb, bcc );
                                }
                        }
                }
@@ -307,7 +352,7 @@ void csr_draw( csr_target *rt, vmf_vert *triangles, u32 triangle_count, m4x3f tr
        }
 }
 
-void draw_vmf_group( csr_target *rt, vmf_map *map, vdf_node *root, csr_filter *filter, m4x3f prev, m4x3f inst )
+void csr_vmf_render( csr_target *rt, vmf_map *map, vdf_node *root, csr_filter *filter, m4x3f prev, m4x3f inst )
 {
        m4x3f transform = M4X3_IDENTITY;
        vmf_solid solid;
@@ -405,7 +450,7 @@ void draw_vmf_group( csr_target *rt, vmf_map *map, vdf_node *root, csr_filter *f
                        m4x3_identity( model );
                        vmf_entity_transform( ent, model );
                        
-                       draw_vmf_group( rt, map, map->cache[ ent->user1 ].root, filter, transform, model );
+                       csr_vmf_render( rt, map, map->cache[ ent->user1 ].root, filter, transform, model );
                }
                else
                {
@@ -442,6 +487,7 @@ void draw_vmf_group( csr_target *rt, vmf_map *map, vdf_node *root, csr_filter *f
        solidgen_ctx_free( &solid );
 }
 
+// Obsolete
 void csr_rt_save_buffers( csr_target *rt, const char *basename, const char *subname )
 {
        char output[ 512 ];
@@ -455,14 +501,13 @@ void csr_rt_save_buffers( csr_target *rt, const char *basename, const char *subn
                for( int x = 0; x < rt->y; x ++ )
                {
                        float *dst = &image[ (l*1024+x)*3 ];
-                       csr_frag *src = &rt->fragments[ ((1023-l)*1024+x)*rt->num_samples ];
+                       void *src = rt->colour + ((1023-l)*1024+x) * rt->num_samples * rt->shader->stride;
                        
-                       v3_zero( dst );
-                       v3_muls( src[0].colour, contrib, dst );
+                       v3_muls( (float *)src, contrib, dst );
                        
                        for( int j = 1; j < rt->num_samples; j ++ )
                        {
-                               v3_muladds( dst, src[j].colour, contrib, dst );
+                               v3_muladds( dst, (float *)(src + j*rt->shader->stride), contrib, dst );
                        }
                }
        }
@@ -476,3 +521,5 @@ void csr_rt_save_buffers( csr_target *rt, const char *basename, const char *subn
        
        free( image );
 }
+
+#endif
diff --git a/csrIO.h b/csrIO.h
index 898b41a3d11977ea2e8b0062b8137b8edc06724b..76bed7e228fd138f0cc5652fad8ff3f4a30042c9 100644 (file)
--- a/csrIO.h
+++ b/csrIO.h
@@ -1,6 +1,36 @@
+// Copyright (C) 2021 Harry Godden (hgn)
+
 // Low level disk reading
 //=======================================================================================================================
 
+// Read binary, or text assets. _s variants also give size in bytes
+void *csr_asset_read_s( const char *path, i64 *size );
+void *csr_asset_read( const char *path );
+char *csr_textasset_read_s( const char *path, i64 *size );
+char *csr_textasset_read( const char *name );
+
+i64 fs_file_size( FILE *fileptr );
+
+// Path handling
+// -------------
+
+// Find file path extension, returns NULL if no ext (0x00)
+char *csr_findext( char *path, char const delim );
+
+// gets rid of extension on string only left with (folder)+filename
+void csr_stripext( char *path );
+
+int csr_path_is_abs( char const *path );
+
+// Convert windows paths to unix.. sortof ( \something\\blahblah .. ) -> /something/blahblah/
+// Does not handle drive letters, idea is to increase windows compatibility will the other functions above
+void csr_path_winunix( char *path );
+
+// Implementation
+//=======================================================================================================================
+
+#ifdef CSR_EXECUTABLE
+
 i64 fs_file_size( FILE *fileptr )
 {
        fseek( fileptr, 0, SEEK_END );
@@ -77,7 +107,6 @@ char *csr_textasset_read( const char *name )
        return fs_disk_load_text( name, &size );
 }
 
-// Find file path extension, returns NULL if no ext (0x00)
 char *csr_findext( char *path, char const delim )
 {
        char *c, *ptr;
@@ -98,7 +127,6 @@ char *csr_findext( char *path, char const delim )
        return ptr;
 }
 
-// gets rid of extension on string only left with folder/filename
 void csr_stripext( char *path )
 {
        char *point, *start;
@@ -118,7 +146,6 @@ void csr_stripext( char *path )
        }
 }
 
-// Convert windows paths to unix-ish ( \something\\blahblah .. ) -> /something/blahblah/
 void csr_path_winunix( char *path )
 {
        char *idx, *wr;
@@ -155,8 +182,4 @@ int csr_path_is_abs( char const *path )
 #endif
 }
 
-#ifdef _WIN32
- #define GetWorkingDir _getcwd
-#else
- #define GetWorkingDir getcwd
 #endif
index 42b16722aab0ec86279b85119647711c69c2e079..eea60ceec15ede3d57c8bc6b9bc3d18766cb8124 100644 (file)
--- a/csrLog.h
+++ b/csrLog.h
@@ -1,6 +1,15 @@
+// Copyright (C) 2021 Harry Godden (hgn)
+
 // Logging with colour
 // ======================================================================================
 
+void log_success( const char *fmt, ... );
+void log_info( const char *fmt, ... );
+void log_warn( const char *fmt, ... );
+void log_error( const char *fmt, ... );
+
+#ifdef CSR_EXECUTABLE
+
 #define KNRM  "\x1B[0m"
 #define KRED  "\x1B[31m"
 #define KGRN  "\x1B[32m"
 #define KCYN  "\x1B[36m"
 #define KWHT  "\x1B[37m"
 
-#define LOG_TYPE_DEV 0
-#define LOG_TYPE_INFO 1
-#define LOG_TYPE_ALLOC 2
-#define LOG_TYPE_FREE 3
-#define LOG_TYPE_SUCCESS 4
-#define LOG_TYPE_ERROR 5
-#define LOG_TYPE_WARN 6
-
-void(*CSR_LOG_REDIR_STDOUT)(int, const char*) = NULL;
-int CSR_LOG_ENABLE_STDOUT = 1;
-
-void csr_log_out( FILE *f, int type, const char* prefix, const char* fmt, ... )
-{
-       if( CSR_LOG_ENABLE_STDOUT )
-       {
-          fprintf( f, "%s", prefix );
-               va_list args;
-               va_start( args, fmt );
-               vfprintf( f, fmt, args );
-               va_end( args );
-               fprintf( f, KNRM ); // reset
-       }
-       
-       // Send to a seperate logging function
-       if( CSR_LOG_REDIR_STDOUT )
-       {
-               char buffer[ 512 ];
-               va_list args;
-               va_start( args, fmt );
-               vsnprintf( buffer, 512, fmt, args );
-               va_end( args );
-               CSR_LOG_REDIR_STDOUT( type, buffer );
-       }
-}
+#define CSR_LOG_WRITE( FILE, PREFIX )  \
+       fprintf( FILE, PREFIX );                                                                \
+       va_list args;                                                                                           \
+       va_start( args, fmt );                                                                  \
+       vfprintf( FILE, fmt, args );                                                    \
+       va_end( args );                                                                                         \
+       fprintf( FILE, KNRM );
 
-#define log_dev(FMT, ...)     csr_log_out( stdout, LOG_TYPE_DEV,     (KNRM "    dev" KWHT "| " KNRM), FMT, ##__VA_ARGS__ )
-#define log_info(FMT, ...)    csr_log_out( stdout, LOG_TYPE_INFO,    (KNRM "   info" KWHT "| " KNRM), FMT, ##__VA_ARGS__ )
-#define log_alloc(FMT, ...)   csr_log_out( stdout, LOG_TYPE_ALLOC,   (KCYN "  alloc" KWHT "| " KNRM), FMT, ##__VA_ARGS__ )
-#define log_free(FMT, ...)    csr_log_out( stdout, LOG_TYPE_FREE,    (KMAG "   free" KWHT "| " KNRM), FMT, ##__VA_ARGS__ )
-#define log_success(FMT, ...) csr_log_out( stdout, LOG_TYPE_SUCCESS, (KGRN "success" KWHT "| " KGRN), FMT, ##__VA_ARGS__ )
-#define log_error(FMT, ...)   csr_log_out( stderr, LOG_TYPE_ERROR,   (KRED "  error" KWHT "| " KRED), FMT, ##__VA_ARGS__ )
-#define log_warn(FMT, ...)    csr_log_out( stdout, LOG_TYPE_WARN,    (KYEL "   warn" KWHT "| " KYEL), FMT, ##__VA_ARGS__ )
-
-#define log_init log_alloc
-#define log_dealloc log_free
+void log_success( const char *fmt, ... ) { CSR_LOG_WRITE( stdout,      (KGRN "success" KWHT "| " KGRN) ); }
+void log_info( const char *fmt, ... )    { CSR_LOG_WRITE( stdout,      (KNRM "   info" KWHT "| " KNRM) ); }
+void log_warn( const char *fmt, ... )    { CSR_LOG_WRITE( stdout,      (KYEL "   warn" KWHT "| " KYEL) ); }
+void log_error( const char *fmt, ... )   { CSR_LOG_WRITE( stderr,      (KRED "  error" KWHT "| " KRED) ); }
 
+// TODO: Remove this?
 const char *csr_prog_msg;
 void csr_prog_begin( const char *msg )
 {
@@ -89,3 +66,5 @@ void csr_prog_end(void)
        csr_prog_update( 1.f );
        printf( "\n" );
 }
+
+#endif
diff --git a/csrMap.h b/csrMap.h
deleted file mode 100644 (file)
index e69de29..0000000
index 77733cf5afdca45b04fa2bc1b2c52b185a511e30..1555361cab68be25f694c6e73dfd27bf8f9a33a3 100644 (file)
--- a/csrMath.h
+++ b/csrMath.h
@@ -1,31 +1,34 @@
+// Copyright (C) 2021 Harry Godden (hgn)
+
 // Util
 // ==================================================================================================================
 
+#define CSR_INLINE static inline
 #define CSR_PIf 3.14159265358979323846264338327950288f
 
 // Simple min/max replacements
-float csr_minf( float a, float b )
+CSR_INLINE float csr_minf( float a, float b )
 {
        return a < b? a: b;
 }
 
-float csr_maxf( float a, float b )
+CSR_INLINE float csr_maxf( float a, float b )
 {
        return a > b? a: b;
 }
 
-int csr_min( int a, int b )
+CSR_INLINE int csr_min( int a, int b )
 {
        return a < b? a: b;
 }
 
-int csr_max( int a, int b )
+CSR_INLINE int csr_max( int a, int b )
 {
        return a > b? a: b;
 }
 
 // Convert double precision vec3 into single
-void v3d_v3f( double a[3], float b[3] )
+CSR_INLINE void v3d_v3f( double a[3], float b[3] )
 {
        b[0] = a[0];
        b[1] = a[1];
@@ -33,7 +36,7 @@ void v3d_v3f( double a[3], float b[3] )
 }
 
 // Convert degrees to radians
-float csr_rad( float deg )
+CSR_INLINE float csr_rad( float deg )
 {
        return deg * CSR_PIf / 180.0f;
 }
@@ -41,44 +44,44 @@ float csr_rad( float deg )
 // Vector 2
 // ==================================================================================================================
 
-void v2_copy( v2f a, v2f b )
+CSR_INLINE void v2_copy( v2f a, v2f b )
 {
        b[0] = a[0]; b[1] = a[1];
 }
 
-void v2_minv( v2f a, v2f b, v2f dest ) 
+CSR_INLINE void v2_minv( v2f a, v2f b, v2f dest ) 
 {
        dest[0] = csr_minf(a[0], b[0]);
        dest[1] = csr_minf(a[1], b[1]);
 }
 
-void v2_maxv( v2f a, v2f b, v2f dest ) 
+CSR_INLINE void v2_maxv( v2f a, v2f b, v2f dest ) 
 {
        dest[0] = csr_maxf(a[0], b[0]);
        dest[1] = csr_maxf(a[1], b[1]);
 }
 
-void v2_sub( v2f a, v2f b, v2f d )
+CSR_INLINE void v2_sub( v2f a, v2f b, v2f d )
 {
        d[0] = a[0]-b[0]; d[1] = a[1]-b[1];
 }
 
-float v2_cross( v2f a, v2f b )
+CSR_INLINE float v2_cross( v2f a, v2f b )
 {
        return a[0] * b[1] - a[1] * b[0];
 }
 
-void v2_add( v2f a, v2f b, v2f d )
+CSR_INLINE void v2_add( v2f a, v2f b, v2f d )
 {
        d[0] = a[0]+b[0]; d[1] = a[1]+b[1];
 }
 
-void v2_muls( v2f a, float s, v2f d )
+CSR_INLINE void v2_muls( v2f a, float s, v2f d )
 {
        d[0] = a[0]*s; d[1] = a[1]*s;
 }
 
-void v2_mul( v2f a, v2f b, v2f d )
+CSR_INLINE void v2_mul( v2f a, v2f b, v2f d )
 {
        d[0] = a[0]*b[0]; d[1] = a[1]*b[1];
 }
@@ -86,127 +89,127 @@ void v2_mul( v2f a, v2f b, v2f d )
 // Vector 3
 // ==================================================================================================================
 
-void v3_zero( v3f a )
+CSR_INLINE void v3_zero( v3f a )
 {
        a[0] = 0.f; a[1] = 0.f; a[2] = 0.f;
 }
 
-void v3_copy( v3f a, v3f b )
+CSR_INLINE void v3_copy( v3f a, v3f b )
 {
        b[0] = a[0]; b[1] = a[1]; b[2] = a[2];
 }
 
-void v3_add( v3f a, v3f b, v3f d )
+CSR_INLINE void v3_add( v3f a, v3f b, v3f d )
 {
        d[0] = a[0]+b[0]; d[1] = a[1]+b[1]; d[2] = a[2]+b[2];
 }
 
-void v3_sub( v3f a, v3f b, v3f d )
+CSR_INLINE void v3_sub( v3f a, v3f b, v3f d )
 {
        d[0] = a[0]-b[0]; d[1] = a[1]-b[1]; d[2] = a[2]-b[2];
 }
 
-void v3_mul( v3f a, v3f b, v3f d )
+CSR_INLINE void v3_mul( v3f a, v3f b, v3f d )
 {
        d[0] = a[0]*b[0]; d[1] = a[1]*b[1]; d[2] = a[2]*b[2];
 }
 
-void v3_div( v3f a, v3f b, v3f d )
+CSR_INLINE void v3_div( v3f a, v3f b, v3f d )
 {
        d[0] = a[0]/b[0]; d[1] = a[1]/b[1];     d[2] = a[2]/b[2];
 }
 
-void v3_muls( v3f a, float s, v3f d )
+CSR_INLINE void v3_muls( v3f a, float s, v3f d )
 {
        d[0] = a[0]*s; d[1] = a[1]*s; d[2] = a[2]*s;
 }
 
-void v3_divs( v3f a, float s, v3f d )
+CSR_INLINE void v3_divs( v3f a, float s, v3f d )
 {
        d[0] = a[0]/s; d[1] = a[1]/s; d[2] = a[2]/s;
 }
 
-void v3_muladds( v3f a, v3f b, float s, v3f d )
+CSR_INLINE void v3_muladds( v3f a, v3f b, float s, v3f d )
 {
        d[0] = a[0]+b[0]*s; d[1] = a[1]+b[1]*s; d[2] = a[2]+b[2]*s;
 }
 
-float v3_dot( v3f a, v3f b )
+CSR_INLINE float v3_dot( v3f a, v3f b )
 {
        return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
 }
 
-void v3_cross( v3f a, v3f b, v3f d )
+CSR_INLINE void v3_cross( v3f a, v3f b, v3f d )
 {
   d[0] = a[1] * b[2] - a[2] * b[1];
   d[1] = a[2] * b[0] - a[0] * b[2];
   d[2] = a[0] * b[1] - a[1] * b[0];
 }
 
-float v3_length2( v3f a )
+CSR_INLINE float v3_length2( v3f a )
 {
        return v3_dot( a, a );
 }
 
-float v3_length( v3f a )
+CSR_INLINE float v3_length( v3f a )
 {
        return sqrtf( v3_length2( a ) );
 }
 
-float v3_dist2( v3f a, v3f b )
+CSR_INLINE float v3_dist2( v3f a, v3f b )
 {
        v3f delta;
        v3_sub( a, b, delta );
        return v3_length2( delta );
 }
 
-float v3_dist( v3f a, v3f b )
+CSR_INLINE float v3_dist( v3f a, v3f b )
 {
        return sqrtf( v3_dist2( a, b ) );
 }
 
-void v3_normalize( v3f a )
+CSR_INLINE void v3_normalize( v3f a )
 {
        v3_muls( a, 1.f / v3_length( a ), a );
 }
 
-float csr_lerpf( float a, float b, float t )
+CSR_INLINE float csr_lerpf( float a, float b, float t )
 {
        return a + t*(b-a);
 }
 
-void v3_lerp( v3f a, v3f b, float t, v3f d )
+CSR_INLINE void v3_lerp( v3f a, v3f b, float t, v3f d )
 {
        d[0] = a[0] + t*(b[0]-a[0]);
        d[1] = a[1] + t*(b[1]-a[1]);
        d[2] = a[2] + t*(b[2]-a[2]);
 }
 
-void v3_minv( v3f a, v3f b, v3f dest ) 
+CSR_INLINE void v3_minv( v3f a, v3f b, v3f dest ) 
 {
        dest[0] = csr_minf(a[0], b[0]);
        dest[1] = csr_minf(a[1], b[1]);
        dest[2] = csr_minf(a[2], b[2]);
 }
 
-void v3_maxv( v3f a, v3f b, v3f dest ) 
+CSR_INLINE void v3_maxv( v3f a, v3f b, v3f dest ) 
 {
        dest[0] = csr_maxf(a[0], b[0]);
        dest[1] = csr_maxf(a[1], b[1]);
        dest[2] = csr_maxf(a[2], b[2]);
 }
 
-float v3_minf( v3f a )
+CSR_INLINE float v3_minf( v3f a )
 {
        return csr_minf( csr_minf( a[0], a[1] ), a[2] );
 }
 
-float v3_maxf( v3f a )
+CSR_INLINE float v3_maxf( v3f a )
 {
        return csr_maxf( csr_maxf( a[0], a[1] ), a[2] );
 }
 
-void v3_fill( v3f a, float v )
+CSR_INLINE void v3_fill( v3f a, float v )
 {
        a[0] = v;
        a[1] = v;
@@ -216,12 +219,12 @@ void v3_fill( v3f a, float v )
 // Vector 4
 // ==================================================================================================================
 
-void v4_copy( v4f a, v4f b )
+CSR_INLINE void v4_copy( v4f a, v4f b )
 {
        b[0] = a[0]; b[1] = a[1]; b[2] = a[2]; b[3] = a[3];
 }
 
-void v4_zero( v4f a )
+CSR_INLINE void v4_zero( v4f a )
 {
        a[0] = 0.f; a[1] = 0.f; a[2] = 0.f; a[3] = 0.f;
 }
@@ -229,7 +232,7 @@ void v4_zero( v4f a )
 // Matrix 3x3
 //======================================================================================================
 
-void m3x3_inv_transpose( m3x3f src, m3x3f dest )
+CSR_INLINE void m3x3_inv_transpose( m3x3f src, m3x3f dest )
 {
        float a = src[0][0], b = src[0][1], c = src[0][2],
                        d = src[1][0], e = src[1][1], f = src[1][2],
@@ -251,7 +254,7 @@ void m3x3_inv_transpose( m3x3f src, m3x3f dest )
        dest[2][2] =  (a*e-d*b)*det;
 }
 
-void m3x3_mulv( m3x3f m, v3f v, v3f d )
+CSR_INLINE void m3x3_mulv( m3x3f m, v3f v, v3f d )
 {
        v3f res;
        
@@ -270,14 +273,14 @@ void m3x3_mulv( m3x3f m, v3f v, v3f d )
                                                                { 0.0f, 0.0f, 1.0f, },\
                                                                { 0.0f, 0.0f, 0.0f }}
 
-void m4x3_to_3x3( m4x3f a, m3x3f b )
+CSR_INLINE void m4x3_to_3x3( m4x3f a, m3x3f b )
 {
        v3_copy( a[0], b[0] );
        v3_copy( a[1], b[1] );
        v3_copy( a[2], b[2] );
 }
 
-void m4x3_copy( m4x3f a, m4x3f b )
+CSR_INLINE void m4x3_copy( m4x3f a, m4x3f b )
 {
        v3_copy( a[0], b[0] );
        v3_copy( a[1], b[1] );
@@ -285,13 +288,13 @@ void m4x3_copy( m4x3f a, m4x3f b )
        v3_copy( a[3], b[3] );
 }
 
-void m4x3_identity( m4x3f a )
+CSR_INLINE void m4x3_identity( m4x3f a )
 {
        m4x3f id = M4X3_IDENTITY;
        m4x3_copy( id, a );
 }
 
-void m4x3_mul( m4x3f a, m4x3f b, m4x3f d ) 
+CSR_INLINE void m4x3_mul( m4x3f a, m4x3f b, m4x3f d ) 
 {
        float 
        a00 = a[0][0], a01 = a[0][1], a02 = a[0][2],
@@ -317,7 +320,7 @@ void m4x3_mul( m4x3f a, m4x3f b, m4x3f d )
        d[3][2] = a02*b30 + a12*b31 + a22*b32 + a32;
 }
 
-void m4x3_mulv( m4x3f m, v3f v, v3f d ) 
+CSR_INLINE void m4x3_mulv( m4x3f m, v3f v, v3f d ) 
 {
        v3f res;
   
@@ -330,21 +333,21 @@ void m4x3_mulv( m4x3f m, v3f v, v3f d )
 
 // Affine transforms
 
-void m4x3_translate( m4x3f m, v3f v )
+CSR_INLINE void m4x3_translate( m4x3f m, v3f v )
 {
        v3_muladds( m[3], m[0], v[0], m[3] );
        v3_muladds( m[3], m[1], v[1], m[3] );
        v3_muladds( m[3], m[2], v[2], m[3] );
 }
 
-void m4x3_scale( m4x3f m, float s )
+CSR_INLINE void m4x3_scale( m4x3f m, float s )
 {
        v3_muls( m[0], s, m[0] );
        v3_muls( m[1], s, m[1] );
        v3_muls( m[2], s, m[2] );
 }
 
-void m4x3_rotate_x( m4x3f m, float angle )
+CSR_INLINE void m4x3_rotate_x( m4x3f m, float angle )
 {
        m4x3f t = M4X3_IDENTITY;
        float c, s;
@@ -360,7 +363,7 @@ void m4x3_rotate_x( m4x3f m, float angle )
        m4x3_mul( m, t, m );
 }
 
-void m4x3_rotate_y( m4x3f m, float angle )
+CSR_INLINE void m4x3_rotate_y( m4x3f m, float angle )
 {
        m4x3f t = M4X3_IDENTITY;
        float c, s;
@@ -376,7 +379,7 @@ void m4x3_rotate_y( m4x3f m, float angle )
        m4x3_mul( m, t, m );
 }
 
-void m4x3_rotate_z( m4x3f m, float angle )
+CSR_INLINE void m4x3_rotate_z( m4x3f m, float angle )
 {
        m4x3f t = M4X3_IDENTITY;
        float c, s;
@@ -393,7 +396,7 @@ void m4x3_rotate_z( m4x3f m, float angle )
 }
 
 // Warning: These functions are unoptimized..
-void m4x3_expand_aabb_point( m4x3f m, boxf box, v3f point )
+CSR_INLINE void m4x3_expand_aabb_point( m4x3f m, boxf box, v3f point )
 {
        v3f v;
        m4x3_mulv( m, point, v );
@@ -402,19 +405,19 @@ void m4x3_expand_aabb_point( m4x3f m, boxf box, v3f point )
        v3_maxv( box[1], v, box[1] );
 }
 
-void box_concat( boxf a, boxf b )
+CSR_INLINE void box_concat( boxf a, boxf b )
 {
        v3_minv( a[0], b[0], a[0] );
        v3_maxv( a[1], b[1], a[1] );
 }
 
-void box_copy( boxf a, boxf b )
+CSR_INLINE void box_copy( boxf a, boxf b )
 {
        v3_copy( a[0], b[0] );
        v3_copy( a[1], b[1] );
 }
 
-void m4x3_transform_aabb( m4x3f m, boxf box )
+CSR_INLINE void m4x3_transform_aabb( m4x3f m, boxf box )
 {
        v3f a; v3f b;
        
@@ -436,7 +439,7 @@ void m4x3_transform_aabb( m4x3f m, boxf box )
 // Planes (double precision)
 // ==================================================================================================================
 
-void tri_to_plane( double a[3], double b[3], double c[3], double p[4] )
+CSR_INLINE void tri_to_plane( double a[3], double b[3], double c[3], double p[4] )
 {
        double edge0[3];
        double edge1[3];
@@ -462,7 +465,7 @@ void tri_to_plane( double a[3], double b[3], double c[3], double p[4] )
        p[2] = p[2] / l;
 }
 
-int plane_intersect( double a[4], double b[4], double c[4], double p[4] )
+CSR_INLINE int plane_intersect( double a[4], double b[4], double c[4], double p[4] )
 {
        double const epsilon = 1e-8f;
        
@@ -496,7 +499,7 @@ int plane_intersect( double a[4], double b[4], double c[4], double p[4] )
        return 1;
 }
 
-double plane_polarity( double p[4], double a[3] )
+CSR_INLINE double plane_polarity( double p[4], double a[3] )
 {
        return 
        (a[0] * p[0] + a[1] * p[1] + a[2] * p[2])
index 25913be651236abce298516b4f570cbc5828fb1d..46f4e7367e8dc0de9a10f3eb839545189712948a 100644 (file)
--- a/csrMem.h
+++ b/csrMem.h
@@ -1,7 +1,42 @@
-#ifndef CSR_MEM_H
-#define CSR_MEM_H
+// Copyright (C) 2021 Harry Godden (hgn)
 
-#include "csrTypes.h"
+// Memory API
+// ==================================================================================================================
+
+// Malloc call wrapper that will exit if out of memory (similar to xalloc)
+void *csr_malloc( size_t size );
+void *csr_calloc( size_t size );
+
+// Dynamic arrays (inspired by stb_stretchy_buffer)
+// ------------------------------------------------
+
+// Reserve x elements of size to this buffer. Must assign back (like realloc)
+__attribute__((warn_unused_result))
+void *csr_sb_reserve( void *arr, u32 amt, u32 esize );
+
+// Get index of next free data and increment count by 1
+void *csr_sb_use( void *arr );
+
+// Increment count by amt
+void csr_sb_inc( void *arr, u32 amt );
+
+u32 csr_sb_count( void *arr );
+void csr_sb_free( void *arr );
+
+// Does not clear memory / capacity, but resets count to 0
+void csr_sb_clear( void *arr );
+
+// Internal
+void *csr_sb_raw( void *arr );
+u32 csr_sb_cap( void *arr );
+
+// djb2 - Dan Bernstein
+unsigned long djb2( unsigned char const *str );
+
+// Implementation
+// ==================================================================================================================
+
+#ifdef CSR_EXECUTABLE
 
 void *csr_malloc( size_t size )
 {
@@ -50,7 +85,6 @@ void csr_sb_inc( void *arr, u32 amt )
        raw[1] += amt;
 }
 
-__attribute__((warn_unused_result))
 void *csr_sb_reserve( void *arr, u32 amt, u32 esize )
 {
        u32 cap = arr? csr_sb_cap( arr ): 0;
index e31c910d70de09298835de9a3c9cb4c76628ac55..922012295b3b5ad186580014756284ea5a1287c9 100644 (file)
--- a/csrOpt.h
+++ b/csrOpt.h
@@ -1,3 +1,7 @@
+// Copyright (C) 2021 Harry Godden (hgn)
+
+#ifdef CSR_EXECUTABLE
+
 // Supported:
 // -abc
 // -a value
@@ -173,3 +177,5 @@ char *csr_arg(void)
        
        return NULL;
 }
+
+#endif
diff --git a/csrPlatform.h b/csrPlatform.h
new file mode 100644 (file)
index 0000000..46f6513
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright (C) 2021 Harry Godden (hgn)
+
+// Cross platform (windows/unix) dynamic linking wrapper
+//=======================================================================================================================
+
+#ifdef CSR_EXECUTABLE
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+       #define CSR_WINDOWS
+       #include <libloaderapi.h>
+   typedef HWMODULE csr_so;
+#else
+   #define CSR_UNIX
+   #include <dlfcn.h>
+       typedef void *csr_so;
+#endif
+
+csr_so csr_libopen( const char *name )
+{
+       char path[ 512 ];
+       strcpy( path, "ext/" );
+       strcat( path, name );
+       
+       #ifdef CSR_UNIX
+               strcat( path, ".so" );
+       #else
+               strcat( path, ".dll" );
+       #endif
+       
+       log_info( "Loading dynamic library (%s)\n", path );
+
+       #ifdef CSR_UNIX
+               return dlopen( path, RTLD_NOW );
+       #else
+               return LoadLibrary( path );
+       #endif
+}
+
+void *csr_get_proc( csr_so so, const char *name )
+{
+       #ifdef CSR_UNIX
+               return dlsym( so, name );
+       #else
+               return (void *)GetProcAddress( so, name );
+       #endif
+}
+
+void csr_libclose( csr_so so )
+{
+       #ifdef CSR_UNIX
+               dlclose( so );
+       #else
+               FreeLibrary( so );
+       #endif
+}
+
+void csr_liberr(void)
+{
+       #ifdef CSR_UNIX
+       log_error( "Could not load that DLL (%s)\n", dlerror() );
+       #else
+       log_error( "Could not load that DLL (Windows unkown)\n" );
+       #endif
+}
+
+#endif
diff --git a/ext_csr_free.c b/ext_csr_free.c
new file mode 100644 (file)
index 0000000..5873802
--- /dev/null
@@ -0,0 +1,100 @@
+// Copyright (C) 2021 Harry Godden (hgn)
+
+// Basic buffers-only version of csRadar
+//=======================================================================================================================
+
+#include "csRadar.h"
+
+// GBuffer shader
+void frag_gbuffer( void *dest, vmf_vert tri[3], float bca, float bcb, float bcc );
+void frag_gbuffer_clear( void *dest );
+
+csr_shader shader_gbuffer =
+{
+       .stride = sizeof(float)*8, // (origin) x,y, (actual height) z
+       .frag = frag_gbuffer,
+       .clear = frag_gbuffer_clear
+};
+
+// Main drawing function
+void draw_buffers( csr_api *api, int bounds_only );
+
+// Extension implementation
+// =========================================================================================================
+
+// API ENTRY
+void csr_ext_main( csr_api *api )
+{
+       if( !csr_init( api ) )
+               return;
+       
+       csr_create_target( &api->target, api->resolution, api->resolution, api->sampling_mode, &shader_gbuffer );
+       csr_rt_clear( &api->target );
+       
+       // Compute bounds, collect models
+       draw_buffers( api, 1 );
+       csr_auto_fit( &api->target, api->padding );
+       vmf_load_models( api->map );
+       
+       // Draw everything
+       draw_buffers( api, 0 ); 
+}
+
+void csr_ext_exit( csr_api *api )
+{
+       csr_rt_free( &api->target );
+}
+
+void draw_buffers( csr_api *api, int bounds_only )
+{
+       csr_filter filter = { .compute_bounds_only = bounds_only };
+       vmf_map *map = api->map;
+
+       if( api->num_strings == 1 )
+       {
+               // Draw everything
+               csr_vmf_render( &api->target, map, map->root, &filter, NULL, NULL );
+               
+               if( !bounds_only )
+               {
+                       csr_rt_save_buffers( &api->target, api->output_path, "all" );
+               }
+       }
+       else
+       {
+               // Draw groups
+               for( int i = 1; i < api->num_strings; i ++ )
+               {
+                       filter.visgroup = api->strings[ i ];
+                       csr_vmf_render( &api->target, map, map->root, &filter, NULL, NULL );
+
+                       if( !bounds_only )
+                       {
+                               csr_rt_save_buffers( &api->target, api->output_path, api->strings[i] );                 
+                               //csr_rt_save_c32f( ... );
+                               //csr_rt_save_tga( ... );
+                               
+                               // tar_write_dds( ... );
+                               
+                               csr_rt_clear( &api->target );
+                       }
+               }
+       }
+}
+
+void frag_gbuffer( void *dest, vmf_vert tri[3], float bca, float bcb, float bcc )
+{
+       float *dest_colour = (float *)dest;
+
+       v3_muls( tri[0].co, bca, dest_colour );
+       v3_muladds( dest_colour, tri[1].co, bcb, dest_colour );
+       v3_muladds( dest_colour, tri[2].co, bcc, dest_colour );
+       
+       // TODO: Normal map
+}
+
+void frag_gbuffer_clear( void *dest )
+{
+       float *dest_colour = (float *)dest;
+       v3_zero( dest_colour );
+}
diff --git a/plugins/geometry_buffers.c b/plugins/geometry_buffers.c
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/vdf.h b/vdf.h
index cacf694557fdc5ad61544c194db74e347a1f15d1..fb242d13cd71239d34519ce583e9c2cf05cf0292 100644 (file)
--- a/vdf.h
+++ b/vdf.h
@@ -1,3 +1,11 @@
+// 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
+
+// VDF aka Keyvalue text format parser / writer
+
 #define vdf_foreach( NODE, STR, AS ) \
 int __vdf_it_##AS = 0; \
 vdf_node * AS;\
@@ -8,10 +16,6 @@ int __kv_it_##AS = 0; \
 const char * AS;\
 while( (AS = kv_iter( NODE, STR, &__kv_it_##AS )) )
 
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <ctype.h>
 
 // TYPES
 // ==================================================================================================================
@@ -63,6 +67,7 @@ void kv_double_array( vdf_node *node, const char *key, u32 count, double *arr );
 
 // INTERNAL API
 // ==================================================================================================================
+#ifdef VALVE_IMPLEMENTATION
 
 // Add keyvalue pair to node
 void vdf_kv_append( vdf_node *p, const char *k, const char *v );
@@ -86,6 +91,8 @@ void vdf_parse_feedbuffer( vdf_ctx *ctx, char *buf );
 // Formatting
 void vdf_out_indent( const int n, FILE *file );
 
+#endif
+
 // IMPLEMENTATION
 // ==================================================================================================================
 
@@ -108,6 +115,8 @@ struct vdf_node
        u32             user1;
 };
 
+#ifdef VALVE_IMPLEMENTATION
+
 vdf_node *vdf_next( vdf_node *node, const char *name, int *it )
 {      
        if( !node ) 
@@ -616,3 +625,5 @@ void vdf_print( vdf_node *node )
 {
        vdf_out( node, -1, 0, stdout );
 }
+
+#endif
index 4e4faa9aaa3ae76e5e5a3ff77173e1cbb7366932..be7e319ed39e9b3904caa3dd3d72946c2db1ffb3 100644 (file)
@@ -1,6 +1,24 @@
+// 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
+
 // Abstract Valve file system 
 //=======================================================================================================================
 
+// Initialize game directories / pakfile
+void fs_set_gameinfo( const char *path );
+void fs_exit(void);
+
+// Read asset as binary in full. Will search VPK, then searchpaths, or return NULL if not found
+char *valve_fs_get( const char *path );
+
+// Implementation
+//=======================================================================================================================
+
+#ifdef VALVE_IMPLEMENTATION
+
 struct valve_filesystem
 {
        char gamedir[ 512 ];
@@ -182,3 +200,5 @@ char *valve_fs_get( const char *path )
        
        return NULL;
 }
+
+#endif
diff --git a/vmdl.h b/vmdl.h
index d6564a3a87dfe4afbb5d1d2eb73d1bb663d51ab8..c558d0dbb45fb6152b1f02abbf3cbd007a0a2bf5 100644 (file)
--- a/vmdl.h
+++ b/vmdl.h
@@ -1,3 +1,38 @@
+// 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 mdl_mesh mdl_mesh_t;
+
+// High level API
+//=======================================================================================================================
+
+// Load model from vfs
+int mdl_from_find_files( const char *mdlname, mdl_mesh_t *ctx );
+void mdl_free( mdl_mesh_t *m );
+
+// Set ctx to blank / 0,0
+void mdl_error( mdl_mesh_t *m );
+
+// Implementation
+//=======================================================================================================================
+
+struct mdl_mesh
+{
+       u16  *indices;  
+       u32     num_indices;
+       
+       float *vertices;
+       u32     num_vertices;
+       
+       // Bounding box
+       boxf bounds;
+};
+
+#ifdef VALVE_IMPLEMENTATION
+
 // VVD
 //=======================================================================================================================
 //StudioMDL constants
@@ -453,19 +488,6 @@ mstudiobodyparts_t *studiohdr_pBodypart( studiohdr_t *t, int i )
 
 #pragma pack(pop)
 
-typedef struct 
-{
-       u16  *indices;  
-       u32     num_indices;
-       
-       float *vertices;
-       u32     num_vertices;
-       
-       // Bounding box
-       boxf bounds;
-} 
-mdl_mesh_t;
-
 void mdl_free( mdl_mesh_t *m )
 {
        free( m->indices );
@@ -596,3 +618,5 @@ int mdl_from_find_files( const char *mdlname, mdl_mesh_t *ctx )
        
        return 1;
 }
+
+#endif
diff --git a/vmf.h b/vmf.h
index 4829d48174599bb6906c802e0cfeef0446d3a20c..c5f736b4474977214d8ef543dbb79ba1029c4a0d 100644 (file)
--- a/vmf.h
+++ b/vmf.h
@@ -1,7 +1,8 @@
-#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;
@@ -12,6 +13,53 @@ typedef struct vmf_map vmf_map;
 
 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 );
+
+u32 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,
@@ -80,7 +128,7 @@ struct vmf_map
        m4x3f transform;
 };
 
-// IMPLEMENTATION
+#ifdef VALVE_IMPLEMENTATION
 
 void solidgen_ctx_reset( vmf_solid *ctx )
 {
@@ -802,3 +850,5 @@ int vmf_visgroup_match( vdf_node *ent, u32 target )
        
        return 0;
 }
+
+#endif
diff --git a/vpk.h b/vpk.h
index b6bd69daf272e69cf8997e18c1330a8b9e54bde7..436994d0f9c493299d02382b71ec5c65874830ce 100644 (file)
--- a/vpk.h
+++ b/vpk.h
@@ -1,8 +1,26 @@
+// 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
+
+// Valve pak file directory reader
+
 // VPK
 //=======================================================================================================================
 
+typedef struct VPKHeader VPKHeader;
+typedef struct VPKDirectoryEntry VPKDirectoryEntry;
+
+// API
+// ---
+
+// There is no load function, reading the header file as binary is enough.
+VPKDirectoryEntry *vpk_find( VPKHeader *self, const char *asset );
+void vpk_free( VPKHeader *self );
+
 #pragma pack(push, 1)
-typedef struct
+struct VPKHeader
 {
        u32 Signature;
        u32 Version;
@@ -11,10 +29,9 @@ typedef struct
        u32 ArchiveMD5SectionSize;
        u32 OtherMD5SectionSize;
        u32 SignatureSectionSize;
-} 
-VPKHeader;
+};
 
-typedef struct
+struct VPKDirectoryEntry
 {
        u32 CRC;
        u16 PreloadBytes; 
@@ -22,10 +39,11 @@ typedef struct
        u32 EntryOffset;
        u32 EntryLength;
        u16 Terminator;
-} 
-VPKDirectoryEntry;
+};
 #pragma pack(pop)
 
+#ifdef VALVE_IMPLEMENTATION
+
 void vpk_free( VPKHeader *self )
 {
        free( self );
@@ -86,3 +104,5 @@ VPKDirectoryEntry *vpk_find( VPKHeader *self, const char *asset )
        
        return NULL;
 }
+
+#endif