Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Q3map2 -scale x y z (freeman) #127

Open
mapmanx opened this Issue · 6 comments

4 participants

@mapmanx

Hi, I think it'd be cool to have a feature to widen hallways, not just scale the entire map!

freeman on #radiant suggested doing the following:

"convert the plane to point-normal instead of normal-distance, turn these into 4d vectors with w=1 for the point and w=0 for the normal, construct a 4x4 transformation matrix for the scaling, invert it, transpose it, then multiply your two vectors by it"

Current solution generally works, but results in tiny invisible gaps, and player falling through the map, where the brushes meet in a few places. It's just a modified Q3map2 "-scale" function which uses VectorScaleX instead of VectorScale, that only scales x and y. It also changes this bit:

    float new_normal_length = 0.0f;
    VectorScaleX(bspPlanes[i].normal,scale, bspPlanes[i].normal);                              
    new_normal_length = VectorNormalize(bspPlanes[i].normal, bspPlanes[i].normal);                     
    bspPlanes[i].dist *= new_normal_length; 

instead of:

    bspPlanes[ i ].dist *= scale;  //<--- old way

///------------------------------------------------
//CODE:

#define VectorScaleX( a,b,c ) ( ( c )[0] = ( b ) * ( a )[0],( c )[1] = ( b ) * ( a )[1] ) //don't scale height

int ScaleBSPMain2( int argc, char **argv ){
int i;
float f, scale;
vec3_t vec;
char str[ 1024 ];

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

/* get scale */
scale = atof( argv[ argc - 2 ] );
if ( scale == 0.0f ) {
    Sys_Printf( "Usage: q3map -scale <value> [-v] <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 ] ) ) {
        VectorScaleX( vec, scale, vec );
        sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
        SetKeyValue( &entities[ i ], "origin", str );
    }

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

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

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

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

/* scale drawverts */
for ( i = 0; i < numBSPDrawVerts; i++ )
    VectorScaleX( bspDrawVerts[ i ].xyz, scale, bspDrawVerts[ i ].xyz );

/* scale planes */
for ( i = 0; i < numBSPPlanes; i++ )
{
    float new_normal_length = 0.0f;
    VectorScaleX(bspPlanes[i].normal,scale, bspPlanes[i].normal);                              
    new_normal_length = VectorNormalize(bspPlanes[i].normal, bspPlanes[i].normal);   // compute the new normal's length and normalize it                          
    bspPlanes[i].dist *= new_normal_length;  // scale the distance by the new normal's length       


    //bspPlanes[ i ].dist *= scale;  //<--- old way

}

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

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

/* return to sender */
return 0;

}

@mapmanx

Thanks to freemancw a properly working version of this function is now part of the radiant/Q3map2 branch!
Wider hallways here we come :)

https://github.com/freemancw/GtkRadiant/blob/e6cc56ba1359b1bd4832f6b7c2820c6974afb605/tools/quake3/q3map2/main.c#L511

usage:
q3map2 -scale3 x y z "path"

ex: (scale map horizontally by a factor of 2)
q3map2 -scale3 2.0 2.0 1.0 "path\mapname.bsp"

@Garux

NetRadiant's q3map2 has the same (cool) feature

-scale SX SY SZ filename.bsp: Scale non-uniformly
-scale -tex SX SY SZ filename.bsp: Scale non-uniformly without texture lock

@mapmanx

Cool, wish I knew this earlier!
But it looks like the NetRadiant's q3map2 version suffers from the same issues, i.e. elevators getting stuck in the floor when scaled:
f = FloatForKey( &entities[ i ], "lip" );
...
f *= scale; // commented this out to have them working!

And visibility issues when scaling sloped surfaces with higher values, i.e. see through brushes / walls :P

Too bad NetRadiant doesn't come with visual studio project file! Plus where do I find documentation for it's version of q3map2, or at least the list of commands it supports?

@Garux

I tested it only with big terrain, no issues stated.

Some bit of info: http://dev.xonotic.org/projects/xonotic/wiki/NetRadiant
Pages, saved from dead dev site: http://dl.dropbox.com/u/108811591/netdocs.rar
Most fresh src: http://ingar.satgnu.net/gtkradiant/files/netradiant-20120705-src.tar.bz2

@TTimo
Owner

I'm not sure I see the value in scaling the .bsp out.

You will loose texture resolution in the scaling up, and since it's a bsp there isn't much to do from there. I suppose you could decompile the result back to map, but decompiled map results are also of poor quality.

Overall it looks like this updates an already existing, not so useful feature of q3map2. If you send in a pull request I think we will merge it in.

@freemancw

I agree that in general scaling isn't something I've ever really used when designing levels, much less non-uniform scaling, but mapmanx had an application for it so...

I'd want to fix the robustness problems/mover lip scaling before adding a seldom-used feature that says "hey, will probably blow up, use with caution"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.