]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_shadow.c
-Added static, global baseDC and baseRC variables to avoid having to call
[xonotic/darkplaces.git] / r_shadow.c
index 79023e78e7e667ad448ab4db76fa156503be5ead..12da8519697f9a36a7c57870b689fbd4ea6e45a9 100644 (file)
@@ -503,8 +503,9 @@ void R_Shadow_PrepareShadowMark(int numtris)
 int R_Shadow_ConstructShadowVolume(int innumvertices, int innumtris, const int *inelement3i, const int *inneighbor3i, const float *invertex3f, int *outnumvertices, int *outelement3i, float *outvertex3f, const float *projectorigin, float projectdistance, int numshadowmarktris, const int *shadowmarktris)
 {
        int i, j, tris = 0, vr[3], t, outvertices = 0;
-       const int *e, *n;
        float f, temp[3];
+       const int *e, *n;
+       const float *v;
 
        if (maxvertexupdate < innumvertices)
        {
@@ -525,10 +526,12 @@ int R_Shadow_ConstructShadowVolume(int innumvertices, int innumtris, const int *
                memset(vertexremap, 0, maxvertexupdate * sizeof(int));
        }
        
+       for (i = 0;i < numshadowmarktris;i++)
+               shadowmark[shadowmarktris[i]] = shadowmarkcount;
+
        for (i = 0;i < numshadowmarktris;i++)
        {
                t = shadowmarktris[i];
-               shadowmark[t] = shadowmarkcount;
                e = inelement3i + t * 3;
                // make sure the vertices are created
                for (j = 0;j < 3;j++)
@@ -537,14 +540,24 @@ int R_Shadow_ConstructShadowVolume(int innumvertices, int innumtris, const int *
                        {
                                vertexupdate[e[j]] = vertexupdatenum;
                                vertexremap[e[j]] = outvertices;
-                               VectorSubtract(invertex3f + e[j] * 3, projectorigin, temp);
+                               v = invertex3f + e[j] * 3;
+                               // project one copy of the vertex to the sphere radius of the light
+                               // (FIXME: would projecting it to the light box be better?)
+                               VectorSubtract(v, projectorigin, temp);
                                f = projectdistance / VectorLength(temp);
-                               VectorCopy(invertex3f + e[j] * 3, outvertex3f);
+                               VectorCopy(v, outvertex3f);
                                VectorMA(projectorigin, f, temp, (outvertex3f + 3));
                                outvertex3f += 6;
                                outvertices += 2;
                        }
                }
+       }
+
+       for (i = 0;i < numshadowmarktris;i++)
+       {
+               t = shadowmarktris[i];
+               e = inelement3i + t * 3;
+               n = inneighbor3i + t * 3;
                // output the front and back triangles
                outelement3i[0] = vertexremap[e[0]];
                outelement3i[1] = vertexremap[e[1]];
@@ -554,13 +567,6 @@ int R_Shadow_ConstructShadowVolume(int innumvertices, int innumtris, const int *
                outelement3i[5] = vertexremap[e[0]] + 1;
                outelement3i += 6;
                tris += 2;
-       }
-
-       for (i = 0;i < numshadowmarktris;i++)
-       {
-               t = shadowmarktris[i];
-               e = inelement3i + t * 3;
-               n = inneighbor3i + t * 3;
                // output the sides (facing outward from this triangle)
                if (shadowmark[n[0]] != shadowmarkcount)
                {
@@ -624,39 +630,41 @@ void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f,
        R_Shadow_RenderVolume(outverts, tris, varray_vertex3f2, shadowelements);
 }
 
-void R_Shadow_VolumeFromBox(int numverts, int numtris, const float *invertex3f, const int *elements, const int *neighbors, const vec3_t projectorigin, float projectdistance, const vec3_t mins, const vec3_t maxs)
+void R_Shadow_MarkVolumeFromBox(int firsttriangle, int numtris, const float *invertex3f, const int *elements, const vec3_t projectorigin, vec3_t lightmins, vec3_t lightmaxs, vec3_t surfacemins, vec3_t surfacemaxs)
 {
-       int i;
+       int t, tend;
+       const int *e;
        const float *v[3];
-
-       // check which triangles are facing the , and then output
-       // triangle elements and vertices...  by clever use of elements we
-       // can construct the whole shadow from the unprojected vertices and
-       // the projected vertices
-
-       // identify lit faces within the bounding box
-       R_Shadow_PrepareShadowMark(numtris);
-       for (i = 0;i < numtris;i++)
+       if (!BoxesOverlap(lightmins, lightmaxs, surfacemins, surfacemaxs))
+               return;
+       tend = firsttriangle + numtris;
+       if (surfacemins[0] >= lightmins[0] && surfacemaxs[0] <= lightmaxs[0]
+        && surfacemins[1] >= lightmins[1] && surfacemaxs[1] <= lightmaxs[1]
+        && surfacemins[2] >= lightmins[2] && surfacemaxs[2] <= lightmaxs[2])
        {
-               v[0] = invertex3f + elements[i*3+0] * 3;
-               v[1] = invertex3f + elements[i*3+1] * 3;
-               v[2] = invertex3f + elements[i*3+2] * 3;
-               if (PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2]) && maxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && mins[0] < max(v[0][0], max(v[1][0], v[2][0])) && maxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && mins[1] < max(v[0][1], max(v[1][1], v[2][1])) && maxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && mins[2] < max(v[0][2], max(v[1][2], v[2][2])))
-                       shadowmarklist[numshadowmark++] = i;
+               // surface box entirely inside light box, no box cull
+               for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
+                       if (PointInfrontOfTriangle(projectorigin, invertex3f + e[0] * 3, invertex3f + e[1] * 3, invertex3f + e[2] * 3))
+                               shadowmarklist[numshadowmark++] = t;
+       }
+       else
+       {
+               // surface box not entirely inside light box, cull each triangle
+               for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
+               {
+                       v[0] = invertex3f + e[0] * 3;
+                       v[1] = invertex3f + e[1] * 3;
+                       v[2] = invertex3f + e[2] * 3;
+                       if (PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
+                        && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0]))
+                        && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0]))
+                        && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1]))
+                        && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1]))
+                        && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2]))
+                        && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
+                               shadowmarklist[numshadowmark++] = t;
+               }
        }
