]> git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake3/q3map2/main.c
less spammy vis output, more useful
[xonotic/netradiant.git] / tools / quake3 / q3map2 / main.c
index 44b0c821595a8ce570afb61305948a5e082ad610..b113247bd4205a5776c1d373d5abf46321b67df3 100644 (file)
@@ -371,6 +371,74 @@ int BSPInfo( int count, char **fileNames )
 }
 
 
+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()
@@ -379,24 +447,37 @@ amaze and confuse your enemies with wierd scaled maps!
 
 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;
        }
@@ -420,57 +501,163 @@ int ScaleBSPMain( int argc, char **argv )
        {
                /* 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 );
 
@@ -608,7 +795,7 @@ int main( int argc, char **argv )
        
        /* set exit call */
        atexit( ExitQ3Map );
-       
+
        /* read general options first */
        for( i = 1; i < argc; i++ )
        {
@@ -624,8 +811,11 @@ int main( int argc, char **argv )
                /* verbose */
                else if( !strcmp( argv[ i ], "-v" ) )
                {
-                       verbose = qtrue;
-                       argv[ i ] = NULL;
+                       if(!verbose)
+                       {
+                               verbose = qtrue;
+                               argv[ i ] = NULL;
+                       }
                }
                
                /* force */
@@ -684,6 +874,10 @@ int main( int argc, char **argv )
        
        /* 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 )