optimized trianglefacing calculation, per Vic's recommendation (yes it's all one...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 30 Sep 2002 18:01:08 +0000 (18:01 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 30 Sep 2002 18:01:08 +0000 (18:01 +0000)
shadow functions now take a vertex array pointer, to make them more broadly useful (in precomputation perhaps?)
beginning work on a precomputed shadow volumes system for static lights

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

gl_models.c
gl_rsurf.c
model_brush.c
model_brush.h
r_shadow.c
r_shadow.h

index 4d5a876..4cc5f9f 100644 (file)
@@ -513,11 +513,11 @@ void R_DrawQ1Q2AliasModelFakeShadow (entity_render_t *ent)
                                        R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
                                        Matrix4x4_Transform(&ent->inversematrix, sl->origin, temp);
                                        GL_Color(0.1 * r_colorscale, 0.025 * r_colorscale, 0.0125 * r_colorscale, 1);
-                                       R_Shadow_Volume(model->numverts, model->numtris, model->mdlmd2data_indices, model->mdlmd2data_triangleneighbors, temp, sl->cullradius + model->radius - sqrt(f), true);
+                                       R_Shadow_Volume(model->numverts, model->numtris, varray_vertex, model->mdlmd2data_indices, model->mdlmd2data_triangleneighbors, temp, sl->cullradius + model->radius - sqrt(f), true);
                                        GL_UseColorArray();
                                        lightscale = d_lightstylevalue[sl->style] * (1.0f / 65536.0f);
                                        VectorScale(sl->light, lightscale, lightcolor);
-                                       R_Shadow_VertexLight(model->numverts, aliasvertnorm, temp, sl->cullradius2, sl->distbias, sl->subtract, lightcolor);
+                                       R_Shadow_VertexLight(model->numverts, varray_vertex, aliasvertnorm, temp, sl->cullradius2, sl->distbias, sl->subtract, lightcolor);
                                        R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
                                }
                        }
@@ -535,9 +535,9 @@ void R_DrawQ1Q2AliasModelFakeShadow (entity_render_t *ent)
                                        R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
                                        Matrix4x4_Transform(&ent->inversematrix, rd->origin, temp);
                                        GL_Color(0.1 * r_colorscale, 0.025 * r_colorscale, 0.0125 * r_colorscale, 1);
-                                       R_Shadow_Volume(model->numverts, model->numtris, model->mdlmd2data_indices, model->mdlmd2data_triangleneighbors, temp, rd->cullradius + model->radius - sqrt(f), true);
+                                       R_Shadow_Volume(model->numverts, model->numtris, varray_vertex, model->mdlmd2data_indices, model->mdlmd2data_triangleneighbors, temp, rd->cullradius + model->radius - sqrt(f), true);
                                        GL_UseColorArray();
-                                       R_Shadow_VertexLight(model->numverts, aliasvertnorm, temp, rd->cullradius2, LIGHTOFFSET, rd->subtract, rd->light);
+                                       R_Shadow_VertexLight(model->numverts, varray_vertex, aliasvertnorm, temp, rd->cullradius2, LIGHTOFFSET, rd->subtract, rd->light);
                                        R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
                                }
                        }
index 9448717..37e048c 100644 (file)
@@ -1856,7 +1856,7 @@ void R_DrawBrushModelShadowVolumes (entity_render_t *ent, vec3_t relativelightor
                                        {
                                                R_Mesh_ResizeCheck(mesh->numverts * 2);
                                                memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-                                               R_Shadow_Volume(mesh->numverts, mesh->numtriangles, mesh->index, mesh->triangleneighbors, relativelightorigin, projectdistance, visiblevolume);
+                                               R_Shadow_Volume(mesh->numverts, mesh->numtriangles, varray_vertex, mesh->index, mesh->triangleneighbors, relativelightorigin, projectdistance, visiblevolume);
                                        }
                                }
                        }
index 51fc0c7..28347fc 100644 (file)
@@ -710,6 +710,13 @@ void Mod_ProcessLightList(void)
                                        e->surfaces[e->numsurfaces++] = loadmodel->surfaces + loadmodel->firstmodelsurface + j;
                }
        }
+       // construct shadow volumes for each light
+       /*
+       for (i = 0, e = loadmodel->lights;i < loadmodel->numlights;i++, e++)
+       {
+               FIXME FINISH THIS CODE!
+       }
+       */
 }
 
 
index f109b1d..8424b53 100644 (file)
@@ -301,6 +301,15 @@ typedef struct mportal_s
 }
 mportal_t;
 
+typedef struct mlightshadowvolumemesh_s
+{
+       struct mlightshadowvolumemesh_s *next;
+       int numverts;
+       int numtris;
+       float *vertex;
+}
+mlightshadowvolumemesh_t;
+
 typedef struct mlight_s
 {
        // location of light
@@ -325,6 +334,8 @@ typedef struct mlight_s
        // surfaces this shines on
        int numsurfaces;
        msurface_t **surfaces;
+       // precomputed shadow volume meshs
+       mlightshadowvolumemesh_t *shadowvolumemeshs;
        // used only for loading calculations, number of leafs this shines on
        //int numleafs;
 }
index c33d04f..aebace1 100644 (file)
@@ -36,10 +36,10 @@ void R_Shadow_Init(void)
        R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap);
 }
 