-       R_Shadow_VolumeFromList(numverts, numtris, invertex3f, elements, neighbors, projectorigin, projectdistance, numshadowmark, shadowmarklist);
-}
-
-void R_Shadow_VolumeFromSphere(int numverts, int numtris, const float *invertex3f, const int *elements, const int *neighbors, const vec3_t projectorigin, float projectdistance, float radius)
-{
-       vec3_t mins, maxs;
-       mins[0] = projectorigin[0] - radius;
-       mins[1] = projectorigin[1] - radius;
-       mins[2] = projectorigin[2] - radius;
-       maxs[0] = projectorigin[0] + radius;
-       maxs[1] = projectorigin[1] + radius;
-       maxs[2] = projectorigin[2] + radius;
-       R_Shadow_VolumeFromBox(numverts, numtris, invertex3f, elements, neighbors, projectorigin, projectdistance, mins, maxs);
 }
 
 void R_Shadow_RenderVolume(int numvertices, int numtriangles, const float *vertex3f, const int *element3i)
@@ -2470,8 +2478,8 @@ void R_Shadow_DrawLightSprites(void)
                        lighttextures[i] = pic->tex;
        }
 
-       for (light = r_shadow_worldlightchain;light;light = light->next)
-               R_MeshQueue_AddTransparent(light->origin, R_Shadow_DrawLightSpriteCallback, light, ((int) light) % 5);
+       for (i = 0, light = r_shadow_worldlightchain;light;i++, light = light->next)
+               R_MeshQueue_AddTransparent(light->origin, R_Shadow_DrawLightSpriteCallback, light, i % 5);
        R_MeshQueue_AddTransparent(r_editlights_cursorlocation, R_Shadow_DrawCursorCallback, NULL, 0);
 }
 
@@ -2591,7 +2599,10 @@ void R_Shadow_SaveWorldLights(void)
        buf = NULL;
        for (light = r_shadow_worldlightchain;light;light = light->next)
        {
-               sprintf(line, "%s%f %f %f %f %f %f %f %d %s %f %f %f %f\n", light->shadow ? "" : "!", light->origin[0], light->origin[1], light->origin[2], light->radius / r_editlights_rtlightssizescale.value, light->color[0] / r_editlights_rtlightscolorscale.value, light->color[1] / r_editlights_rtlightscolorscale.value, light->color[2] / r_editlights_rtlightscolorscale.value, light->style, light->cubemapname[0] ? light->cubemapname : "\"\"", light->corona, light->angles[0], light->angles[1], light->angles[2]);
+               if (light->cubemapname[0] || light->corona || light->angles[0] || light->angles[1] || light->angles[2])
+                       sprintf(line, "%s%f %f %f %f %f %f %f %d \"%s\" %f %f %f %f\n", light->shadow ? "" : "!", light->origin[0], light->origin[1], light->origin[2], light->radius / r_editlights_rtlightssizescale.value, light->color[0] / r_editlights_rtlightscolorscale.value, light->color[1] / r_editlights_rtlightscolorscale.value, light->color[2] / r_editlights_rtlightscolorscale.value, light->style, light->cubemapname, light->corona, light->angles[0], light->angles[1], light->angles[2]);
+               else
+                       sprintf(line, "%s%f %f %f %f %f %f %f %d\n", light->shadow ? "" : "!", light->origin[0], light->origin[1], light->origin[2], light->radius / r_editlights_rtlightssizescale.value, light->color[0] / r_editlights_rtlightscolorscale.value, light->color[1] / r_editlights_rtlightscolorscale.value, light->color[2] / r_editlights_rtlightscolorscale.value, light->style);
                if (bufchars + (int) strlen(line) > bufmaxchars)
                {
                        bufmaxchars = bufchars + strlen(line) + 2048;