1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #include "sys/platform.h"
30 
31 #include "renderer/tr_local.h"
32 
33 int	c_turboUsedVerts;
34 int c_turboUnusedVerts;
35 
36 /*
37 =====================
38 R_CreateVertexProgramTurboShadowVolume
39 
40 are dangling edges that are outside the light frustum still making planes?
41 =====================
42 */
R_CreateVertexProgramTurboShadowVolume(const idRenderEntityLocal * ent,const srfTriangles_t * tri,const idRenderLightLocal * light,srfCullInfo_t & cullInfo)43 srfTriangles_t *R_CreateVertexProgramTurboShadowVolume( const idRenderEntityLocal *ent,
44 														const srfTriangles_t *tri, const idRenderLightLocal *light,
45 														srfCullInfo_t &cullInfo ) {
46 	int		i, j;
47 	srfTriangles_t	*newTri;
48 	silEdge_t	*sil;
49 	const glIndex_t *indexes;
50 	const byte *facing;
51 
52 	R_CalcInteractionFacing( ent, tri, light, cullInfo );
53 	if ( r_useShadowProjectedCull.GetBool() ) {
54 		R_CalcInteractionCullBits( ent, tri, light, cullInfo );
55 	}
56 
57 	int numFaces = tri->numIndexes / 3;
58 	int	numShadowingFaces = 0;
59 	facing = cullInfo.facing;
60 
61 	// if all the triangles are inside the light frustum
62 	if ( cullInfo.cullBits == LIGHT_CULL_ALL_FRONT || !r_useShadowProjectedCull.GetBool() ) {
63 
64 		// count the number of shadowing faces
65 		for ( i = 0; i < numFaces; i++ ) {
66 			numShadowingFaces += facing[i];
67 		}
68 		numShadowingFaces = numFaces - numShadowingFaces;
69 
70 	} else {
71 
72 		// make all triangles that are outside the light frustum "facing", so they won't cast shadows
73 		indexes = tri->indexes;
74 		byte *modifyFacing = cullInfo.facing;
75 		const byte *cullBits = cullInfo.cullBits;
76 		for ( j = i = 0; i < tri->numIndexes; i += 3, j++ ) {
77 			if ( !modifyFacing[j] ) {
78 				int	i1 = indexes[i+0];
79 				int	i2 = indexes[i+1];
80 				int	i3 = indexes[i+2];
81 				if ( cullBits[i1] & cullBits[i2] & cullBits[i3] ) {
82 					modifyFacing[j] = 1;
83 				} else {
84 					numShadowingFaces++;
85 				}
86 			}
87 		}
88 	}
89 
90 	if ( !numShadowingFaces ) {
91 		// no faces are inside the light frustum and still facing the right way
92 		return NULL;
93 	}
94 
95 	// shadowVerts will be NULL on these surfaces, so the shadowVerts will be taken from the ambient surface
96 	newTri = R_AllocStaticTriSurf();
97 
98 	newTri->numVerts = tri->numVerts * 2;
99 
100 	// alloc the max possible size
101 #ifdef USE_TRI_DATA_ALLOCATOR
102 	R_AllocStaticTriSurfIndexes( newTri, ( numShadowingFaces + tri->numSilEdges ) * 6 );
103 	glIndex_t *tempIndexes = newTri->indexes;
104 	glIndex_t *shadowIndexes = newTri->indexes;
105 #else
106 	glIndex_t *tempIndexes = (glIndex_t *)_alloca16( tri->numSilEdges * 6 * sizeof( tempIndexes[0] ) );
107 	glIndex_t *shadowIndexes = tempIndexes;
108 #endif
109 
110 	// create new triangles along sil planes
111 	for ( sil = tri->silEdges, i = tri->numSilEdges; i > 0; i--, sil++ ) {
112 
113 		int f1 = facing[sil->p1];
114 		int f2 = facing[sil->p2];
115 
116 		if ( !( f1 ^ f2 ) ) {
117 			continue;
118 		}
119 
120 		int v1 = sil->v1 << 1;
121 		int v2 = sil->v2 << 1;
122 
123 		// set the two triangle winding orders based on facing
124 		// without using a poorly-predictable branch
125 
126 		shadowIndexes[0] = v1;
127 		shadowIndexes[1] = v2 ^ f1;
128 		shadowIndexes[2] = v2 ^ f2;
129 		shadowIndexes[3] = v1 ^ f2;
130 		shadowIndexes[4] = v1 ^ f1;
131 		shadowIndexes[5] = v2 ^ 1;
132 
133 		shadowIndexes += 6;
134 	}
135 
136 	int	numShadowIndexes = shadowIndexes - tempIndexes;
137 
138 	// we aren't bothering to separate front and back caps on these
139 	newTri->numIndexes = newTri->numShadowIndexesNoFrontCaps = numShadowIndexes + numShadowingFaces * 6;
140 	newTri->numShadowIndexesNoCaps = numShadowIndexes;
141 	newTri->shadowCapPlaneBits = SHADOW_CAP_INFINITE;
142 
143 #ifdef USE_TRI_DATA_ALLOCATOR
144 	// decrease the size of the memory block to only store the used indexes
145 	R_ResizeStaticTriSurfIndexes( newTri, newTri->numIndexes );
146 #else
147 	// allocate memory for the indexes
148 	R_AllocStaticTriSurfIndexes( newTri, newTri->numIndexes );
149 	// copy the indexes we created for the sil planes
150 	SIMDProcessor->Memcpy( newTri->indexes, tempIndexes, numShadowIndexes * sizeof( tempIndexes[0] ) );
151 #endif
152 
153 	// these have no effect, because they extend to infinity
154 	newTri->bounds.Clear();
155 
156 	// put some faces on the model and some on the distant projection
157 	indexes = tri->indexes;
158 	shadowIndexes = newTri->indexes + numShadowIndexes;
159 	for ( i = 0, j = 0; i < tri->numIndexes; i += 3, j++ ) {
160 		if ( facing[j] ) {
161 			continue;
162 		}
163 
164 		int i0 = indexes[i+0] << 1;
165 		shadowIndexes[2] = i0;
166 		shadowIndexes[3] = i0 ^ 1;
167 		int i1 = indexes[i+1] << 1;
168 		shadowIndexes[1] = i1;
169 		shadowIndexes[4] = i1 ^ 1;
170 		int i2 = indexes[i+2] << 1;
171 		shadowIndexes[0] = i2;
172 		shadowIndexes[5] = i2 ^ 1;
173 
174 		shadowIndexes += 6;
175 	}
176 
177 	return newTri;
178 }
179 
180 /*
181 =====================
182 R_CreateTurboShadowVolume
183 =====================
184 */
R_CreateTurboShadowVolume(const idRenderEntityLocal * ent,const srfTriangles_t * tri,const idRenderLightLocal * light,srfCullInfo_t & cullInfo)185 srfTriangles_t *R_CreateTurboShadowVolume( const idRenderEntityLocal *ent,
186 											const srfTriangles_t *tri, const idRenderLightLocal *light,
187 											srfCullInfo_t &cullInfo ) {
188 	int		i, j;
189 	idVec3	localLightOrigin;
190 	srfTriangles_t	*newTri;
191 	silEdge_t	*sil;
192 	const glIndex_t *indexes;
193 	const byte *facing;
194 
195 	R_CalcInteractionFacing( ent, tri, light, cullInfo );
196 	if ( r_useShadowProjectedCull.GetBool() ) {
197 		R_CalcInteractionCullBits( ent, tri, light, cullInfo );
198 	}
199 
200 	int numFaces = tri->numIndexes / 3;
201 	int	numShadowingFaces = 0;
202 	facing = cullInfo.facing;
203 
204 	// if all the triangles are inside the light frustum
205 	if ( cullInfo.cullBits == LIGHT_CULL_ALL_FRONT || !r_useShadowProjectedCull.GetBool() ) {
206 
207 		// count the number of shadowing faces
208 		for ( i = 0; i < numFaces; i++ ) {
209 			numShadowingFaces += facing[i];
210 		}
211 		numShadowingFaces = numFaces - numShadowingFaces;
212 
213 	} else {
214 
215 		// make all triangles that are outside the light frustum "facing", so they won't cast shadows
216 		indexes = tri->indexes;
217 		byte *modifyFacing = cullInfo.facing;
218 		const byte *cullBits = cullInfo.cullBits;
219 		for ( j = i = 0; i < tri->numIndexes; i += 3, j++ ) {
220 			if ( !modifyFacing[j] ) {
221 				int	i1 = indexes[i+0];
222 				int	i2 = indexes[i+1];
223 				int	i3 = indexes[i+2];
224 				if ( cullBits[i1] & cullBits[i2] & cullBits[i3] ) {
225 					modifyFacing[j] = 1;
226 				} else {
227 					numShadowingFaces++;
228 				}
229 			}
230 		}
231 	}
232 
233 	if ( !numShadowingFaces ) {
234 		// no faces are inside the light frustum and still facing the right way
235 		return NULL;
236 	}
237 
238 	newTri = R_AllocStaticTriSurf();
239 
240 #ifdef USE_TRI_DATA_ALLOCATOR
241 	R_AllocStaticTriSurfShadowVerts( newTri, tri->numVerts * 2 );
242 	shadowCache_t *shadowVerts = newTri->shadowVertexes;
243 #else
244 	shadowCache_t *shadowVerts = (shadowCache_t *)_alloca16( tri->numVerts * 2 * sizeof( shadowVerts[0] ) );
245 #endif
246 
247 	R_GlobalPointToLocal( ent->modelMatrix, light->globalLightOrigin, localLightOrigin );
248 
249 	int	*vertRemap = (int *)_alloca16( tri->numVerts * sizeof( vertRemap[0] ) );
250 
251 	SIMDProcessor->Memset( vertRemap, -1, tri->numVerts * sizeof( vertRemap[0] ) );
252 
253 	for ( i = 0, j = 0; i < tri->numIndexes; i += 3, j++ ) {
254 		if ( facing[j] ) {
255 			continue;
256 		}
257 		// this may pull in some vertexes that are outside
258 		// the frustum, because they connect to vertexes inside
259 		vertRemap[tri->silIndexes[i+0]] = 0;
260 		vertRemap[tri->silIndexes[i+1]] = 0;
261 		vertRemap[tri->silIndexes[i+2]] = 0;
262 	}
263 
264 	newTri->numVerts = SIMDProcessor->CreateShadowCache( &shadowVerts->xyz, vertRemap, localLightOrigin, tri->verts, tri->numVerts );
265 
266 	c_turboUsedVerts += newTri->numVerts;
267 	c_turboUnusedVerts += tri->numVerts * 2 - newTri->numVerts;
268 
269 #ifdef USE_TRI_DATA_ALLOCATOR
270 	R_ResizeStaticTriSurfShadowVerts( newTri, newTri->numVerts );
271 #else
272 	R_AllocStaticTriSurfShadowVerts( newTri, newTri->numVerts );
273 	SIMDProcessor->Memcpy( newTri->shadowVertexes, shadowVerts, newTri->numVerts * sizeof( shadowVerts[0] ) );
274 #endif
275 
276 	// alloc the max possible size
277 #ifdef USE_TRI_DATA_ALLOCATOR
278 	R_AllocStaticTriSurfIndexes( newTri, ( numShadowingFaces + tri->numSilEdges ) * 6 );
279 	glIndex_t *tempIndexes = newTri->indexes;
280 	glIndex_t *shadowIndexes = newTri->indexes;
281 #else
282 	glIndex_t *tempIndexes = (glIndex_t *)_alloca16( tri->numSilEdges * 6 * sizeof( tempIndexes[0] ) );
283 	glIndex_t *shadowIndexes = tempIndexes;
284 #endif
285 
286 	// create new triangles along sil planes
287 	for ( sil = tri->silEdges, i = tri->numSilEdges; i > 0; i--, sil++ ) {
288 
289 		int f1 = facing[sil->p1];
290 		int f2 = facing[sil->p2];
291 
292 		if ( !( f1 ^ f2 ) ) {
293 			continue;
294 		}
295 
296 		int v1 = vertRemap[sil->v1];
297 		int v2 = vertRemap[sil->v2];
298 
299 		// set the two triangle winding orders based on facing
300 		// without using a poorly-predictable branch
301 
302 		shadowIndexes[0] = v1;
303 		shadowIndexes[1] = v2 ^ f1;
304 		shadowIndexes[2] = v2 ^ f2;
305 		shadowIndexes[3] = v1 ^ f2;
306 		shadowIndexes[4] = v1 ^ f1;
307 		shadowIndexes[5] = v2 ^ 1;
308 
309 		shadowIndexes += 6;
310 	}
311 
312 	int numShadowIndexes = shadowIndexes - tempIndexes;
313 
314 	// we aren't bothering to separate front and back caps on these
315 	newTri->numIndexes = newTri->numShadowIndexesNoFrontCaps = numShadowIndexes + numShadowingFaces * 6;
316 	newTri->numShadowIndexesNoCaps = numShadowIndexes;
317 	newTri->shadowCapPlaneBits = SHADOW_CAP_INFINITE;
318 
319 #ifdef USE_TRI_DATA_ALLOCATOR
320 	// decrease the size of the memory block to only store the used indexes
321 	R_ResizeStaticTriSurfIndexes( newTri, newTri->numIndexes );
322 #else
323 	// allocate memory for the indexes
324 	R_AllocStaticTriSurfIndexes( newTri, newTri->numIndexes );
325 	// copy the indexes we created for the sil planes
326 	SIMDProcessor->Memcpy( newTri->indexes, tempIndexes, numShadowIndexes * sizeof( tempIndexes[0] ) );
327 #endif
328 
329 	// these have no effect, because they extend to infinity
330 	newTri->bounds.Clear();
331 
332 	// put some faces on the model and some on the distant projection
333 	indexes = tri->silIndexes;
334 	shadowIndexes = newTri->indexes + numShadowIndexes;
335 	for ( i = 0, j = 0; i < tri->numIndexes; i += 3, j++ ) {
336 		if ( facing[j] ) {
337 			continue;
338 		}
339 
340 		int i0 = vertRemap[indexes[i+0]];
341 		shadowIndexes[2] = i0;
342 		shadowIndexes[3] = i0 ^ 1;
343 		int i1 = vertRemap[indexes[i+1]];
344 		shadowIndexes[1] = i1;
345 		shadowIndexes[4] = i1 ^ 1;
346 		int i2 = vertRemap[indexes[i+2]];
347 		shadowIndexes[0] = i2;
348 		shadowIndexes[5] = i2 ^ 1;
349 
350 		shadowIndexes += 6;
351 	}
352 
353 	return newTri;
354 }
355