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