]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/q3map2/surface_extra.c
split bsp conversion stuff from q3map2
[xonotic/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         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
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
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
151 static surfaceExtra_t *GetSurfaceExtra( int num ){
152         if ( num < 0 || num >= numSurfaceExtras ) {
153                 return &seDefault;
154         }
155         return &surfaceExtras[ num ];
156 }
157
158
159 shaderInfo_t *GetSurfaceExtraShaderInfo( int num ){
160         surfaceExtra_t  *se = GetSurfaceExtra( num );
161         return se->si;
162 }
163
164
165 int GetSurfaceExtraParentSurfaceNum( int num ){
166         surfaceExtra_t  *se = GetSurfaceExtra( num );
167         return se->parentSurfaceNum;
168 }
169
170
171 int GetSurfaceExtraEntityNum( int num ){
172         surfaceExtra_t  *se = GetSurfaceExtra( num );
173         return se->entityNum;
174 }
175
176
177 int GetSurfaceExtraCastShadows( int num ){
178         surfaceExtra_t  *se = GetSurfaceExtra( num );
179         return se->castShadows;
180 }
181
182
183 int GetSurfaceExtraRecvShadows( int num ){
184         surfaceExtra_t  *se = GetSurfaceExtra( num );
185         return se->recvShadows;
186 }
187
188
189 int GetSurfaceExtraSampleSize( int num ){
190         surfaceExtra_t  *se = GetSurfaceExtra( num );
191         return se->sampleSize;
192 }
193
194
195 float GetSurfaceExtraLongestCurve( int num ){
196         surfaceExtra_t  *se = GetSurfaceExtra( num );
197         return se->longestCurve;
198 }
199
200
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
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
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 }