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