1 /* -------------------------------------------------------------------------------
2
3 Copyright (C) 1999-2007 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 surfaceExtra_t *se;
76
77
78 /* enough space? */
79 if ( numSurfaceExtras >= maxSurfaceExtras ) {
80 /* reallocate more room */
81 maxSurfaceExtras += GROW_SURFACE_EXTRAS;
82 se = safe_malloc( maxSurfaceExtras * sizeof( surfaceExtra_t ) );
83 if ( surfaceExtras != NULL ) {
84 memcpy( se, surfaceExtras, numSurfaceExtras * sizeof( surfaceExtra_t ) );
85 free( surfaceExtras );
86 }
87 surfaceExtras = se;
88 }
89
90 /* add another */
91 se = &surfaceExtras[ numSurfaceExtras ];
92 numSurfaceExtras++;
93 memcpy( se, &seDefault, sizeof( surfaceExtra_t ) );
94
95 /* return it */
96 return se;
97 }
98
99
100
101 /*
102 SetDefaultSampleSize()
103 sets the default lightmap sample size
104 */
105
SetDefaultSampleSize(int sampleSize)106 void SetDefaultSampleSize( int sampleSize ){
107 seDefault.sampleSize = sampleSize;
108 }
109
110
111
112 /*
113 SetSurfaceExtra()
114 stores extra (q3map2) data for the specific numbered drawsurface
115 */
116
SetSurfaceExtra(mapDrawSurface_t * ds,int num)117 void SetSurfaceExtra( mapDrawSurface_t *ds, int num ){
118 surfaceExtra_t *se;
119
120
121 /* dummy check */
122 if ( ds == NULL || num < 0 ) {
123 return;
124 }
125
126 /* get a new extra */
127 se = AllocSurfaceExtra();
128
129 /* copy out the relevant bits */
130 se->mds = ds;
131 se->si = ds->shaderInfo;
132 se->parentSurfaceNum = ds->parent != NULL ? ds->parent->outputNum : -1;
133 se->entityNum = ds->entityNum;
134 se->castShadows = ds->castShadows;
135 se->recvShadows = ds->recvShadows;
136 se->sampleSize = ds->sampleSize;
137 se->longestCurve = ds->longestCurve;
138 VectorCopy( ds->lightmapAxis, se->lightmapAxis );
139
140 /* debug code */
141 //% Sys_FPrintf( SYS_VRB, "SetSurfaceExtra(): entityNum = %d\n", ds->entityNum );
142 }
143
144
145
146 /*
147 GetSurfaceExtra*()
148 getter functions for extra surface data
149 */
150
GetSurfaceExtra(int num)151 static surfaceExtra_t *GetSurfaceExtra( int num ){
152 if ( num < 0 || num >= numSurfaceExtras ) {
153 return &seDefault;
154 }
155 return &surfaceExtras[ num ];
156 }
157
158
GetSurfaceExtraShaderInfo(int num)159 shaderInfo_t *GetSurfaceExtraShaderInfo( int num ){
160 surfaceExtra_t *se = GetSurfaceExtra( num );
161 return se->si;
162 }
163
164
GetSurfaceExtraParentSurfaceNum(int num)165 int GetSurfaceExtraParentSurfaceNum( int num ){
166 surfaceExtra_t *se = GetSurfaceExtra( num );
167 return se->parentSurfaceNum;
168 }
169
170
GetSurfaceExtraEntityNum(int num)171 int GetSurfaceExtraEntityNum( int num ){
172 surfaceExtra_t *se = GetSurfaceExtra( num );
173 return se->entityNum;
174 }
175
176
GetSurfaceExtraCastShadows(int num)177 int GetSurfaceExtraCastShadows( int num ){
178 surfaceExtra_t *se = GetSurfaceExtra( num );
179 return se->castShadows;
180 }
181
182
GetSurfaceExtraRecvShadows(int num)183 int GetSurfaceExtraRecvShadows( int num ){
184 surfaceExtra_t *se = GetSurfaceExtra( num );
185 return se->recvShadows;
186 }
187
188
GetSurfaceExtraSampleSize(int num)189 int GetSurfaceExtraSampleSize( int num ){
190 surfaceExtra_t *se = GetSurfaceExtra( num );
191 return se->sampleSize;
192 }
193
194
GetSurfaceExtraLongestCurve(int num)195 float GetSurfaceExtraLongestCurve( int num ){
196 surfaceExtra_t *se = GetSurfaceExtra( num );
197 return se->longestCurve;
198 }
199
200
GetSurfaceExtraLightmapAxis(int num,vec3_t lightmapAxis)201 void GetSurfaceExtraLightmapAxis( int num, vec3_t lightmapAxis ){
202 surfaceExtra_t *se = GetSurfaceExtra( num );
203 VectorCopy( se->lightmapAxis, lightmapAxis );
204 }
205
206
207
208
209 /*
210 WriteSurfaceExtraFile()
211 writes out a surface info file (<map>.srf)
212 */
213
WriteSurfaceExtraFile(const char * path)214 void WriteSurfaceExtraFile( const char *path ){
215 char srfPath[ 1024 ];
216 FILE *sf;
217 surfaceExtra_t *se;
218 int i;
219
220
221 /* dummy check */
222 if ( path == NULL || path[ 0 ] == '\0' ) {
223 return;
224 }
225
226 /* note it */
227 Sys_Printf( "--- WriteSurfaceExtraFile ---\n" );
228
229 /* open the file */
230 strcpy( srfPath, path );
231 StripExtension( srfPath );
232 strcat( srfPath, ".srf" );
233 Sys_Printf( "Writing %s\n", srfPath );
234 sf = fopen( srfPath, "w" );
235 if ( sf == NULL ) {
236 Error( "Error opening %s for writing", srfPath );
237 }
238
239 /* lap through the extras list */
240 for ( i = -1; i < numSurfaceExtras; i++ )
241 {
242 /* get extra */
243 se = GetSurfaceExtra( i );
244
245 /* default or surface num? */
246 if ( i < 0 ) {
247 fprintf( sf, "default" );
248 }
249 else{
250 fprintf( sf, "%d", i );
251 }
252
253 /* valid map drawsurf? */
254 if ( se->mds == NULL ) {
255 fprintf( sf, "\n" );
256 }
257 else
258 {
259 fprintf( sf, " // %s V: %d I: %d %s\n",
260 surfaceTypes[ se->mds->type ],
261 se->mds->numVerts,
262 se->mds->numIndexes,
263 ( se->mds->planar ? "planar" : "" ) );
264 }
265
266 /* open braces */
267 fprintf( sf, "{\n" );
268
269 /* shader */
270 if ( se->si != NULL ) {
271 fprintf( sf, "\tshader %s\n", se->si->shader );
272 }
273
274 /* parent surface number */
275 if ( se->parentSurfaceNum != seDefault.parentSurfaceNum ) {
276 fprintf( sf, "\tparent %d\n", se->parentSurfaceNum );
277 }
278
279 /* entity number */
280 if ( se->entityNum != seDefault.entityNum ) {
281 fprintf( sf, "\tentity %d\n", se->entityNum );
282 }
283
284 /* cast shadows */
285 if ( se->castShadows != seDefault.castShadows || se == &seDefault ) {
286 fprintf( sf, "\tcastShadows %d\n", se->castShadows );
287 }
288
289 /* recv shadows */
290 if ( se->recvShadows != seDefault.recvShadows || se == &seDefault ) {
291 fprintf( sf, "\treceiveShadows %d\n", se->recvShadows );
292 }
293
294 /* lightmap sample size */
295 if ( se->sampleSize != seDefault.sampleSize || se == &seDefault ) {
296 fprintf( sf, "\tsampleSize %d\n", se->sampleSize );
297 }
298
299 /* longest curve */
300 if ( se->longestCurve != seDefault.longestCurve || se == &seDefault ) {
301 fprintf( sf, "\tlongestCurve %f\n", se->longestCurve );
302 }
303
304 /* lightmap axis vector */
305 if ( VectorCompare( se->lightmapAxis, seDefault.lightmapAxis ) == qfalse ) {
306 fprintf( sf, "\tlightmapAxis ( %f %f %f )\n", se->lightmapAxis[ 0 ], se->lightmapAxis[ 1 ], se->lightmapAxis[ 2 ] );
307 }
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 char srfPath[ 1024 ];
326 surfaceExtra_t *se;
327 int surfaceNum, size;
328 byte *buffer;
329
330
331 /* dummy check */
332 if ( path == NULL || path[ 0 ] == '\0' ) {
333 return;
334 }
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 Sys_Printf( "WARNING: Unable to find surface file %s, using defaults.\n", srfPath );
344 return;
345 }
346
347 /* parse the file */
348 ParseFromMemory( (char *) buffer, size );
349
350 /* tokenize it */
351 while ( 1 )
352 {
353 /* test for end of file */
354 if ( !GetToken( qtrue ) ) {
355 break;
356 }
357
358 /* default? */
359 if ( !Q_stricmp( token, "default" ) ) {
360 se = &seDefault;
361 }
362
363 /* surface number */
364 else
365 {
366 surfaceNum = atoi( token );
367 if ( surfaceNum < 0 || surfaceNum > MAX_MAP_DRAW_SURFS ) {
368 Error( "ReadSurfaceExtraFile(): %s, line %d: bogus surface num %d", srfPath, scriptline, surfaceNum );
369 }
370 while ( surfaceNum >= numSurfaceExtras )
371 se = AllocSurfaceExtra();
372 se = &surfaceExtras[ surfaceNum ];
373 }
374
375 /* handle { } section */
376 if ( !GetToken( qtrue ) || strcmp( token, "{" ) ) {
377 Error( "ReadSurfaceExtraFile(): %s, line %d: { not found", srfPath, scriptline );
378 }
379 while ( 1 )
380 {
381 if ( !GetToken( qtrue ) ) {
382 break;
383 }
384 if ( !strcmp( token, "}" ) ) {
385 break;
386 }
387
388 /* shader */
389 if ( !Q_stricmp( token, "shader" ) ) {
390 GetToken( qfalse );
391 se->si = ShaderInfoForShader( token );
392 }
393
394 /* parent surface number */
395 else if ( !Q_stricmp( token, "parent" ) ) {
396 GetToken( qfalse );
397 se->parentSurfaceNum = atoi( token );
398 }
399
400 /* entity number */
401 else if ( !Q_stricmp( token, "entity" ) ) {
402 GetToken( qfalse );
403 se->entityNum = atoi( token );
404 }
405
406 /* cast shadows */
407 else if ( !Q_stricmp( token, "castShadows" ) ) {
408 GetToken( qfalse );
409 se->castShadows = atoi( token );
410 }
411
412 /* recv shadows */
413 else if ( !Q_stricmp( token, "receiveShadows" ) ) {
414 GetToken( qfalse );
415 se->recvShadows = atoi( token );
416 }
417
418 /* lightmap sample size */
419 else if ( !Q_stricmp( token, "sampleSize" ) ) {
420 GetToken( qfalse );
421 se->sampleSize = atoi( token );
422 }
423
424 /* longest curve */
425 else if ( !Q_stricmp( token, "longestCurve" ) ) {
426 GetToken( qfalse );
427 se->longestCurve = atof( token );
428 }
429
430 /* lightmap axis vector */
431 else if ( !Q_stricmp( token, "lightmapAxis" ) ) {
432 Parse1DMatrix( 3, se->lightmapAxis );
433 }
434
435 /* ignore all other tokens on the line */
436 while ( TokenAvailable() )
437 GetToken( qfalse );
438 }
439 }
440
441 /* free the buffer */
442 free( buffer );
443 }
444