command line, multisampling, optimisations
[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
8 // CSR lib
9 #include "csrOpt.h"
10 #include "csrTypes.h"
11 #include "csrMath.h"
12 #include "csrMem.h"
13 #include "csrIO.h"
14 #include "csrComb.h"
15
16 // Valve formats
17 #include "vdf.h"
18 #include "vpk.h"
19 #include "vfilesys.h"
20
21 #include "vmdl.h"
22 #include "vmf.h"
23
24 // CSR main
25 #include "csr32f.h"
26 #include "csrDraw.h"
27
28 #define CSR_VERSION "0.0.1"
29
30 // gcc -Wall -fsanitize=address csRadar.c -o csRadar -lm
31
32 int main( int argc, char *argv[] )
33 {
34 char *arg;
35 char *strings[ 20 ];
36 int num_strings = 0;
37
38 float padding = 128.f;
39 u32 resolution = 1024;
40 int standard_layers = 0;
41 int write_txt = 1;
42 int multi_sample = 1;
43 char output_path[ 512 ]; // Full path eg. /home/harry/my_map.vmf
44 char vmf_name[ 128 ]; // Just the base name eg. my_map
45 int output_set = 0;
46
47 while( csr_argp( argc, argv ) )
48 {
49 if( (arg = csr_arg()) )
50 {
51 if( num_strings == 20 )
52 {
53 fprintf( stderr, "Too many arguments! Max 20\n" );
54 fs_exit();
55 exit(0);
56 }
57
58 strings[ num_strings ++ ] = arg;
59 }
60
61 if( (arg = csr_opt_arg( 'o' )) )
62 {
63 strcpy( output_path, arg );
64 csr_path_winunix( output_path );
65
66 output_set = 1;
67 }
68
69 if( (arg = csr_opt_arg( 'g' )) )
70 {
71 fs_set_gameinfo( arg );
72 }
73
74 if( (arg = csr_opt_arg( 'r' )) )
75 {
76 resolution = atoi( arg );
77 }
78
79 if( (arg = csr_long_opt_arg( "padding" )) )
80 {
81 padding = atof( arg );
82 }
83
84 if( csr_opt( 'v' ) || csr_long_opt( "version" ) )
85 {
86 printf( "csRadar version: " CSR_VERSION "\n" );
87 return 0;
88 }
89
90 if( csr_opt( 'h' ) || csr_long_opt( "help" ) )
91 {
92 // Display help
93 printf
94 (
95 "csRadar Copyright (C) 2021 Harry Godden (hgn)\n"
96 "\n"
97 "Usage: ./csRadar map.vmf -g \"/gamedir/gameinfo.txt\" layout cover\n"
98 " VMF file is first, then any other arguments (eg. layout, cover), will specify\n"
99 " visgroups to be rendered into individual files\n"
100 " No visgroups specified will simply draw everything\n"
101 "\n"
102 "Options:\n"
103 " -g <gameinfo.txt path> Required if you are loading models\n"
104 " -r 1024 Output resolution\n"
105 " -o <output> Specify output name/path\n"
106 " --padding=128 When cropping radar, add padding units to border\n"
107 " --standard-layers Use standard TAR layers/groups\n"
108 " --no-txt Don't create matching radar txt\n"
109 " --multi-sample= [ none, 2, 4, 4r, 8kn (default), 16c ]\n"
110 "\n"
111 " -v --version Display program version\n"
112 " -h --help Display this help text\n"
113 );
114
115 return 0;
116 }
117 }
118
119 if( num_strings )
120 {
121 vmf_map *map = vmf_init( strings[0], 1 );
122
123 if( map )
124 {
125 // Path handling
126 if( !output_set )
127 {
128 strcpy( output_path, strings[0] );
129 csr_stripext( output_path );
130 }
131
132 char *base_name;
133 if( !(base_name = csr_findext( output_path, '/' ) ))
134 {
135 base_name = output_path;
136 }
137
138 strcpy( vmf_name, base_name );
139
140 printf( "output_path: '%s'\nvmf_name: '%s'\n", output_path, vmf_name );
141
142
143 // Main
144
145 csr_target target;
146
147 csr_create_target( &target, resolution, resolution );
148 csr_rt_clear( &target );
149
150 // Compute bounds
151 csr_filter filter =
152 {
153 .classname = NULL,
154 .visgroup = NULL,
155 .compute_bounds_only = 1
156 };
157 draw_vmf_group( &target, map, map->root, &filter, NULL, NULL );
158 csr_auto_fit( &target, padding );
159 filter.compute_bounds_only = 0;
160
161 if( num_strings == 1 )
162 {
163 // Draw everything
164 draw_vmf_group( &target, map, map->root, NULL, NULL, NULL );
165 csr_rt_save_buffers( &target, output_path, "all" );
166 }
167 else
168 {
169 // Draw groups
170 for( int i = 1; i < num_strings; i ++ )
171 {
172 filter.visgroup = strings[ i ];
173
174 draw_vmf_group( &target, map, map->root, NULL, NULL, NULL );
175 csr_rt_save_buffers( &target, output_path, strings[i] );
176
177 csr_rt_clear( &target );
178 }
179 }
180
181 if( write_txt )
182 {
183 char txt_path[ 512 ];
184
185 strcpy( txt_path, output_path );
186 strcat( txt_path, ".txt" );
187
188 csr_write_txt( txt_path, vmf_name, &target );
189 }
190
191 csr_rt_free( &target );
192 vmf_free( map );
193 }
194 else
195 {
196 fprintf( stderr, "Could not load VMF\n" );
197 }
198 }
199 else
200 {
201 fprintf( stderr, "Missing required argument: mapfile\n" );
202 }
203
204 fs_exit();
205
206 return 0;
207 }