}
+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()
int ScaleBSPMain( int argc, char **argv )
{
- int i;
- float f, scale;
+ int i, j;
+ float f, a;
+ vec3_t scale;
vec3_t vec;
char str[ 1024 ];
+ int uniform, axis;
+ qboolean texscale;
+ float *old_xyzst = NULL;
/* arg checking */
- if( argc < 2 )
+ if( argc < 3 )
{
- Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
+ Sys_Printf( "Usage: q3map [-v] -scale [-tex] <value> <mapname>\n" );
return 0;
}
/* get scale */
- scale = atof( argv[ argc - 2 ] );
- if( scale == 0.0f )
+ scale[2] = scale[1] = scale[0] = atof( argv[ argc - 2 ] );
+ if(argc >= 4)
+ scale[1] = scale[0] = atof( argv[ argc - 3 ] );
+ if(argc >= 5)
+ scale[0] = atof( argv[ argc - 4 ] );
+
+ texscale = !strcmp(argv[1], "-tex");
+
+ 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 -scale <value> [-v] <mapname>\n" );
+ Sys_Printf( "Usage: q3map [-v] -scale [-tex] <value> <mapname>\n" );
Sys_Printf( "Non-zero scale value required.\n" );
return 0;
}
{
/* scale origin */
GetVectorForKey( &entities[ i ], "origin", vec );
- if( (vec[ 0 ] + vec[ 1 ] + vec[ 2 ]) )
+ if( (vec[ 0 ] || vec[ 1 ] || vec[ 2 ]) )
{
- VectorScale( vec, scale, 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[ 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;
+ 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++ )
{
- VectorScale( bspModels[ i ].mins, scale, bspModels[ i ].mins );
- VectorScale( bspModels[ i ].maxs, scale, bspModels[ i ].maxs );
+ 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++ )
{
- VectorScale( bspNodes[ i ].mins, scale, bspNodes[ i ].mins );
- VectorScale( bspNodes[ i ].maxs, scale, bspNodes[ i ].maxs );
+ 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++ )
{
- VectorScale( bspLeafs[ i ].mins, scale, bspLeafs[ i ].mins );
- VectorScale( bspLeafs[ i ].maxs, scale, bspLeafs[ i ].maxs );
+ 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++ )
- VectorScale( bspDrawVerts[ i ].xyz, scale, bspDrawVerts[ i ].xyz );
+ {
+ 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 */
- for( i = 0; i < numBSPPlanes; i++ )
- bspPlanes[ i ].dist *= scale;
+ 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 );
- VectorScale( vec, scale, 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();
/* set exit call */
atexit( ExitQ3Map );
-
+
/* read general options first */
for( i = 1; i < argc; i++ )
{
/* verbose */
else if( !strcmp( argv[ i ], "-v" ) )
{
- verbose = qtrue;
- argv[ i ] = NULL;
+ if(!verbose)
+ {
+ verbose = qtrue;
+ argv[ i ] = NULL;
+ }
}
/* force */
/* ydnar: new path initialization */
InitPaths( &argc, argv );
+
+ /* set game options */
+ if (!patchSubdivisions)
+ patchSubdivisions = game->patchSubdivisions;
/* check if we have enough options left to attempt something */
if( argc < 2 )