1 /* -------------------------------------------------------------------------------
2
3 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
4 For a list of contributors, see the accompanying CONTRIBUTORS file.
5
6 This file is part of GtkRadiant.
7
8 GtkRadiant is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 GtkRadiant is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GtkRadiant; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
22 ----------------------------------------------------------------------------------
23
24 This code has been altered significantly from its original form, to support
25 several games based on the Quake III Arena engine, in the form of "Q3Map2."
26
27 ------------------------------------------------------------------------------- */
28
29
30
31 /* marker */
32 #define SURFACE_EXTRA_C
33
34
35
36 /* dependencies */
37 #include "q3map2.h"
38
39
40
41 /* -------------------------------------------------------------------------------
42
43 ydnar: srf file module
44
45 ------------------------------------------------------------------------------- */
46
47 typedef struct surfaceExtra_s
48 {
49 mapDrawSurface_t *mds;
50 shaderInfo_t *si;
51 int parentSurfaceNum;
52 int entityNum;
53 int castShadows, recvShadows;
54 int sampleSize;
55 float longestCurve;
56 vec3_t lightmapAxis;
57 }
58 surfaceExtra_t;
59
60 #define GROW_SURFACE_EXTRAS 1024
61
62 int numSurfaceExtras = 0;
63 int maxSurfaceExtras = 0;
64 surfaceExtra_t *surfaceExtras;
65 surfaceExtra_t seDefault = { NULL, NULL, -1, 0, WORLDSPAWN_CAST_SHADOWS, WORLDSPAWN_RECV_SHADOWS, 0, 0, { 0, 0, 0 } };
66
67
68
69 /*
70 AllocSurfaceExtra()
71 allocates a new extra storage
72 */
73
AllocSurfaceExtra(void)74 static surfaceExtra_t *AllocSurfaceExtra( void )
75 {
76 surfaceExtra_t *se;
77
78
79 /* enough space? */
80 if( numSurfaceExtras >= maxSurfaceExtras )
81 {
82 /* reallocate more room */
83 maxSurfaceExtras += GROW_SURFACE_EXTRAS;
84 se = safe_malloc( maxSurfaceExtras * sizeof( surfaceExtra_t ) );
85 if( surfaceExtras != NULL )
86 {
87 memcpy( se, surfaceExtras, numSurfaceExtras * sizeof( surfaceExtra_t ) );
88 free( surfaceExtras );
89 }
90 surfaceExtras = se;
91 }
92
93 /* add another */
94 se = &surfaceExtras[ numSurfaceExtras ];
95 numSurfaceExtras++;
96 memcpy( se, &seDefault, sizeof( surfaceExtra_t ) );
97
98 /* return it */
99 return se;
100 }
101
102
103
104 /*
105 SetDefaultSampleSize()
106 sets the default lightmap sample size
107 */
108
SetDefaultSampleSize(int sampleSize)109 void SetDefaultSampleSize( int sampleSize )
110 {
111 seDefault.sampleSize = sampleSize;
112 }
113
114
115
116 /*
117 SetSurfaceExtra()
118 stores extra (q3map2) data for the specific numbered drawsurface
119 */
120
SetSurfaceExtra(mapDrawSurface_t * ds,int num)121 void SetSurfaceExtra( mapDrawSurface_t *ds, int num )
122 {
123 surfaceExtra_t *se;
124
125
126 /* dummy check */
127 if( ds == NULL || num < 0 )
128 return;
129
130 /* get a new extra */
131 se = AllocSurfaceExtra();
132
133 /* copy out the relevant bits */
134 se->mds = ds;
135 se->si = ds->shaderInfo;
136 se->parentSurfaceNum = ds->parent != NULL ? ds->parent->outputNum : -1;
137 se->entityNum = ds->entityNum;
138 se->castShadows = ds->castShadows;
139 se->recvShadows = ds->recvShadows;
140 se->sampleSize = ds->sampleSize;
141 se->longestCurve = ds->longestCurve;
142 VectorCopy( ds->lightmapAxis, se->lightmapAxis );
143
144 /* debug code */
145 //% Sys_FPrintf( SYS_VRB, "SetSurfaceExtra(): entityNum = %d\n", ds->entityNum );
146 }
147
148
149
150 /*
151 GetSurfaceExtra*()
152 getter functions for extra surface data
153 */
154
GetSurfaceExtra(int num)155 static surfaceExtra_t *GetSurfaceExtra( int num )
156 {
157 if( num < 0 || num >= numSurfaceExtras )
158 return &seDefault;
159 return &surfaceExtras[ num ];
160 }
161
162
GetSurfaceExtraShaderInfo(int num)163 shaderInfo_t *GetSurfaceExtraShaderInfo( int num )
164 {
165 surfaceExtra_t *se = GetSurfaceExtra( num );
166 return se->si;
167 }
168
169
GetSurfaceExtraParentSurfaceNum(int num)170 int GetSurfaceExtraParentSurfaceNum( int num )
171 {
172 surfaceExtra_t *se = GetSurfaceExtra( num );
173 return se->parentSurfaceNum;
174 }
175
176
GetSurfaceExtraEntityNum(int num)177 int GetSurfaceExtraEntityNum( int num )
178 {
179 surfaceExtra_t *se = GetSurfaceExtra( num );
180 return se->entityNum;
181 }
182
183
GetSurfaceExtraCastShadows(int num)184 int GetSurfaceExtraCastShadows( int num )
185 {
186 surfaceExtra_t *se = GetSurfaceExtra( num );
187 return se->castShadows;
188 }
189
190
GetSurfaceExtraRecvShadows(int num)191 int GetSurfaceExtraRecvShadows( int num )
192 {
193 surfaceExtra_t *se = GetSurfaceExtra( num );
194 return se->recvShadows;
195 }
196
197
GetSurfaceExtraSampleSize(int num)198 int GetSurfaceExtraSampleSize( int num )
199 {
200 surfaceExtra_t *se = GetSurfaceExtra( num );
201 return se->sampleSize;
202 }
203
204
GetSurfaceExtraLongestCurve(int num)205 float GetSurfaceExtraLongestCurve( int num )
206 {
207 surfaceExtra_t *se = GetSurfaceExtra( num );
208 return se->longestCurve;
209 }
210
211
GetSurfaceExtraLightmapAxis(int num,vec3_t lightmapAxis)212 void GetSurfaceExtraLightmapAxis( int num, vec3_t lightmapAxis )
213 {
214 surfaceExtra_t *se = GetSurfaceExtra( num );
215 VectorCopy( se->lightmapAxis, lightmapAxis );
216 }
217
218
219
220
221 /*
222 WriteSurfaceExtraFile()
223 writes out a surface info file (<map>.srf)
224 */
225
WriteSurfaceExtraFile(const char * path)226 void WriteSurfaceExtraFile( const char *path )
227 {
228 char srfPath[ 1024 ];
229 FILE *sf;
230 surfaceExtra_t *se;
231 int i;
232
233
234 /* dummy check */
235 if( path == NULL || path[ 0 ] == '\0' )
236 return;
237
238 /* note it */
239 Sys_Printf( "--- WriteSurfaceExtraFile ---\n" );
240
241 /* open the file */
242 strcpy( srfPath, path );
243 StripExtension( srfPath );
244 strcat( srfPath, ".srf" );
245 Sys_Printf( "Writing %s\n", srfPath );
246 sf = fopen( srfPath, "w" );
247 if( sf == NULL )
248 Error( "Error opening %s for writing", srfPath );
249
250 /* lap through the extras list */
251 for( i = -1; i < numSurfaceExtras; i++ )
252 {
253 /* get extra */
254 se = GetSurfaceExtra( i );
255
256 /* default or surface num? */
257 if( i < 0 )
258 fprintf( sf, "default" );
259 else
260 fprintf( sf, "%d", i );
261
262 /* valid map drawsurf? */
263 if( se->mds == NULL )
264 fprintf( sf, "\n" );
265 else
266 {
267 fprintf( sf, " // %s V: %d I: %d %s\n",
268 surfaceTypes[ se->mds->type ],
269 se->mds->numVerts,
270 se->mds->numIndexes,
271 (se->mds->planar ? "planar" : "") );
272 }
273
274 /* open braces */
275 fprintf( sf, "{\n" );
276
277 /* shader */
278 if( se->si != NULL )
279 fprintf( sf, "\tshader %s\n", se->si->shader );
280
281 /* parent surface number */
282 if( se->parentSurfaceNum != seDefault.parentSurfaceNum )
283 fprintf( sf, "\tparent %d\n", se->parentSurfaceNum );
284
285 /* entity number */
286 if( se->entityNum != seDefault.entityNum )
287 fprintf( sf, "\tentity %d\n", se->entityNum );
288
289 /* cast shadows */
290 if( se->castShadows != seDefault.castShadows || se == &seDefault )
291 fprintf( sf, "\tcastShadows %d\n", se->castShadows );
292
293 /* recv shadows */
294 if( se->recvShadows != seDefault.recvShadows || se == &seDefault )
295 fprintf( sf, "\treceiveShadows %d\n", se->recvShadows );
296
297 /* lightmap sample size */
298 if( se->sampleSize != seDefault.sampleSize || se == &seDefault )
299 fprintf( sf, "\tsampleSize %d\n", se->sampleSize );
300
301 /* longest curve */
302 if( se->longestCurve != seDefault.longestCurve || se == &seDefault )
303 fprintf( sf, "\tlongestCurve %f\n", se->longestCurve );
304
305 /* lightmap axis vector */
306 if( VectorCompare( se->lightmapAxis, seDefault.lightmapAxis ) == qfalse )
307 fprintf( sf, "\tlightmapAxis ( %f %f %f )\n", se->lightmapAxis[ 0 ], se->lightmapAxis[ 1 ], se->lightmapAxis[ 2 ] );
308
309 /* close braces */
310 fprintf( sf, "}\n\n" );
311 }
312
313 /* close the file */
314 fclose( sf );
315 }
316
317
318
319 /*
320 LoadSurfaceExtraFile()
321 reads a surface info file (<map>.srf)
322 */
323
LoadSurfaceExtraFile(const char * path)324 void LoadSurfaceExtraFile( const char *path )
325 {
326 char srfPath[ 1024 ];
327 surfaceExtra_t *se;
328 int surfaceNum, size;
329 byte *buffer;
330
331
332 /* dummy check */
333 if( path == NULL || path[ 0 ] == '\0' )
334 return;
335
336 /* load the file */
337 strcpy( srfPath, path );
338 StripExtension( srfPath );
339 strcat( srfPath, ".srf" );
340 Sys_Printf( "Loading %s\n", srfPath );
341 size = LoadFile( srfPath, (void**) &buffer );
342 if( size <= 0 )
343 {
344 Sys_Printf( "WARNING: Unable to find surface file %s, using defaults.\n", srfPath );
345 return;
346 }
347
348 /* parse the file */
349 ParseFromMemory( buffer, size );
350
351 /* tokenize it */
352 while( 1 )
353 {
354 /* test for end of file */
355 if( !GetToken( qtrue ) )
356 break;
357
358 /* default? */
359 if( !Q_stricmp( token, "default" ) )
360 se = &seDefault;
361
362 /* surface number */
363 else
364 {
365 surfaceNum = atoi( token );
366 if( surfaceNum < 0 || surfaceNum > MAX_MAP_DRAW_SURFS )
367 Error( "ReadSurfaceExtraFile(): %s, line %d: bogus surface num %d", srfPath, scriptline, surfaceNum );
368 while( surfaceNum >= numSurfaceExtras )
369 se = AllocSurfaceExtra();
370 se = &surfaceExtras[ surfaceNum ];
371 }
372
373 /* handle { } section */
374 if( !GetToken( qtrue ) || strcmp( token, "{" ) )
375 Error( "ReadSurfaceExtraFile(): %s, line %d: { not found", srfPath, scriptline );
376 while( 1 )
377 {
378 if( !GetToken( qtrue ) )
379 break;
380 if( !strcmp( token, "}" ) )
381 break;
382
383 /* shader */
384 if( !Q_stricmp( token, "shader" ) )
385 {
386 GetToken( qfalse );
387 se->si = ShaderInfoForShader( token );
388 }
389
390 /* parent surface number */
391 else if( !Q_stricmp( token, "parent" ) )
392 {
393 GetToken( qfalse );
394 se->parentSurfaceNum = atoi( token );
395 }
396
397 /* entity number */
398 else if( !Q_stricmp( token, "entity" ) )
399 {
400 GetToken( qfalse );
401 se->entityNum = atoi( token );
402 }
403
404 /* cast shadows */
405 else if( !Q_stricmp( token, "castShadows" ) )
406 {
407 GetToken( qfalse );
408 se->castShadows = atoi( token );
409 }
410
411 /* recv shadows */
412 else if( !Q_stricmp( token, "receiveShadows" ) )
413 {
414 GetToken( qfalse );
415 se->recvShadows = atoi( token );
416 }
417
418 /* lightmap sample size */
419 else if( !Q_stricmp( token, "sampleSize" ) )
420 {
421 GetToken( qfalse );
422 se->sampleSize = atoi( token );
423 }
424
425 /* longest curve */
426 else if( !Q_stricmp( token, "longestCurve" ) )
427 {
428 GetToken( qfalse );
429 se->longestCurve = atof( token );
430 }
431
432 /* lightmap axis vector */
433 else if( !Q_stricmp( token, "lightmapAxis" ) )
434 Parse1DMatrix( 3, se->lightmapAxis );
435
436 /* ignore all other tokens on the line */
437 while( TokenAvailable() )
438 GetToken( qfalse );
439 }
440 }
441
442 /* free the buffer */
443 free( buffer );
444 }
445
446