TRAIN BAR
[csRadar.git] / csRadar.c
1 #include <stdint.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <math.h>
6 #include <time.h>
7 #include <stdarg.h>
8
9
10 #include <unistd.h>
11
12 // CSR lib
13 #include "csrLog.h"
14 #include "csrOpt.h"
15 #include "csrTypes.h"
16 #include "csrMath.h"
17 #include "csrMem.h"
18 #include "csrIO.h"
19 #include "csrComb.h"
20
21 // Valve formats
22 #include "vdf.h"
23 #include "vpk.h"
24 #include "vfilesys.h"
25
26 #include "vmdl.h"
27 #include "vmf.h"
28
29 // CSR main
30 #include "csr32f.h"
31 #include "csrDraw.h"
32
33 #define CSR_VERSION "0.0.1"
34
35 // gcc -Wall -fsanitize=address csRadar.c -o csRadar -lm
36
37 int main( int argc, char *argv[] )
38 {
39 char *arg;
40 char *strings[ 20 ];
41 int num_strings = 0;
42
43 float padding = 128.f;
44 u32 resolution = 1024;
45 int write_txt = 1;
46 char output_path[ 512 ]; // Full path eg. /home/harry/my_map.vmf
47 char vmf_name[ 128 ]; // Just the base name eg. my_map
48 int output_set = 0;
49 EMSAA sampling_mode = k_EMSAA_RGSS;
50
51 while( csr_argp( argc, argv ) )
52 {
53 if( (arg = csr_arg()) )
54 {
55 if( num_strings == 20 )
56 {
57 log_error( "Too many arguments! Max 20\n" );
58 goto IL_CSR_EXIT;
59 }
60
61 strings[ num_strings ++ ] = arg;
62 }
63
64 if( (arg = csr_opt_arg( 'o' )) )
65 {
66 strcpy( output_path, arg );
67 csr_path_winunix( output_path );
68
69 output_set = 1;
70 }
71
72 if( (arg = csr_opt_arg( 'g' )) )
73 {
74 fs_set_gameinfo( arg );
75 }
76
77 if( (arg = csr_opt_arg( 'r' )) )
78 {
79 resolution = atoi( arg );
80 }
81
82 if( (arg = csr_long_opt_arg( "padding" )) )
83 {
84 padding = atof( arg );
85 }
86
87 if( (arg = csr_long_opt_arg( "multi-sample" )) )
88 {
89 if( !strcmp( arg, "none" ))
90 {
91 sampling_mode = k_EMSAA_none;
92 }
93 else if( !strcmp( arg, "rgss" ))
94 {
95 sampling_mode = k_EMSAA_RGSS;
96 }
97 else if( !strcmp( arg, "2x" ))
98 {
99 sampling_mode = k_EMSAA_2x2;
100 }
101 else if( !strcmp( arg, "8r" ))
102 {
103 sampling_mode = k_EMSAA_8R;
104 }
105 else
106 {
107 log_error( "Invalid sampling pattern '%s'\n", arg );
108 goto IL_CSR_EXIT;
109 }
110 }
111
112 if( csr_opt( 'v' ) || csr_long_opt( "version" ) )
113 {
114 printf( "csRadar version: " CSR_VERSION "\n" );
115 goto IL_CSR_EXIT;
116 }
117
118 if( csr_opt( 'h' ) || csr_long_opt( "help" ) )
119 {
120 // Display help
121 printf
122 (
123 "csRadar Copyright (C) 2021 Harry Godden (hgn)\n"
124 "\n"
125 "Usage: ./csRadar map.vmf -g \"/gamedir/gameinfo.txt\" layout cover\n"
126 " VMF file is first, then any other arguments (eg. layout, cover), will specify\n"
127 " visgroups to be rendered into individual files\n"
128 " No visgroups specified will simply draw everything\n"
129 "\n"
130 "Options:\n"
131 " -g <gameinfo.txt path> Required if you are loading models\n"
132 " -r 1024 Output resolution\n"
133 " -o <output> Specify output name/path\n"
134 " --padding=128 When cropping radar, add padding units to border\n"
135 //" --standard-layers Use standard TAR layers/groups\n"
136 " --no-txt Don't create matching radar txt\n"
137 " --multi-sample=RGSS [ none, 2x, rgss, 8r ]\n"
138 " --extension=TAR Use an extension binary instead\n"
139 "\n"
140 " -v --version Display program version\n"
141 " -h --help Display this help text\n"
142 );
143
144 goto IL_CSR_EXIT;
145 }
146 }
147
148 if( num_strings )
149 {
150 vmf_map *map = vmf_init( strings[0] );
151
152 if( map )
153 {
154 // Path handling
155 if( !output_set )
156 {
157 strcpy( output_path, strings[0] );
158 csr_stripext( output_path );
159 }
160
161 char *base_name;
162 if( !(base_name = csr_findext( output_path, '/' ) ))
163 {
164 base_name = output_path;
165 }
166
167 strcpy( vmf_name, base_name );
168
169 log_info( "output_path: '%s'\n", output_path );
170 log_info( "vmf_name: '%s'\n", vmf_name );
171
172 // Main
173 csr_target target;
174
175 csr_create_target( &target, resolution, resolution, sampling_mode );
176 csr_rt_clear( &target );
177
178 csr_use_program( &target, frag_gbuffer );
179
180 // Compute bounds
181 csr_filter filter =
182 {
183 .classname = NULL,
184 .visgroup = NULL,
185 .compute_bounds_only = 1
186 };
187
188 // One pass for fitting, second pass for drawing
189 for( int i = 0; i < 2; i ++ )
190 {
191 if( num_strings == 1 )
192 {
193 // Draw everything
194 draw_vmf_group( &target, map, map->root, &filter, NULL, NULL );
195 csr_rt_save_buffers( &target, output_path, "all" );
196 }
197 else
198 {
199 // Draw groups
200 for( int i = 1; i < num_strings; i ++ )
201 {
202 filter.visgroup = strings[ i ];
203
204 draw_vmf_group( &target, map, map->root, &filter, NULL, NULL );
205 csr_rt_save_buffers( &target, output_path, strings[i] );
206
207 csr_rt_clear( &target );
208 }
209 }
210
211 if( i == 0 )
212 {
213 filter.compute_bounds_only = 0;
214 csr_auto_fit( &target, padding );
215 vmf_load_models( map );
216 }
217 else
218 {
219 float prog = 0.f;
220 csr_prog_begin( "Rendering" );
221 for(;;)
222 {
223 if( prog > 1.f )
224 break;
225
226 csr_prog_update( prog );
227 usleep( 20000 );
228
229 prog += 0.01f;
230 }
231
232 csr_prog_end();
233 }
234 }
235
236 if( write_txt )
237 {
238 char txt_path[ 512 ];
239
240 strcpy( txt_path, output_path );
241 strcat( txt_path, ".txt" );
242
243 csr_write_txt( txt_path, vmf_name, &target );
244 }
245
246 csr_rt_free( &target );
247 vmf_free( map );
248 }
249 else
250 {
251 log_error( "Could not load VMF\n" );
252 }
253 }
254 else
255 {
256 log_error( "Missing required argument: mapfile\n" );
257 }
258
259 IL_CSR_EXIT:
260 fs_exit();
261 return 0;
262 }