new experimental shadow volumes, try r_shadows 2 to see the shadow volumes cast by...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 30 Sep 2002 01:57:43 +0000 (01:57 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 30 Sep 2002 01:57:43 +0000 (01:57 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2477 d7cf8633-e32d-0410-b094-e92efae38249

darkplaces.dsp
gl_models.c
gl_rmain.c
makefile
makefile.mingw
r_shadow.c [new file with mode: 0644]

index b79f26a..de49a84 100644 (file)
@@ -332,6 +332,10 @@ SOURCE=.\r_modules.c
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\r_shadow.c\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\r_sky.c\r
 # End Source File\r
 # Begin Source File\r
index 8735761..1731091 100644 (file)
@@ -1,6 +1,7 @@
 
 #include "quakedef.h"
 #include "cl_collision.h"
+#include "r_shadow.h"
 
 cvar_t r_quickmodels = {0, "r_quickmodels", "1"};
 
@@ -471,6 +472,7 @@ void R_DrawQ1Q2AliasModelCallback (const void *calldata1, int calldata2)
        }
 }
 
+extern cvar_t r_shadows;
 void R_DrawQ1Q2AliasModelFakeShadow (entity_render_t *ent)
 {
        int i;
@@ -478,6 +480,34 @@ void R_DrawQ1Q2AliasModelFakeShadow (entity_render_t *ent)
        model_t *model;
        float *v, planenormal[3], planedist, dist, projection[3], floororigin[3], surfnormal[3], lightdirection[3], v2[3];
 
+       if (r_shadows.integer > 1)
+       {
+               float f;
+               vec3_t temp;
+               for (i = 0;i < r_numdlights;i++)
+               {
+                       if (ent != r_dlight[i].ent)
+                       {
+                               VectorSubtract(ent->origin, r_dlight[i].origin, temp);
+                               f = DotProduct(temp,temp);
+                               if (f < (ent->model->radius2 + r_dlight[i].cullradius2))
+                               {
+                                       model = ent->model;
+                                       R_Mesh_ResizeCheck(model->numverts * 2);
+                                       memset(&m, 0, sizeof(m));
+                                       m.blendfunc1 = GL_ONE;
+                                       m.blendfunc2 = GL_ONE;
+                                       R_Mesh_State(&m);
+                                       R_Mesh_Matrix(&ent->matrix);
+                                       R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
+                                       R_FillColors(varray_color, model->numverts * 2, 0.1 * r_colorscale, 0.025 * r_colorscale, 0.0125 * r_colorscale, 1);
+                                       Matrix4x4_Transform(&ent->inversematrix, r_dlight[i].origin, temp);
+                                       R_ShadowVolume(model->numverts, model->numtris, model->mdlmd2data_indices, model->mdlmd2data_triangleneighbors, temp, r_dlight[i].cullradius + model->radius - sqrt(f));
+                               }
+                       }
+               }
+       }
+
        lightdirection[0] = 0.5;
        lightdirection[1] = 0.2;
        lightdirection[2] = -1;
index b989580..1b10e6c 100644 (file)
@@ -282,6 +282,7 @@ extern void R_Textures_Init(void);
 extern void Mod_RenderInit(void);
 extern void GL_Draw_Init(void);
 extern void GL_Main_Init(void);
+extern void R_Shadow_Init(void);
 extern void GL_Models_Init(void);
 extern void R_Sky_Init(void);
 extern void GL_Surf_Init(void);
@@ -301,6 +302,7 @@ void Render_Init(void)
        R_MeshQueue_Init();
        GL_Draw_Init();
        GL_Main_Init();
+       R_Shadow_Init();
        GL_Models_Init();
        R_Sky_Init();
        GL_Surf_Init();
@@ -324,9 +326,6 @@ void GL_Init (void)
 
        // LordHavoc: report supported extensions
        Con_Printf ("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
-
-       qglCullFace(GL_FRONT);
-       qglEnable(GL_TEXTURE_2D);
 }
 
 int R_CullBox(const vec3_t emins, const vec3_t emaxs)
index 8c487a9..2b2b623 100644 (file)
--- a/makefile
+++ b/makefile
@@ -22,7 +22,7 @@ SOUNDLIB=
 #if you want no CD audio
 CD=cd_null.o
 
-CLIENTOBJECTS= cgame.o cgamevm.o chase.o cl_collision.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_particles.o cl_screen.o cl_video.o console.o dpvsimpledecode.o fractalnoise.o gl_backend.o gl_draw.o gl_models.o gl_rmain.o gl_rsurf.o gl_textures.o keys.o menu.o meshqueue.o r_crosshairs.o r_explosion.o r_explosion.o r_lerpanim.o r_light.o r_modules.o r_sky.o r_sprites.o sbar.o ui.o vid_shared.o view.o wavefile.o
+CLIENTOBJECTS= cgame.o cgamevm.o chase.o cl_collision.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_particles.o cl_screen.o cl_video.o console.o dpvsimpledecode.o fractalnoise.o gl_backend.o gl_draw.o gl_models.o gl_rmain.o gl_rsurf.o gl_textures.o keys.o menu.o meshqueue.o r_crosshairs.o r_explosion.o r_explosion.o r_lerpanim.o r_light.o r_modules.o r_sky.o r_sprites.o sbar.o ui.o vid_shared.o view.o wavefile.o r_shadow.c
 SERVEROBJECTS= pr_cmds.o pr_edict.o pr_exec.o sv_light.o sv_main.o sv_move.o sv_phys.o sv_user.o
 SHAREDOBJECTS= builddate.o cmd.o collision.o common.o crc.o cvar.o filematch.o host.o host_cmd.o image.o mathlib.o matrixlib.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_dgrm.o net_loop.o net_main.o net_master.o net_udp.o palette.o portals.o protocol.o quakeio.o sys_linux.o sys_shared.o transform.o world.o wad.o zone.o $(NETOBJECTS) $(SERVEROBJECTS)
 
index ff8344d..b85e788 100644 (file)
@@ -1,5 +1,5 @@
 
-OBJECTS= builddate.o chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cmd.o common.o console.o crc.o cvar.o fractalnoise.o gl_draw.o r_sky.o gl_rmain.o gl_rsurf.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_dgrm.o net_loop.o net_main.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_explosion.o sbar.o snd_dma.o snd_mem.o snd_mix.o sv_main.o sv_move.o sv_phys.o sv_user.o sv_light.o transform.o view.o wad.o world.o zone.o vid_shared.o palette.o r_crosshairs.o gl_textures.o gl_models.o r_sprites.o r_modules.o r_explosion.o r_lerpanim.o protocol.o quakeio.o ui.o portals.o sys_shared.o gl_backend.o cl_particles.o cl_screen.o cgamevm.o cgame.o filematch.o collision.o cl_collision.o matrixlib.o cl_video.o dpvsimpledecode.o wavefile.o meshqueue.o net_master.o
+OBJECTS= builddate.o chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cmd.o common.o console.o crc.o cvar.o fractalnoise.o gl_draw.o r_sky.o gl_rmain.o gl_rsurf.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_dgrm.o net_loop.o net_main.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_explosion.o sbar.o snd_dma.o snd_mem.o snd_mix.o sv_main.o sv_move.o sv_phys.o sv_user.o sv_light.o transform.o view.o wad.o world.o zone.o vid_shared.o palette.o r_crosshairs.o gl_textures.o gl_models.o r_sprites.o r_modules.o r_explosion.o r_lerpanim.o protocol.o quakeio.o ui.o portals.o sys_shared.o gl_backend.o cl_particles.o cl_screen.o cgamevm.o cgame.o filematch.o collision.o cl_collision.o matrixlib.o cl_video.o dpvsimpledecode.o wavefile.o meshqueue.o net_master.o r_shadow.o
 
 #K6/athlon optimizations
 #CPUOPTIMIZATIONS=-march=k6
diff --git a/r_shadow.c b/r_shadow.c
new file mode 100644 (file)
index 0000000..f18b155
--- /dev/null
@@ -0,0 +1,168 @@
+
+#include "quakedef.h"
+
+mempool_t *r_shadow_mempool;
+
+int maxshadowelements;
+int *shadowelements;
+int maxtrianglefacinglight;
+qbyte *trianglefacinglight;
+
+void r_shadow_start(void)
+{
+       // allocate vertex processing arrays
+       r_shadow_mempool = Mem_AllocPool("R_Shadow");
+       maxshadowelements = 0;
+       shadowelements = NULL;
+       maxtrianglefacinglight = 0;
+       trianglefacinglight = NULL;
+}
+
+void r_shadow_shutdown(void)
+{
+       maxshadowelements = 0;
+       shadowelements = NULL;
+       maxtrianglefacinglight = 0;
+       trianglefacinglight = NULL;
+       Mem_FreePool(&r_shadow_mempool);
+}
+
+void r_shadow_newmap(void)
+{
+}
+
+void R_Shadow_Init(void)
+{
+       R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap);
+}
+
+void R_ShadowVolume(int numverts, int numtris, int *elements, int *neighbors, vec3_t relativelightorigin, float projectdistance)
+{
+       int i, *e, *n, *out, tris;
+       float *v0, *v1, *v2, dir0[3], dir1[3], temp[3], f;
+// terminology:
+//
+// frontface:
+// a triangle facing the light source
+//
+// backface:
+// a triangle not facing the light source
+//
+// shadow volume:
+// an extrusion of the backfaces, beginning at the original geometry and
+// ending further from the light source than the original geometry
+// (presumably at least as far as the light's radius, if the light has a
+// radius at all), capped at both front and back to avoid any problems
+//
+// 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.
+
+       // make sure trianglefacinglight is big enough for this volume
+       if (maxtrianglefacinglight < numtris)
+       {
+               maxtrianglefacinglight = numtris;
+               if (trianglefacinglight)
+                       Mem_Free(trianglefacinglight);
+               trianglefacinglight = Mem_Alloc(r_shadow_mempool, maxtrianglefacinglight);
+       }
+
+       // make sure shadowelements is big enough for this volume
+       if (maxshadowelements < numtris * 24)
+       {
+               maxshadowelements = numtris * 24;
+               if (shadowelements)
+                       Mem_Free(shadowelements);
+               shadowelements = Mem_Alloc(r_shadow_mempool, maxshadowelements * sizeof(int));
+       }
+
+       // 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)
+       {
+               VectorSubtract(v0, relativelightorigin, temp);
+               f = projectdistance / sqrt(DotProduct(temp,temp));
+               VectorMA(v0, f, temp, v1);
+       }
+
+       // 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;
+               VectorSubtract(v0, v1, dir0);
+               VectorSubtract(v2, v1, dir1);
+               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...
+               trianglefacinglight[i] = DotProduct(relativelightorigin, temp) >= DotProduct(v0, temp);
+       }
+
+       // output triangle elements
+       out = shadowelements;
+       tris = 0;
+
+       // check each backface for bordering frontfaces,
+       // and cast shadow polygons from those edges,
+       // also create front and back caps for shadow volume
+       for (i = 0, e = elements, n = neighbors;i < numtris;i++, e += 3, n += 3)
+       {
+               if (!trianglefacinglight[i])
+               {
+                       // triangle is backface and therefore casts shadow,
+                       // output front and back caps for shadow volume
+                       // front cap (with flipped winding order)
+                       out[0] = e[0];
+                       out[1] = e[2];
+                       out[2] = e[1];
+                       // rear cap
+                       out[3] = e[0] + numverts;
+                       out[4] = e[1] + numverts;
+                       out[5] = e[2] + numverts;
+                       out += 6;
+                       tris += 2;
+                       // check the edges
+                       if (trianglefacinglight[n[0]])
+                       {
+                               out[0] = e[0];
+                               out[1] = e[1];
+                               out[2] = e[1] + numverts;
+                               out[3] = e[0];
+                               out[4] = e[1] + numverts;
+                               out[5] = e[0] + numverts;
+                               out += 6;
+                               tris += 2;
+                       }
+                       if (trianglefacinglight[n[1]])
+                       {
+                               out[0] = e[1];
+                               out[1] = e[2];
+                               out[2] = e[2] + numverts;
+                               out[3] = e[1];
+                               out[4] = e[2] + numverts;
+                               out[5] = e[1] + numverts;
+                               out += 6;
+                               tris += 2;
+                       }
+                       if (trianglefacinglight[n[2]])
+                       {
+                               out[0] = e[2];
+                               out[1] = e[0];
+                               out[2] = e[0] + numverts;
+                               out[3] = e[2];
+                               out[4] = e[0] + numverts;
+                               out[5] = e[2] + numverts;
+                               out += 6;
+                               tris += 2;
+                       }
+               }
+       }
+       // draw the volume
+       R_Mesh_Draw(numverts * 2, tris, shadowelements);
+}