now clears stencil to 128 instead of 0, this avoids problems with arbitrary incr...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 4 Nov 2002 01:09:33 +0000 (01:09 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 4 Nov 2002 01:09:33 +0000 (01:09 +0000)
stencil shadows are now always erased by glClear, never by drawing again, removes r_shadow_erasebydrawing cvar
shadow volumes now have a nudge away from the surface that cast them, this is controlled by the r_shadow_shadownudge cvar (default 1 unit), avoids rare z fighting issues
shadow volume projection distance is now not infinite for alias model volumes, because they are more well-behaved than the world shadows...
msurface_t poly_radius and poly_radius2 removed
now validates elements in more parts of loading (hoped this would reveal a model shadow bug, but it didn't)
Mod_ShadowMesh_AddVertex now uses a hash table search to speed up static shadow volume building (unfortunately this doesn't seem to be the real speed problem)
removed ALLOCMESHINPIECES option from Mod_ShadowMesh code
removed non-PRECOMPUTEDSHADOWVOLUMES option from static shadow volume creation
removed some unused variables

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2597 d7cf8633-e32d-0410-b094-e92efae38249

gl_backend.c
gl_rmain.c
gl_rsurf.c
model_alias.c
model_brush.c
model_brush.h
model_shared.c
model_shared.h
r_shadow.c
r_shadow.h

index 8125cb7..a664871 100644 (file)
@@ -882,7 +882,10 @@ void R_ClearScreen(void)
                qglClearDepth(1);CHECKGLERROR
                if (gl_stencil)
                {
-                       qglClearStencil(0);CHECKGLERROR
+                       // LordHavoc: we use a stencil centered around 128 instead of 0,
+                       // to avoid clamping interfering with strange shadow volume
+                       // drawing orders
+                       qglClearStencil(128);CHECKGLERROR
                }
                // clear the screen
                qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | (gl_stencil ? GL_STENCIL_BUFFER_BIT : 0));CHECKGLERROR
index fcc9f67..2fe41e5 100644 (file)
@@ -939,27 +939,6 @@ void R_ShadowVolumeLighting (int visiblevolumes)
                                        }
                                }
                        }
-
-                       if (R_Shadow_Stage_EraseShadowVolumes())
-                       {
-                               ent = &cl_entities[0].render;
-                               if (wl->shadowvolume && r_staticworldlights.integer)
-                                       R_Shadow_DrawWorldLightShadowVolume(&ent->matrix, wl);
-                               else
-                                       R_TestAndDrawShadowVolume(ent, wl->origin, cullradius / ent->scale, lightradius / ent->scale, clipmins, clipmaxs);
-                               if (r_drawentities.integer)
-                               {
-                                       for (i = 0;i < r_refdef.numentities;i++)
-                                       {
-                                               ent = r_refdef.entities[i];
-                                               if (ent->maxs[0] >= wl->mins[0] && ent->mins[0] <= wl->maxs[0]
-                                                && ent->maxs[1] >= wl->mins[1] && ent->mins[1] <= wl->maxs[1]
-                                                && ent->maxs[2] >= wl->mins[2] && ent->mins[2] <= wl->maxs[2]
-                                                && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
-                                                       R_TestAndDrawShadowVolume(r_refdef.entities[i], wl->origin, cullradius / ent->scale, lightradius / ent->scale, clipmins, clipmaxs);
-                                       }
-                               }
-                       }
                }
        }
        /*
@@ -1023,24 +1002,6 @@ void R_ShadowVolumeLighting (int visiblevolumes)
                                        }
                                }
                        }
-
-                       R_Shadow_Stage_EraseShadowVolumes();
-                       if (sl->shadowvolume && r_staticworldlights.integer)
-                               R_DrawWorldLightShadowVolume(&cl_entities[0].render.matrix, sl->shadowvolume);
-                       else
-                               R_TestAndDrawShadowVolume(&cl_entities[0].render, sl->origin, cullradius, lightradius);
-                       if (r_drawentities.integer)
-                       {
-                               for (i = 0;i < r_refdef.numentities;i++)
-                               {
-                                       ent = r_refdef.entities[i];
-                                       if (ent->maxs[0] >= sl->mins[0] && ent->mins[0] <= sl->maxs[0]
-                                       && ent->maxs[1] >= sl->mins[1] && ent->mins[1] <= sl->maxs[1]
-                                       && ent->maxs[2] >= sl->mins[2] && ent->mins[2] <= sl->maxs[2]
-                                       && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
-                                               R_TestAndDrawShadowVolume(r_refdef.entities[i], sl->origin, cullradius, lightradius);
-                               }
-                       }
                }
        }
        */
@@ -1100,21 +1061,6 @@ void R_ShadowVolumeLighting (int visiblevolumes)
                                        }
                                }
                        }
