split bsp conversion stuff from q3map2
This commit is contained in:
parent
27b1549a2d
commit
68f8cabf95
1
Makefile
1
Makefile
|
|
@ -545,6 +545,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 \
|
||||
|
|
|
|||
987
tools/quake3/q3map2/convert_bsp.c
Normal file
987
tools/quake3/q3map2/convert_bsp.c
Normal file
|
|
@ -0,0 +1,987 @@
|
|||
/* -------------------------------------------------------------------------------
|
||||
|
||||
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] <mapname>\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 <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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
ShiftBSPMain()
|
||||
shifts a map: for testing physics with huge coordinates
|
||||
*/
|
||||
|
||||
int ShiftBSPMain( int argc, char **argv ){
|
||||
int i, j;
|
||||
vec3_t scale;
|
||||
vec3_t vec;
|
||||
char str[ 1024 ];
|
||||
float spawn_ref = 0;
|
||||
|
||||
|
||||
/* arg checking */
|
||||
if ( argc < 3 ) {
|
||||
Sys_Printf( "Usage: q3map [-v] -shift [-tex] [-spawn_ref <value>] <value> <mapname>\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
for ( i = 1; i < argc - 2; ++i )
|
||||
{
|
||||
if ( !strcmp( argv[i], "-tex" ) ) {
|
||||
}
|
||||
else if ( !strcmp( argv[i], "-spawn_ref" ) ) {
|
||||
spawn_ref = atof( argv[i + 1] );
|
||||
++i;
|
||||
}
|
||||
else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* get shift */
|
||||
// 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 ] );
|
||||
}
|
||||
|
||||
|
||||
/* 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( "--- ShiftBSP ---\n" );
|
||||
Sys_FPrintf( SYS_VRB, "%9d entities\n", numEntities );
|
||||
|
||||
/* shift entity keys */
|
||||
for ( i = 0; i < numBSPEntities && i < numEntities; i++ )
|
||||
{
|
||||
/* shift 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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* shift 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];
|
||||
}
|
||||
|
||||
/* shift 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];
|
||||
}
|
||||
|
||||
/* shift 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];
|
||||
}
|
||||
|
||||
/* shift 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];
|
||||
}
|
||||
|
||||
/* shift planes */
|
||||
|
||||
vec3_t point;
|
||||
|
||||
for ( i = 0; i < numBSPPlanes; i++ )
|
||||
{
|
||||
//find point on plane
|
||||
for ( j=0; j<3; j++ ){
|
||||
//point[j] = bspPlanes[ i ].dist * bspPlanes[ i ].normal[j];
|
||||
if ( fabs( bspPlanes[ i ].normal[j] ) > 0.5 ){
|
||||
point[j] = bspPlanes[ i ].dist / bspPlanes[ i ].normal[j];
|
||||
point[(j+1)%3] = point[(j+2)%3] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//shift point
|
||||
for ( j=0; j<3; j++ ){
|
||||
point[j] += scale[j];
|
||||
}
|
||||
//calc new plane dist
|
||||
bspPlanes[ i ].dist = DotProduct( point, bspPlanes[ i ].normal );
|
||||
}
|
||||
|
||||
/* 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, "_sh.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[16];
|
||||
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 <ase|obj|map_bp|map>] [-shadersasbitmap|-lightmapsastexcoord|-deluxemapsastexcoord] [-readbsp|-readmap [-meta|-patchmeta]] [-v] <mapname>\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;
|
||||
}
|
||||
else if ( !strcmp( argv[ i ], "-fast" ) ) {
|
||||
fast = 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_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 );
|
||||
}
|
||||
|
|
@ -174,721 +174,6 @@ int FixAAS( int argc, char **argv ){
|
|||
|
||||
|
||||
|
||||
/*
|
||||
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] <mapname>\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 <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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
ShiftBSPMain()
|
||||
shifts a map: for testing physics with huge coordinates
|
||||
*/
|
||||
|
||||
int ShiftBSPMain( int argc, char **argv ){
|
||||
int i, j;
|
||||
vec3_t scale;
|
||||
vec3_t vec;
|
||||
char str[ 1024 ];
|
||||
float spawn_ref = 0;
|
||||
|
||||
|
||||
/* arg checking */
|
||||
if ( argc < 3 ) {
|
||||
Sys_Printf( "Usage: q3map [-v] -shift [-tex] [-spawn_ref <value>] <value> <mapname>\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
for ( i = 1; i < argc - 2; ++i )
|
||||
{
|
||||
if ( !strcmp( argv[i], "-tex" ) ) {
|
||||
}
|
||||
else if ( !strcmp( argv[i], "-spawn_ref" ) ) {
|
||||
spawn_ref = atof( argv[i + 1] );
|
||||
++i;
|
||||
}
|
||||
else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* get shift */
|
||||
// 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 ] );
|
||||
}
|
||||
|
||||
|
||||
/* 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( "--- ShiftBSP ---\n" );
|
||||
Sys_FPrintf( SYS_VRB, "%9d entities\n", numEntities );
|
||||
|
||||
/* shift entity keys */
|
||||
for ( i = 0; i < numBSPEntities && i < numEntities; i++ )
|
||||
{
|
||||
/* shift 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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* shift 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];
|
||||
}
|
||||
|
||||
/* shift 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];
|
||||
}
|
||||
|
||||
/* shift 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];
|
||||
}
|
||||
|
||||
/* shift 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];
|
||||
}
|
||||
|
||||
/* shift planes */
|
||||
|
||||
vec3_t point;
|
||||
|
||||
for ( i = 0; i < numBSPPlanes; i++ )
|
||||
{
|
||||
//find point on plane
|
||||
for ( j=0; j<3; j++ ){
|
||||
//point[j] = bspPlanes[ i ].dist * bspPlanes[ i ].normal[j];
|
||||
if ( fabs( bspPlanes[ i ].normal[j] ) > 0.5 ){
|
||||
point[j] = bspPlanes[ i ].dist / bspPlanes[ i ].normal[j];
|
||||
point[(j+1)%3] = point[(j+2)%3] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//shift point
|
||||
for ( j=0; j<3; j++ ){
|
||||
point[j] += scale[j];
|
||||
}
|
||||
//calc new plane dist
|
||||
bspPlanes[ i ].dist = DotProduct( point, bspPlanes[ i ].normal );
|
||||
}
|
||||
|
||||
/* 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, "_sh.bsp" );
|
||||
Sys_Printf( "Writing %s\n", source );
|
||||
WriteBSPFile( source );
|
||||
|
||||
/* return to sender */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void FixDOSName( char *src ){
|
||||
if ( src == NULL ) {
|
||||
return;
|
||||
|
|
@ -2702,246 +1987,6 @@ skipEXrefile:
|
|||
|
||||
|
||||
|
||||
/*
|
||||
PseudoCompileBSP()
|
||||
a stripped down ProcessModels
|
||||
*/
|
||||
void PseudoCompileBSP( qboolean need_tree ){
|
||||
int models;
|
||||
char modelValue[16];
|
||||
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 <ase|obj|map_bp|map>] [-shadersasbitmap|-lightmapsastexcoord|-deluxemapsastexcoord] [-readbsp|-readmap [-meta|-patchmeta]] [-v] <mapname>\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;
|
||||
}
|
||||
else if ( !strcmp( argv[ i ], "-fast" ) ) {
|
||||
fast = 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_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 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
main()
|
||||
q3map mojo...
|
||||
|
|
|
|||
|
|
@ -1523,10 +1523,6 @@ vec_t Random( void );
|
|||
char *Q_strncpyz( char *dst, const char *src, size_t len );
|
||||
char *Q_strcat( char *dst, size_t dlen, const char *src );
|
||||
char *Q_strncat( char *dst, size_t dlen, const char *src, size_t slen );
|
||||
int BSPInfo( int count, char **fileNames );
|
||||
int ScaleBSPMain( int argc, char **argv );
|
||||
int ShiftBSPMain( int argc, char **argv );
|
||||
int ConvertMain( int argc, char **argv );
|
||||
|
||||
/* help.c */
|
||||
void HelpMain(const char* arg);
|
||||
|
|
@ -1543,6 +1539,13 @@ int BSPMain( int argc, char **argv );
|
|||
/* minimap.c */
|
||||
int MiniMapBSPMain( int argc, char **argv );
|
||||
|
||||
/* convert_bsp.c */
|
||||
int AnalyzeBSP( int argc, char **argv );
|
||||
int BSPInfo( int count, char **fileNames );
|
||||
int ScaleBSPMain( int argc, char **argv );
|
||||
int ShiftBSPMain( int argc, char **argv );
|
||||
int ConvertBSPMain( int argc, char **argv );
|
||||
|
||||
/* convert_map.c */
|
||||
int ConvertBSPToMap( char *bspName );
|
||||
int ConvertBSPToMap_BP( char *bspName );
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user