From: Thomas Debesse Date: Mon, 20 Jul 2015 11:07:37 +0000 (+0200) Subject: split bsp conversion stuff from q3map2 X-Git-Tag: xonotic-v0.8.2~15^2~4 X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fnetradiant.git;a=commitdiff_plain;h=f73901765f3c26c1f31120453b3b9288f4ab0f0c split bsp conversion stuff from q3map2 --- diff --git a/Makefile b/Makefile index 10b4ec96..9cde277d 100644 --- a/Makefile +++ b/Makefile @@ -502,6 +502,7 @@ $(INSTALLDIR)/q3map2.$(EXE): \ tools/quake3/q3map2/bspfile_rbsp.o \ tools/quake3/q3map2/bsp.o \ tools/quake3/q3map2/convert_ase.o \ + tools/quake3/q3map2/convert_bsp.o \ tools/quake3/q3map2/convert_obj.o \ tools/quake3/q3map2/convert_map.o \ tools/quake3/q3map2/decals.o \ diff --git a/tools/quake3/q3map2/convert_bsp.c b/tools/quake3/q3map2/convert_bsp.c new file mode 100644 index 00000000..929855d0 --- /dev/null +++ b/tools/quake3/q3map2/convert_bsp.c @@ -0,0 +1,815 @@ +/* ------------------------------------------------------------------------------- + + Copyright (C) 1999-2007 id Software, Inc. and contributors. + For a list of contributors, see the accompanying CONTRIBUTORS file. + + This file is part of GtkRadiant. + + GtkRadiant is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + GtkRadiant is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GtkRadiant; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + ------------------------------------------------------------------------------- + + This code has been altered significantly from its original form, to support + several games based on the Quake III Arena engine, in the form of "Q3Map2." + + ------------------------------------------------------------------------------- */ + + + +/* dependencies */ +#include "q3map2.h" + + + +/* + AnalyzeBSP() - ydnar + analyzes a Quake engine BSP file + */ + +typedef struct abspHeader_s +{ + char ident[ 4 ]; + int version; + + bspLump_t lumps[ 1 ]; /* unknown size */ +} +abspHeader_t; + +typedef struct abspLumpTest_s +{ + int radix, minCount; + char *name; +} +abspLumpTest_t; + +int AnalyzeBSP( int argc, char **argv ){ + abspHeader_t *header; + int size, i, version, offset, length, lumpInt, count; + char ident[ 5 ]; + void *lump; + float lumpFloat; + char lumpString[ 1024 ], source[ 1024 ]; + qboolean lumpSwap = qfalse; + abspLumpTest_t *lumpTest; + static abspLumpTest_t lumpTests[] = + { + { sizeof( bspPlane_t ), 6, "IBSP LUMP_PLANES" }, + { sizeof( bspBrush_t ), 1, "IBSP LUMP_BRUSHES" }, + { 8, 6, "IBSP LUMP_BRUSHSIDES" }, + { sizeof( bspBrushSide_t ), 6, "RBSP LUMP_BRUSHSIDES" }, + { sizeof( bspModel_t ), 1, "IBSP LUMP_MODELS" }, + { sizeof( bspNode_t ), 2, "IBSP LUMP_NODES" }, + { sizeof( bspLeaf_t ), 1, "IBSP LUMP_LEAFS" }, + { 104, 3, "IBSP LUMP_DRAWSURFS" }, + { 44, 3, "IBSP LUMP_DRAWVERTS" }, + { 4, 6, "IBSP LUMP_DRAWINDEXES" }, + { 128 * 128 * 3, 1, "IBSP LUMP_LIGHTMAPS" }, + { 256 * 256 * 3, 1, "IBSP LUMP_LIGHTMAPS (256 x 256)" }, + { 512 * 512 * 3, 1, "IBSP LUMP_LIGHTMAPS (512 x 512)" }, + { 0, 0, NULL } + }; + + + /* arg checking */ + if ( argc < 1 ) { + Sys_Printf( "Usage: q3map -analyze [-lumpswap] [-v] \n" ); + return 0; + } + + /* process arguments */ + for ( i = 1; i < ( argc - 1 ); i++ ) + { + /* -format map|ase|... */ + if ( !strcmp( argv[ i ], "-lumpswap" ) ) { + Sys_Printf( "Swapped lump structs enabled\n" ); + lumpSwap = qtrue; + } + } + + /* clean up map name */ + strcpy( source, ExpandArg( argv[ i ] ) ); + Sys_Printf( "Loading %s\n", source ); + + /* load the file */ + size = LoadFile( source, (void**) &header ); + if ( size == 0 || header == NULL ) { + Sys_Printf( "Unable to load %s.\n", source ); + return -1; + } + + /* analyze ident/version */ + memcpy( ident, header->ident, 4 ); + ident[ 4 ] = '\0'; + version = LittleLong( header->version ); + + Sys_Printf( "Identity: %s\n", ident ); + Sys_Printf( "Version: %d\n", version ); + Sys_Printf( "---------------------------------------\n" ); + + /* analyze each lump */ + for ( i = 0; i < 100; i++ ) + { + /* call of duty swapped lump pairs */ + if ( lumpSwap ) { + offset = LittleLong( header->lumps[ i ].length ); + length = LittleLong( header->lumps[ i ].offset ); + } + + /* standard lump pairs */ + else + { + offset = LittleLong( header->lumps[ i ].offset ); + length = LittleLong( header->lumps[ i ].length ); + } + + /* extract data */ + lump = (byte*) header + offset; + lumpInt = LittleLong( (int) *( (int*) lump ) ); + lumpFloat = LittleFloat( (float) *( (float*) lump ) ); + memcpy( lumpString, (char*) lump, ( (size_t)length < sizeof( lumpString ) ? (size_t)length : sizeof( lumpString ) - 1 ) ); + lumpString[ sizeof( lumpString ) - 1 ] = '\0'; + + /* print basic lump info */ + Sys_Printf( "Lump: %d\n", i ); + Sys_Printf( "Offset: %d bytes\n", offset ); + Sys_Printf( "Length: %d bytes\n", length ); + + /* only operate on valid lumps */ + if ( length > 0 ) { + /* print data in 4 formats */ + Sys_Printf( "As hex: %08X\n", lumpInt ); + Sys_Printf( "As int: %d\n", lumpInt ); + Sys_Printf( "As float: %f\n", lumpFloat ); + Sys_Printf( "As string: %s\n", lumpString ); + + /* guess lump type */ + if ( lumpString[ 0 ] == '{' && lumpString[ 2 ] == '"' ) { + Sys_Printf( "Type guess: IBSP LUMP_ENTITIES\n" ); + } + else if ( strstr( lumpString, "textures/" ) ) { + Sys_Printf( "Type guess: IBSP LUMP_SHADERS\n" ); + } + else + { + /* guess based on size/count */ + for ( lumpTest = lumpTests; lumpTest->radix > 0; lumpTest++ ) + { + if ( ( length % lumpTest->radix ) != 0 ) { + continue; + } + count = length / lumpTest->radix; + if ( count < lumpTest->minCount ) { + continue; + } + Sys_Printf( "Type guess: %s (%d x %d)\n", lumpTest->name, count, lumpTest->radix ); + } + } + } + + Sys_Printf( "---------------------------------------\n" ); + + /* end of file */ + if ( offset + length >= size ) { + break; + } + } + + /* last stats */ + Sys_Printf( "Lump count: %d\n", i + 1 ); + Sys_Printf( "File size: %d bytes\n", size ); + + /* return to caller */ + return 0; +} + + + +/* + BSPInfo() + emits statistics about the bsp file + */ + +int BSPInfo( int count, char **fileNames ){ + int i; + char source[ 1024 ], ext[ 64 ]; + int size; + FILE *f; + + + /* dummy check */ + if ( count < 1 ) { + Sys_Printf( "No files to dump info for.\n" ); + return -1; + } + + /* enable info mode */ + infoMode = qtrue; + + /* walk file list */ + for ( i = 0; i < count; i++ ) + { + Sys_Printf( "---------------------------------\n" ); + + /* mangle filename and get size */ + strcpy( source, fileNames[ i ] ); + ExtractFileExtension( source, ext ); + if ( !Q_stricmp( ext, "map" ) ) { + StripExtension( source ); + } + DefaultExtension( source, ".bsp" ); + f = fopen( source, "rb" ); + if ( f ) { + size = Q_filelength( f ); + fclose( f ); + } + else{ + size = 0; + } + + /* load the bsp file and print lump sizes */ + Sys_Printf( "%s\n", source ); + LoadBSPFile( source ); + PrintBSPFileSizes(); + + /* print sizes */ + Sys_Printf( "\n" ); + Sys_Printf( " total %9d\n", size ); + Sys_Printf( " %9d KB\n", size / 1024 ); + Sys_Printf( " %9d MB\n", size / ( 1024 * 1024 ) ); + + Sys_Printf( "---------------------------------\n" ); + } + + /* return count */ + return i; +} + + +static void ExtrapolateTexcoords( const float *axyz, const float *ast, const float *bxyz, const float *bst, const float *cxyz, const float *cst, const float *axyz_new, float *ast_out, const float *bxyz_new, float *bst_out, const float *cxyz_new, float *cst_out ){ + vec4_t scoeffs, tcoeffs; + float md; + m4x4_t solvematrix; + + vec3_t norm; + vec3_t dab, dac; + VectorSubtract( bxyz, axyz, dab ); + VectorSubtract( cxyz, axyz, dac ); + CrossProduct( dab, dac, norm ); + + // assume: + // s = f(x, y, z) + // s(v + norm) = s(v) when n ortho xyz + + // s(v) = DotProduct(v, scoeffs) + scoeffs[3] + + // solve: + // scoeffs * (axyz, 1) == ast[0] + // scoeffs * (bxyz, 1) == bst[0] + // scoeffs * (cxyz, 1) == cst[0] + // scoeffs * (norm, 0) == 0 + // scoeffs * [axyz, 1 | bxyz, 1 | cxyz, 1 | norm, 0] = [ast[0], bst[0], cst[0], 0] + solvematrix[0] = axyz[0]; + solvematrix[4] = axyz[1]; + solvematrix[8] = axyz[2]; + solvematrix[12] = 1; + solvematrix[1] = bxyz[0]; + solvematrix[5] = bxyz[1]; + solvematrix[9] = bxyz[2]; + solvematrix[13] = 1; + solvematrix[2] = cxyz[0]; + solvematrix[6] = cxyz[1]; + solvematrix[10] = cxyz[2]; + solvematrix[14] = 1; + solvematrix[3] = norm[0]; + solvematrix[7] = norm[1]; + solvematrix[11] = norm[2]; + solvematrix[15] = 0; + + md = m4_det( solvematrix ); + if ( md * md < 1e-10 ) { + Sys_Printf( "Cannot invert some matrix, some texcoords aren't extrapolated!" ); + return; + } + + m4x4_invert( solvematrix ); + + scoeffs[0] = ast[0]; + scoeffs[1] = bst[0]; + scoeffs[2] = cst[0]; + scoeffs[3] = 0; + m4x4_transform_vec4( solvematrix, scoeffs ); + tcoeffs[0] = ast[1]; + tcoeffs[1] = bst[1]; + tcoeffs[2] = cst[1]; + tcoeffs[3] = 0; + m4x4_transform_vec4( solvematrix, tcoeffs ); + + ast_out[0] = scoeffs[0] * axyz_new[0] + scoeffs[1] * axyz_new[1] + scoeffs[2] * axyz_new[2] + scoeffs[3]; + ast_out[1] = tcoeffs[0] * axyz_new[0] + tcoeffs[1] * axyz_new[1] + tcoeffs[2] * axyz_new[2] + tcoeffs[3]; + bst_out[0] = scoeffs[0] * bxyz_new[0] + scoeffs[1] * bxyz_new[1] + scoeffs[2] * bxyz_new[2] + scoeffs[3]; + bst_out[1] = tcoeffs[0] * bxyz_new[0] + tcoeffs[1] * bxyz_new[1] + tcoeffs[2] * bxyz_new[2] + tcoeffs[3]; + cst_out[0] = scoeffs[0] * cxyz_new[0] + scoeffs[1] * cxyz_new[1] + scoeffs[2] * cxyz_new[2] + scoeffs[3]; + cst_out[1] = tcoeffs[0] * cxyz_new[0] + tcoeffs[1] * cxyz_new[1] + tcoeffs[2] * cxyz_new[2] + tcoeffs[3]; +} + +/* + ScaleBSPMain() + amaze and confuse your enemies with wierd scaled maps! + */ + +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 ] \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 ] \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; +} + + +/* + PseudoCompileBSP() + a stripped down ProcessModels + */ +void PseudoCompileBSP( qboolean need_tree ){ + int models; + char modelValue[10]; + entity_t *entity; + face_t *faces; + tree_t *tree; + node_t *node; + brush_t *brush; + side_t *side; + int i; + + SetDrawSurfacesBuffer(); + mapDrawSurfs = safe_malloc( sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS ); + memset( mapDrawSurfs, 0, sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS ); + numMapDrawSurfs = 0; + + BeginBSPFile(); + models = 1; + for ( mapEntityNum = 0; mapEntityNum < numEntities; mapEntityNum++ ) + { + /* get entity */ + entity = &entities[ mapEntityNum ]; + if ( entity->brushes == NULL && entity->patches == NULL ) { + continue; + } + + if ( mapEntityNum != 0 ) { + sprintf( modelValue, "*%d", models++ ); + SetKeyValue( entity, "model", modelValue ); + } + + /* process the model */ + Sys_FPrintf( SYS_VRB, "############### model %i ###############\n", numBSPModels ); + BeginModel(); + + entity->firstDrawSurf = numMapDrawSurfs; + + ClearMetaTriangles(); + PatchMapDrawSurfs( entity ); + + if ( mapEntityNum == 0 && need_tree ) { + faces = MakeStructuralBSPFaceList( entities[0].brushes ); + tree = FaceBSP( faces ); + node = tree->headnode; + } + else + { + node = AllocNode(); + node->planenum = PLANENUM_LEAF; + tree = AllocTree(); + tree->headnode = node; + } + + /* a minimized ClipSidesIntoTree */ + for ( brush = entity->brushes; brush; brush = brush->next ) + { + /* walk the brush sides */ + for ( i = 0; i < brush->numsides; i++ ) + { + /* get side */ + side = &brush->sides[ i ]; + if ( side->winding == NULL ) { + continue; + } + /* shader? */ + if ( side->shaderInfo == NULL ) { + continue; + } + /* save this winding as a visible surface */ + DrawSurfaceForSide( entity, brush, side, side->winding ); + } + } + + if ( meta ) { + ClassifyEntitySurfaces( entity ); + MakeEntityDecals( entity ); + MakeEntityMetaTriangles( entity ); + SmoothMetaTriangles(); + MergeMetaTriangles(); + } + FilterDrawsurfsIntoTree( entity, tree ); + + FilterStructuralBrushesIntoTree( entity, tree ); + FilterDetailBrushesIntoTree( entity, tree ); + + EmitBrushes( entity->brushes, &entity->firstBrush, &entity->numBrushes ); + EndModel( entity, node ); + } + EndBSPFile( qfalse ); +} + +/* + ConvertBSPMain() + main argument processing function for bsp conversion + */ + +int ConvertBSPMain( int argc, char **argv ){ + int i; + int ( *convertFunc )( char * ); + game_t *convertGame; + char ext[1024]; + qboolean map_allowed, force_bsp, force_map; + + + /* set default */ + convertFunc = ConvertBSPToASE; + convertGame = NULL; + map_allowed = qfalse; + force_bsp = qfalse; + force_map = qfalse; + + /* arg checking */ + if ( argc < 1 ) { + Sys_Printf( "Usage: q3map -convert [-format ] [-shadersasbitmap|-lightmapsastexcoord|-deluxemapsastexcoord] [-readbsp|-readmap [-meta|-patchmeta]] [-v] \n" ); + return 0; + } + + /* process arguments */ + for ( i = 1; i < ( argc - 1 ); i++ ) + { + /* -format map|ase|... */ + if ( !strcmp( argv[ i ], "-format" ) ) { + i++; + if ( !Q_stricmp( argv[ i ], "ase" ) ) { + convertFunc = ConvertBSPToASE; + map_allowed = qfalse; + } + else if ( !Q_stricmp( argv[ i ], "obj" ) ) { + convertFunc = ConvertBSPToOBJ; + map_allowed = qfalse; + } + else if ( !Q_stricmp( argv[ i ], "map_bp" ) ) { + convertFunc = ConvertBSPToMap_BP; + map_allowed = qtrue; + } + else if ( !Q_stricmp( argv[ i ], "map" ) ) { + convertFunc = ConvertBSPToMap; + map_allowed = qtrue; + } + else + { + convertGame = GetGame( argv[ i ] ); + map_allowed = qfalse; + if ( convertGame == NULL ) { + Sys_Printf( "Unknown conversion format \"%s\". Defaulting to ASE.\n", argv[ i ] ); + } + } + } + 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 ], "-shaderasbitmap" ) || !strcmp( argv[ i ], "-shadersasbitmap" ) ) { + shadersAsBitmap = qtrue; + } + else if ( !strcmp( argv[ i ], "-lightmapastexcoord" ) || !strcmp( argv[ i ], "-lightmapsastexcoord" ) ) { + lightmapsAsTexcoord = qtrue; + } + else if ( !strcmp( argv[ i ], "-deluxemapastexcoord" ) || !strcmp( argv[ i ], "-deluxemapsastexcoord" ) ) { + lightmapsAsTexcoord = qtrue; + deluxemap = qtrue; + } + else if ( !strcmp( argv[ i ], "-readbsp" ) ) { + force_bsp = qtrue; + } + else if ( !strcmp( argv[ i ], "-readmap" ) ) { + force_map = qtrue; + } + else if ( !strcmp( argv[ i ], "-meta" ) ) { + meta = qtrue; + } + else if ( !strcmp( argv[ i ], "-patchmeta" ) ) { + meta = qtrue; + patchMeta = qtrue; + } + } + + LoadShaderInfo(); + + /* clean up map name */ + strcpy( source, ExpandArg( argv[i] ) ); + ExtractFileExtension( source, ext ); + + if ( !map_allowed && !force_map ) { + force_bsp = qtrue; + } + + if ( force_map || ( !force_bsp && !Q_stricmp( ext, "map" ) && map_allowed ) ) { + if ( !map_allowed ) { + Sys_Printf( "WARNING: the requested conversion should not be done from .map files. Compile a .bsp first.\n" ); + } + StripExtension( source ); + DefaultExtension( source, ".map" ); + Sys_Printf( "Loading %s\n", source ); + LoadMapFile( source, qfalse, convertGame == NULL ); + PseudoCompileBSP( convertGame != NULL ); + } + else + { + StripExtension( source ); + DefaultExtension( source, ".bsp" ); + Sys_Printf( "Loading %s\n", source ); + LoadBSPFile( source ); + ParseEntities(); + } + + /* bsp format convert? */ + if ( convertGame != NULL ) { + /* set global game */ + game = convertGame; + + /* write bsp */ + StripExtension( source ); + DefaultExtension( source, "_c.bsp" ); + Sys_Printf( "Writing %s\n", source ); + WriteBSPFile( source ); + + /* return to sender */ + return 0; + } + + /* normal convert */ + return convertFunc( source ); +} diff --git a/tools/quake3/q3map2/main.c b/tools/quake3/q3map2/main.c index bd8140f9..6c3b165c 100644 --- a/tools/quake3/q3map2/main.c +++ b/tools/quake3/q3map2/main.c @@ -168,790 +168,6 @@ int FixAAS( int argc, char **argv ){ return 0; } - - -/* - AnalyzeBSP() - ydnar - analyzes a Quake engine BSP file - */ - -typedef struct abspHeader_s -{ - char ident[ 4 ]; - int version; - - bspLump_t lumps[ 1 ]; /* unknown size */ -} -abspHeader_t; - -typedef struct abspLumpTest_s -{ - int radix, minCount; - char *name; -} -abspLumpTest_t; - -int AnalyzeBSP( int argc, char **argv ){ - abspHeader_t *header; - int size, i, version, offset, length, lumpInt, count; - char ident[ 5 ]; - void *lump; - float lumpFloat; - char lumpString[ 1024 ], source[ 1024 ]; - qboolean lumpSwap = qfalse; - abspLumpTest_t *lumpTest; - static abspLumpTest_t lumpTests[] = - { - { sizeof( bspPlane_t ), 6, "IBSP LUMP_PLANES" }, - { sizeof( bspBrush_t ), 1, "IBSP LUMP_BRUSHES" }, - { 8, 6, "IBSP LUMP_BRUSHSIDES" }, - { sizeof( bspBrushSide_t ), 6, "RBSP LUMP_BRUSHSIDES" }, - { sizeof( bspModel_t ), 1, "IBSP LUMP_MODELS" }, - { sizeof( bspNode_t ), 2, "IBSP LUMP_NODES" }, - { sizeof( bspLeaf_t ), 1, "IBSP LUMP_LEAFS" }, - { 104, 3, "IBSP LUMP_DRAWSURFS" }, - { 44, 3, "IBSP LUMP_DRAWVERTS" }, - { 4, 6, "IBSP LUMP_DRAWINDEXES" }, - { 128 * 128 * 3, 1, "IBSP LUMP_LIGHTMAPS" }, - { 256 * 256 * 3, 1, "IBSP LUMP_LIGHTMAPS (256 x 256)" }, - { 512 * 512 * 3, 1, "IBSP LUMP_LIGHTMAPS (512 x 512)" }, - { 0, 0, NULL } - }; - - - /* arg checking */ - if ( argc < 1 ) { - Sys_Printf( "Usage: q3map -analyze [-lumpswap] [-v] \n" ); - return 0; - } - - /* process arguments */ - for ( i = 1; i < ( argc - 1 ); i++ ) - { - /* -format map|ase|... */ - if ( !strcmp( argv[ i ], "-lumpswap" ) ) { - Sys_Printf( "Swapped lump structs enabled\n" ); - lumpSwap = qtrue; - } - } - - /* clean up map name */ - strcpy( source, ExpandArg( argv[ i ] ) ); - Sys_Printf( "Loading %s\n", source ); - - /* load the file */ - size = LoadFile( source, (void**) &header ); - if ( size == 0 || header == NULL ) { - Sys_Printf( "Unable to load %s.\n", source ); - return -1; - } - - /* analyze ident/version */ - memcpy( ident, header->ident, 4 ); - ident[ 4 ] = '\0'; - version = LittleLong( header->version ); - - Sys_Printf( "Identity: %s\n", ident ); - Sys_Printf( "Version: %d\n", version ); - Sys_Printf( "---------------------------------------\n" ); - - /* analyze each lump */ - for ( i = 0; i < 100; i++ ) - { - /* call of duty swapped lump pairs */ - if ( lumpSwap ) { - offset = LittleLong( header->lumps[ i ].length ); - length = LittleLong( header->lumps[ i ].offset ); - } - - /* standard lump pairs */ - else - { - offset = LittleLong( header->lumps[ i ].offset ); - length = LittleLong( header->lumps[ i ].length ); - } - - /* extract data */ - lump = (byte*) header + offset; - lumpInt = LittleLong( (int) *( (int*) lump ) ); - lumpFloat = LittleFloat( (float) *( (float*) lump ) ); - memcpy( lumpString, (char*) lump, ( (size_t)length < sizeof( lumpString ) ? (size_t)length : sizeof( lumpString ) - 1 ) ); - lumpString[ sizeof( lumpString ) - 1 ] = '\0'; - - /* print basic lump info */ - Sys_Printf( "Lump: %d\n", i ); - Sys_Printf( "Offset: %d bytes\n", offset ); - Sys_Printf( "Length: %d bytes\n", length ); - - /* only operate on valid lumps */ - if ( length > 0 ) { - /* print data in 4 formats */ - Sys_Printf( "As hex: %08X\n", lumpInt ); - Sys_Printf( "As int: %d\n", lumpInt ); - Sys_Printf( "As float: %f\n", lumpFloat ); - Sys_Printf( "As string: %s\n", lumpString ); - - /* guess lump type */ - if ( lumpString[ 0 ] == '{' && lumpString[ 2 ] == '"' ) { - Sys_Printf( "Type guess: IBSP LUMP_ENTITIES\n" ); - } - else if ( strstr( lumpString, "textures/" ) ) { - Sys_Printf( "Type guess: IBSP LUMP_SHADERS\n" ); - } - else - { - /* guess based on size/count */ - for ( lumpTest = lumpTests; lumpTest->radix > 0; lumpTest++ ) - { - if ( ( length % lumpTest->radix ) != 0 ) { - continue; - } - count = length / lumpTest->radix; - if ( count < lumpTest->minCount ) { - continue; - } - Sys_Printf( "Type guess: %s (%d x %d)\n", lumpTest->name, count, lumpTest->radix ); - } - } - } - - Sys_Printf( "---------------------------------------\n" ); - - /* end of file */ - if ( offset + length >= size ) { - break; - } - } - - /* last stats */ - Sys_Printf( "Lump count: %d\n", i + 1 ); - Sys_Printf( "File size: %d bytes\n", size ); - - /* return to caller */ - return 0; -} - - - -/* - BSPInfo() - emits statistics about the bsp file - */ - -int BSPInfo( int count, char **fileNames ){ - int i; - char source[ 1024 ], ext[ 64 ]; - int size; - FILE *f; - - - /* dummy check */ - if ( count < 1 ) { - Sys_Printf( "No files to dump info for.\n" ); - return -1; - } - - /* enable info mode */ - infoMode = qtrue; - - /* walk file list */ - for ( i = 0; i < count; i++ ) - { - Sys_Printf( "---------------------------------\n" ); - - /* mangle filename and get size */ - strcpy( source, fileNames[ i ] ); - ExtractFileExtension( source, ext ); - if ( !Q_stricmp( ext, "map" ) ) { - StripExtension( source ); - } - DefaultExtension( source, ".bsp" ); - f = fopen( source, "rb" ); - if ( f ) { - size = Q_filelength( f ); - fclose( f ); - } - else{ - size = 0; - } - - /* load the bsp file and print lump sizes */ - Sys_Printf( "%s\n", source ); - LoadBSPFile( source ); - PrintBSPFileSizes(); - - /* print sizes */ - Sys_Printf( "\n" ); - Sys_Printf( " total %9d\n", size ); - Sys_Printf( " %9d KB\n", size / 1024 ); - Sys_Printf( " %9d MB\n", size / ( 1024 * 1024 ) ); - - Sys_Printf( "---------------------------------\n" ); - } - - /* return count */ - return i; -} - - -static void ExtrapolateTexcoords( const float *axyz, const float *ast, const float *bxyz, const float *bst, const float *cxyz, const float *cst, const float *axyz_new, float *ast_out, const float *bxyz_new, float *bst_out, const float *cxyz_new, float *cst_out ){ - vec4_t scoeffs, tcoeffs; - float md; - m4x4_t solvematrix; - - vec3_t norm; - vec3_t dab, dac; - VectorSubtract( bxyz, axyz, dab ); - VectorSubtract( cxyz, axyz, dac ); - CrossProduct( dab, dac, norm ); - - // assume: - // s = f(x, y, z) - // s(v + norm) = s(v) when n ortho xyz - - // s(v) = DotProduct(v, scoeffs) + scoeffs[3] - - // solve: - // scoeffs * (axyz, 1) == ast[0] - // scoeffs * (bxyz, 1) == bst[0] - // scoeffs * (cxyz, 1) == cst[0] - // scoeffs * (norm, 0) == 0 - // scoeffs * [axyz, 1 | bxyz, 1 | cxyz, 1 | norm, 0] = [ast[0], bst[0], cst[0], 0] - solvematrix[0] = axyz[0]; - solvematrix[4] = axyz[1]; - solvematrix[8] = axyz[2]; - solvematrix[12] = 1; - solvematrix[1] = bxyz[0]; - solvematrix[5] = bxyz[1]; - solvematrix[9] = bxyz[2]; - solvematrix[13] = 1; - solvematrix[2] = cxyz[0]; - solvematrix[6] = cxyz[1]; - solvematrix[10] = cxyz[2]; - solvematrix[14] = 1; - solvematrix[3] = norm[0]; - solvematrix[7] = norm[1]; - solvematrix[11] = norm[2]; - solvematrix[15] = 0; - - md = m4_det( solvematrix ); - if ( md * md < 1e-10 ) { - Sys_Printf( "Cannot invert some matrix, some texcoords aren't extrapolated!" ); - return; - } - - m4x4_invert( solvematrix ); - - scoeffs[0] = ast[0]; - scoeffs[1] = bst[0]; - scoeffs[2] = cst[0]; - scoeffs[3] = 0; - m4x4_transform_vec4( solvematrix, scoeffs ); - tcoeffs[0] = ast[1]; - tcoeffs[1] = bst[1]; - tcoeffs[2] = cst[1]; - tcoeffs[3] = 0; - m4x4_transform_vec4( solvematrix, tcoeffs ); - - ast_out[0] = scoeffs[0] * axyz_new[0] + scoeffs[1] * axyz_new[1] + scoeffs[2] * axyz_new[2] + scoeffs[3]; - ast_out[1] = tcoeffs[0] * axyz_new[0] + tcoeffs[1] * axyz_new[1] + tcoeffs[2] * axyz_new[2] + tcoeffs[3]; - bst_out[0] = scoeffs[0] * bxyz_new[0] + scoeffs[1] * bxyz_new[1] + scoeffs[2] * bxyz_new[2] + scoeffs[3]; - bst_out[1] = tcoeffs[0] * bxyz_new[0] + tcoeffs[1] * bxyz_new[1] + tcoeffs[2] * bxyz_new[2] + tcoeffs[3]; - cst_out[0] = scoeffs[0] * cxyz_new[0] + scoeffs[1] * cxyz_new[1] + scoeffs[2] * cxyz_new[2] + scoeffs[3]; - cst_out[1] = tcoeffs[0] * cxyz_new[0] + tcoeffs[1] * cxyz_new[1] + tcoeffs[2] * cxyz_new[2] + tcoeffs[3]; -} - -/* - ScaleBSPMain() - amaze and confuse your enemies with wierd scaled maps! - */ - -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 ] \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 ] \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; -} - - -/* - PseudoCompileBSP() - a stripped down ProcessModels - */ -void PseudoCompileBSP( qboolean need_tree ){ - int models; - char modelValue[10]; - entity_t *entity; - face_t *faces; - tree_t *tree; - node_t *node; - brush_t *brush; - side_t *side; - int i; - - SetDrawSurfacesBuffer(); - mapDrawSurfs = safe_malloc( sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS ); - memset( mapDrawSurfs, 0, sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS ); - numMapDrawSurfs = 0; - - BeginBSPFile(); - models = 1; - for ( mapEntityNum = 0; mapEntityNum < numEntities; mapEntityNum++ ) - { - /* get entity */ - entity = &entities[ mapEntityNum ]; - if ( entity->brushes == NULL && entity->patches == NULL ) { - continue; - } - - if ( mapEntityNum != 0 ) { - sprintf( modelValue, "*%d", models++ ); - SetKeyValue( entity, "model", modelValue ); - } - - /* process the model */ - Sys_FPrintf( SYS_VRB, "############### model %i ###############\n", numBSPModels ); - BeginModel(); - - entity->firstDrawSurf = numMapDrawSurfs; - - ClearMetaTriangles(); - PatchMapDrawSurfs( entity ); - - if ( mapEntityNum == 0 && need_tree ) { - faces = MakeStructuralBSPFaceList( entities[0].brushes ); - tree = FaceBSP( faces ); - node = tree->headnode; - } - else - { - node = AllocNode(); - node->planenum = PLANENUM_LEAF; - tree = AllocTree(); - tree->headnode = node; - } - - /* a minimized ClipSidesIntoTree */ - for ( brush = entity->brushes; brush; brush = brush->next ) - { - /* walk the brush sides */ - for ( i = 0; i < brush->numsides; i++ ) - { - /* get side */ - side = &brush->sides[ i ]; - if ( side->winding == NULL ) { - continue; - } - /* shader? */ - if ( side->shaderInfo == NULL ) { - continue; - } - /* save this winding as a visible surface */ - DrawSurfaceForSide( entity, brush, side, side->winding ); - } - } - - if ( meta ) { - ClassifyEntitySurfaces( entity ); - MakeEntityDecals( entity ); - MakeEntityMetaTriangles( entity ); - SmoothMetaTriangles(); - MergeMetaTriangles(); - } - FilterDrawsurfsIntoTree( entity, tree ); - - FilterStructuralBrushesIntoTree( entity, tree ); - FilterDetailBrushesIntoTree( entity, tree ); - - EmitBrushes( entity->brushes, &entity->firstBrush, &entity->numBrushes ); - EndModel( entity, node ); - } - EndBSPFile( qfalse ); -} - -/* - ConvertBSPMain() - main argument processing function for bsp conversion - */ - -int ConvertBSPMain( int argc, char **argv ){ - int i; - int ( *convertFunc )( char * ); - game_t *convertGame; - char ext[1024]; - qboolean map_allowed, force_bsp, force_map; - - - /* set default */ - convertFunc = ConvertBSPToASE; - convertGame = NULL; - map_allowed = qfalse; - force_bsp = qfalse; - force_map = qfalse; - - /* arg checking */ - if ( argc < 1 ) { - Sys_Printf( "Usage: q3map -convert [-format ] [-shadersasbitmap|-lightmapsastexcoord|-deluxemapsastexcoord] [-readbsp|-readmap [-meta|-patchmeta]] [-v] \n" ); - return 0; - } - - /* process arguments */ - for ( i = 1; i < ( argc - 1 ); i++ ) - { - /* -format map|ase|... */ - if ( !strcmp( argv[ i ], "-format" ) ) { - i++; - if ( !Q_stricmp( argv[ i ], "ase" ) ) { - convertFunc = ConvertBSPToASE; - map_allowed = qfalse; - } - else if ( !Q_stricmp( argv[ i ], "obj" ) ) { - convertFunc = ConvertBSPToOBJ; - map_allowed = qfalse; - } - else if ( !Q_stricmp( argv[ i ], "map_bp" ) ) { - convertFunc = ConvertBSPToMap_BP; - map_allowed = qtrue; - } - else if ( !Q_stricmp( argv[ i ], "map" ) ) { - convertFunc = ConvertBSPToMap; - map_allowed = qtrue; - } - else - { - convertGame = GetGame( argv[ i ] ); - map_allowed = qfalse; - if ( convertGame == NULL ) { - Sys_Printf( "Unknown conversion format \"%s\". Defaulting to ASE.\n", argv[ i ] ); - } - } - } - 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 ], "-shaderasbitmap" ) || !strcmp( argv[ i ], "-shadersasbitmap" ) ) { - shadersAsBitmap = qtrue; - } - else if ( !strcmp( argv[ i ], "-lightmapastexcoord" ) || !strcmp( argv[ i ], "-lightmapsastexcoord" ) ) { - lightmapsAsTexcoord = qtrue; - } - else if ( !strcmp( argv[ i ], "-deluxemapastexcoord" ) || !strcmp( argv[ i ], "-deluxemapsastexcoord" ) ) { - lightmapsAsTexcoord = qtrue; - deluxemap = qtrue; - } - else if ( !strcmp( argv[ i ], "-readbsp" ) ) { - force_bsp = qtrue; - } - else if ( !strcmp( argv[ i ], "-readmap" ) ) { - force_map = qtrue; - } - else if ( !strcmp( argv[ i ], "-meta" ) ) { - meta = qtrue; - } - else if ( !strcmp( argv[ i ], "-patchmeta" ) ) { - meta = qtrue; - patchMeta = qtrue; - } - } - - LoadShaderInfo(); - - /* clean up map name */ - strcpy( source, ExpandArg( argv[i] ) ); - ExtractFileExtension( source, ext ); - - if ( !map_allowed && !force_map ) { - force_bsp = qtrue; - } - - if ( force_map || ( !force_bsp && !Q_stricmp( ext, "map" ) && map_allowed ) ) { - if ( !map_allowed ) { - Sys_Printf( "WARNING: the requested conversion should not be done from .map files. Compile a .bsp first.\n" ); - } - StripExtension( source ); - DefaultExtension( source, ".map" ); - Sys_Printf( "Loading %s\n", source ); - LoadMapFile( source, qfalse, convertGame == NULL ); - PseudoCompileBSP( convertGame != NULL ); - } - else - { - StripExtension( source ); - DefaultExtension( source, ".bsp" ); - Sys_Printf( "Loading %s\n", source ); - LoadBSPFile( source ); - ParseEntities(); - } - - /* bsp format convert? */ - if ( convertGame != NULL ) { - /* set global game */ - game = convertGame; - - /* write bsp */ - StripExtension( source ); - DefaultExtension( source, "_c.bsp" ); - Sys_Printf( "Writing %s\n", source ); - WriteBSPFile( source ); - - /* return to sender */ - return 0; - } - - /* normal convert */ - return convertFunc( source ); -} - - struct HelpOption { const char* name; diff --git a/tools/quake3/q3map2/q3map2.h b/tools/quake3/q3map2/q3map2.h index fd9a346f..36e8fc91 100644 --- a/tools/quake3/q3map2/q3map2.h +++ b/tools/quake3/q3map2/q3map2.h @@ -1532,6 +1532,10 @@ int BSPMain( int argc, char **argv ); /* minimap.c */ int MiniMapBSPMain( int argc, char **argv ); +/* convert_bsp.c */ +int ScaleBSPMain( int argc, char **argv ); +int ConvertBSPMain( int argc, char **argv ); + /* convert_map.c */ int ConvertBSPToMap( char *bspName ); int ConvertBSPToMap_BP( char *bspName );