示例#1
0
文件: bsp.c 项目: Triang3l/netradiant
int BSPMain( int argc, char **argv ){
	int i;
	char path[ 1024 ], tempSource[ 1024 ];
	qboolean onlyents = qfalse;


	/* note it */
	Sys_Printf( "--- BSP ---\n" );

	SetDrawSurfacesBuffer();
	mapDrawSurfs = safe_malloc( sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
	memset( mapDrawSurfs, 0, sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
	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++ )
	{
		if ( !strcmp( argv[ i ], "-onlyents" ) ) {
			Sys_Printf( "Running entity-only compile\n" );
			onlyents = qtrue;
		}
		else if ( !strcmp( argv[ i ], "-tempname" ) ) {
			strcpy( tempSource, argv[ ++i ] );
		}
		else if ( !strcmp( argv[ i ], "-tmpout" ) ) {
			strcpy( outbase, "/tmp" );
		}
		else if ( !strcmp( argv[ i ],  "-nowater" ) ) {
			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;
		}
		else if ( !strcmp( argv[ i ],  "-fulldetail" ) ) {
			Sys_Printf( "Turning detail brushes into structural brushes\n" );
			fulldetail = qtrue;
		}
		else if ( !strcmp( argv[ i ],  "-nofog" ) ) {
			Sys_Printf( "Fog volumes disabled\n" );
			nofog = qtrue;
		}
		else if ( !strcmp( argv[ i ],  "-nosubdivide" ) ) {
			Sys_Printf( "Disabling brush face subdivision\n" );
			nosubdivide = qtrue;
		}
		else if ( !strcmp( argv[ i ],  "-leaktest" ) ) {
			Sys_Printf( "Leaktest enabled\n" );
			leaktest = qtrue;
		}
		else if ( !strcmp( argv[ i ],  "-verboseentities" ) ) {
			Sys_Printf( "Verbose entities enabled\n" );
			verboseEntities = qtrue;
		}
		else if ( !strcmp( argv[ i ], "-nocurves" ) ) {
			Sys_Printf( "Ignoring curved surfaces (patches)\n" );
			noCurveBrushes = qtrue;
		}
		else if ( !strcmp( argv[ i ], "-notjunc" ) ) {
			Sys_Printf( "T-junction fixing disabled\n" );
			notjunc = qtrue;
		}
		else if ( !strcmp( argv[ i ], "-fakemap" ) ) {
			Sys_Printf( "Generating fakemap.map\n" );
			fakemap = qtrue;
		}
		else if ( !strcmp( argv[ i ],  "-samplesize" ) ) {
			sampleSize = atoi( argv[ i + 1 ] );
			if ( sampleSize < 1 ) {
				sampleSize = 1;
			}
			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;
		}

		/* sof2 args */
		else if ( !strcmp( argv[ i ], "-rename" ) ) {
			Sys_Printf( "Appending _bsp suffix to misc_model shaders (SOF2)\n" );
			renameModelShaders = qtrue;
		}

		/* ydnar args */
		else if ( !strcmp( argv[ i ],  "-ne" ) ) {
			normalEpsilon = atof( argv[ i + 1 ] );
			i++;
			Sys_Printf( "Normal epsilon set to %f\n", normalEpsilon );
		}
		else if ( !strcmp( argv[ i ],  "-de" ) ) {
			distanceEpsilon = atof( argv[ i + 1 ] );
			i++;
			Sys_Printf( "Distance epsilon set to %f\n", distanceEpsilon );
		}
		else if ( !strcmp( argv[ i ],  "-mv" ) ) {
			maxLMSurfaceVerts = atoi( argv[ i + 1 ] );
			if ( maxLMSurfaceVerts < 3 ) {
				maxLMSurfaceVerts = 3;
			}
			if ( maxLMSurfaceVerts > maxSurfaceVerts ) {
				maxSurfaceVerts = maxLMSurfaceVerts;
			}
			i++;
			Sys_Printf( "Maximum lightmapped surface vertex count set to %d\n", maxLMSurfaceVerts );
		}
		else if ( !strcmp( argv[ i ],  "-mi" ) ) {
			maxSurfaceIndexes = atoi( argv[ i + 1 ] );
			if ( maxSurfaceIndexes < 3 ) {
				maxSurfaceIndexes = 3;
			}
			i++;
			Sys_Printf( "Maximum per-surface index count set to %d\n", maxSurfaceIndexes );
		}
		else if ( !strcmp( argv[ i ], "-np" ) ) {
			npDegrees = atof( argv[ i + 1 ] );
			if ( npDegrees < 0.0f ) {
				npDegrees = 0.0f;
			}
			else if ( npDegrees > 0.0f ) {
				Sys_Printf( "Forcing nonplanar surfaces with a breaking angle of %f degrees\n", npDegrees );
			}
			i++;
		}
		else if ( !strcmp( argv[ i ],  "-snap" ) ) {
			bevelSnap = atoi( argv[ i + 1 ] );
			if ( bevelSnap < 0 ) {
				bevelSnap = 0;
			}
			i++;
			if ( bevelSnap > 0 ) {
				Sys_Printf( "Snapping brush bevel planes to %d units\n", bevelSnap );
			}
		}
		else if ( !strcmp( argv[ i ],  "-texrange" ) ) {
			texRange = atoi( argv[ i + 1 ] );
			if ( texRange < 0 ) {
				texRange = 0;
			}
			i++;
			Sys_Printf( "Limiting per-surface texture range to %d texels\n", texRange );
		}
		else if ( !strcmp( argv[ i ], "-nohint" ) ) {
			Sys_Printf( "Hint brushes disabled\n" );
			noHint = qtrue;
		}
		else if ( !strcmp( argv[ i ], "-flat" ) ) {
			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;
		}
		else if ( !strcmp( argv[ i ], "-flares" ) ) {
			Sys_Printf( "Flare surfaces enabled\n" );
			emitFlares = qtrue;
		}
		else if ( !strcmp( argv[ i ], "-noflares" ) ) {
			Sys_Printf( "Flare surfaces disabled\n" );
			emitFlares = qfalse;
		}
		else if ( !strcmp( argv[ i ], "-skyfix" ) ) {
			Sys_Printf( "GL_CLAMP sky fix/hack/workaround enabled\n" );
			skyFixHack = qtrue;
		}
		else if ( !strcmp( argv[ i ], "-debugsurfaces" ) ) {
			Sys_Printf( "emitting debug surfaces\n" );
			debugSurfaces = qtrue;
		}
		else if ( !strcmp( argv[ i ], "-debuginset" ) ) {
			Sys_Printf( "Debug surface triangle insetting enabled\n" );
			debugInset = qtrue;
		}
		else if ( !strcmp( argv[ i ], "-debugportals" ) ) {
			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 ], "-bsp" ) ) {
			Sys_Printf( "-bsp argument unnecessary\n" );
		}
		else
		{
			Sys_Printf( "WARNING: Unknown option \"%s\"\n", argv[ i ] );
		}
	}

	/* fixme: print more useful usage here */
	if ( i != ( argc - 1 ) ) {
		Error( "usage: q3map [options] mapfile" );
	}

	/* copy source name */
	strcpy( source, ExpandArg( argv[ i ] ) );
	StripExtension( source );

	/* ydnar: set default sample size */
	SetDefaultSampleSize( sampleSize );

	/* 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 );

	/* expand mapname */
	strcpy( name, ExpandArg( argv[ i ] ) );
	if ( strcmp( name + strlen( name ) - 4, ".reg" ) ) {
		/* if we are doing a full map, delete the last saved region map */
		sprintf( path, "%s.reg", source );
		remove( path );
		DefaultExtension( name, ".map" );   /* might be .reg */
	}

	/* if onlyents, just grab the entites and resave */
	if ( onlyents ) {
		OnlyEnts();
		return 0;
	}

	/* load shaders */
	LoadShaderInfo();

	/* 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, qfalse );
	}
	else{
		LoadMapFile( name, qfalse, qfalse );
	}

	/* div0: inject command line parameters */
	InjectCommandLine( argv, 1, argc - 1 );

	/* ydnar: decal setup */
	ProcessDecals();

	/* ydnar: cloned brush model entities */
	SetCloneModelNumbers();

	/* process world and submodels */
	ProcessModels();

	/* set light styles from targetted light entities */
	SetLightStyles();

	/* process in game advertisements */
	ProcessAdvertisements();

	/* finish and write bsp */
	EndBSPFile( qtrue );

	/* remove temp map source file if appropriate */
	if ( strlen( tempSource ) > 0 ) {
		remove( tempSource );
	}

	/* return to sender */
	return 0;
}
示例#2
0
/*
===========
VisMain
===========
*/
int VisMain(int argc, char **argv)
{
	char            portalfile[1024];
	int             i;


	/* note it */
	Sys_Printf("--- Vis ---\n");

	/* process arguments */
	for(i = 1; i < (argc - 1); i++)
	{
		if(!strcmp(argv[i], "-fast"))
		{
			Sys_Printf("fastvis = true\n");
			fastvis = qtrue;
		}
		else if(!strcmp(argv[i], "-merge"))
		{
			Sys_Printf("merge = true\n");
			mergevis = qtrue;
		}
		else if(!strcmp(argv[i], "-mergeportals"))
		{
			Sys_Printf("mergeportals = true\n");
			mergevisportals = qtrue;
		}
		else if(!strcmp(argv[i], "-nopassage"))
		{
			Sys_Printf("nopassage = true\n");
			noPassageVis = qtrue;
		}
		else if(!strcmp(argv[i], "-passageOnly"))
		{
			Sys_Printf("passageOnly = true\n");
			passageVisOnly = qtrue;
		}
		else if(!strcmp(argv[i], "-nosort"))
		{
			Sys_Printf("nosort = true\n");
			nosort = qtrue;
		}
		else if(!strcmp(argv[i], "-v"))
		{
			debugCluster = qtrue;
			Sys_Printf("Extra verbose mode enabled\n");
		}
		else if(!strcmp(argv[i], "-tmpin"))
		{
			strcpy(inbase, "/tmp");
		}
		else if(!strcmp(argv[i], "-tmpout"))
		{
			strcpy(outbase, "/tmp");
		}


		/* ydnar: -hint to merge all but hint portals */
		else if(!strcmp(argv[i], "-hint"))
		{
			Sys_Printf("hint = true\n");
			hint = qtrue;
			mergevis = qtrue;
		}

		else
		{
			Sys_Printf("WARNING: Unknown option \"%s\"\n", argv[i]);
		}
	}

	if(i != argc - 1)
		Error("usage: vis [-threads #] [-level 0-4] [-fast] [-v] bspfile");


	/* load the bsp */
	sprintf(source, "%s%s", inbase, ExpandArg(argv[i]));
	StripExtension(source);
	strcat(source, ".bsp");
	Sys_Printf("Loading %s\n", source);
	LoadBSPFile(source);

	/* load the portal file */
	sprintf(portalfile, "%s%s", inbase, ExpandArg(argv[i]));
	StripExtension(portalfile);
	strcat(portalfile, ".prt");
	Sys_Printf("Loading %s\n", portalfile);
	LoadPortals(portalfile);

	/* ydnar: exit if no portals, hence no vis */
	if(numportals == 0)
	{
		Sys_Printf("No portals means no vis, exiting.\n");
		return 0;
	}

	/* ydnar: for getting far plane */
	ParseEntities();

	/* inject command line parameters */
	InjectCommandLine(argv, 0, argc - 1);
	UnparseEntities();

	if(mergevis)
		MergeLeaves();

	if(mergevis || mergevisportals)
		MergeLeafPortals();

	CountActivePortals();
	/* WritePortals( "maps/hints.prs" ); */

	Sys_Printf("visdatasize:%i\n", numBSPVisBytes);

	CalcVis();

	/* write the bsp file */
	Sys_Printf("Writing %s\n", source);
	WriteBSPFile(source);

	return 0;
}
示例#3
0
文件: bsp_scale.c 项目: Elzair/q3map2
int ScaleBSPMain( int argc, char **argv ){
	int i, j;
	float f, a;
	vec3_t scale;
	vec3_t vec;
	char str[ 1024 ];
	int uniform, axis;
	qboolean texscale;
	float *old_xyzst = NULL;
	float spawn_ref = 0;


	/* arg checking */
	if ( argc < 3 ) {
		Sys_Printf( "Usage: q3map [-v] -scale [-tex] [-spawn_ref <value>] <value> <mapname>\n" );
		return 0;
	}

	texscale = qfalse;
	for ( i = 1; i < argc - 2; ++i )
	{
		if ( !strcmp( argv[i], "-tex" ) ) {
			texscale = qtrue;
		}
		else if ( !strcmp( argv[i], "-spawn_ref" ) ) {
			spawn_ref = atof( argv[i + 1] );
			++i;
		}
		else{
			break;
		}
	}

	/* get scale */
	// if(argc-2 >= i) // always true
	scale[2] = scale[1] = scale[0] = atof( argv[ argc - 2 ] );
	if ( argc - 3 >= i ) {
		scale[1] = scale[0] = atof( argv[ argc - 3 ] );
	}
	if ( argc - 4 >= i ) {
		scale[0] = atof( argv[ argc - 4 ] );
	}

	uniform = ( ( scale[0] == scale[1] ) && ( scale[1] == scale[2] ) );

	if ( scale[0] == 0.0f || scale[1] == 0.0f || scale[2] == 0.0f ) {
		Sys_Printf( "Usage: q3map [-v] -scale [-tex] [-spawn_ref <value>] <value> <mapname>\n" );
		Sys_Printf( "Non-zero scale value required.\n" );
		return 0;
	}

	/* do some path mangling */
	strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
	StripExtension( source );
	DefaultExtension( source, ".bsp" );

	/* load the bsp */
	Sys_Printf( "Loading %s\n", source );
	LoadBSPFile( source );
	ParseEntities();

	/* note it */
	Sys_Printf( "--- ScaleBSP ---\n" );
	Sys_FPrintf( SYS_VRB, "%9d entities\n", numEntities );

	/* scale entity keys */
	for ( i = 0; i < numBSPEntities && i < numEntities; i++ )
	{
		/* scale origin */
		GetVectorForKey( &entities[ i ], "origin", vec );
		if ( ( vec[ 0 ] || vec[ 1 ] || vec[ 2 ] ) ) {
			if ( !strncmp( ValueForKey( &entities[i], "classname" ), "info_player_", 12 ) ) {
				vec[2] += spawn_ref;
			}
			vec[0] *= scale[0];
			vec[1] *= scale[1];
			vec[2] *= scale[2];
			if ( !strncmp( ValueForKey( &entities[i], "classname" ), "info_player_", 12 ) ) {
				vec[2] -= spawn_ref;
			}
			sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
			SetKeyValue( &entities[ i ], "origin", str );
		}

		a = FloatForKey( &entities[ i ], "angle" );
		if ( a == -1 || a == -2 ) { // z scale
			axis = 2;
		}
		else if ( fabs( sin( DEG2RAD( a ) ) ) < 0.707 ) {
			axis = 0;
		}
		else{
			axis = 1;
		}

		/* scale door lip */
		f = FloatForKey( &entities[ i ], "lip" );
		if ( f ) {
			f *= scale[axis];
			sprintf( str, "%f", f );
			SetKeyValue( &entities[ i ], "lip", str );
		}

		/* scale plat height */
		f = FloatForKey( &entities[ i ], "height" );
		if ( f ) {
			f *= scale[2];
			sprintf( str, "%f", f );
			SetKeyValue( &entities[ i ], "height", str );
		}

		// TODO maybe allow a definition file for entities to specify which values are scaled how?
	}

	/* scale models */
	for ( i = 0; i < numBSPModels; i++ )
	{
		bspModels[ i ].mins[0] *= scale[0];
		bspModels[ i ].mins[1] *= scale[1];
		bspModels[ i ].mins[2] *= scale[2];
		bspModels[ i ].maxs[0] *= scale[0];
		bspModels[ i ].maxs[1] *= scale[1];
		bspModels[ i ].maxs[2] *= scale[2];
	}

	/* scale nodes */
	for ( i = 0; i < numBSPNodes; i++ )
	{
		bspNodes[ i ].mins[0] *= scale[0];
		bspNodes[ i ].mins[1] *= scale[1];
		bspNodes[ i ].mins[2] *= scale[2];
		bspNodes[ i ].maxs[0] *= scale[0];
		bspNodes[ i ].maxs[1] *= scale[1];
		bspNodes[ i ].maxs[2] *= scale[2];
	}

	/* scale leafs */
	for ( i = 0; i < numBSPLeafs; i++ )
	{
		bspLeafs[ i ].mins[0] *= scale[0];
		bspLeafs[ i ].mins[1] *= scale[1];
		bspLeafs[ i ].mins[2] *= scale[2];
		bspLeafs[ i ].maxs[0] *= scale[0];
		bspLeafs[ i ].maxs[1] *= scale[1];
		bspLeafs[ i ].maxs[2] *= scale[2];
	}

	if ( texscale ) {
		Sys_Printf( "Using texture unlocking (and probably breaking texture alignment a lot)\n" );
		old_xyzst = safe_malloc( sizeof( *old_xyzst ) * numBSPDrawVerts * 5 );
		for ( i = 0; i < numBSPDrawVerts; i++ )
		{
			old_xyzst[5 * i + 0] = bspDrawVerts[i].xyz[0];
			old_xyzst[5 * i + 1] = bspDrawVerts[i].xyz[1];
			old_xyzst[5 * i + 2] = bspDrawVerts[i].xyz[2];
			old_xyzst[5 * i + 3] = bspDrawVerts[i].st[0];
			old_xyzst[5 * i + 4] = bspDrawVerts[i].st[1];
		}
	}

	/* scale drawverts */
	for ( i = 0; i < numBSPDrawVerts; i++ )
	{
		bspDrawVerts[i].xyz[0] *= scale[0];
		bspDrawVerts[i].xyz[1] *= scale[1];
		bspDrawVerts[i].xyz[2] *= scale[2];
		bspDrawVerts[i].normal[0] /= scale[0];
		bspDrawVerts[i].normal[1] /= scale[1];
		bspDrawVerts[i].normal[2] /= scale[2];
		VectorNormalize( bspDrawVerts[i].normal, bspDrawVerts[i].normal );
	}

	if ( texscale ) {
		for ( i = 0; i < numBSPDrawSurfaces; i++ )
		{
			switch ( bspDrawSurfaces[i].surfaceType )
			{
			case SURFACE_FACE:
			case SURFACE_META:
				if ( bspDrawSurfaces[i].numIndexes % 3 ) {
					Error( "Not a triangulation!" );
				}
				for ( j = bspDrawSurfaces[i].firstIndex; j < bspDrawSurfaces[i].firstIndex + bspDrawSurfaces[i].numIndexes; j += 3 )
				{
					int ia = bspDrawIndexes[j] + bspDrawSurfaces[i].firstVert, ib = bspDrawIndexes[j + 1] + bspDrawSurfaces[i].firstVert, ic = bspDrawIndexes[j + 2] + bspDrawSurfaces[i].firstVert;
					bspDrawVert_t *a = &bspDrawVerts[ia], *b = &bspDrawVerts[ib], *c = &bspDrawVerts[ic];
					float *oa = &old_xyzst[ia * 5], *ob = &old_xyzst[ib * 5], *oc = &old_xyzst[ic * 5];
					// extrapolate:
					//   a->xyz -> oa
					//   b->xyz -> ob
					//   c->xyz -> oc
					ExtrapolateTexcoords(
						&oa[0], &oa[3],
						&ob[0], &ob[3],
						&oc[0], &oc[3],
						a->xyz, a->st,
						b->xyz, b->st,
						c->xyz, c->st );
				}
				break;
			}
		}
	}

	/* scale planes */
	if ( uniform ) {
		for ( i = 0; i < numBSPPlanes; i++ )
		{
			bspPlanes[ i ].dist *= scale[0];
		}
	}
	else
	{
		for ( i = 0; i < numBSPPlanes; i++ )
		{
			bspPlanes[ i ].normal[0] /= scale[0];
			bspPlanes[ i ].normal[1] /= scale[1];
			bspPlanes[ i ].normal[2] /= scale[2];
			f = 1 / VectorLength( bspPlanes[i].normal );
			VectorScale( bspPlanes[i].normal, f, bspPlanes[i].normal );
			bspPlanes[ i ].dist *= f;
		}
	}

	/* scale gridsize */
	GetVectorForKey( &entities[ 0 ], "gridsize", vec );
	if ( ( vec[ 0 ] + vec[ 1 ] + vec[ 2 ] ) == 0.0f ) {
		VectorCopy( gridSize, vec );
	}
	vec[0] *= scale[0];
	vec[1] *= scale[1];
	vec[2] *= scale[2];
	sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
	SetKeyValue( &entities[ 0 ], "gridsize", str );

	/* inject command line parameters */
	InjectCommandLine( argv, 0, argc - 1 );

	/* write the bsp */
	UnparseEntities();
	StripExtension( source );
	DefaultExtension( source, "_s.bsp" );
	Sys_Printf( "Writing %s\n", source );
	WriteBSPFile( source );

	/* return to sender */
	return 0;
}