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