-void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, vec3_t relativelightorigin, float projectdistance, int visiblevolume)
+void R_Shadow_Volume(int numverts, int numtris, float *vertex, int *elements, int *neighbors, vec3_t relativelightorigin, float projectdistance, int visiblevolume)
 {
        int i, *e, *n, *out, tris;
-       float *v0, *v1, *v2, dir0[3], dir1[3], temp[3], f;
+       float *v0, *v1, *v2, temp[3], f;
 // terminology:
 //
 // frontface:
@@ -57,8 +57,8 @@ void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, v
 // description:
 // draws the shadow volumes of the model.
 // requirements:
-// vertex loations must already be in varray_vertex before use.
-// varray_vertex must have capacity for numverts * 2.
+// vertex loations must already be in vertex before use.
+// vertex must have capacity for numverts * 2.
 
        // make sure trianglefacinglight is big enough for this volume
        if (maxtrianglefacinglight < numtris)
@@ -81,7 +81,7 @@ void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, v
        // make projected vertices
        // by clever use of elements we'll construct the whole shadow from
        // the unprojected vertices and these projected vertices
-       for (i = 0, v0 = varray_vertex, v1 = varray_vertex + numverts * 4;i < numverts;i++, v0 += 4, v1 += 4)
+       for (i = 0, v0 = vertex, v1 = vertex + numverts * 4;i < numverts;i++, v0 += 4, v1 += 4)
        {
                VectorSubtract(v0, relativelightorigin, temp);
                f = projectdistance / sqrt(DotProduct(temp,temp));
@@ -91,17 +91,50 @@ void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, v
        // check which triangles are facing the light
        for (i = 0, e = elements;i < numtris;i++, e += 3)
        {
-               // calculate surface plane
-               v0 = varray_vertex + e[0] * 4;
-               v1 = varray_vertex + e[1] * 4;
-               v2 = varray_vertex + e[2] * 4;
+               // calculate triangle facing flag
+               v0 = vertex + e[0] * 4;
+               v1 = vertex + e[1] * 4;
+               v2 = vertex + e[2] * 4;
+               // we do not need to normalize the surface normal because both sides
+               // of the comparison use it, therefore they are both multiplied the
+               // same amount...  furthermore the subtract can be done on the
+               // vectors, saving a little bit of math in the dotproducts
+#if 1
+               // fast version
+               // subtracts v1 from v0 and v2, combined into a crossproduct,
+               // combined with a dotproduct of the light location relative to the
+               // first point of the triangle (any point works, since the triangle
+               // is obviously flat), and finally a comparison to determine if the
+               // light is infront of the triangle (the goal of this statement)
+               trianglefacinglight[i] =
+                  (relativelightorigin[0] - v0[0]) * ((v0[1] - v1[1]) * (v2[2] - v1[2]) - (v0[2] - v1[2]) * (v2[1] - v1[1]))
+                + (relativelightorigin[1] - v0[1]) * ((v0[2] - v1[2]) * (v2[0] - v1[0]) - (v0[0] - v1[0]) * (v2[2] - v1[2]))
+                + (relativelightorigin[2] - v0[2]) * ((v0[0] - v1[0]) * (v2[1] - v1[1]) - (v0[1] - v1[1]) * (v2[0] - v1[0])) > 0;
+#else
+               // readable version
+               {
+               float dir0[3], dir1[3],
+
+               // calculate two mostly perpendicular edge directions
                VectorSubtract(v0, v1, dir0);
                VectorSubtract(v2, v1, dir1);
+
+               // we have two edge directions, we can calculate a third vector from
+               // them, which is the direction of the surface normal (it's magnitude
+               // is not 1 however)
                CrossProduct(dir0, dir1, temp);
-               // we do not need to normalize the surface normal because both sides
-               // of the comparison use it, therefore they are both multiplied the
-               // same amount...
+
+               // this is entirely unnecessary, but kept for clarity
+               //VectorNormalize(temp);
+
+               // compare distance of light along normal, with distance of any point
+               // of the triangle along the same normal (the triangle is planar,
+               // I.E. flat, so all points give the same answer)
+               // the normal is not normalized because it is used on both sides of
+               // the comparison, so it's magnitude does not matter
                trianglefacinglight[i] = DotProduct(relativelightorigin, temp) >= DotProduct(v0, temp);
+               }
+#endif
        }
 
        // output triangle elements
@@ -189,12 +222,12 @@ void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, v
        }
 }
 
-void R_Shadow_VertexLight(int numverts, float *normals, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor)
+void R_Shadow_VertexLight(int numverts, float *vertex, float *normals, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor)
 {
        int i;
        float *n, *v, *c, f, dist, temp[3];
        // calculate vertex colors
-       for (i = 0, v = varray_vertex, c = varray_color, n = normals;i < numverts;i++, v += 4, c += 4, n += 3)
+       for (i = 0, v = vertex, c = varray_color, n = normals;i < numverts;i++, v += 4, c += 4, n += 3)
        {
                VectorSubtract(relativelightorigin, v, temp);
                c[0] = 0;
index 470d96d..cef3d81 100644 (file)
@@ -3,8 +3,8 @@
 #define R_SHADOW_H
 
 void R_Shadow_Init(void);
-void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, vec3_t relativelightorigin, float projectdistance, int visiblevolume);
-void R_Shadow_VertexLight(int numverts, float *normals, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
+void R_Shadow_Volume(int numverts, int numtris, float *vertex, int *elements, int *neighbors, vec3_t relativelightorigin, float projectdistance, int visiblevolume);
+void R_Shadow_VertexLight(int numverts, float *vertex, float *normals, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
 void R_Shadow_RenderLightThroughStencil(int numverts, int numtris, int *elements, vec3_t relativelightorigin, float *normals);
 void R_Shadow_ClearStencil(void);