]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake3/q3map2/surface.c
fix patch collision issue by linking patches into all nodes that touch a
[xonotic/netradiant.git] / tools / quake3 / q3map2 / surface.c
index 82968420ce57cd5e2e28b854bfde5ba2af281c90..6a49c791f3eb5e33f34a1abff0815cf8a54f1565 100644 (file)
@@ -181,6 +181,7 @@ mapDrawSurface_t *MakeCelSurface( mapDrawSurface_t *src, shaderInfo_t *si )
        /* do some fixups for celshading */
        ds->planar = qfalse;
        ds->planeNum = -1;
+       ds->celShader = NULL; /* don't cel shade cels :P */
        
        /* return the surface */
        return ds;
@@ -630,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;
        }
 }
 
@@ -913,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 ) );
@@ -988,6 +995,10 @@ mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, windin
        
        /* set cel shader */
        ds->celShader = b->celShader;
+
+       /* set shade angle */
+       if( b->shadeAngleDegrees > 0.0f )
+               ds->shadeAngleDegrees = b->shadeAngleDegrees;
        
        /* ydnar: gs mods: moved st biasing elsewhere */
        return ds;
@@ -1096,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;
@@ -1953,6 +1965,44 @@ int FilterPointIntoTree_r( vec3_t point, mapDrawSurface_t *ds, node_t *node )
        return AddReferenceToLeaf( ds, node );
 }
 
+/*
+FilterBoxIntoTree_r() - ydnar
+filters a box from a surface into the tree
+*/
+
+int FilterBoxIntoTree_r( vec3_t mins, vec3_t maxs, mapDrawSurface_t *ds, node_t *node )
+{
+       float                   d, d0, d1, d2, dmin, dmax;
+       plane_t                 *plane;
+       int                             refs = 0;
+       
+       
+       /* is this a decision node? */
+       if( node->planenum != PLANENUM_LEAF )
+       {
+               /* classify the point in relation to the plane */
+               plane = &mapplanes[ node->planenum ];
+               d = DotProduct( mins, plane->normal ) - plane->dist;
+               d0 = (maxs[0] - mins[0]) * plane->normal[0];
+               d1 = (maxs[1] - mins[1]) * plane->normal[1];
+               d2 = (maxs[2] - mins[2]) * plane->normal[2];
+               dmax = d + (d0>0 ? d0 : 0) + (d1>0 ? d1 : 0) + (d2>0 ? d2 : 0);
+               dmin = d + (d0<0 ? d0 : 0) + (d1<0 ? d1 : 0) + (d2<0 ? d2 : 0);
+               
+               /* filter by this plane */
+               refs = 0;
+               if( dmax >= -ON_EPSILON )
+                       refs += FilterBoxIntoTree_r( mins, maxs, ds, node->children[ 0 ] );
+               if( dmin <= ON_EPSILON )
+                       refs += FilterBoxIntoTree_r( mins, maxs, ds, node->children[ 1 ] );
+               
+               /* return */
+               return refs;
+       }
+       
+       /* add a reference */
+       return AddReferenceToLeaf( ds, node );
+}
 
 
 /*
@@ -2083,14 +2133,13 @@ static int FilterPatchIntoTree( mapDrawSurface_t *ds, tree_t *tree )
        mesh_t                          src, *mesh;
        winding_t                       *w;
        
-       
+#if 0
        /* 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++ )
@@ -2121,6 +2170,25 @@ static int FilterPatchIntoTree( mapDrawSurface_t *ds, tree_t *tree )
        
        /* free the subdivided mesh and return */
        FreeMesh( mesh );
+#else
+       for(y = 0; y + 2 < ds->patchHeight; y += 2)
+               for(x = 0; x + 2 < ds->patchWidth; x += 2)
+               {
+                       vec3_t mins, maxs;
+                       ClearBounds(mins, maxs);
+                       AddPointToBounds(ds->verts[(y+0) * ds->patchWidth + (x+0)].xyz, mins, maxs);
+                       AddPointToBounds(ds->verts[(y+0) * ds->patchWidth + (x+1)].xyz, mins, maxs);
+                       AddPointToBounds(ds->verts[(y+0) * ds->patchWidth + (x+2)].xyz, mins, maxs);
+                       AddPointToBounds(ds->verts[(y+1) * ds->patchWidth + (x+0)].xyz, mins, maxs);
+                       AddPointToBounds(ds->verts[(y+1) * ds->patchWidth + (x+1)].xyz, mins, maxs);
+                       AddPointToBounds(ds->verts[(y+1) * ds->patchWidth + (x+2)].xyz, mins, maxs);
+                       AddPointToBounds(ds->verts[(y+2) * ds->patchWidth + (x+0)].xyz, mins, maxs);
+                       AddPointToBounds(ds->verts[(y+2) * ds->patchWidth + (x+1)].xyz, mins, maxs);
+                       AddPointToBounds(ds->verts[(y+2) * ds->patchWidth + (x+2)].xyz, mins, maxs);
+                       refs += FilterBoxIntoTree_r(mins, maxs, ds, tree->headnode);
+               }
+#endif
+
        return refs;
 }
 
