1 /* -------------------------------------------------------------------------------
3 Copyright (C) 1999-2007 id Software, Inc. and contributors.
4 For a list of contributors, see the accompanying CONTRIBUTORS file.
6 This file is part of GtkRadiant.
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.
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.
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
22 ----------------------------------------------------------------------------------
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."
27 ------------------------------------------------------------------------------- */
32 #define SURFACE_EXTRA_C
41 /* -------------------------------------------------------------------------------
43 ydnar: srf file module
45 ------------------------------------------------------------------------------- */
47 typedef struct surfaceExtra_s
49 mapDrawSurface_t *mds;
53 int castShadows, recvShadows;
60 #define GROW_SURFACE_EXTRAS 1024
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 } };
71 allocates a new extra storage
74 static surfaceExtra_t *AllocSurfaceExtra( void ){
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 );
91 se = &surfaceExtras[ numSurfaceExtras ];
93 memcpy( se, &seDefault, sizeof( surfaceExtra_t ) );
102 SetDefaultSampleSize()
103 sets the default lightmap sample size
106 void SetDefaultSampleSize( int sampleSize ){
107 seDefault.sampleSize = sampleSize;
114 stores extra (q3map2) data for the specific numbered drawsurface
117 void SetSurfaceExtra( mapDrawSurface_t *ds, int num ){
122 if ( ds == NULL || num < 0 ) {
126 /* get a new extra */
127 se = AllocSurfaceExtra();
129 /* copy out the relevant bits */
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 );
141 //% Sys_FPrintf( SYS_VRB, "SetSurfaceExtra(): entityNum = %d\n", ds->entityNum );
148 getter functions for extra surface data
151 static surfaceExtra_t *GetSurfaceExtra( int num ){
152 if ( num < 0 || num >= numSurfaceExtras ) {
155 return &surfaceExtras[ num ];
159 shaderInfo_t *GetSurfaceExtraShaderInfo( int num ){
160 surfaceExtra_t *se = GetSurfaceExtra( num );
165 int GetSurfaceExtraParentSurfaceNum( int num ){
166 surfaceExtra_t *se = GetSurfaceExtra( num );
167 return se->parentSurfaceNum;
171 int GetSurfaceExtraEntityNum( int num ){
172 surfaceExtra_t *se = GetSurfaceExtra( num );
173 return se->entityNum;
177 int GetSurfaceExtraCastShadows( int num ){
178 surfaceExtra_t *se = GetSurfaceExtra( num );
179 return se->castShadows;
183 int GetSurfaceExtraRecvShadows( int num ){
184 surfaceExtra_t *se = GetSurfaceExtra( num );
185 return se->recvShadows;
189 int GetSurfaceExtraSampleSize( int num ){
190 surfaceExtra_t *se = GetSurfaceExtra( num );
191 return se->sampleSize;
195 float GetSurfaceExtraLongestCurve( int num ){
196 surfaceExtra_t *se = GetSurfaceExtra( num );
197 return se->longestCurve;
201 void GetSurfaceExtraLightmapAxis( int num, vec3_t lightmapAxis ){
202 surfaceExtra_t *se = GetSurfaceExtra( num );
203 VectorCopy( se->lightmapAxis, lightmapAxis );
210 WriteSurfaceExtraFile()
211 writes out a surface info file (<map>.srf)
214 void WriteSurfaceExtraFile( const char *surfaceFilePath ){
221 if ( surfaceFilePath == NULL || surfaceFilePath[ 0 ] == '\0' ) {
226 Sys_Printf( "--- WriteSurfaceExtraFile ---\n" );
229 Sys_Printf( "Writing %s\n", surfaceFilePath );
230 sf = fopen( surfaceFilePath, "w" );
232 Error( "Error opening %s for writing", surfaceFilePath );
235 /* lap through the extras list */
236 for ( i = -1; i < numSurfaceExtras; i++ )
239 se = GetSurfaceExtra( i );
241 /* default or surface num? */
243 fprintf( sf, "default" );
246 fprintf( sf, "%d", i );
249 /* valid map drawsurf? */
250 if ( se->mds == NULL ) {
255 fprintf( sf, " // %s V: %d I: %d %s\n",
256 surfaceTypes[ se->mds->type ],
259 ( se->mds->planar ? "planar" : "" ) );
263 fprintf( sf, "{\n" );
266 if ( se->si != NULL ) {
267 fprintf( sf, "\tshader %s\n", se->si->shader );
270 /* parent surface number */
271 if ( se->parentSurfaceNum != seDefault.parentSurfaceNum ) {
272 fprintf( sf, "\tparent %d\n", se->parentSurfaceNum );
276 if ( se->entityNum != seDefault.entityNum ) {
277 fprintf( sf, "\tentity %d\n", se->entityNum );
281 if ( se->castShadows != seDefault.castShadows || se == &seDefault ) {
282 fprintf( sf, "\tcastShadows %d\n", se->castShadows );
286 if ( se->recvShadows != seDefault.recvShadows || se == &seDefault ) {
287 fprintf( sf, "\treceiveShadows %d\n", se->recvShadows );
290 /* lightmap sample size */
291 if ( se->sampleSize != seDefault.sampleSize || se == &seDefault ) {
292 fprintf( sf, "\tsampleSize %d\n", se->sampleSize );
296 if ( se->longestCurve != seDefault.longestCurve || se == &seDefault ) {
297 fprintf( sf, "\tlongestCurve %f\n", se->longestCurve );
300 /* lightmap axis vector */
301 if ( VectorCompare( se->lightmapAxis, seDefault.lightmapAxis ) == qfalse ) {
302 fprintf( sf, "\tlightmapAxis ( %f %f %f )\n", se->lightmapAxis[ 0 ], se->lightmapAxis[ 1 ], se->lightmapAxis[ 2 ] );
306 fprintf( sf, "}\n\n" );
316 LoadSurfaceExtraFile()
317 reads a surface info file (<map>.srf)
320 void LoadSurfaceExtraFile( const char *surfaceFilePath ){
322 int surfaceNum, size;
327 if ( surfaceFilePath == NULL || surfaceFilePath[ 0 ] == '\0' ) {
332 Sys_Printf( "Loading %s\n", surfaceFilePath );
333 size = LoadFile( surfaceFilePath, (void**) &buffer );
335 Sys_FPrintf( SYS_WRN, "WARNING: Unable to find surface file %s, using defaults.\n", surfaceFilePath );
340 ParseFromMemory( (char*) buffer, size );
345 /* test for end of file */
346 if ( !GetToken( qtrue ) ) {
351 if ( !Q_stricmp( token, "default" ) ) {
358 surfaceNum = atoi( token );
359 if ( surfaceNum < 0 || surfaceNum > MAX_MAP_DRAW_SURFS ) {
360 Error( "ReadSurfaceExtraFile(): %s, line %d: bogus surface num %d", surfaceFilePath, scriptline, surfaceNum );
362 while ( surfaceNum >= numSurfaceExtras )
363 se = AllocSurfaceExtra();
364 se = &surfaceExtras[ surfaceNum ];
367 /* handle { } section */
368 if ( !GetToken( qtrue ) || strcmp( token, "{" ) ) {
369 Error( "ReadSurfaceExtraFile(): %s, line %d: { not found", surfaceFilePath, scriptline );
373 if ( !GetToken( qtrue ) ) {
376 if ( !strcmp( token, "}" ) ) {
381 if ( !Q_stricmp( token, "shader" ) ) {
383 se->si = ShaderInfoForShader( token );
386 /* parent surface number */
387 else if ( !Q_stricmp( token, "parent" ) ) {
389 se->parentSurfaceNum = atoi( token );
393 else if ( !Q_stricmp( token, "entity" ) ) {
395 se->entityNum = atoi( token );
399 else if ( !Q_stricmp( token, "castShadows" ) ) {
401 se->castShadows = atoi( token );
405 else if ( !Q_stricmp( token, "receiveShadows" ) ) {
407 se->recvShadows = atoi( token );
410 /* lightmap sample size */
411 else if ( !Q_stricmp( token, "sampleSize" ) ) {
413 se->sampleSize = atoi( token );
417 else if ( !Q_stricmp( token, "longestCurve" ) ) {
419 se->longestCurve = atof( token );
422 /* lightmap axis vector */
423 else if ( !Q_stricmp( token, "lightmapAxis" ) ) {
424 Parse1DMatrix( 3, se->lightmapAxis );
427 /* ignore all other tokens on the line */
428 while ( TokenAvailable() )
433 /* free the buffer */