1 /* -------------------------------------------------------------------------------
3 Copyright (C) 1999-2006 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 ------------------------------------------------------------------------------- */
41 /* -------------------------------------------------------------------------------
45 ------------------------------------------------------------------------------- */
50 SetCloneModelNumbers() - ydnar
51 sets the model numbers for brush entities
54 static void SetCloneModelNumbers( void )
58 char modelValue[ 10 ];
59 const char *value, *value2, *value3;
62 /* start with 1 (worldspawn is model 0) */
64 for( i = 1; i < numEntities; i++ )
66 /* only entities with brushes or patches get a model number */
67 if( entities[ i ].brushes == NULL && entities[ i ].patches == NULL )
70 /* is this a clone? */
71 value = ValueForKey( &entities[ i ], "_clone" );
72 if( value[ 0 ] != '\0' )
75 /* add the model key */
76 sprintf( modelValue, "*%d", models );
77 SetKeyValue( &entities[ i ], "model", modelValue );
79 /* increment model count */
84 for( i = 1; i < numEntities; i++ )
86 /* only entities with brushes or patches get a model number */
87 if( entities[ i ].brushes == NULL && entities[ i ].patches == NULL )
90 /* is this a clone? */
91 value = ValueForKey( &entities[ i ], "_ins" );
92 if( value[ 0 ] == '\0' )
93 value = ValueForKey( &entities[ i ], "_instance" );
94 if( value[ 0 ] == '\0' )
95 value = ValueForKey( &entities[ i ], "_clone" );
96 if( value[ 0 ] == '\0' )
99 /* find an entity with matching clone name */
100 for( j = 0; j < numEntities; j++ )
102 /* is this a clone parent? */
103 value2 = ValueForKey( &entities[ j ], "_clonename" );
104 if( value2[ 0 ] == '\0' )
108 if( strcmp( value, value2 ) == 0 )
110 /* get the model num */
111 value3 = ValueForKey( &entities[ j ], "model" );
112 if( value3[ 0 ] == '\0' )
114 Sys_Printf( "WARNING: Cloned entity %s referenced entity without model\n", value2 );
117 models = atoi( &value2[ 1 ] );
119 /* add the model key */
120 sprintf( modelValue, "*%d", models );
121 SetKeyValue( &entities[ i ], "model", modelValue );
123 /* nuke the brushes/patches for this entity (fixme: leak!) */
124 entities[ i ].brushes = NULL;
125 entities[ i ].patches = NULL;
134 FixBrushSides() - ydnar
135 matches brushsides back to their appropriate drawsurface and shader
138 static void FixBrushSides( entity_t *e )
141 mapDrawSurface_t *ds;
143 bspBrushSide_t *side;
147 Sys_FPrintf( SYS_VRB, "--- FixBrushSides ---\n" );
149 /* walk list of drawsurfaces */
150 for( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ )
152 /* get surface and try to early out */
153 ds = &mapDrawSurfs[ i ];
154 if( ds->outputNum < 0 )
157 /* walk sideref list */
158 for( sideRef = ds->sideRef; sideRef != NULL; sideRef = sideRef->next )
160 /* get bsp brush side */
161 if( sideRef->side == NULL || sideRef->side->outputNum < 0 )
163 side = &bspBrushSides[ sideRef->side->outputNum ];
165 /* set drawsurface */
166 side->surfaceNum = ds->outputNum;
167 //% Sys_FPrintf( SYS_VRB, "DS: %7d Side: %7d ", ds->outputNum, sideRef->side->outputNum );
170 if( strcmp( bspShaders[ side->shaderNum ].shader, ds->shaderInfo->shader ) )
172 //% Sys_FPrintf( SYS_VRB, "Remapping %s to %s\n", bspShaders[ side->shaderNum ].shader, ds->shaderInfo->shader );
173 side->shaderNum = EmitShader( ds->shaderInfo->shader, &ds->shaderInfo->contentFlags, &ds->shaderInfo->surfaceFlags );
183 creates a full bsp + surfaces for the worldspawn entity
186 void ProcessWorldModel( void )
192 qboolean ignoreLeaks, leaked;
193 xmlNodePtr polyline, leaknode;
194 char level[ 2 ], shader[ 1024 ];
198 /* sets integer blockSize from worldspawn "_blocksize" key if it exists */
199 value = ValueForKey( &entities[ 0 ], "_blocksize" );
200 if( value[ 0 ] == '\0' )
201 value = ValueForKey( &entities[ 0 ], "blocksize" );
202 if( value[ 0 ] == '\0' )
203 value = ValueForKey( &entities[ 0 ], "chopsize" ); /* sof2 */
204 if( value[ 0 ] != '\0' )
207 s = sscanf( value, "%d %d %d", &blockSize[ 0 ], &blockSize[ 1 ], &blockSize[ 2 ] );
209 /* handle legacy case */
212 blockSize[ 1 ] = blockSize[ 0 ];
213 blockSize[ 2 ] = blockSize[ 0 ];
216 Sys_Printf( "block size = { %d %d %d }\n", blockSize[ 0 ], blockSize[ 1 ], blockSize[ 2 ] );
218 /* sof2: ignore leaks? */
219 value = ValueForKey( &entities[ 0 ], "_ignoreleaks" ); /* ydnar */
220 if( value[ 0 ] == '\0' )
221 value = ValueForKey( &entities[ 0 ], "ignoreleaks" );
222 if( value[ 0 ] == '1' )
225 ignoreLeaks = qfalse;
227 /* begin worldspawn model */
230 e->firstDrawSurf = 0;
233 ClearMetaTriangles();
235 /* check for patches with adjacent edges that need to lod together */
236 PatchMapDrawSurfs( e );
238 /* build an initial bsp tree using all of the sides of all of the structural brushes */
239 faces = MakeStructuralBSPFaceList( entities[ 0 ].brushes );
240 tree = FaceBSP( faces );
241 MakeTreePortals( tree );
242 FilterStructuralBrushesIntoTree( e, tree );
244 /* see if the bsp is completely enclosed */
245 if( FloodEntities( tree ) || ignoreLeaks )
247 /* rebuild a better bsp tree using only the sides that are visible from the inside */
248 FillOutside( tree->headnode );
250 /* chop the sides to the convex hull of their visible fragments, giving us the smallest polygons */
251 ClipSidesIntoTree( e, tree );
253 /* build a visible face tree */
254 faces = MakeVisibleBSPFaceList( entities[ 0 ].brushes );
256 tree = FaceBSP( faces );
257 MakeTreePortals( tree );
258 FilterStructuralBrushesIntoTree( e, tree );
261 /* ydnar: flood again for skybox */
263 FloodEntities( tree );
267 Sys_FPrintf( SYS_NOXML, "**********************\n" );
268 Sys_FPrintf( SYS_NOXML, "******* leaked *******\n" );
269 Sys_FPrintf( SYS_NOXML, "**********************\n" );
270 polyline = LeakFile( tree );
271 leaknode = xmlNewNode( NULL, "message" );
272 xmlNodeSetContent( leaknode, "MAP LEAKED\n" );
273 xmlAddChild( leaknode, polyline );
274 level[0] = (int) '0' + SYS_ERR;
276 xmlSetProp( leaknode, "level", (char*) &level );
277 xml_SendNode( leaknode );
280 Sys_Printf ("--- MAP LEAKED, ABORTING LEAKTEST ---\n");
285 /* chop the sides to the convex hull of their visible fragments, giving us the smallest polygons */
286 ClipSidesIntoTree( e, tree );
289 /* save out information for visibility processing */
290 NumberClusters( tree );
292 WritePortalFile( tree );
294 /* flood from entities */
297 /* create drawsurfs for triangle models */
298 AddTriangleModels( e );
300 /* create drawsurfs for surface models */
301 AddEntitySurfaceModels( e );
303 /* generate bsp brushes from map brushes */
304 EmitBrushes( e->brushes, &e->firstBrush, &e->numBrushes );
306 /* add references to the detail brushes */
307 FilterDetailBrushesIntoTree( e, tree );
309 /* drawsurfs that cross fog boundaries will need to be split along the fog boundary */
311 FogDrawSurfaces( e );
313 /* subdivide each drawsurf as required by shader tesselation */
315 SubdivideFaceSurfaces( e, tree );
317 /* add in any vertexes required to fix t-junctions */
321 /* ydnar: classify the surfaces */
322 ClassifyEntitySurfaces( e );
324 /* ydnar: project decals */
325 MakeEntityDecals( e );
327 /* ydnar: meta surfaces */
328 MakeEntityMetaTriangles( e );
329 SmoothMetaTriangles();
331 MergeMetaTriangles();
333 /* ydnar: debug portals */
335 MakeDebugPortalSurfs( tree );
337 /* ydnar: fog hull */
338 value = ValueForKey( &entities[ 0 ], "_foghull" );
339 if( value[ 0 ] != '\0' )
341 sprintf( shader, "textures/%s", value );
342 MakeFogHullSurfs( e, tree, shader );
345 /* ydnar: bug 645: do flares for lights */
346 for( i = 0; i < numEntities && emitFlares; i++ )
348 entity_t *light, *target;
349 const char *value, *flareShader;
350 vec3_t origin, targetOrigin, normal, color;
355 light = &entities[ i ];
356 value = ValueForKey( light, "classname" );
357 if( !strcmp( value, "light" ) )
359 /* get flare shader */
360 flareShader = ValueForKey( light, "_flareshader" );
361 value = ValueForKey( light, "_flare" );
362 if( flareShader[ 0 ] != '\0' || value[ 0 ] != '\0' )
365 GetVectorForKey( light, "origin", origin );
366 GetVectorForKey( light, "_color", color );
367 lightStyle = IntForKey( light, "_style" );
368 if( lightStyle == 0 )
369 lightStyle = IntForKey( light, "style" );
371 /* handle directional spotlights */
372 value = ValueForKey( light, "target" );
373 if( value[ 0 ] != '\0' )
375 /* get target light */
376 target = FindTargetEntity( value );
379 GetVectorForKey( target, "origin", targetOrigin );
380 VectorSubtract( targetOrigin, origin, normal );
381 VectorNormalize( normal, normal );
385 //% VectorClear( normal );
386 VectorSet( normal, 0, 0, -1 );
388 /* create the flare surface (note shader defaults automatically) */
389 DrawSurfaceForFlare( mapEntityNum, origin, normal, color, (char*) flareShader, lightStyle );
394 /* add references to the final drawsurfs in the apropriate clusters */
395 FilterDrawsurfsIntoTree( e, tree );
397 /* match drawsurfaces back to original brushsides (sof2) */
401 EndModel( e, tree->headnode );
409 creates bsp + surfaces for other brush models
412 void ProcessSubModel( void )
420 /* start a brush model */
422 e = &entities[ mapEntityNum ];
423 e->firstDrawSurf = numMapDrawSurfs;
426 ClearMetaTriangles();
428 /* check for patches with adjacent edges that need to lod together */
429 PatchMapDrawSurfs( e );
431 /* allocate a tree */
433 node->planenum = PLANENUM_LEAF;
435 tree->headnode = node;
437 /* add the sides to the tree */
438 ClipSidesIntoTree( e, tree );
440 /* ydnar: create drawsurfs for triangle models */
441 AddTriangleModels( e );
443 /* create drawsurfs for surface models */
444 AddEntitySurfaceModels( e );
446 /* generate bsp brushes from map brushes */
447 EmitBrushes( e->brushes, &e->firstBrush, &e->numBrushes );
449 /* just put all the brushes in headnode */
450 for( b = e->brushes; b; b = b->next )
453 bc->next = node->brushlist;
454 node->brushlist = bc;
457 /* subdivide each drawsurf as required by shader tesselation */
459 SubdivideFaceSurfaces( e, tree );
461 /* add in any vertexes required to fix t-junctions */
465 /* ydnar: classify the surfaces and project lightmaps */
466 ClassifyEntitySurfaces( e );
468 /* ydnar: project decals */
469 MakeEntityDecals( e );
471 /* ydnar: meta surfaces */
472 MakeEntityMetaTriangles( e );
473 SmoothMetaTriangles();
475 MergeMetaTriangles();
477 /* add references to the final drawsurfs in the apropriate clusters */
478 FilterDrawsurfsIntoTree( e, tree );
480 /* match drawsurfaces back to original brushsides (sof2) */
492 process world + other models into the bsp
495 void ProcessModels( void )
501 /* preserve -v setting */
502 oldVerbose = verbose;
504 /* start a new bsp */
507 /* create map fogs */
510 /* walk entity list */
511 for( mapEntityNum = 0; mapEntityNum < numEntities; mapEntityNum++ )
514 entity = &entities[ mapEntityNum ];
515 if( entity->brushes == NULL && entity->patches == NULL )
518 /* process the model */
519 Sys_FPrintf( SYS_VRB, "############### model %i ###############\n", numBSPModels );
520 if( mapEntityNum == 0 )
525 /* potentially turn off the deluge of text */
526 verbose = verboseEntities;
529 /* restore -v setting */
530 verbose = oldVerbose;
540 this is probably broken unless teamed with a radiant version that preserves entity order
543 void OnlyEnts( void )
549 Sys_Printf( "--- OnlyEnts ---\n" );
551 sprintf( out, "%s.bsp", source );
556 LoadMapFile( name, qfalse );
560 numBSPEntities = numEntities;
570 handles creation of a bsp from a map file
573 int BSPMain( int argc, char **argv )
576 char path[ 1024 ], tempSource[ 1024 ];
577 qboolean onlyents = qfalse;
581 Sys_Printf( "--- BSP ---\n" );
583 SetDrawSurfacesBuffer();
584 mapDrawSurfs = safe_malloc( sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
585 memset( mapDrawSurfs, 0, sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
588 tempSource[ 0 ] = '\0';
590 /* set standard game flags */
591 maxSurfaceVerts = game->maxSurfaceVerts;
592 maxSurfaceIndexes = game->maxSurfaceIndexes;
593 emitFlares = game->emitFlares;
595 /* process arguments */
596 for( i = 1; i < (argc - 1); i++ )
598 if( !strcmp( argv[ i ], "-onlyents" ) )
600 Sys_Printf( "Running entity-only compile\n" );
603 else if( !strcmp( argv[ i ], "-tempname" ) )
604 strcpy( tempSource, argv[ ++i ] );
605 else if( !strcmp( argv[ i ], "-tmpout" ) )
606 strcpy( outbase, "/tmp" );
607 else if( !strcmp( argv[ i ], "-nowater" ) )
609 Sys_Printf( "Disabling water\n" );
612 else if( !strcmp( argv[ i ], "-nodetail" ) )
614 Sys_Printf( "Ignoring detail brushes\n") ;
617 else if( !strcmp( argv[ i ], "-fulldetail" ) )
619 Sys_Printf( "Turning detail brushes into structural brushes\n" );
622 else if( !strcmp( argv[ i ], "-nofog" ) )
624 Sys_Printf( "Fog volumes disabled\n" );
627 else if( !strcmp( argv[ i ], "-nosubdivide" ) )
629 Sys_Printf( "Disabling brush face subdivision\n" );
632 else if( !strcmp( argv[ i ], "-leaktest" ) )
634 Sys_Printf( "Leaktest enabled\n" );
637 else if( !strcmp( argv[ i ], "-verboseentities" ) )
639 Sys_Printf( "Verbose entities enabled\n" );
640 verboseEntities = qtrue;
642 else if( !strcmp( argv[ i ], "-nocurves" ) )
644 Sys_Printf( "Ignoring curved surfaces (patches)\n" );
645 noCurveBrushes = qtrue;
647 else if( !strcmp( argv[ i ], "-notjunc" ) )
649 Sys_Printf( "T-junction fixing disabled\n" );
652 else if( !strcmp( argv[ i ], "-fakemap" ) )
654 Sys_Printf( "Generating fakemap.map\n" );
657 else if( !strcmp( argv[ i ], "-samplesize" ) )
659 sampleSize = atoi( argv[ i + 1 ] );
663 Sys_Printf( "Lightmap sample size set to %dx%d units\n", sampleSize, sampleSize );
665 else if( !strcmp( argv[ i ], "-custinfoparms") )
667 Sys_Printf( "Custom info parms enabled\n" );
668 useCustomInfoParms = qtrue;
672 else if( !strcmp( argv[ i ], "-rename" ) )
674 Sys_Printf( "Appending _bsp suffix to misc_model shaders (SOF2)\n" );
675 renameModelShaders = qtrue;
679 else if( !strcmp( argv[ i ], "-ne" ) )
681 normalEpsilon = atof( argv[ i + 1 ] );
683 Sys_Printf( "Normal epsilon set to %f\n", normalEpsilon );
685 else if( !strcmp( argv[ i ], "-de" ) )
687 distanceEpsilon = atof( argv[ i + 1 ] );
689 Sys_Printf( "Distance epsilon set to %f\n", distanceEpsilon );
691 else if( !strcmp( argv[ i ], "-mv" ) )
693 maxLMSurfaceVerts = atoi( argv[ i + 1 ] );
694 if( maxLMSurfaceVerts < 3 )
695 maxLMSurfaceVerts = 3;
696 if( maxLMSurfaceVerts > maxSurfaceVerts )
697 maxSurfaceVerts = maxLMSurfaceVerts;
699 Sys_Printf( "Maximum lightmapped surface vertex count set to %d\n", maxLMSurfaceVerts );
701 else if( !strcmp( argv[ i ], "-mi" ) )
703 maxSurfaceIndexes = atoi( argv[ i + 1 ] );
704 if( maxSurfaceIndexes < 3 )
705 maxSurfaceIndexes = 3;
707 Sys_Printf( "Maximum per-surface index count set to %d\n", maxSurfaceIndexes );
709 else if( !strcmp( argv[ i ], "-np" ) )
711 npDegrees = atof( argv[ i + 1 ] );
712 if( npDegrees < 0.0f )
713 shadeAngleDegrees = 0.0f;
714 else if( npDegrees > 0.0f )
715 Sys_Printf( "Forcing nonplanar surfaces with a breaking angle of %f degrees\n", npDegrees );
718 else if( !strcmp( argv[ i ], "-snap" ) )
720 bevelSnap = atoi( argv[ i + 1 ]);
725 Sys_Printf( "Snapping brush bevel planes to %d units\n", bevelSnap );
727 else if( !strcmp( argv[ i ], "-texrange" ) )
729 texRange = atoi( argv[ i + 1 ]);
733 Sys_Printf( "Limiting per-surface texture range to %d texels\n", texRange );
735 else if( !strcmp( argv[ i ], "-nohint" ) )
737 Sys_Printf( "Hint brushes disabled\n" );
740 else if( !strcmp( argv[ i ], "-flat" ) )
742 Sys_Printf( "Flatshading enabled\n" );
745 else if( !strcmp( argv[ i ], "-meta" ) )
747 Sys_Printf( "Creating meta surfaces from brush faces\n" );
750 else if( !strcmp( argv[ i ], "-patchmeta" ) )
752 Sys_Printf( "Creating meta surfaces from patches\n" );
755 else if( !strcmp( argv[ i ], "-flares" ) )
757 Sys_Printf( "Flare surfaces enabled\n" );
760 else if( !strcmp( argv[ i ], "-noflares" ) )
762 Sys_Printf( "Flare surfaces disabled\n" );
765 else if( !strcmp( argv[ i ], "-skyfix" ) )
767 Sys_Printf( "GL_CLAMP sky fix/hack/workaround enabled\n" );
770 else if( !strcmp( argv[ i ], "-debugsurfaces" ) )
772 Sys_Printf( "emitting debug surfaces\n" );
773 debugSurfaces = qtrue;
775 else if( !strcmp( argv[ i ], "-debuginset" ) )
777 Sys_Printf( "Debug surface triangle insetting enabled\n" );
780 else if( !strcmp( argv[ i ], "-debugportals" ) )
782 Sys_Printf( "Debug portal surfaces enabled\n" );
783 debugPortals = qtrue;
785 else if( !strcmp( argv[ i ], "-bsp" ) )
786 Sys_Printf( "-bsp argument unnecessary\n" );
788 Sys_Printf( "WARNING: Unknown option \"%s\"\n", argv[ i ] );
791 /* fixme: print more useful usage here */
792 if( i != (argc - 1) )
793 Error( "usage: q3map [options] mapfile" );
795 /* copy source name */
796 strcpy( source, ExpandArg( argv[ i ] ) );
797 StripExtension( source );
799 /* ydnar: set default sample size */
800 SetDefaultSampleSize( sampleSize );
802 /* delete portal, line and surface files */
803 sprintf( path, "%s.prt", source );
805 sprintf( path, "%s.lin", source );
807 //% sprintf( path, "%s.srf", source ); /* ydnar */
811 strcpy( name, ExpandArg( argv[ i ] ) );
812 if( strcmp( name + strlen( name ) - 4, ".reg" ) )
814 /* if we are doing a full map, delete the last saved region map */
815 sprintf( path, "%s.reg", source );
817 DefaultExtension( name, ".map" ); /* might be .reg */
820 /* if onlyents, just grab the entites and resave */
830 /* load original file from temp spot in case it was renamed by the editor on the way in */
831 if( strlen( tempSource ) > 0 )
832 LoadMapFile( tempSource, qfalse );
834 LoadMapFile( name, qfalse );
836 /* ydnar: decal setup */
839 /* ydnar: cloned brush model entities */
840 SetCloneModelNumbers();
842 /* process world and submodels */
845 /* set light styles from targetted light entities */
848 /* finish and write bsp */
851 /* remove temp map source file if appropriate */
852 if( strlen( tempSource ) > 0)
853 remove( tempSource );
855 /* return to sender */