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 ------------------------------------------------------------------------------- */
41 /* -------------------------------------------------------------------------------
45 ------------------------------------------------------------------------------- */
47 static const char *miniMap = NULL;
49 void WriteTGA24( char *filename, byte *data, int width, int height, qboolean flip );
50 qboolean BrushIntersectionWithLine(bspBrush_t *brush, vec3_t start, vec3_t dir, float *t_in, float *t_out)
53 qboolean in = qfalse, out = qfalse;
54 bspBrushSide_t *sides = &bspBrushSides[brush->firstSide];
56 for(i = 0; i < brush->numSides; ++i)
58 bspPlane_t *p = &bspPlanes[sides[i].planeNum];
59 float sn = DotProduct(start, p->normal);
60 float dn = DotProduct(dir, p->normal);
64 return qfalse; // outside!
68 float t = (p->dist - sn) / dn;
75 // as t_in can only increase, and t_out can only decrease, early out
82 if(!out || t < *t_out)
86 // as t_in can only increase, and t_out can only decrease, early out
96 static float MiniMapSample(float x, float y)
114 for(i = 0; i < bspModels[0].numBSPBrushes; ++i)
116 bi = bspModels[0].firstBSPBrush + i;
117 if(opaqueBrushes[bi >> 3] & (1 << (bi & 7)))
120 if(BrushIntersectionWithLine(b, org, dir, &t0, &t1))
131 #define MINIMAP_SIZE 512
132 #define MINIMAP_SAMPLES 16
133 static byte radarmapdata[MINIMAP_SIZE * MINIMAP_SIZE * 3];
134 static vec3_t mi_min, mi_sz;
135 static void GenerateMiniMapRunner(int y)
139 float ymin = mi_min[1] + mi_sz[1] * ( y / (float) MINIMAP_SIZE);
140 float ymax = mi_min[1] + mi_sz[1] * ((y + 1) / (float) MINIMAP_SIZE);
141 for(x = 0; x < MINIMAP_SIZE; ++x)
143 byte *p = &radarmapdata[(y * MINIMAP_SIZE + x) * 3];
144 float xmin = mi_min[0] + mi_sz[0] * ( x / (float) MINIMAP_SIZE);
145 float xmax = mi_min[0] + mi_sz[0] * ((x + 1) / (float) MINIMAP_SIZE);
147 for(i = 0; i < MINIMAP_SAMPLES; ++i)
148 val += MiniMapSample(
149 xmin + Random() * (xmax - xmin),
150 ymin + Random() * (ymax - ymin)
152 val /= MINIMAP_SAMPLES * mi_sz[2];
155 if(val > 255.0/256.0)
157 p[0] = p[1] = p[2] = val * 256.0;
161 static void GenerateMiniMap()
163 VectorCopy(bspModels[0].mins, mi_min);
164 VectorSubtract(bspModels[0].maxs, bspModels[0].mins, mi_sz);
168 Sys_Printf( "\n--- GenerateMiniMap (%d) ---\n", MINIMAP_SIZE );
169 RunThreadsOnIndividual(MINIMAP_SIZE, qtrue, GenerateMiniMapRunner);
171 WriteTGA24(miniMap, radarmapdata, MINIMAP_SIZE, MINIMAP_SIZE, qfalse);
175 ProcessAdvertisements()
176 copies advertisement info into the BSP structures
179 static void ProcessAdvertisements( void ) {
181 const char* className;
182 const char* modelKey;
185 bspDrawSurface_t* adSurface;
187 Sys_FPrintf( SYS_VRB, "--- ProcessAdvertisements ---\n" );
189 for( i = 0; i < numEntities; i++ ) {
191 /* is an advertisement? */
192 className = ValueForKey( &entities[ i ], "classname" );
194 if( !Q_stricmp( "advertisement", className ) ) {
196 modelKey = ValueForKey( &entities[ i ], "model" );
198 if( strlen( modelKey ) > MAX_QPATH - 1 ) {
199 Error( "Model Key for entity exceeds ad struct string length." );
201 if( numBSPAds < MAX_MAP_ADVERTISEMENTS ) {
202 bspAds[numBSPAds].cellId = IntForKey( &entities[ i ], "cellId" );
203 strncpy( bspAds[numBSPAds].model, modelKey, sizeof( bspAds[numBSPAds].model ) );
206 modelNum = atoi( modelKey );
207 adModel = &bspModels[modelNum];
209 if( adModel->numBSPSurfaces != 1 ) {
210 Error( "Ad cell id %d has more than one surface.", bspAds[numBSPAds].cellId );
213 adSurface = &bspDrawSurfaces[adModel->firstBSPSurface];
215 // store the normal for use at run time.. all ad verts are assumed to
216 // have identical normals (because they should be a simple rectangle)
217 // so just use the first vert's normal
218 VectorCopy( bspDrawVerts[adSurface->firstVert].normal, bspAds[numBSPAds].normal );
220 // store the ad quad for quick use at run time
221 if( adSurface->surfaceType == MST_PATCH ) {
222 int v0 = adSurface->firstVert + adSurface->patchHeight - 1;
223 int v1 = adSurface->firstVert + adSurface->numVerts - 1;
224 int v2 = adSurface->firstVert + adSurface->numVerts - adSurface->patchWidth;
225 int v3 = adSurface->firstVert;
226 VectorCopy( bspDrawVerts[v0].xyz, bspAds[numBSPAds].rect[0] );
227 VectorCopy( bspDrawVerts[v1].xyz, bspAds[numBSPAds].rect[1] );
228 VectorCopy( bspDrawVerts[v2].xyz, bspAds[numBSPAds].rect[2] );
229 VectorCopy( bspDrawVerts[v3].xyz, bspAds[numBSPAds].rect[3] );
231 Error( "Ad cell %d has an unsupported Ad Surface type.", bspAds[numBSPAds].cellId );
236 Error( "Maximum number of map advertisements exceeded." );
242 Sys_FPrintf( SYS_VRB, "%9d in-game advertisements\n", numBSPAds );
246 SetCloneModelNumbers() - ydnar
247 sets the model numbers for brush entities
250 static void SetCloneModelNumbers( void )
254 char modelValue[ 10 ];
255 const char *value, *value2, *value3;
258 /* start with 1 (worldspawn is model 0) */
260 for( i = 1; i < numEntities; i++ )
262 /* only entities with brushes or patches get a model number */
263 if( entities[ i ].brushes == NULL && entities[ i ].patches == NULL )
266 /* is this a clone? */
267 value = ValueForKey( &entities[ i ], "_clone" );
268 if( value[ 0 ] != '\0' )
271 /* add the model key */
272 sprintf( modelValue, "*%d", models );
273 SetKeyValue( &entities[ i ], "model", modelValue );
275 /* increment model count */
280 for( i = 1; i < numEntities; i++ )
282 /* only entities with brushes or patches get a model number */
283 if( entities[ i ].brushes == NULL && entities[ i ].patches == NULL )
286 /* is this a clone? */
287 value = ValueForKey( &entities[ i ], "_ins" );
288 if( value[ 0 ] == '\0' )
289 value = ValueForKey( &entities[ i ], "_instance" );
290 if( value[ 0 ] == '\0' )
291 value = ValueForKey( &entities[ i ], "_clone" );
292 if( value[ 0 ] == '\0' )
295 /* find an entity with matching clone name */
296 for( j = 0; j < numEntities; j++ )
298 /* is this a clone parent? */
299 value2 = ValueForKey( &entities[ j ], "_clonename" );
300 if( value2[ 0 ] == '\0' )
304 if( strcmp( value, value2 ) == 0 )
306 /* get the model num */
307 value3 = ValueForKey( &entities[ j ], "model" );
308 if( value3[ 0 ] == '\0' )
310 Sys_Printf( "WARNING: Cloned entity %s referenced entity without model\n", value2 );
313 models = atoi( &value2[ 1 ] );
315 /* add the model key */
316 sprintf( modelValue, "*%d", models );
317 SetKeyValue( &entities[ i ], "model", modelValue );
319 /* nuke the brushes/patches for this entity (fixme: leak!) */
320 entities[ i ].brushes = NULL;
321 entities[ i ].patches = NULL;
330 FixBrushSides() - ydnar
331 matches brushsides back to their appropriate drawsurface and shader
334 static void FixBrushSides( entity_t *e )
337 mapDrawSurface_t *ds;
339 bspBrushSide_t *side;
343 Sys_FPrintf( SYS_VRB, "--- FixBrushSides ---\n" );
345 /* walk list of drawsurfaces */
346 for( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ )
348 /* get surface and try to early out */
349 ds = &mapDrawSurfs[ i ];
350 if( ds->outputNum < 0 )
353 /* walk sideref list */
354 for( sideRef = ds->sideRef; sideRef != NULL; sideRef = sideRef->next )
356 /* get bsp brush side */
357 if( sideRef->side == NULL || sideRef->side->outputNum < 0 )
359 side = &bspBrushSides[ sideRef->side->outputNum ];
361 /* set drawsurface */
362 side->surfaceNum = ds->outputNum;
363 //% Sys_FPrintf( SYS_VRB, "DS: %7d Side: %7d ", ds->outputNum, sideRef->side->outputNum );
366 if( strcmp( bspShaders[ side->shaderNum ].shader, ds->shaderInfo->shader ) )
368 //% Sys_FPrintf( SYS_VRB, "Remapping %s to %s\n", bspShaders[ side->shaderNum ].shader, ds->shaderInfo->shader );
369 side->shaderNum = EmitShader( ds->shaderInfo->shader, &ds->shaderInfo->contentFlags, &ds->shaderInfo->surfaceFlags );
379 creates a full bsp + surfaces for the worldspawn entity
382 void ProcessWorldModel( void )
388 qboolean ignoreLeaks, leaked;
389 xmlNodePtr polyline, leaknode;
390 char level[ 2 ], shader[ 1024 ];
393 /* sets integer blockSize from worldspawn "_blocksize" key if it exists */
394 value = ValueForKey( &entities[ 0 ], "_blocksize" );
395 if( value[ 0 ] == '\0' )
396 value = ValueForKey( &entities[ 0 ], "blocksize" );
397 if( value[ 0 ] == '\0' )
398 value = ValueForKey( &entities[ 0 ], "chopsize" ); /* sof2 */
399 if( value[ 0 ] != '\0' )
402 s = sscanf( value, "%d %d %d", &blockSize[ 0 ], &blockSize[ 1 ], &blockSize[ 2 ] );
404 /* handle legacy case */
407 blockSize[ 1 ] = blockSize[ 0 ];
408 blockSize[ 2 ] = blockSize[ 0 ];
411 Sys_Printf( "block size = { %d %d %d }\n", blockSize[ 0 ], blockSize[ 1 ], blockSize[ 2 ] );
413 /* sof2: ignore leaks? */
414 value = ValueForKey( &entities[ 0 ], "_ignoreleaks" ); /* ydnar */
415 if( value[ 0 ] == '\0' )
416 value = ValueForKey( &entities[ 0 ], "ignoreleaks" );
417 if( value[ 0 ] == '1' )
420 ignoreLeaks = qfalse;
422 /* begin worldspawn model */
425 e->firstDrawSurf = 0;
428 ClearMetaTriangles();
430 /* check for patches with adjacent edges that need to lod together */
431 PatchMapDrawSurfs( e );
433 /* build an initial bsp tree using all of the sides of all of the structural brushes */
434 faces = MakeStructuralBSPFaceList( entities[ 0 ].brushes );
435 tree = FaceBSP( faces );
436 MakeTreePortals( tree );
437 FilterStructuralBrushesIntoTree( e, tree );
439 /* see if the bsp is completely enclosed */
440 if( FloodEntities( tree ) || ignoreLeaks )
442 /* rebuild a better bsp tree using only the sides that are visible from the inside */
443 FillOutside( tree->headnode );
445 /* chop the sides to the convex hull of their visible fragments, giving us the smallest polygons */
446 ClipSidesIntoTree( e, tree );
448 /* build a visible face tree */
449 faces = MakeVisibleBSPFaceList( entities[ 0 ].brushes );
451 tree = FaceBSP( faces );
452 MakeTreePortals( tree );
453 FilterStructuralBrushesIntoTree( e, tree );
456 /* ydnar: flood again for skybox */
458 FloodEntities( tree );
462 Sys_FPrintf( SYS_NOXML, "**********************\n" );
463 Sys_FPrintf( SYS_NOXML, "******* leaked *******\n" );
464 Sys_FPrintf( SYS_NOXML, "**********************\n" );
465 polyline = LeakFile( tree );
466 leaknode = xmlNewNode( NULL, "message" );
467 xmlNodeSetContent( leaknode, "MAP LEAKED\n" );
468 xmlAddChild( leaknode, polyline );
469 level[0] = (int) '0' + SYS_ERR;
471 xmlSetProp( leaknode, "level", (char*) &level );
472 xml_SendNode( leaknode );
475 Sys_Printf ("--- MAP LEAKED, ABORTING LEAKTEST ---\n");
480 /* chop the sides to the convex hull of their visible fragments, giving us the smallest polygons */
481 ClipSidesIntoTree( e, tree );
484 /* save out information for visibility processing */
485 NumberClusters( tree );
487 WritePortalFile( tree );
489 /* flood from entities */
492 /* create drawsurfs for triangle models */
493 AddTriangleModels( e );
495 /* create drawsurfs for surface models */
496 AddEntitySurfaceModels( e );
498 /* generate bsp brushes from map brushes */
499 EmitBrushes( e->brushes, &e->firstBrush, &e->numBrushes );
501 /* add references to the detail brushes */
502 FilterDetailBrushesIntoTree( e, tree );
504 /* drawsurfs that cross fog boundaries will need to be split along the fog boundary */
506 FogDrawSurfaces( e );
508 /* subdivide each drawsurf as required by shader tesselation */
510 SubdivideFaceSurfaces( e, tree );
512 /* add in any vertexes required to fix t-junctions */
516 /* ydnar: classify the surfaces */
517 ClassifyEntitySurfaces( e );
519 /* ydnar: project decals */
520 MakeEntityDecals( e );
522 /* ydnar: meta surfaces */
523 MakeEntityMetaTriangles( e );
524 SmoothMetaTriangles();
526 MergeMetaTriangles();
528 /* ydnar: debug portals */
530 MakeDebugPortalSurfs( tree );
532 /* ydnar: fog hull */
533 value = ValueForKey( &entities[ 0 ], "_foghull" );
534 if( value[ 0 ] != '\0' )
536 sprintf( shader, "textures/%s", value );
537 MakeFogHullSurfs( e, tree, shader );
540 /* ydnar: bug 645: do flares for lights */
541 for( i = 0; i < numEntities && emitFlares; i++ )
543 entity_t *light, *target;
544 const char *value, *flareShader;
545 vec3_t origin, targetOrigin, normal, color;
550 light = &entities[ i ];
551 value = ValueForKey( light, "classname" );
552 if( !strcmp( value, "light" ) )
554 /* get flare shader */
555 flareShader = ValueForKey( light, "_flareshader" );
556 value = ValueForKey( light, "_flare" );
557 if( flareShader[ 0 ] != '\0' || value[ 0 ] != '\0' )
560 GetVectorForKey( light, "origin", origin );
561 GetVectorForKey( light, "_color", color );
562 lightStyle = IntForKey( light, "_style" );
563 if( lightStyle == 0 )
564 lightStyle = IntForKey( light, "style" );
566 /* handle directional spotlights */
567 value = ValueForKey( light, "target" );
568 if( value[ 0 ] != '\0' )
570 /* get target light */
571 target = FindTargetEntity( value );
574 GetVectorForKey( target, "origin", targetOrigin );
575 VectorSubtract( targetOrigin, origin, normal );
576 VectorNormalize( normal, normal );
580 //% VectorClear( normal );
581 VectorSet( normal, 0, 0, -1 );
583 /* create the flare surface (note shader defaults automatically) */
584 DrawSurfaceForFlare( mapEntityNum, origin, normal, color, (char*) flareShader, lightStyle );
589 /* add references to the final drawsurfs in the apropriate clusters */
590 FilterDrawsurfsIntoTree( e, tree );
592 /* match drawsurfaces back to original brushsides (sof2) */
596 EndModel( e, tree->headnode );
604 creates bsp + surfaces for other brush models
607 void ProcessSubModel( void )
615 /* start a brush model */
617 e = &entities[ mapEntityNum ];
618 e->firstDrawSurf = numMapDrawSurfs;
621 ClearMetaTriangles();
623 /* check for patches with adjacent edges that need to lod together */
624 PatchMapDrawSurfs( e );
626 /* allocate a tree */
628 node->planenum = PLANENUM_LEAF;
630 tree->headnode = node;
632 /* add the sides to the tree */
633 ClipSidesIntoTree( e, tree );
635 /* ydnar: create drawsurfs for triangle models */
636 AddTriangleModels( e );
638 /* create drawsurfs for surface models */
639 AddEntitySurfaceModels( e );
641 /* generate bsp brushes from map brushes */
642 EmitBrushes( e->brushes, &e->firstBrush, &e->numBrushes );
644 /* just put all the brushes in headnode */
645 for( b = e->brushes; b; b = b->next )
648 bc->next = node->brushlist;
649 node->brushlist = bc;
652 /* subdivide each drawsurf as required by shader tesselation */
654 SubdivideFaceSurfaces( e, tree );
656 /* add in any vertexes required to fix t-junctions */
660 /* ydnar: classify the surfaces and project lightmaps */
661 ClassifyEntitySurfaces( e );
663 /* ydnar: project decals */
664 MakeEntityDecals( e );
666 /* ydnar: meta surfaces */
667 MakeEntityMetaTriangles( e );
668 SmoothMetaTriangles();
670 MergeMetaTriangles();
672 /* add references to the final drawsurfs in the apropriate clusters */
673 FilterDrawsurfsIntoTree( e, tree );
675 /* match drawsurfaces back to original brushsides (sof2) */
687 process world + other models into the bsp
690 void ProcessModels( void )
696 /* preserve -v setting */
697 oldVerbose = verbose;
699 /* start a new bsp */
702 /* create map fogs */
705 /* walk entity list */
706 for( mapEntityNum = 0; mapEntityNum < numEntities; mapEntityNum++ )
709 entity = &entities[ mapEntityNum ];
710 if( entity->brushes == NULL && entity->patches == NULL )
713 /* process the model */
714 Sys_FPrintf( SYS_VRB, "############### model %i ###############\n", numBSPModels );
715 if( mapEntityNum == 0 )
720 /* potentially turn off the deluge of text */
721 verbose = verboseEntities;
724 /* restore -v setting */
725 verbose = oldVerbose;
730 /* vortex: emit meta stats */
738 this is probably broken unless teamed with a radiant version that preserves entity order
741 void OnlyEnts( void )
745 char save_cmdline[1024], save_version[1024];
749 Sys_Printf( "--- OnlyEnts ---\n" );
751 sprintf( out, "%s.bsp", source );
755 p = ValueForKey(&entities[0], "_q3map2_cmdline");
756 strncpy(save_cmdline, p, sizeof(save_cmdline));
757 save_cmdline[sizeof(save_cmdline)-1] = 0;
758 p = ValueForKey(&entities[0], "_q3map2_version");
759 strncpy(save_version, p, sizeof(save_version));
760 save_version[sizeof(save_version)-1] = 0;
765 LoadMapFile( name, qfalse );
770 SetKeyValue(&entities[0], "_q3map2_cmdline", save_cmdline);
772 SetKeyValue(&entities[0], "_q3map2_version", save_version);
774 numBSPEntities = numEntities;
784 handles creation of a bsp from a map file
787 int BSPMain( int argc, char **argv )
790 char path[ 1024 ], tempSource[ 1024 ];
791 qboolean onlyents = qfalse;
795 Sys_Printf( "--- BSP ---\n" );
797 SetDrawSurfacesBuffer();
798 mapDrawSurfs = safe_malloc( sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
799 memset( mapDrawSurfs, 0, sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
802 tempSource[ 0 ] = '\0';
803 globalCelShader[0] = 0;
805 /* set standard game flags */
806 maxSurfaceVerts = game->maxSurfaceVerts;
807 maxSurfaceIndexes = game->maxSurfaceIndexes;
808 emitFlares = game->emitFlares;
810 /* process arguments */
811 for( i = 1; i < (argc - 1); i++ )
813 if( !strcmp( argv[ i ], "-onlyents" ) )
815 Sys_Printf( "Running entity-only compile\n" );
818 else if( !strcmp( argv[ i ], "-tempname" ) )
819 strcpy( tempSource, argv[ ++i ] );
820 else if( !strcmp( argv[ i ], "-tmpout" ) )
821 strcpy( outbase, "/tmp" );
822 else if( !strcmp( argv[ i ], "-nowater" ) )
824 Sys_Printf( "Disabling water\n" );
827 else if( !strcmp( argv[ i ], "-nodetail" ) )
829 Sys_Printf( "Ignoring detail brushes\n") ;
832 else if( !strcmp( argv[ i ], "-fulldetail" ) )
834 Sys_Printf( "Turning detail brushes into structural brushes\n" );
837 else if( !strcmp( argv[ i ], "-nofog" ) )
839 Sys_Printf( "Fog volumes disabled\n" );
842 else if( !strcmp( argv[ i ], "-nosubdivide" ) )
844 Sys_Printf( "Disabling brush face subdivision\n" );
847 else if( !strcmp( argv[ i ], "-leaktest" ) )
849 Sys_Printf( "Leaktest enabled\n" );
852 else if( !strcmp( argv[ i ], "-verboseentities" ) )
854 Sys_Printf( "Verbose entities enabled\n" );
855 verboseEntities = qtrue;
857 else if( !strcmp( argv[ i ], "-nocurves" ) )
859 Sys_Printf( "Ignoring curved surfaces (patches)\n" );
860 noCurveBrushes = qtrue;
862 else if( !strcmp( argv[ i ], "-notjunc" ) )
864 Sys_Printf( "T-junction fixing disabled\n" );
867 else if( !strcmp( argv[ i ], "-fakemap" ) )
869 Sys_Printf( "Generating fakemap.map\n" );
872 else if( !strcmp( argv[ i ], "-samplesize" ) )
874 sampleSize = atoi( argv[ i + 1 ] );
878 Sys_Printf( "Lightmap sample size set to %dx%d units\n", sampleSize, sampleSize );
880 else if( !strcmp( argv[ i ], "-minsamplesize" ) )
882 minSampleSize = atoi( argv[ i + 1 ] );
883 if( minSampleSize < 1 )
886 Sys_Printf( "Minimum lightmap sample size set to %dx%d units\n", minSampleSize, minSampleSize );
888 else if( !strcmp( argv[ i ], "-custinfoparms") )
890 Sys_Printf( "Custom info parms enabled\n" );
891 useCustomInfoParms = qtrue;
895 else if( !strcmp( argv[ i ], "-rename" ) )
897 Sys_Printf( "Appending _bsp suffix to misc_model shaders (SOF2)\n" );
898 renameModelShaders = qtrue;
902 else if( !strcmp( argv[ i ], "-ne" ) )
904 normalEpsilon = atof( argv[ i + 1 ] );
906 Sys_Printf( "Normal epsilon set to %f\n", normalEpsilon );
908 else if( !strcmp( argv[ i ], "-de" ) )
910 distanceEpsilon = atof( argv[ i + 1 ] );
912 Sys_Printf( "Distance epsilon set to %f\n", distanceEpsilon );
914 else if( !strcmp( argv[ i ], "-mv" ) )
916 maxLMSurfaceVerts = atoi( argv[ i + 1 ] );
917 if( maxLMSurfaceVerts < 3 )
918 maxLMSurfaceVerts = 3;
919 if( maxLMSurfaceVerts > maxSurfaceVerts )
920 maxSurfaceVerts = maxLMSurfaceVerts;
922 Sys_Printf( "Maximum lightmapped surface vertex count set to %d\n", maxLMSurfaceVerts );
924 else if( !strcmp( argv[ i ], "-mi" ) )
926 maxSurfaceIndexes = atoi( argv[ i + 1 ] );
927 if( maxSurfaceIndexes < 3 )
928 maxSurfaceIndexes = 3;
930 Sys_Printf( "Maximum per-surface index count set to %d\n", maxSurfaceIndexes );
932 else if( !strcmp( argv[ i ], "-np" ) )
934 npDegrees = atof( argv[ i + 1 ] );
935 if( npDegrees < 0.0f )
936 shadeAngleDegrees = 0.0f;
937 else if( npDegrees > 0.0f )
938 Sys_Printf( "Forcing nonplanar surfaces with a breaking angle of %f degrees\n", npDegrees );
941 else if( !strcmp( argv[ i ], "-snap" ) )
943 bevelSnap = atoi( argv[ i + 1 ]);
948 Sys_Printf( "Snapping brush bevel planes to %d units\n", bevelSnap );
950 else if( !strcmp( argv[ i ], "-texrange" ) )
952 texRange = atoi( argv[ i + 1 ]);
956 Sys_Printf( "Limiting per-surface texture range to %d texels\n", texRange );
958 else if( !strcmp( argv[ i ], "-nohint" ) )
960 Sys_Printf( "Hint brushes disabled\n" );
963 else if( !strcmp( argv[ i ], "-flat" ) )
965 Sys_Printf( "Flatshading enabled\n" );
968 else if( !strcmp( argv[ i ], "-celshader" ) )
972 sprintf( globalCelShader, "textures/%s", argv[ i ] );
974 *globalCelShader = 0;
975 Sys_Printf( "Global cel shader set to \"%s\"\n", globalCelShader );
977 else if( !strcmp( argv[ i ], "-meta" ) )
979 Sys_Printf( "Creating meta surfaces from brush faces\n" );
982 else if( !strcmp( argv[ i ], "-patchmeta" ) )
984 Sys_Printf( "Creating meta surfaces from patches\n" );
987 else if( !strcmp( argv[ i ], "-flares" ) )
989 Sys_Printf( "Flare surfaces enabled\n" );
992 else if( !strcmp( argv[ i ], "-noflares" ) )
994 Sys_Printf( "Flare surfaces disabled\n" );
997 else if( !strcmp( argv[ i ], "-skyfix" ) )
999 Sys_Printf( "GL_CLAMP sky fix/hack/workaround enabled\n" );
1002 else if( !strcmp( argv[ i ], "-debugsurfaces" ) )
1004 Sys_Printf( "emitting debug surfaces\n" );
1005 debugSurfaces = qtrue;
1007 else if( !strcmp( argv[ i ], "-debuginset" ) )
1009 Sys_Printf( "Debug surface triangle insetting enabled\n" );
1012 else if( !strcmp( argv[ i ], "-debugportals" ) )
1014 Sys_Printf( "Debug portal surfaces enabled\n" );
1015 debugPortals = qtrue;
1017 else if( !strcmp( argv[ i ], "-altsplit" ) )
1019 Sys_Printf( "Alternate BSP splitting (by 27) enabled\n" );
1020 bspAlternateSplitWeights = qtrue;
1022 else if( !strcmp( argv[ i ], "-deep" ) )
1024 Sys_Printf( "Deep BSP tree generation enabled\n" );
1027 else if( !strcmp( argv[ i ], "-minimap" ) )
1029 miniMap = argv[i + 1];
1032 else if( !strcmp( argv[ i ], "-bsp" ) )
1033 Sys_Printf( "-bsp argument unnecessary\n" );
1036 Sys_Printf( "WARNING: Unknown option \"%s\"\n", argv[ i ] );
1040 /* fixme: print more useful usage here */
1041 if( i != (argc - 1) )
1042 Error( "usage: q3map [options] mapfile" );
1044 /* copy source name */
1045 strcpy( source, ExpandArg( argv[ i ] ) );
1046 StripExtension( source );
1048 /* ydnar: set default sample size */
1049 SetDefaultSampleSize( sampleSize );
1051 /* delete portal, line and surface files */
1052 sprintf( path, "%s.prt", source );
1054 sprintf( path, "%s.lin", source );
1056 //% sprintf( path, "%s.srf", source ); /* ydnar */
1059 /* expand mapname */
1060 strcpy( name, ExpandArg( argv[ i ] ) );
1061 if( strcmp( name + strlen( name ) - 4, ".reg" ) )
1063 /* if we are doing a full map, delete the last saved region map */
1064 sprintf( path, "%s.reg", source );
1066 DefaultExtension( name, ".map" ); /* might be .reg */
1069 /* if onlyents, just grab the entites and resave */
1079 /* load original file from temp spot in case it was renamed by the editor on the way in */
1080 if( strlen( tempSource ) > 0 )
1081 LoadMapFile( tempSource, qfalse );
1083 LoadMapFile( name, qfalse );
1085 /* div0: inject command line parameters */
1086 InjectCommandLine(argv, 1, argc - 1);
1088 /* ydnar: decal setup */
1091 /* ydnar: cloned brush model entities */
1092 SetCloneModelNumbers();
1094 /* process world and submodels */
1097 /* set light styles from targetted light entities */
1100 /* process in game advertisements */
1101 ProcessAdvertisements();
1103 /* finish and write bsp */
1106 /* write the mini map if needed */
1110 /* remove temp map source file if appropriate */
1111 if( strlen( tempSource ) > 0)
1112 remove( tempSource );
1114 /* return to sender */