@@ -2445,25 +2513,27 @@ void EmitFlareSurface( mapDrawSurface_t *ds )
        numSurfacesByType[ ds->type ]++;
 }
 
-
-
 /*
 EmitPatchSurface()
 emits a bsp patch drawsurface
 */
 
-void EmitPatchSurface( mapDrawSurface_t *ds )
+void EmitPatchSurface( entity_t *e, mapDrawSurface_t *ds )
 {
        int                                     i, j;
        bspDrawSurface_t        *out;
        int                                     surfaceFlags, contentFlags;
-       
+       int                                     forcePatchMeta;
+
+       /* vortex: _patchMeta support */
+       forcePatchMeta = IntForKey(e, "_patchMeta" );
+       if (!forcePatchMeta)
+               forcePatchMeta = IntForKey(e, "patchMeta" );
        
        /* invert the surface if necessary */
        if( ds->backSide || ds->shaderInfo->invert )
        {
                bspDrawVert_t   *dv1, *dv2, temp;
-               
 
                /* walk the verts, flip the normal */
                for( i = 0; i < ds->numVerts; i++ )
@@ -2485,7 +2555,7 @@ void EmitPatchSurface( mapDrawSurface_t *ds )
                /* invert facing */
                VectorScale( ds->lightmapVecs[ 2 ], -1.0f, ds->lightmapVecs[ 2 ] );
        }
-       
+
        /* allocate a new surface */
        if( numBSPDrawSurfaces == MAX_MAP_DRAW_SURFS )
                Error( "MAX_MAP_DRAW_SURFS" );
@@ -2493,12 +2563,12 @@ void EmitPatchSurface( mapDrawSurface_t *ds )
        ds->outputNum = numBSPDrawSurfaces;
        numBSPDrawSurfaces++;
        memset( out, 0, sizeof( *out ) );
-       
+
        /* set it up */
        out->surfaceType = MST_PATCH;
        if( debugSurfaces )
                out->shaderNum = EmitShader( "debugsurfaces", NULL, NULL );
-       else if( patchMeta )
+       else if( patchMeta || forcePatchMeta )
        {
                /* patch meta requires that we have nodraw patches for collision */
                surfaceFlags = ds->shaderInfo->surfaceFlags;
@@ -2548,8 +2618,6 @@ void EmitPatchSurface( mapDrawSurface_t *ds )
        numSurfacesByType[ ds->type ]++;
 }
 
-
-
 /*
 OptimizeTriangleSurface() - ydnar
 optimizes the vertex/index data in a triangle surface
@@ -2673,12 +2741,11 @@ EmitTriangleSurface()
 creates a bsp drawsurface from arbitrary triangle surfaces
 */
 
-static void EmitTriangleSurface( mapDrawSurface_t *ds )
+void EmitTriangleSurface( mapDrawSurface_t *ds )
 {
        int                                             i, temp;
        bspDrawSurface_t                *out;
-       
-       
+
        /* invert the surface if necessary */
        if( ds->backSide || ds->shaderInfo->invert )
        {
@@ -2689,15 +2756,15 @@ static void EmitTriangleSurface( mapDrawSurface_t *ds )
                        ds->indexes[ i ] = ds->indexes[ i + 1 ];
                        ds->indexes[ i + 1 ] = temp;
                }
-               
+                       
                /* walk the verts, flip the normal */
                for( i = 0; i < ds->numVerts; i++ )
                        VectorScale( ds->verts[ i ].normal, -1.0f, ds->verts[ i ].normal );
-               
+                       
                /* invert facing */
                VectorScale( ds->lightmapVecs[ 2 ], -1.0f, ds->lightmapVecs[ 2 ] );
        }
-       
+               
        /* allocate a new surface */
        if( numBSPDrawSurfaces == MAX_MAP_DRAW_SURFS )
                Error( "MAX_MAP_DRAW_SURFS" );
@@ -2804,15 +2871,14 @@ EmitFaceSurface()
 emits a bsp planar winding (brush face) drawsurface
 */
 
-static void EmitFaceSurface( mapDrawSurface_t *ds )
+static void EmitFaceSurface(mapDrawSurface_t *ds )
 {
        /* strip/fan finding was moved elsewhere */
        StripFaceSurface( ds );
-       EmitTriangleSurface( ds );
+       EmitTriangleSurface(ds);
 }
 
 
-
 /*
 MakeDebugPortalSurfs_r() - ydnar
 generates drawsurfaces for passable portals in the bsp
@@ -3128,7 +3194,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 );
+                       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;
@@ -3502,7 +3568,7 @@ void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree )
                                if( refs == 0 )
                                        refs = FilterPatchIntoTree( ds, tree );
                                if( refs > 0 )
-                                       EmitPatchSurface( ds );
+                                       EmitPatchSurface( e, ds );
                                break;
                        
                        /* handle triangle surfaces */