]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake3/q3map2/surface.c
fix a nasty bug breaking "deformvertexes move"
[xonotic/netradiant.git] / tools / quake3 / q3map2 / surface.c
index 98baf9219cf6adb48b867da1e96abe81250caef4..7f511b93e4f382e22ed7ce5a0180c0ee02d78017 100644 (file)
@@ -631,21 +631,26 @@ void ClassifySurfaces( int numSurfs, mapDrawSurface_t *ds )
                        //%     Sys_Printf( "Failed to map axis %d onto patch\n", bestAxis );
                }
                
-               /* get lightmap sample size */
-               if( ds->sampleSize <= 0 )
+               /* calculate lightmap sample size */
+               if( ds->shaderInfo->lightmapSampleSize > 0 ) /* shader value overrides every other */
+                       ds->sampleSize = ds->shaderInfo->lightmapSampleSize;
+               else if( ds->sampleSize <= 0 ) /* may contain the entity asigned value */
+                       ds->sampleSize = sampleSize; /* otherwise use global default */
+
+               if( ds->lightmapScale > 0.0f ) /* apply surface lightmap scaling factor */
                {
-                       ds->sampleSize = sampleSize;
-                       if( ds->shaderInfo->lightmapSampleSize )
-                               ds->sampleSize = ds->shaderInfo->lightmapSampleSize;
-                       if( ds->lightmapScale > 0 )
-                               ds->sampleSize *= ds->lightmapScale;
-                       if( ds->sampleSize <= 0 )
-                               ds->sampleSize = 1;
-                       if(ds->sampleSize < minSampleSize)
-                               ds->sampleSize = minSampleSize;
-                       if( ds->sampleSize > 16384 )    /* powers of 2 are preferred */
-                               ds->sampleSize = 16384;
+                       ds->sampleSize = ds->lightmapScale * (float)ds->sampleSize;
+                       ds->lightmapScale = 0; /* applied */
                }
+
+               if( ds->sampleSize < minSampleSize )
+                       ds->sampleSize = minSampleSize;
+
+               if( ds->sampleSize < 1 )
+                       ds->sampleSize = 1;
+
+               if( ds->sampleSize > 16384 ) /* powers of 2 are preferred */
+                       ds->sampleSize = 16384;
        }
 }
 
@@ -914,6 +919,7 @@ mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, windin
        ds->mapBrush = b;
        ds->sideRef = AllocSideRef( s, NULL );
        ds->fogNum = -1;
+       ds->sampleSize = b->lightmapSampleSize;
        ds->lightmapScale = b->lightmapScale;
        ds->numVerts = w->numpoints;
        ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) );
@@ -991,10 +997,8 @@ mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, windin
        ds->celShader = b->celShader;
 
        /* set shade angle */
-       if( si->shadeAngleDegrees )
-               ds->shadeAngleDegrees = ds->shadeAngleDegrees;
-       else
-               ds->shadeAngleDegrees = b->shadeAngleDegrees; /* otherwise it's 0 */
+       if( b->shadeAngleDegrees > 0.0f )
+               ds->shadeAngleDegrees = b->shadeAngleDegrees;
        
        /* ydnar: gs mods: moved st biasing elsewhere */
        return ds;
@@ -1103,6 +1107,7 @@ mapDrawSurface_t *DrawSurfaceForMesh( entity_t *e, parseMesh_t *p, mesh_t *mesh
        
        ds->shaderInfo = si;
        ds->mapMesh = p;
+       ds->sampleSize = p->lightmapSampleSize;
        ds->lightmapScale = p->lightmapScale;   /* ydnar */
        ds->patchWidth = mesh->width;
        ds->patchHeight = mesh->height;
@@ -1960,6 +1965,51 @@ int FilterPointIntoTree_r( vec3_t point, mapDrawSurface_t *ds, node_t *node )
        return AddReferenceToLeaf( ds, node );
 }
 
+/*
+FilterPointConvexHullIntoTree_r() - ydnar
+filters the convex hull of multiple points from a surface into the tree
+*/
+
+int FilterPointConvexHullIntoTree_r( vec3_t **points, int npoints, mapDrawSurface_t *ds, node_t *node )
+{
+       float                   d, dmin, dmax;
+       plane_t                 *plane;
+       int                             refs = 0;
+       int                             i;
+
+       if(!points)
+               return 0;
+       
+       /* is this a decision node? */
+       if( node->planenum != PLANENUM_LEAF )
+       {
+               /* classify the point in relation to the plane */
+               plane = &mapplanes[ node->planenum ];
+
+               dmin = dmax = DotProduct( *(points[0]), plane->normal ) - plane->dist;
+               for(i = 1; i < npoints; ++i)
+               {
+                       d = DotProduct( *(points[i]), plane->normal ) - plane->dist;
+                       if(d > dmax)
+                               dmax = d;
+                       if(d < dmin)
+                               dmin = d;
+               }
+               
+               /* filter by this plane */
+               refs = 0;
+               if( dmax >= -ON_EPSILON )
+                       refs += FilterPointConvexHullIntoTree_r( points, npoints, ds, node->children[ 0 ] );
+               if( dmin <= ON_EPSILON )
+                       refs += FilterPointConvexHullIntoTree_r( points, npoints, ds, node->children[ 1 ] );
+               
+               /* return */
+               return refs;
+       }
+       
+       /* add a reference */
+       return AddReferenceToLeaf( ds, node );
+}
 
 
 /*
@@ -1987,14 +2037,25 @@ int FilterWindingIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node )
        {
                /* 'fatten' the winding by the shader mins/maxs (parsed from vertexDeform move) */
                /* note this winding is completely invalid (concave, nonplanar, etc) */
