4 mempool_t *r_shadow_mempool;
8 int maxtrianglefacinglight;
9 qbyte *trianglefacinglight;
11 void r_shadow_start(void)
13 // allocate vertex processing arrays
14 r_shadow_mempool = Mem_AllocPool("R_Shadow");
15 maxshadowelements = 0;
16 shadowelements = NULL;
17 maxtrianglefacinglight = 0;
18 trianglefacinglight = NULL;
21 void r_shadow_shutdown(void)
23 maxshadowelements = 0;
24 shadowelements = NULL;
25 maxtrianglefacinglight = 0;
26 trianglefacinglight = NULL;
27 Mem_FreePool(&r_shadow_mempool);
30 void r_shadow_newmap(void)
34 void R_Shadow_Init(void)
36 R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap);
39 void R_ShadowVolume(int numverts, int numtris, int *elements, int *neighbors, vec3_t relativelightorigin, float projectdistance)
41 int i, *e, *n, *out, tris;
42 float *v0, *v1, *v2, dir0[3], dir1[3], temp[3], f;
46 // a triangle facing the light source
49 // a triangle not facing the light source
52 // an extrusion of the backfaces, beginning at the original geometry and
53 // ending further from the light source than the original geometry
54 // (presumably at least as far as the light's radius, if the light has a
55 // radius at all), capped at both front and back to avoid any problems
58 // draws the shadow volumes of the model.
60 // vertex loations must already be in varray_vertex before use.
61 // varray_vertex must have capacity for numverts * 2.
63 // make sure trianglefacinglight is big enough for this volume
64 if (maxtrianglefacinglight < numtris)
66 maxtrianglefacinglight = numtris;
67 if (trianglefacinglight)
68 Mem_Free(trianglefacinglight);
69 trianglefacinglight = Mem_Alloc(r_shadow_mempool, maxtrianglefacinglight);
72 // make sure shadowelements is big enough for this volume
73 if (maxshadowelements < numtris * 24)
75 maxshadowelements = numtris * 24;
77 Mem_Free(shadowelements);
78 shadowelements = Mem_Alloc(r_shadow_mempool, maxshadowelements * sizeof(int));
81 // make projected vertices
82 // by clever use of elements we'll construct the whole shadow from
83 // the unprojected vertices and these projected vertices
84 for (i = 0, v0 = varray_vertex, v1 = varray_vertex + numverts * 4;i < numverts;i++, v0 += 4, v1 += 4)
86 VectorSubtract(v0, relativelightorigin, temp);
87 f = projectdistance / sqrt(DotProduct(temp,temp));
88 VectorMA(v0, f, temp, v1);
91 // check which triangles are facing the light
92 for (i = 0, e = elements;i < numtris;i++, e += 3)
94 // calculate surface plane
95 v0 = varray_vertex + e[0] * 4;
96 v1 = varray_vertex + e[1] * 4;
97 v2 = varray_vertex + e[2] * 4;
98 VectorSubtract(v0, v1, dir0);
99 VectorSubtract(v2, v1, dir1);
100 CrossProduct(dir0, dir1, temp);
101 // we do not need to normalize the surface normal because both sides
102 // of the comparison use it, therefore they are both multiplied the
104 trianglefacinglight[i] = DotProduct(relativelightorigin, temp) >= DotProduct(v0, temp);
107 // output triangle elements
108 out = shadowelements;
111 // check each backface for bordering frontfaces,
112 // and cast shadow polygons from those edges,
113 // also create front and back caps for shadow volume
114 for (i = 0, e = elements, n = neighbors;i < numtris;i++, e += 3, n += 3)
116 if (!trianglefacinglight[i])
118 // triangle is backface and therefore casts shadow,
119 // output front and back caps for shadow volume
120 // front cap (with flipped winding order)
125 out[3] = e[0] + numverts;
126 out[4] = e[1] + numverts;
127 out[5] = e[2] + numverts;
131 if (trianglefacinglight[n[0]])
135 out[2] = e[1] + numverts;
137 out[4] = e[1] + numverts;
138 out[5] = e[0] + numverts;
142 if (trianglefacinglight[n[1]])
146 out[2] = e[2] + numverts;
148 out[4] = e[2] + numverts;
149 out[5] = e[1] + numverts;
153 if (trianglefacinglight[n[2]])
157 out[2] = e[0] + numverts;
159 out[4] = e[0] + numverts;
160 out[5] = e[2] + numverts;
167 R_Mesh_Draw(numverts * 2, tris, shadowelements);