Author: rambetter
[divverent/netradiant.git] / tools / quake3 / q3map2 / surface_extra.c
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
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
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
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
155 static surfaceExtra_t *GetSurfaceExtra( int num )
156 {
157         if( num < 0 || num >= numSurfaceExtras )
158                 return &seDefault;
159         return &surfaceExtras[ num ];
160 }
161
162
163 shaderInfo_t *GetSurfaceExtraShaderInfo( int num )
164 {
165         surfaceExtra_t  *se = GetSurfaceExtra( num );
166         return se->si;
167 }
168
169
170 int GetSurfaceExtraParentSurfaceNum( int num )
171 {
172         surfaceExtra_t  *se = GetSurfaceExtra( num );
173         return se->parentSurfaceNum;
174 }
175
176
177 int GetSurfaceExtraEntityNum( int num )
178 {
179         surfaceExtra_t  *se = GetSurfaceExtra( num );
180         return se->entityNum;
181 }
182
183
184 int GetSurfaceExtraCastShadows( int num )
185 {
186         surfaceExtra_t  *se = GetSurfaceExtra( num );
187         return se->castShadows;
188 }
189
190
191 int GetSurfaceExtraRecvShadows( int num )
192 {
193         surfaceExtra_t  *se = GetSurfaceExtra( num );
194         return se->recvShadows;
195 }
196
197
198 int GetSurfaceExtraSampleSize( int num )
199 {
200         surfaceExtra_t  *se = GetSurfaceExtra( num );
201         return se->sampleSize;
202 }
203
204
205 float GetSurfaceExtraLongestCurve( int num )
206 {
207         surfaceExtra_t  *se = GetSurfaceExtra( num );
208         return se->longestCurve;
209 }
210
211
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
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
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( (char *) 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