-
-                       if (R_Shadow_Stage_EraseShadowVolumes())
-                       {
-                               ent = &cl_entities[0].render;
-                               R_TestAndDrawShadowVolume(ent, rd->origin, cullradius / ent->scale, lightradius / ent->scale, clipmins, clipmaxs);
-                               if (r_drawentities.integer)
-                               {
-                                       for (i = 0;i < r_refdef.numentities;i++)
-                                       {
-                                               ent = r_refdef.entities[i];
-                                               if (ent != rd->ent && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
-                                                       R_TestAndDrawShadowVolume(ent, rd->origin, cullradius / ent->scale, lightradius / ent->scale, clipmins, clipmaxs);
-                                       }
-                               }
-                       }
                }
        }
 
index 7177b46..8bdb5db 100644 (file)
@@ -1824,6 +1824,7 @@ void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelighto
        R_Mesh_Matrix(&ent->matrix);
        lightradius2 = lightradius * lightradius;
        R_UpdateTextureInfo(ent);
+       projectdistance = 1000000000.0f;//lightradius + ent->model->radius;
        for (i = 0, surf = ent->model->surfaces + ent->model->firstmodelsurface;i < ent->model->nummodelsurfaces;i++, surf++)
        {
                if (surf->texinfo->texture->rendertype == SURFRENDER_OPAQUE && surf->flags & SURF_SHADOWCAST)
@@ -1831,12 +1832,13 @@ void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelighto
                        f = PlaneDiff(relativelightorigin, surf->plane);
                        if (surf->flags & SURF_PLANEBACK)
                                f = -f;
-                       // draw shadows only for frontfaces
-                       projectdistance = lightradius - f;
-                       if (projectdistance >= 0.1 && projectdistance < lightradius)
+                       // draw shadows only for frontfaces and only if they are close
+                       if (f >= 0.1 && f < lightradius)
                        {
-                               VectorSubtract(relativelightorigin, surf->poly_center, temp);
-                               if (DotProduct(temp, temp) < lightradius2 - surf->poly_radius2)
+                               temp[0] = bound(surf->poly_mins[0], relativelightorigin[0], surf->poly_maxs[0]) - relativelightorigin[0];
+                               temp[1] = bound(surf->poly_mins[1], relativelightorigin[1], surf->poly_maxs[1]) - relativelightorigin[1];
+                               temp[2] = bound(surf->poly_mins[2], relativelightorigin[2], surf->poly_maxs[2]) - relativelightorigin[2];
+                               if (DotProduct(temp, temp) < lightradius2)
                                {
                                        for (mesh = surf->mesh;mesh;mesh = mesh->chain)
                                        {
@@ -1893,8 +1895,10 @@ void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, v
                // bmodel, cull crudely to view and light
                for (surfnum = 0, surf = ent->model->surfaces + ent->model->firstmodelsurface;surfnum < ent->model->nummodelsurfaces;surfnum++, surf++)
                {
-                       VectorSubtract(relativelightorigin, surf->poly_center, temp);
-                       if (DotProduct(temp, temp) < lightradius2 - surf->poly_radius2)
+                       temp[0] = bound(surf->poly_mins[0], relativelightorigin[0], surf->poly_maxs[0]) - relativelightorigin[0];
+                       temp[1] = bound(surf->poly_mins[1], relativelightorigin[1], surf->poly_maxs[1]) - relativelightorigin[1];
+                       temp[2] = bound(surf->poly_mins[2], relativelightorigin[2], surf->poly_maxs[2]) - relativelightorigin[2];
+                       if (DotProduct(temp, temp) < lightradius2)
                        {
                                f = PlaneDiff(relativelightorigin, surf->plane);
                                if (surf->flags & SURF_PLANEBACK)
@@ -1929,8 +1933,10 @@ void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, v
                {
                        if (surf->visframe == r_framecount)
                        {
-                               VectorSubtract(relativelightorigin, surf->poly_center, temp);
-                               if (DotProduct(temp, temp) < lightradius2 - surf->poly_radius2)
+                               temp[0] = bound(surf->poly_mins[0], relativelightorigin[0], surf->poly_maxs[0]) - relativelightorigin[0];
+                               temp[1] = bound(surf->poly_mins[1], relativelightorigin[1], surf->poly_maxs[1]) - relativelightorigin[1];
+                               temp[2] = bound(surf->poly_mins[2], relativelightorigin[2], surf->poly_maxs[2]) - relativelightorigin[2];
+                               if (DotProduct(temp, temp) < lightradius2)
                                {
                                        f = PlaneDiff(relativelightorigin, surf->plane);
                                        if (surf->flags & SURF_PLANEBACK)
index 24829cf..2d42510 100644 (file)
@@ -495,6 +495,7 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
        loadmodel->radius2 = modelradius * modelradius;
 
        loadmodel->mdlmd2data_triangleneighbors = Mem_Alloc(loadmodel->mempool, loadmodel->numtris * sizeof(int[3]));
+       Mod_ValidateElements(loadmodel->mdlmd2data_indices, loadmodel->numtris, loadmodel->numverts, __FILE__, __LINE__);
        Mod_BuildTriangleNeighbors(loadmodel->mdlmd2data_triangleneighbors, loadmodel->mdlmd2data_indices, loadmodel->numtris);
 }
 
@@ -757,6 +758,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
        loadmodel->radius2 = modelradius * modelradius;
 
        loadmodel->mdlmd2data_triangleneighbors = Mem_Alloc(loadmodel->mempool, loadmodel->numtris * sizeof(int[3]));
+       Mod_ValidateElements(loadmodel->mdlmd2data_indices, loadmodel->numtris, loadmodel->numverts, __FILE__, __LINE__);
        Mod_BuildTriangleNeighbors(loadmodel->mdlmd2data_triangleneighbors, loadmodel->mdlmd2data_indices, loadmodel->numtris);
 }
 
index f62506f..c003fb2 100644 (file)
@@ -783,8 +783,10 @@ void Mod_ProcessLightList(void)
                                                dist = -dist;
                                        if (dist > 0 && dist < e->cullradius)
                                        {
-                                               VectorSubtract(e->origin, surf->poly_center, temp);
-                                               if (DotProduct(temp, temp) < e->cullradius2 - surf->poly_radius2)
+                                               temp[0] = bound(surf->poly_mins[0], e->origin[0], surf->poly_maxs[0]) - e->origin[0];
+                                               temp[1] = bound(surf->poly_mins[1], e->origin[1], surf->poly_maxs[1]) - e->origin[1];
+                                               temp[2] = bound(surf->poly_mins[2], e->origin[2], surf->poly_maxs[2]) - e->origin[2];
+                                               if (DotProduct(temp, temp) < lightradius2)
                                                        loadmodel->surfacevisframes[*mark] = -2;
                                        }
                                }
@@ -1587,7 +1589,7 @@ void Mod_GenerateVertexMesh (msurface_t *surf)
 void Mod_GenerateSurfacePolygon (msurface_t *surf)
 {
        int i, lindex;
-       float *vec, *vert, mins[3], maxs[3], temp[3], dist;
+       float *vec, *vert, mins[3], maxs[3];
 
        // convert edges back to a normal polygon
        surf->poly_numverts = surf->numedges;
@@ -1606,29 +1608,17 @@ void Mod_GenerateSurfacePolygon (msurface_t *surf)
        VectorCopy(vert, mins);
        VectorCopy(vert, maxs);
        vert += 3;
-       for (i = 1;i < surf->poly_numverts;i++)
+       for (i = 1;i < surf->poly_numverts;i++, vert += 3)
        {
                if (mins[0] > vert[0]) mins[0] = vert[0];if (maxs[0] < vert[0]) maxs[0] = vert[0];
                if (mins[1] > vert[1]) mins[1] = vert[1];if (maxs[1] < vert[1]) maxs[1] = vert[1];
                if (mins[2] > vert[2]) mins[2] = vert[2];if (maxs[2] < vert[2]) maxs[2] = vert[2];
-               vert += 3;
        }
        VectorCopy(mins, surf->poly_mins);
        VectorCopy(maxs, surf->poly_maxs);
        surf->poly_center[0] = (mins[0] + maxs[0]) * 0.5f;
        surf->poly_center[1] = (mins[1] + maxs[1]) * 0.5f;
        surf->poly_center[2] = (mins[2] + maxs[2]) * 0.5f;
-       surf->poly_radius2 = 0;
-       vert = surf->poly_verts;
-       for (i = 0;i < surf->poly_numverts;i++)
-       {
-               VectorSubtract(vert, surf->poly_center, temp);
-               dist = DotProduct(temp, temp);
-               if (surf->poly_radius2 < dist)
-                       surf->poly_radius2 = dist;
-               vert += 3;
-       }
-       surf->poly_radius = sqrt(surf->poly_radius2);
 }
 
 /*
index fb4c30a..120679b 100644 (file)
@@ -216,8 +216,6 @@ typedef struct msurface_s
        float *poly_verts;
        // bounding box for onscreen checks, and center for sorting
        vec3_t poly_mins, poly_maxs, poly_center;
-       // bounding sphere radius (around poly_center)
-       float poly_radius, poly_radius2;
 
        // neighboring surfaces (one per poly_numverts)
        struct msurface_s **neighborsurfaces;
index 2ab19e6..4c75ef0 100644 (file)
@@ -523,47 +523,28 @@ void Mod_BuildTextureVectorsAndNormals(int numverts, int numtriangles, const flo
 shadowmesh_t *Mod_ShadowMesh_Alloc(mempool_t *mempool, int maxverts)
 {
        shadowmesh_t *mesh;
-#define ALLOCMESHINPIECES 0
-#if ALLOCMESHINPIECES
-       mesh = Mem_Alloc(mempool, sizeof(shadowmesh_t));
-#else
-       mesh = Mem_Alloc(mempool, sizeof(shadowmesh_t) + maxverts * sizeof(float[4]) + maxverts * sizeof(int[3]) + maxverts * sizeof(int[3]));
-#endif
+       mesh = Mem_Alloc(mempool, sizeof(shadowmesh_t) + maxverts * sizeof(float[4]) + maxverts * sizeof(int[3]) + maxverts * sizeof(int[3]) + SHADOWMESHVERTEXHASH * sizeof(shadowmeshvertexhash_t *) + maxverts * sizeof(shadowmeshvertexhash_t));
        mesh->maxverts = maxverts;
        mesh->maxtriangles = maxverts;
        mesh->numverts = 0;
        mesh->numtriangles = 0;
-#if ALLOCMESHINPIECES
-       mesh->verts = Mem_Alloc(mempool, maxverts * sizeof(float[4]));
-       mesh->elements = Mem_Alloc(mempool, maxverts * sizeof(int[3]));
-       mesh->neighbors = Mem_Alloc(mempool, maxverts * sizeof(int[3]));
-#else
        mesh->verts = (float *)(mesh + 1);
        mesh->elements = (int *)(mesh->verts + mesh->maxverts * 4);
        mesh->neighbors = (int *)(mesh->elements + mesh->maxtriangles * 3);
-#endif
+       mesh->vertexhashtable = (shadowmeshvertexhash_t **)(mesh->neighbors + mesh->maxtriangles * 3);
+       mesh->vertexhashentries = (shadowmeshvertexhash_t *)(mesh->vertexhashtable + SHADOWMESHVERTEXHASH);
        return mesh;
 }
 
 shadowmesh_t *Mod_ShadowMesh_ReAlloc(mempool_t *mempool, shadowmesh_t *oldmesh)
 {
        shadowmesh_t *newmesh;
-#if ALLOCMESHINPIECES
-       newmesh = Mem_Alloc(mempool, sizeof(shadowmesh_t));
-#else
        newmesh = Mem_Alloc(mempool, sizeof(shadowmesh_t) + oldmesh->numverts * sizeof(float[4]) + oldmesh->numtriangles * sizeof(int[3]) + oldmesh->numtriangles * sizeof(int[3]));
-#endif
        newmesh->maxverts = newmesh->numverts = oldmesh->numverts;
        newmesh->maxtriangles = newmesh->numtriangles = oldmesh->numtriangles;
-#if ALLOCMESHINPIECES
-       newmesh->verts = Mem_Alloc(mempool, newmesh->maxverts * sizeof(float[4]));
-       newmesh->elements = Mem_Alloc(mempool, newmesh->numtriangles * sizeof(int[3]));
-       newmesh->neighbors = Mem_Alloc(mempool, newmesh->numtriangles * sizeof(int[3]));
-#else
        newmesh->verts = (float *)(newmesh + 1);
        newmesh->elements = (int *)(newmesh->verts + newmesh->maxverts * 4);
        newmesh->neighbors = (int *)(newmesh->elements + newmesh->maxtriangles * 3);
-#endif
        memcpy(newmesh->verts, oldmesh->verts, newmesh->numverts * sizeof(float[4]));
        memcpy(newmesh->elements, oldmesh->elements, newmesh->numtriangles * sizeof(int[3]));
        memcpy(newmesh->neighbors, oldmesh->neighbors, newmesh->numtriangles * sizeof(int[3]));
@@ -572,17 +553,24 @@ shadowmesh_t *Mod_ShadowMesh_ReAlloc(mempool_t *mempool, shadowmesh_t *oldmesh)
 
 int Mod_ShadowMesh_AddVertex(shadowmesh_t *mesh, float *v)
 {
-       int j;
-       float *m, temp[3];
-       for (j = 0, m = mesh->verts;j < mesh->numverts;j++, m += 4)
+       int hashindex;
+       float *m;
+       shadowmeshvertexhash_t *hash;
+       // this uses prime numbers intentionally
+       hashindex = (int) (v[0] * 3 + v[1] * 5 + v[2] * 7) % SHADOWMESHVERTEXHASH;
+       for (hash = mesh->vertexhashtable[hashindex];hash;hash = hash->next)
        {
-               VectorSubtract(v, m, temp);
-               if (DotProduct(temp, temp) < 0.1)
-                       return j;
+               m = mesh->verts + (hash - mesh->vertexhashentries) * 4;
+               if (m[0] == v[0] && m[1] == v[1] &&  m[2] == v[2])
+                       return hash - mesh->vertexhashentries;
        }
-       mesh->numverts++;
+       hash = mesh->vertexhashentries + mesh->numverts;
+       hash->next = mesh->vertexhashtable[hashindex];
+       mesh->vertexhashtable[hashindex] = hash;
+       m = mesh->verts + (hash - mesh->vertexhashentries) * 4;
        VectorCopy(v, m);
-       return j;
+       mesh->numverts++;
+       return mesh->numverts - 1;
 }
 
 void Mod_ShadowMesh_AddTriangle(mempool_t *mempool, shadowmesh_t *mesh, float *vert0, float *vert1, float *vert2)
@@ -658,6 +646,7 @@ shadowmesh_t *Mod_ShadowMesh_Finish(mempool_t *mempool, shadowmesh_t *firstmesh)
                        //Con_Printf("mesh\n");
                        //for (i = 0;i < newmesh->numtriangles;i++)
                        //      Con_Printf("tri %d %d %d\n", newmesh->elements[i * 3 + 0], newmesh->elements[i * 3 + 1], newmesh->elements[i * 3 + 2]);
+                       Mod_ValidateElements(newmesh->elements, newmesh->numtriangles, newmesh->numverts, __FILE__, __LINE__);
                        Mod_BuildTriangleNeighbors(newmesh->neighbors, newmesh->elements, newmesh->numtriangles);
                }
                Mem_Free(mesh);
@@ -665,7 +654,10 @@ shadowmesh_t *Mod_ShadowMesh_Finish(mempool_t *mempool, shadowmesh_t *firstmesh)
 #else
        shadowmesh_t *mesh;
        for (mesh = firstmesh;mesh;mesh = mesh->next)
+       {
+               Mod_ValidateElements(mesh->elements, mesh->numtriangles, mesh->numverts, __FILE__, __LINE__);
                Mod_BuildTriangleNeighbors(mesh->neighbors, mesh->elements, mesh->numtriangles);
+       }
 #endif
        return firstmesh;
 }
@@ -723,11 +715,6 @@ void Mod_ShadowMesh_Free(shadowmesh_t *mesh)
        for (;mesh;mesh = nextmesh)
        {
                nextmesh = mesh->next;
-#if ALLOCMESHINPIECES
-               Mem_Free(mesh->verts);
-               Mem_Free(mesh->elements);
-               Mem_Free(mesh->neighbors);
-#endif
                Mem_Free(mesh);
        }
 }
index cebb49d..83d981f 100644 (file)
@@ -60,6 +60,13 @@ skinframe_t;
 
 #define MAX_SKINS 256
 
+#define SHADOWMESHVERTEXHASH 1024
+typedef struct shadowmeshvertexhash_s
+{
+       struct shadowmeshvertexhash_s *next;
+}
+shadowmeshvertexhash_t;
+
 typedef struct shadowmesh_s
 {
        struct shadowmesh_s *next;
@@ -68,6 +75,9 @@ typedef struct shadowmesh_s
        float *verts;
        int *elements;
        int *neighbors;
+       // these are NULL after Mod_ShadowMesh_Finish is performed, only used
+       // while building meshes
+       shadowmeshvertexhash_t **vertexhashtable, *vertexhashentries;
 }
 shadowmesh_t;
 
index 54ce758..449e2a4 100644 (file)
@@ -33,12 +33,12 @@ rtexture_t *r_shadow_blankwhitetexture;
 cvar_t r_shadow_lightattenuationscale = {0, "r_shadow_lightattenuationscale", "2"};
 cvar_t r_shadow_lightintensityscale = {0, "r_shadow_lightintensityscale", "1"};
 cvar_t r_shadow_realtime = {0, "r_shadow_realtime", "0"};
-cvar_t r_shadow_erasebydrawing = {0, "r_shadow_erasebydrawing", "0"};
 cvar_t r_shadow_texture3d = {0, "r_shadow_texture3d", "0"};
 cvar_t r_shadow_gloss = {0, "r_shadow_gloss", "1"};
 cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1"};
 cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1"};
 cvar_t r_shadow_bumpscale = {0, "r_shadow_bumpscale", "4"};
+cvar_t r_shadow_shadownudge = {0, "r_shadow_shadownudge", "1"};
 
 void R_Shadow_ClearWorldLights(void);
 void R_Shadow_SaveWorldLights(void);
@@ -97,33 +97,25 @@ void R_Shadow_Init(void)
        Cvar_RegisterVariable(&r_shadow_texture3d);
        Cvar_RegisterVariable(&r_shadow_gloss);
        Cvar_RegisterVariable(&r_shadow_debuglight);
-       Cvar_RegisterVariable(&r_shadow_erasebydrawing);
        Cvar_RegisterVariable(&r_shadow_scissor);
        Cvar_RegisterVariable(&r_shadow_bumpscale);
+       Cvar_RegisterVariable(&r_shadow_shadownudge);
        R_Shadow_EditLights_Init();
        R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap);
 }
 
-void R_Shadow_ProjectVertices(const float *in, float *out, int numverts, const float *relativelightorigin, float projectdistance)
+void R_Shadow_ProjectVertices(float *verts, int numverts, const float *relativelightorigin, float projectdistance)
 {
        int i;
+       float *in, *out, diff[4];
+       in = verts;
+       out = verts + numverts * 4;
        for (i = 0;i < numverts;i++, in += 4, out += 4)
        {
-#if 1
-               out[0] = in[0] + 1000000.0f * (in[0] - relativelightorigin[0]);
-               out[1] = in[1] + 1000000.0f * (in[1] - relativelightorigin[1]);
-               out[2] = in[2] + 1000000.0f * (in[2] - relativelightorigin[2]);
-#elif 0
-               VectorSubtract(in, relativelightorigin, temp);
-               f = lightradius / sqrt(DotProduct(temp,temp));
-               if (f < 1)
-                       f = 1;
-               VectorMA(relativelightorigin, f, temp, out);
-#else
-               VectorSubtract(in, relativelightorigin, temp);
-               f = projectdistance / sqrt(DotProduct(temp,temp));
-               VectorMA(in, f, temp, out);
-#endif
+               VectorSubtract(in, relativelightorigin, diff);
+               VectorNormalizeFast(diff);
+               VectorMA(in, projectdistance, diff, out);
+               VectorMA(in, r_shadow_shadownudge.value, diff, in);
        }
 }
 
@@ -304,13 +296,13 @@ void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, v
        if (maxshadowelements < numtris * 24)
                R_Shadow_ResizeShadowElements(numtris);
 
+       // check which triangles are facing the light
+       R_Shadow_MakeTriangleShadowFlags(elements, varray_vertex, numtris, trianglefacinglight, relativelightorigin, lightradius);
+
        // generate projected vertices
        // by clever use of elements we'll construct the whole shadow from
        // the unprojected vertices and these projected vertices
-       R_Shadow_ProjectVertices(varray_vertex, varray_vertex + numverts * 4, numverts, relativelightorigin, projectdistance);
-
-       // check which triangles are facing the light
-       R_Shadow_MakeTriangleShadowFlags(elements, varray_vertex, numtris, trianglefacinglight, relativelightorigin, lightradius);
+       R_Shadow_ProjectVertices(varray_vertex, numverts, relativelightorigin, projectdistance);
 
        // output triangle elements
        tris = R_Shadow_BuildShadowVolumeTriangles(elements, neighbors, numtris, numverts, trianglefacinglight, shadowelements);
@@ -541,12 +533,11 @@ void R_Shadow_Stage_ShadowVolumes(void)
        qglDepthFunc(GL_LESS);
        qglEnable(GL_STENCIL_TEST);
        qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-       qglStencilFunc(GL_ALWAYS, 0, 0xFF);
+       qglStencilFunc(GL_ALWAYS, 128, 0xFF);
        qglEnable(GL_CULL_FACE);
        qglEnable(GL_DEPTH_TEST);
        r_shadowstage = SHADOWSTAGE_STENCIL;
-       if (!r_shadow_erasebydrawing.integer)
-               qglClear(GL_STENCIL_BUFFER_BIT);
+       qglClear(GL_STENCIL_BUFFER_BIT);
 }
 
 void R_Shadow_Stage_Light(void)
@@ -565,37 +556,13 @@ void R_Shadow_Stage_Light(void)
        qglEnable(GL_STENCIL_TEST);
        qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
        // only draw light where this geometry was already rendered AND the
-       // stencil is 0 (non-zero means shadow)
-       qglStencilFunc(GL_EQUAL, 0, 0xFF);
+       // stencil is 128 (values other than this mean shadow)
+       qglStencilFunc(GL_EQUAL, 128, 0xFF);
        qglEnable(GL_CULL_FACE);
        qglEnable(GL_DEPTH_TEST);
        r_shadowstage = SHADOWSTAGE_LIGHT;
 }
 
-int R_Shadow_Stage_EraseShadowVolumes(void)
-{
-       if (r_shadow_erasebydrawing.integer)
-       {
-               rmeshstate_t m;
-               memset(&m, 0, sizeof(m));
-               R_Mesh_TextureState(&m);
-               GL_Color(1, 1, 1, 1);
-               qglColorMask(0, 0, 0, 0);
-               qglDisable(GL_BLEND);
-               qglDepthMask(0);
-               qglDepthFunc(GL_LESS);
-               qglEnable(GL_STENCIL_TEST);
-               qglStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
-               qglStencilFunc(GL_ALWAYS, 0, 0xFF);
-               qglDisable(GL_CULL_FACE);
-               qglDisable(GL_DEPTH_TEST);
-               r_shadowstage = SHADOWSTAGE_ERASESTENCIL;
-               return true;
-       }
-       else
-               return false;
-}
-
 void R_Shadow_Stage_End(void)
 {
        rmeshstate_t m;
@@ -610,7 +577,7 @@ void R_Shadow_Stage_End(void)
        qglDepthFunc(GL_LEQUAL);
        qglDisable(GL_STENCIL_TEST);
        qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-       qglStencilFunc(GL_ALWAYS, 0, 0xFF);
+       qglStencilFunc(GL_ALWAYS, 128, 0xFF);
        qglEnable(GL_CULL_FACE);
        qglEnable(GL_DEPTH_TEST);
        // force mesh state to reset by using various combinations of features
@@ -1076,22 +1043,10 @@ void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elemen
        }
 }
 
-#define PRECOMPUTEDSHADOWVOLUMES 1
 void R_Shadow_DrawWorldLightShadowVolume(matrix4x4_t *matrix, worldlight_t *light)
 {
-#if PRECOMPUTEDSHADOWVOLUMES
        R_Mesh_Matrix(matrix);
        R_Shadow_RenderShadowMeshVolume(light->shadowvolume);
-#else
-       shadowmesh_t *mesh;
-       R_Mesh_Matrix(matrix);
-       for (mesh = light->shadowvolume;mesh;mesh = mesh->next)
-       {
-               R_Mesh_ResizeCheck(mesh->numverts * 2);
-               memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-               R_Shadow_Volume(mesh->numverts, mesh->numtriangles, varray_vertex, mesh->elements, mesh->neighbors, light->origin, light->lightradius, light->lightradius);
-       }
-#endif
 }
 
 cvar_t r_editlights = {0, "r_editlights", "0"};
@@ -1106,13 +1061,15 @@ vec3_t r_editlights_cursorlocation;
 static int castshadowcount = 1;
 void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style, const char *cubemapname)
 {
-       int i, j, k, l, maxverts, *mark;
-       float *verts, *v, *v0, *v1, f, projectdistance, temp[3], temp2[3], temp3[3], radius2;
+       int i, j, k, l, maxverts, *mark, tris;
+       float *verts, *v, f, temp[3], radius2;
+       //float projectdistance, *v0, *v1, temp2[3], temp3[3];
        worldlight_t *e;
-       shadowmesh_t *mesh;
+       shadowmesh_t *mesh, *castmesh;
        mleaf_t *leaf;
        msurface_t *surf;
        qbyte *pvs;
+       surfmesh_t *surfmesh;
 
        e = Mem_Alloc(r_shadow_mempool, sizeof(worldlight_t));
        VectorCopy(origin, e->origin);
@@ -1160,8 +1117,10 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style
                                                                f = -f;
                                                        if (f > 0 && f < e->lightradius)
                                                        {
-                                                               VectorSubtract(e->origin, surf->poly_center, temp);
-                                                               if (DotProduct(temp, temp) - surf->poly_radius2 < e->lightradius * e->lightradius)
+                                                               temp[0] = bound(surf->poly_mins[0], e->origin[0], surf->poly_maxs[0]) - e->origin[0];
+                                                               temp[1] = bound(surf->poly_mins[1], e->origin[1], surf->poly_maxs[1]) - e->origin[1];
+                                                               temp[2] = bound(surf->poly_mins[2], e->origin[2], surf->poly_maxs[2]) - e->origin[2];
+                                                               if (DotProduct(temp, temp) < e->lightradius * e->lightradius)
                                                                        surf->castshadow = castshadowcount;
                                                        }
                                                }
@@ -1236,17 +1195,6 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style
                        }
                }
                e->shadowvolume = Mod_ShadowMesh_Begin(r_shadow_mempool, 32768);
-#if !PRECOMPUTEDSHADOWVOLUMES
-               // make a mesh to cast a shadow volume from
-               for (j = 0;j < e->numsurfaces;j++)
-                       if (e->surfaces[j]->castshadow == castshadowcount)
-                               Mod_ShadowMesh_AddPolygon(r_shadow_mempool, e->shadowvolume, e->surfaces[j]->poly_numverts, e->surfaces[j]->poly_verts);
-#else
-#if 1
-               {
-               int tris;
-               shadowmesh_t *castmesh, *mesh;
-               surfmesh_t *surfmesh;
                // make a mesh to cast a shadow volume from
                castmesh = Mod_ShadowMesh_Begin(r_shadow_mempool, 32768);
                for (j = 0;j < e->numsurfaces;j++)
@@ -1273,7 +1221,7 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style
 
                        // now that we have the buffers big enough, construct shadow volume mesh
                        memcpy(verts, castmesh->verts, castmesh->numverts * sizeof(float[4]));
-                       R_Shadow_ProjectVertices(verts, verts + castmesh->numverts * 4, castmesh->numverts, e->origin, e->lightradius);
+                       R_Shadow_ProjectVertices(verts, castmesh->numverts, e->origin, 1000000.0f);//, e->lightradius);
                        R_Shadow_MakeTriangleShadowFlags(castmesh->elements, verts, castmesh->numtriangles, trianglefacinglight, e->origin, e->lightradius);
                        tris = R_Shadow_BuildShadowVolumeTriangles(castmesh->elements, castmesh->neighbors, castmesh->numtriangles, castmesh->numverts, trianglefacinglight, shadowelements);
                        // add the constructed shadow volume mesh
@@ -1281,72 +1229,6 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style
                }
                // we're done with castmesh now
                Mod_ShadowMesh_Free(castmesh);
-               }
-#else
-               // make a shadow volume mesh
-               if (verts == NULL && maxverts > 0)
-                       verts = Mem_Alloc(r_shadow_mempool, maxverts * sizeof(float[4]));
-               for (j = 0;j < e->numsurfaces;j++)
-               {
-                       surf = e->surfaces[j];
-                       if (surf->castshadow != castshadowcount)
-                               continue;
-                       projectdistance = 1000000.0f;//e->lightradius;
-                       // copy the original polygon, for the front cap of the volume
-                       for (k = 0, v0 = surf->poly_verts, v1 = verts;k < surf->poly_numverts;k++, v0 += 3, v1 += 3)
-                               VectorCopy(v0, v1);
-                       Mod_ShadowMesh_AddPolygon(r_shadow_mempool, e->shadowvolume, surf->poly_numverts, verts);
-                       // project the original polygon, reversed, for the back cap of the volume
-                       for (k = 0, v0 = surf->poly_verts + (surf->poly_numverts - 1) * 3, v1 = verts;k < surf->poly_numverts;k++, v0 -= 3, v1 += 3)
-                       {
-                               VectorSubtract(v0, e->origin, temp);
-                               //VectorNormalize(temp);
-                               VectorMA(v0, projectdistance, temp, v1);
-                       }
-                       Mod_ShadowMesh_AddPolygon(r_shadow_mempool, e->shadowvolume, surf->poly_numverts, verts);
-                       // project the shadow volume sides
-                       for (l = surf->poly_numverts - 1, k = 0, v0 = surf->poly_verts + (surf->poly_numverts - 1) * 3, v1 = surf->poly_verts;k < surf->poly_numverts;l = k, k++, v0 = v1, v1 += 3)
-                       {
-                               if (surf->neighborsurfaces == NULL || surf->neighborsurfaces[l] == NULL || surf->neighborsurfaces[l]->castshadow != castshadowcount)
-                               {
-                                       VectorCopy(v1, &verts[0]);
-                                       VectorCopy(v0, &verts[3]);
-                                       VectorCopy(v0, &verts[6]);
-                                       VectorCopy(v1, &verts[9]);
-                                       VectorSubtract(&verts[6], e->origin, temp);
-                                       //VectorNormalize(temp);
-                                       VectorMA(&verts[6], projectdistance, temp, &verts[6]);
-                                       VectorSubtract(&verts[9], e->origin, temp);
-                                       //VectorNormalize(temp);
-                                       VectorMA(&verts[9], projectdistance, temp, &verts[9]);
-
-#if 0
-                                       VectorSubtract(&verts[0], &verts[3], temp);
-                                       VectorSubtract(&verts[6], &verts[3], temp2);
-                                       CrossProduct(temp, temp2, temp3);
-                                       VectorNormalize(temp3);
-                                       if (DotProduct(surf->poly_center, temp3) > DotProduct(&verts[0], temp3))
-                                       {
-                                               VectorCopy(v0, &verts[0]);
-                                               VectorCopy(v1, &verts[3]);
-                                               VectorCopy(v1, &verts[6]);
-                                               VectorCopy(v0, &verts[9]);
-                                               VectorSubtract(&verts[6], e->origin, temp);
-                                               //VectorNormalize(temp);
-                                               VectorMA(&verts[6], projectdistance, temp, &verts[6]);
-                                               VectorSubtract(&verts[9], e->origin, temp);
-                                               //VectorNormalize(temp);
-                                               VectorMA(&verts[9], projectdistance, temp, &verts[9]);
-                                               Con_Printf("flipped shadow volume edge %8p %i\n", surf, l);
-                                       }
-#endif
-
-                                       Mod_ShadowMesh_AddPolygon(r_shadow_mempool, e->shadowvolume, 4, verts);
-                               }
-                       }
-               }
-#endif
-#endif
                e->shadowvolume = Mod_ShadowMesh_Finish(r_shadow_mempool, e->shadowvolume);
                for (l = 0, mesh = e->shadowvolume;mesh;mesh = mesh->next)
                        l += mesh->numtriangles;
@@ -1399,7 +1281,7 @@ void R_Shadow_FreeSelectedWorldLight(void)
 
 void R_Shadow_SelectLightInView(void)
 {
-       float bestrating, rating, temp[3], dist;
+       float bestrating, temp[3], dist;
        worldlight_t *best, *light;
        best = NULL;
        bestrating = 1e30;
@@ -1498,7 +1380,7 @@ void R_Shadow_SaveWorldLights(void)
 void R_Shadow_LoadLightsFile(void)
 {
        int n, a, style;
-       char name[MAX_QPATH], cubemapname[MAX_QPATH], *lightsstring, *s, *t;
+       char name[MAX_QPATH], *lightsstring, *s, *t;
        float origin[3], radius, color[3], subtract, spotdir[3], spotcone, falloff, distbias;
        COM_StripExtension(cl.worldmodel->name, name);
        strcat(name, ".lights");
index 9b11935..40eb5ab 100644 (file)
@@ -20,9 +20,6 @@ void R_Shadow_RenderShadowMeshVolume(shadowmesh_t *mesh);
 void R_Shadow_Stage_Begin(void);
 void R_Shadow_Stage_ShadowVolumes(void);
 void R_Shadow_Stage_Light(void);
-// returns true if shadow volumes should be drawn again to erase,
-// otherwise clears stencil
-int R_Shadow_Stage_EraseShadowVolumes(void);
 void R_Shadow_Stage_End(void);
 int R_Shadow_ScissorForBBoxAndSphere(const float *mins, const float *maxs, const float *origin, float radius);