-               fat = AllocWinding( w->numpoints * 3 );
-               fat->numpoints = w->numpoints * 3;
+               fat = AllocWinding( w->numpoints * 3 + 3 );
+               fat->numpoints = w->numpoints * 3 + 3;
                for( i = 0; i < w->numpoints; i++ )
                {
                        VectorCopy( w->p[ i ], fat->p[ i ] );
-                       VectorAdd( w->p[ i ], si->mins, fat->p[ i * 2 ] );
-                       VectorAdd( w->p[ i ], si->maxs, fat->p[ i * 3 ] );
+                       VectorAdd( w->p[ i ], si->mins, fat->p[ i + (w->numpoints+1) ] );
+                       VectorAdd( w->p[ i ], si->maxs, fat->p[ i + (w->numpoints+1) * 2 ] );
                }
+               VectorCopy( w->p[ 0 ], fat->p[ i ] );
+               VectorAdd( w->p[ 0 ], si->mins, fat->p[ i + w->numpoints ] );
+               VectorAdd( w->p[ 0 ], si->maxs, fat->p[ i + w->numpoints * 2 ] );
+
+               /*
+                * note: this winding is STILL not suitable for ClipWindingEpsilon, and
+                * also does not really fulfill the intention as it only contains
+                * origin, +mins, +maxs, but thanks to the "closing" points I just
+                * added to the three sub-windings, the fattening at least doesn't make
+                * it worse
+                */
                
                FreeWinding( w );
                w = fat;
@@ -2086,48 +2147,24 @@ subdivides a patch into an approximate curve and filters it into the tree
 
 static int FilterPatchIntoTree( mapDrawSurface_t *ds, tree_t *tree )
 {
-       int                                     i, x, y, refs;
-       mesh_t                          src, *mesh;
-       winding_t                       *w;
-       
+       int                                     x, y, refs;
        
-       /* subdivide the surface */
-       src.width = ds->patchWidth;
-       src.height = ds->patchHeight;
-       src.verts = ds->verts;
-       mesh = SubdivideMesh( src, FILTER_SUBDIVISION, 32 );
-       
-       
-       /* filter each quad into the tree (fixme: use new patch x-triangulation code?) */
-       refs = 0;
-       for( y = 0; y < (mesh->height - 1); y++ )
-       {
-               for( x = 0; x < (mesh->width - 1); x++ )
+       for(y = 0; y + 2 < ds->patchHeight; y += 2)
+               for(x = 0; x + 2 < ds->patchWidth; x += 2)
                {
-                       /* triangle 1 */
-                       w = AllocWinding( 3 );
-                       w->numpoints = 3;
-                       VectorCopy( mesh->verts[ y * mesh->width + x ].xyz, w->p[ 0 ] );
-                       VectorCopy( mesh->verts[ y * mesh->width + x + 1 ].xyz, w->p[ 1 ] );
-                       VectorCopy( mesh->verts[ (y + 1) * mesh->width + x ].xyz, w->p[ 2 ] );
-                       refs += FilterWindingIntoTree_r( w, ds, tree->headnode );
-                       
-                       /* triangle 2 */
-                       w = AllocWinding( 3 );
-                       w->numpoints = 3;
-                       VectorCopy( mesh->verts[ y * mesh->width + x + 1 ].xyz, w->p[ 0 ] );
-                       VectorCopy( mesh->verts[ (y + 1 ) * mesh->width + x + 1 ].xyz, w->p[ 1 ] );
-                       VectorCopy( mesh->verts[ (y + 1 ) * mesh->width + x ].xyz, w->p[ 2 ] );
-                       refs += FilterWindingIntoTree_r( w, ds, tree->headnode );
+                       vec3_t *points[9];
+                       points[0] = &ds->verts[(y+0) * ds->patchWidth + (x+0)].xyz;
+                       points[1] = &ds->verts[(y+0) * ds->patchWidth + (x+1)].xyz;
+                       points[2] = &ds->verts[(y+0) * ds->patchWidth + (x+2)].xyz;
+                       points[3] = &ds->verts[(y+1) * ds->patchWidth + (x+0)].xyz;
+                       points[4] = &ds->verts[(y+1) * ds->patchWidth + (x+1)].xyz;
+                       points[5] = &ds->verts[(y+1) * ds->patchWidth + (x+2)].xyz;
+                       points[6] = &ds->verts[(y+2) * ds->patchWidth + (x+0)].xyz;
+                       points[7] = &ds->verts[(y+2) * ds->patchWidth + (x+1)].xyz;
+                       points[8] = &ds->verts[(y+2) * ds->patchWidth + (x+2)].xyz;
+                       refs += FilterPointConvexHullIntoTree_r(points, 9, ds, tree->headnode);
                }
-       }
-       
-       /* use point filtering as well */
-       for( i = 0; i < (mesh->width * mesh->height); i++ )
-               refs += FilterPointIntoTree_r( mesh->verts[ i ].xyz, ds, tree->headnode );
-       
-       /* free the subdivided mesh and return */
-       FreeMesh( mesh );
+
        return refs;
 }
 
@@ -3133,7 +3170,7 @@ int AddSurfaceModelsToTriangle_r( mapDrawSurface_t *ds, surfaceModel_t *model, b
                        }
                        
                        /* insert the model */
-                       InsertModel( (char *) model->model, 0, transform, NULL, ds->celShader, ds->entityNum, ds->castShadows, ds->recvShadows, 0, ds->lightmapScale, 0 );
+                       InsertModel( (char *) model->model, 0, transform, NULL, ds->celShader, ds->entityNum, ds->castShadows, ds->recvShadows, 0, ds->lightmapScale, 0, 0 );
                        
                        /* return to sender */
                        return 1;