]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake3/q3map2/bsp.c
enable q3map2 out of tree compilation
[xonotic/netradiant.git] / tools / quake3 / q3map2 / bsp.c
index 5f9faa4a41ba92459b4f659c78bd023290169646..4ac39f36ded15067c8476df765a8c61965a46ab7 100644 (file)
@@ -44,7 +44,6 @@
 
    ------------------------------------------------------------------------------- */
 
-
 /*
    ProcessAdvertisements()
    copies advertisement info into the BSP structures
@@ -141,7 +140,13 @@ static void SetCloneModelNumbers( void ){
                }
 
                /* is this a clone? */
-               value = ValueForKey( &entities[ i ], "_clone" );
+               value = ValueForKey( &entities[ i ], "_ins" );
+               if ( value[ 0 ] == '\0' ) {
+                       value = ValueForKey( &entities[ i ], "_instance" );
+               }
+               if ( value[ 0 ] == '\0' ) {
+                       value = ValueForKey( &entities[ i ], "_clone" );
+               }
                if ( value[ 0 ] != '\0' ) {
                        continue;
                }
@@ -260,7 +265,7 @@ static void FixBrushSides( entity_t *e ){
    creates a full bsp + surfaces for the worldspawn entity
  */
 
-void ProcessWorldModel( void ){
+void ProcessWorldModel( const char *portalFilePath, const char *lineFilePath ){
        int i, s;
        entity_t    *e;
        tree_t      *tree;
@@ -269,7 +274,7 @@ void ProcessWorldModel( void ){
        xmlNodePtr polyline, leaknode;
        char level[ 2 ], shader[ 1024 ];
        const char  *value;
-
+       int leakStatus;
 
        /* sets integer blockSize from worldspawn "_blocksize" key if it exists */
        value = ValueForKey( &entities[ 0 ], "_blocksize" );
@@ -321,53 +326,61 @@ void ProcessWorldModel( void ){
        FilterStructuralBrushesIntoTree( e, tree );
 
        /* see if the bsp is completely enclosed */
-       if ( FloodEntities( tree ) || ignoreLeaks ) {
-               /* rebuild a better bsp tree using only the sides that are visible from the inside */
-               FillOutside( tree->headnode );
-
-               /* chop the sides to the convex hull of their visible fragments, giving us the smallest polygons */
-               ClipSidesIntoTree( e, tree );
+       leakStatus = FloodEntities( tree );
+       if ( ignoreLeaks ) {
+               if ( leakStatus == FLOODENTITIES_LEAKED ) {
+                       leakStatus = FLOODENTITIES_GOOD;
+               }
+       }
 
-               /* build a visible face tree */
-               faces = MakeVisibleBSPFaceList( entities[ 0 ].brushes );
-               FreeTree( tree );
-               tree = FaceBSP( faces );
-               MakeTreePortals( tree );
-               FilterStructuralBrushesIntoTree( e, tree );
+       if ( leakStatus == FLOODENTITIES_GOOD ) {
                leaked = qfalse;
-
-               /* ydnar: flood again for skybox */
-               if ( skyboxPresent ) {
-                       FloodEntities( tree );
-               }
        }
        else
        {
+               leaked = qtrue;
+
                Sys_FPrintf( SYS_NOXML, "**********************\n" );
                Sys_FPrintf( SYS_NOXML, "******* leaked *******\n" );
                Sys_FPrintf( SYS_NOXML, "**********************\n" );
-               polyline = LeakFile( tree );
-               leaknode = xmlNewNode( NULL, "message" );
-               xmlNodeSetContent( leaknode, "MAP LEAKED\n" );
+               polyline = LeakFile( tree, lineFilePath );
+               leaknode = xmlNewNode( NULL, (xmlChar*)"message" );
+               xmlNodeSetContent( leaknode, (xmlChar*)"MAP LEAKED\n" );
                xmlAddChild( leaknode, polyline );
                level[0] = (int) '0' + SYS_ERR;
                level[1] = 0;
-               xmlSetProp( leaknode, "level", (char*) &level );
+               xmlSetProp( leaknode, (xmlChar*)"level", (xmlChar*) &level );
                xml_SendNode( leaknode );
                if ( leaktest ) {
                        Sys_Printf( "--- MAP LEAKED, ABORTING LEAKTEST ---\n" );
                        exit( 0 );
                }
-               leaked = qtrue;
+       }
+
+       if ( leakStatus != FLOODENTITIES_EMPTY ) { /* if no entities exist, this would accidentally the whole map, and that IS bad */
+               /* rebuild a better bsp tree using only the sides that are visible from the inside */
+               FillOutside( tree->headnode );
 
                /* chop the sides to the convex hull of their visible fragments, giving us the smallest polygons */
                ClipSidesIntoTree( e, tree );
+
+               /* build a visible face tree (same thing as the initial bsp tree but after reducing the faces) */
+               faces = MakeVisibleBSPFaceList( entities[ 0 ].brushes );
+               FreeTree( tree );
+               tree = FaceBSP( faces );
+               MakeTreePortals( tree );
+               FilterStructuralBrushesIntoTree( e, tree );
+
+               /* ydnar: flood again for skybox */
+               if ( skyboxPresent ) {
+                       FloodEntities( tree );
+               }
        }
 
        /* save out information for visibility processing */
        NumberClusters( tree );
        if ( !leaked ) {
-               WritePortalFile( tree );
+               WritePortalFile( tree, portalFilePath );
        }
 
        /* flood from entities */
@@ -465,8 +478,14 @@ void ProcessWorldModel( void ){
                                        VectorSet( normal, 0, 0, -1 );
                                }
 
+                               if ( colorsRGB ) {
+                                       color[0] = Image_LinearFloatFromsRGBFloat( color[0] );
+                                       color[1] = Image_LinearFloatFromsRGBFloat( color[1] );
+                                       color[2] = Image_LinearFloatFromsRGBFloat( color[2] );
+                               }
+
                                /* create the flare surface (note shader defaults automatically) */
-                               DrawSurfaceForFlare( mapEntityNum, origin, normal, color, (char*) flareShader, lightStyle );
+                               DrawSurfaceForFlare( mapEntityNum, origin, normal, color, flareShader, lightStyle );
                        }
                }
        }
@@ -573,7 +592,7 @@ void ProcessSubModel( void ){
    process world + other models into the bsp
  */
 
-void ProcessModels( void ){
+void ProcessModels( const char *portalFilePath, const char *lineFilePath ){
        qboolean oldVerbose;
        entity_t    *entity;
 
@@ -599,7 +618,7 @@ void ProcessModels( void ){
                /* process the model */
                Sys_FPrintf( SYS_VRB, "############### model %i ###############\n", numBSPModels );
                if ( mapEntityNum == 0 ) {
-                       ProcessWorldModel();
+                       ProcessWorldModel(portalFilePath, lineFilePath);
                }
                else{
                        ProcessSubModel();
@@ -614,6 +633,9 @@ void ProcessModels( void ){
 
        /* write fogs */
        EmitFogs();
+
+       /* vortex: emit meta stats */
+       EmitMetaStats();
 }
 
 
@@ -623,26 +645,47 @@ void ProcessModels( void ){
    this is probably broken unless teamed with a radiant version that preserves entity order
  */
 
-void OnlyEnts( void ){
-       char out[ 1024 ];
-
+void OnlyEnts( const char *BSPFilePath ){
+       char save_cmdline[1024], save_version[1024], save_gridsize[1024];
+       const char *p;
 
        /* note it */
        Sys_Printf( "--- OnlyEnts ---\n" );
 
-       sprintf( out, "%s.bsp", source );
-       LoadBSPFile( out );
+       LoadBSPFile( BSPFilePath );
+
+       ParseEntities();
+       p = ValueForKey( &entities[0], "_q3map2_cmdline" );
+       strncpy( save_cmdline, p, sizeof( save_cmdline ) );
+       save_cmdline[sizeof( save_cmdline ) - 1] = 0;
+       p = ValueForKey( &entities[0], "_q3map2_version" );
+       strncpy( save_version, p, sizeof( save_version ) );
+       save_version[sizeof( save_version ) - 1] = 0;
+       p = ValueForKey( &entities[0], "gridsize" );
+       strncpy( save_gridsize, p, sizeof( save_gridsize ) );
+       save_gridsize[sizeof( save_gridsize ) - 1] = 0;
+
        numEntities = 0;
 
        LoadShaderInfo();
-       LoadMapFile( name, qfalse );
+       LoadMapFile( name, qfalse, qfalse );
        SetModelNumbers();
        SetLightStyles();
 
+       if ( *save_cmdline ) {
+               SetKeyValue( &entities[0], "_q3map2_cmdline", save_cmdline );
+       }
+       if ( *save_version ) {
+               SetKeyValue( &entities[0], "_q3map2_version", save_version );
+       }
+       if ( *save_gridsize ) {
+               SetKeyValue( &entities[0], "gridsize", save_gridsize );
+       }
+
        numBSPEntities = numEntities;
        UnparseEntities();
 
-       WriteBSPFile( out );
+       WriteBSPFile( BSPFilePath );
 }
 
 
@@ -656,6 +699,14 @@ int BSPMain( int argc, char **argv ){
        int i;
        char path[ 1024 ], tempSource[ 1024 ];
        qboolean onlyents = qfalse;
+       char BSPFilePath [ 1024 ];
+       char lineFilePath [ 1024 ];
+       char portalFilePath [ 1024 ];
+       char surfaceFilePath [ 1024 ];
+       BSPFilePath[0] = 0;
+       lineFilePath[0] = 0;
+       portalFilePath[0] = 0;
+       surfaceFilePath[0] = 0;
 
 
        /* note it */
@@ -667,11 +718,14 @@ int BSPMain( int argc, char **argv ){
        numMapDrawSurfs = 0;
 
        tempSource[ 0 ] = '\0';
+       globalCelShader[0] = 0;
 
        /* set standard game flags */
        maxSurfaceVerts = game->maxSurfaceVerts;
        maxSurfaceIndexes = game->maxSurfaceIndexes;
        emitFlares = game->emitFlares;
+       texturesRGB = game->texturesRGB;
+       colorsRGB = game->colorsRGB;
 
        /* process arguments */
        for ( i = 1; i < ( argc - 1 ); i++ )
@@ -690,6 +744,10 @@ int BSPMain( int argc, char **argv ){
                        Sys_Printf( "Disabling water\n" );
                        nowater = qtrue;
                }
+               else if ( !strcmp( argv[ i ], "-keeplights" ) ) {
+                       keepLights = qtrue;
+                       Sys_Printf( "Leaving light entities on map after compile\n" );
+               }
                else if ( !strcmp( argv[ i ],  "-nodetail" ) ) {
                        Sys_Printf( "Ignoring detail brushes\n" ) ;
                        nodetail = qtrue;
@@ -734,6 +792,14 @@ int BSPMain( int argc, char **argv ){
                        i++;
                        Sys_Printf( "Lightmap sample size set to %dx%d units\n", sampleSize, sampleSize );
                }
+               else if ( !strcmp( argv[ i ], "-minsamplesize" ) ) {
+                       minSampleSize = atoi( argv[ i + 1 ] );
+                       if ( minSampleSize < 1 ) {
+                               minSampleSize = 1;
+                       }
+                       i++;
+                       Sys_Printf( "Minimum lightmap sample size set to %dx%d units\n", minSampleSize, minSampleSize );
+               }
                else if ( !strcmp( argv[ i ],  "-custinfoparms" ) ) {
                        Sys_Printf( "Custom info parms enabled\n" );
                        useCustomInfoParms = qtrue;
@@ -778,7 +844,7 @@ int BSPMain( int argc, char **argv ){
                else if ( !strcmp( argv[ i ], "-np" ) ) {
                        npDegrees = atof( argv[ i + 1 ] );
                        if ( npDegrees < 0.0f ) {
-                               shadeAngleDegrees = 0.0f;
+                               npDegrees = 0.0f;
                        }
                        else if ( npDegrees > 0.0f ) {
                                Sys_Printf( "Forcing nonplanar surfaces with a breaking angle of %f degrees\n", npDegrees );
@@ -811,10 +877,50 @@ int BSPMain( int argc, char **argv ){
                        Sys_Printf( "Flatshading enabled\n" );
                        flat = qtrue;
                }
+               else if ( !strcmp( argv[ i ], "-celshader" ) ) {
+                       ++i;
+                       if ( argv[i][0] ) {
+                               sprintf( globalCelShader, "textures/%s", argv[ i ] );
+                       }
+                       else{
+                               *globalCelShader = 0;
+                       }
+                       Sys_Printf( "Global cel shader set to \"%s\"\n", globalCelShader );
+               }
                else if ( !strcmp( argv[ i ], "-meta" ) ) {
                        Sys_Printf( "Creating meta surfaces from brush faces\n" );
                        meta = qtrue;
                }
+               else if ( !strcmp( argv[ i ], "-metaadequatescore" ) ) {
+                       metaAdequateScore = atoi( argv[ i + 1 ] );
+                       if ( metaAdequateScore < 0 ) {
+                               metaAdequateScore = -1;
+                       }
+                       i++;
+                       if ( metaAdequateScore >= 0 ) {
+                               Sys_Printf( "Setting ADEQUATE meta score to %d (see surface_meta.c)\n", metaAdequateScore );
+                       }
+               }
+               else if ( !strcmp( argv[ i ], "-metagoodscore" ) ) {
+                       metaGoodScore = atoi( argv[ i + 1 ] );
+                       if ( metaGoodScore < 0 ) {
+                               metaGoodScore = -1;
+                       }
+                       i++;
+                       if ( metaGoodScore >= 0 ) {
+                               Sys_Printf( "Setting GOOD meta score to %d (see surface_meta.c)\n", metaGoodScore );
+                       }
+               }
+               else if ( !strcmp( argv[ i ], "-metamaxbboxdistance" ) ) {
+                       metaMaxBBoxDistance = atof( argv[ i + 1 ] );
+                       if ( metaMaxBBoxDistance < 0 ) {
+                               metaMaxBBoxDistance = -1;
+                       }
+                       i++;
+                       if ( metaMaxBBoxDistance >= 0 ) {
+                               Sys_Printf( "Setting meta maximum bounding box distance to %f\n", metaMaxBBoxDistance );
+                       }
+               }
                else if ( !strcmp( argv[ i ], "-patchmeta" ) ) {
                        Sys_Printf( "Creating meta surfaces from patches\n" );
                        patchMeta = qtrue;
@@ -843,10 +949,69 @@ int BSPMain( int argc, char **argv ){
                        Sys_Printf( "Debug portal surfaces enabled\n" );
                        debugPortals = qtrue;
                }
+               else if ( !strcmp( argv[ i ], "-sRGBtex" ) ) {
+                       texturesRGB = qtrue;
+                       Sys_Printf( "Textures are in sRGB\n" );
+               }
+               else if ( !strcmp( argv[ i ], "-nosRGBtex" ) ) {
+                       texturesRGB = qfalse;
+                       Sys_Printf( "Textures are linear\n" );
+               }
+               else if ( !strcmp( argv[ i ], "-sRGBcolor" ) ) {
+                       colorsRGB = qtrue;
+                       Sys_Printf( "Colors are in sRGB\n" );
+               }
+               else if ( !strcmp( argv[ i ], "-nosRGBcolor" ) ) {
+                       colorsRGB = qfalse;
+                       Sys_Printf( "Colors are linear\n" );
+               }
+               else if ( !strcmp( argv[ i ], "-nosRGB" ) ) {
+                       texturesRGB = qfalse;
+                       Sys_Printf( "Textures are linear\n" );
+                       colorsRGB = qfalse;
+                       Sys_Printf( "Colors are linear\n" );
+               }
+               else if ( !strcmp( argv[ i ], "-altsplit" ) ) {
+                       Sys_Printf( "Alternate BSP splitting (by 27) enabled\n" );
+                       bspAlternateSplitWeights = qtrue;
+               }
+               else if ( !strcmp( argv[ i ], "-deep" ) ) {
+                       Sys_Printf( "Deep BSP tree generation enabled\n" );
+                       deepBSP = qtrue;
+               }
+               else if ( !strcmp( argv[ i ], "-maxarea" ) ) {
+                       Sys_Printf( "Max Area face surface generation enabled\n" );
+                       maxAreaFaceSurface = qtrue;
+               }
+               else if ( !strcmp( argv[ i ], "-bspfile" ) )
+               {
+                       strcpy( BSPFilePath, argv[i + 1] );
+                       i++;
+                       Sys_Printf( "Use %s as bsp file\n", BSPFilePath );
+               }
+               else if ( !strcmp( argv[ i ], "-linfile" ) )
+               {
+                       strcpy( lineFilePath, argv[i + 1] );
+                       i++;
+                       Sys_Printf( "Use %s as line file\n", lineFilePath );
+               }
+               else if ( !strcmp( argv[ i ], "-prtfile" ) )
+               {
+                       strcpy( portalFilePath, argv[i + 1] );
+                       i++;
+                       Sys_Printf( "Use %s as portal file\n", portalFilePath );
+               }
+               else if ( !strcmp( argv[ i ], "-srffile" ) )
+               {
+                       strcpy( surfaceFilePath, argv[i + 1] );
+                       i++;
+                       Sys_Printf( "Use %s as surface file\n", surfaceFilePath );
+               }
                else if ( !strcmp( argv[ i ], "-bsp" ) ) {
                        Sys_Printf( "-bsp argument unnecessary\n" );
                }
-               else{
+               else
+               {
                        Sys_Printf( "WARNING: Unknown option \"%s\"\n", argv[ i ] );
                }
        }
@@ -863,13 +1028,23 @@ int BSPMain( int argc, char **argv ){
        /* ydnar: set default sample size */
        SetDefaultSampleSize( sampleSize );
 
+       if (!BSPFilePath[0]) {
+               sprintf( BSPFilePath, "%s.bsp", source );
+       }
+       if (!lineFilePath[0]) {
+               sprintf( lineFilePath, "%s.lin", source );
+       }
+       if (!portalFilePath[0]) {
+               sprintf( portalFilePath, "%s.prt", source );
+       }
+       if (!surfaceFilePath[0]) {
+               sprintf( surfaceFilePath, "%s.srf", source );
+       }
+
        /* delete portal, line and surface files */
-       sprintf( path, "%s.prt", source );
-       remove( path );
-       sprintf( path, "%s.lin", source );
-       remove( path );
-       //%     sprintf( path, "%s.srf", source );      /* ydnar */
-       //%     remove( path );
+       remove( portalFilePath );
+       remove( lineFilePath );
+       //%     remove( surfaceFilePath )       /* ydnar */
 
        /* expand mapname */
        strcpy( name, ExpandArg( argv[ i ] ) );
@@ -882,7 +1057,7 @@ int BSPMain( int argc, char **argv ){
 
        /* if onlyents, just grab the entites and resave */
        if ( onlyents ) {
-               OnlyEnts();
+               OnlyEnts( BSPFilePath );
                return 0;
        }
 
@@ -891,12 +1066,15 @@ int BSPMain( int argc, char **argv ){
 
        /* load original file from temp spot in case it was renamed by the editor on the way in */
        if ( strlen( tempSource ) > 0 ) {
-               LoadMapFile( tempSource, qfalse );
+               LoadMapFile( tempSource, qfalse, qfalse );
        }
        else{
-               LoadMapFile( name, qfalse );
+               LoadMapFile( name, qfalse, qfalse );
        }
 
+       /* div0: inject command line parameters */
+       InjectCommandLine( argv, 1, argc - 1 );
+
        /* ydnar: decal setup */
        ProcessDecals();
 
@@ -904,7 +1082,7 @@ int BSPMain( int argc, char **argv ){
        SetCloneModelNumbers();
 
        /* process world and submodels */
-       ProcessModels();
+       ProcessModels( portalFilePath, lineFilePath );
 
        /* set light styles from targetted light entities */
        SetLightStyles();
@@ -913,7 +1091,7 @@ int BSPMain( int argc, char **argv ){
        ProcessAdvertisements();
 
        /* finish and write bsp */
-       EndBSPFile();
+       EndBSPFile( qtrue, BSPFilePath, surfaceFilePath );
 
        /* remove temp map source file if appropriate */
        if ( strlen( tempSource ) > 0 ) {