From 8382aed7f0cdc38bc5c58832d4a15277cf56d4be Mon Sep 17 00:00:00 2001 From: hgn Date: Fri, 16 Jul 2021 11:42:05 +0100 Subject: [PATCH] finish up plugin architecture --- build.sh | 6 ++ csRadar.c | 215 +++++++++++++------------------------ csRadar.h | 70 ++++++++++++ csrComb.h | 38 +++++++ csrDraw.h | 177 +++++++++++++++++++----------- csrIO.h | 37 +++++-- csrLog.h | 67 ++++-------- csrMap.h | 0 csrMath.h | 119 ++++++++++---------- csrMem.h | 42 +++++++- csrOpt.h | 6 ++ csrPlatform.h | 66 ++++++++++++ ext_csr_free.c | 100 +++++++++++++++++ plugins/geometry_buffers.c | 0 vdf.h | 19 +++- vfilesys.h | 20 ++++ vmdl.h | 50 ++++++--- vmf.h | 60 ++++++++++- vpk.h | 32 ++++-- 19 files changed, 778 insertions(+), 346 deletions(-) create mode 100755 build.sh create mode 100644 csRadar.h delete mode 100644 csrMap.h create mode 100644 csrPlatform.h create mode 100644 ext_csr_free.c delete mode 100644 plugins/geometry_buffers.c diff --git a/build.sh b/build.sh new file mode 100755 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 diff --git a/csRadar.c b/csRadar.c index 5347d75..9af5cda 100644 --- a/csRadar.c +++ b/csRadar.c @@ -1,70 +1,41 @@ -#include -#include -#include -#include -#include -#include -#include - - -#include - -// 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 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 index 0000000..95e1048 --- /dev/null +++ b/csRadar.h @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include +#include + +// 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 diff --git a/csrComb.h b/csrComb.h index 1a549d4..92a1e0d 100644 --- 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 diff --git a/csrDraw.h b/csrDraw.h index 00346e4..97fd8a5 100644 --- 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 898b41a..76bed7e 100644 --- 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 diff --git a/csrLog.h b/csrLog.h index 42b1672..eea60ce 100644 --- 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" @@ -10,52 +19,20 @@ #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 index e69de29..0000000 diff --git a/csrMath.h b/csrMath.h index 77733cf..1555361 100644 --- 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]) diff --git a/csrMem.h b/csrMem.h index 25913be..46f4e73 100644 --- 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; diff --git a/csrOpt.h b/csrOpt.h index e31c910..9220122 100644 --- 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 index 0000000..46f6513 --- /dev/null +++ b/csrPlatform.h @@ -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 + typedef HWMODULE csr_so; +#else + #define CSR_UNIX + #include + 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 index 0000000..5873802 --- /dev/null +++ b/ext_csr_free.c @@ -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 index e69de29..0000000 diff --git a/vdf.h b/vdf.h index cacf694..fb242d1 100644 --- 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 -#include -#include -#include // 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 diff --git a/vfilesys.h b/vfilesys.h index 4e4faa9..be7e319 100644 --- a/vfilesys.h +++ b/vfilesys.h @@ -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 d6564a3..c558d0d 100644 --- 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 4829d48..c5f736b 100644 --- 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 b6bd69d..436994d 100644 --- 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 -- 2.25.1