1 /*
2 ===========================================================================
3 
4 Return to Castle Wolfenstein multiplayer GPL Source Code
5 Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (“RTCW MP Source Code”).
8 
9 RTCW MP 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 RTCW MP 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 RTCW MP Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the RTCW MP 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 RTCW MP 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 "tr_local.h"
30 
31 
32 /*
33 
34   for a projection shadow:
35 
36   point[x] += light vector * ( z - shadow plane )
37   point[y] +=
38   point[z] = shadow plane
39 
40   1 0 light[x] / light[z]
41 
42 */
43 
44 typedef struct {
45 	int i2;
46 	int facing;
47 } edgeDef_t;
48 
49 #define MAX_EDGE_DEFS   32
50 
51 static edgeDef_t edgeDefs[SHADER_MAX_VERTEXES][MAX_EDGE_DEFS];
52 static int numEdgeDefs[SHADER_MAX_VERTEXES];
53 //static int facing[SHADER_MAX_INDEXES / 3];
54 //static vec3_t shadowXyz[SHADER_MAX_VERTEXES];
55 
R_AddEdgeDef(int i1,int i2,int facing)56 void R_AddEdgeDef( int i1, int i2, int facing ) {
57 	int c;
58 
59 	c = numEdgeDefs[ i1 ];
60 	if ( c == MAX_EDGE_DEFS ) {
61 		return;     // overflow
62 	}
63 	edgeDefs[ i1 ][ c ].i2 = i2;
64 	edgeDefs[ i1 ][ c ].facing = facing;
65 
66 	numEdgeDefs[ i1 ]++;
67 }
68 
R_RenderShadowEdges(void)69 void R_RenderShadowEdges( void ) {
70 	// FIXME: implement this
71 #if 0
72 	int i;
73 
74 #if 0
75 	int numTris;
76 
77 	// dumb way -- render every triangle's edges
78 	numTris = tess.numIndexes / 3;
79 
80 	for ( i = 0 ; i < numTris ; i++ ) {
81 		int i1, i2, i3;
82 
83 		if ( !facing[i] ) {
84 			continue;
85 		}
86 
87 		i1 = tess.indexes[ i * 3 + 0 ];
88 		i2 = tess.indexes[ i * 3 + 1 ];
89 		i3 = tess.indexes[ i * 3 + 2 ];
90 
91 		qglBegin( GL_TRIANGLE_STRIP );
92 		qglVertex3fv( tess.xyz[ i1 ] );
93 		qglVertex3fv( shadowXyz[ i1 ] );
94 		qglVertex3fv( tess.xyz[ i2 ] );
95 		qglVertex3fv( shadowXyz[ i2 ] );
96 		qglVertex3fv( tess.xyz[ i3 ] );
97 		qglVertex3fv( shadowXyz[ i3 ] );
98 		qglVertex3fv( tess.xyz[ i1 ] );
99 		qglVertex3fv( shadowXyz[ i1 ] );
100 		qglEnd();
101 	}
102 #else
103 	int c, c2;
104 	int j, k;
105 	int i2;
106 	int c_edges, c_rejected;
107 	int hit[2];
108 
109 	// an edge is NOT a silhouette edge if its face doesn't face the light,
110 	// or if it has a reverse paired edge that also faces the light.
111 	// A well behaved polyhedron would have exactly two faces for each edge,
112 	// but lots of models have dangling edges or overfanned edges
113 	c_edges = 0;
114 	c_rejected = 0;
115 
116 	for ( i = 0 ; i < tess.numVertexes ; i++ ) {
117 		c = numEdgeDefs[ i ];
118 		for ( j = 0 ; j < c ; j++ ) {
119 			if ( !edgeDefs[ i ][ j ].facing ) {
120 				continue;
121 			}
122 
123 			hit[0] = 0;
124 			hit[1] = 0;
125 
126 			i2 = edgeDefs[ i ][ j ].i2;
127 			c2 = numEdgeDefs[ i2 ];
128 			for ( k = 0 ; k < c2 ; k++ ) {
129 				if ( edgeDefs[ i2 ][ k ].i2 == i ) {
130 					hit[ edgeDefs[ i2 ][ k ].facing ]++;
131 				}
132 			}
133 
134 			// if it doesn't share the edge with another front facing
135 			// triangle, it is a sil edge
136 			if ( hit[ 1 ] == 0 ) {
137 				qglBegin( GL_TRIANGLE_STRIP );
138 				qglVertex3fv( tess.xyz[ i ] );
139 				qglVertex3fv( shadowXyz[ i ] );
140 				qglVertex3fv( tess.xyz[ i2 ] );
141 				qglVertex3fv( shadowXyz[ i2 ] );
142 				qglEnd();
143 				c_edges++;
144 			} else {
145 				c_rejected++;
146 			}
147 		}
148 	}
149 #endif
150 #endif
151 }
152 
153 /*
154 =================
155 RB_ShadowTessEnd
156 
157 triangleFromEdge[ v1 ][ v2 ]
158 
159 
160   set triangle from edge( v1, v2, tri )
161   if ( facing[ triangleFromEdge[ v1 ][ v2 ] ] && !facing[ triangleFromEdge[ v2 ][ v1 ] ) {
162   }
163 =================
164 */
RB_ShadowTessEnd(void)165 void RB_ShadowTessEnd( void ) {
166 	// FIXME: implement this
167 #if 0
168 	int i;
169 	int numTris;
170 	vec3_t lightDir;
171 	GLboolean rgba[4];
172 
173 	if ( glConfig.stencilBits < 4 ) {
174 		return;
175 	}
176 
177 	VectorCopy( backEnd.currentEntity->lightDir, lightDir );
178 
179 	// project vertexes away from light direction
180 	for ( i = 0 ; i < tess.numVertexes ; i++ ) {
181 		VectorMA( tess.xyz[i], -512, lightDir, shadowXyz[i] );
182 	}
183 
184 	// decide which triangles face the light
185 	memset( numEdgeDefs, 0, 4 * tess.numVertexes );
186 
187 	numTris = tess.numIndexes / 3;
188 	for ( i = 0 ; i < numTris ; i++ ) {
189 		int i1, i2, i3;
190 		vec3_t d1, d2, normal;
191 		float   *v1, *v2, *v3;
192 		float d;
193 
194 		i1 = tess.indexes[ i * 3 + 0 ];
195 		i2 = tess.indexes[ i * 3 + 1 ];
196 		i3 = tess.indexes[ i * 3 + 2 ];
197 
198 		v1 = tess.xyz[ i1 ];
199 		v2 = tess.xyz[ i2 ];
200 		v3 = tess.xyz[ i3 ];
201 
202 		VectorSubtract( v2, v1, d1 );
203 		VectorSubtract( v3, v1, d2 );
204 		CrossProduct( d1, d2, normal );
205 
206 		d = DotProduct( normal, lightDir );
207 		if ( d > 0 ) {
208 			facing[ i ] = 1;
209 		} else {
210 			facing[ i ] = 0;
211 		}
212 
213 		// create the edges
214 		R_AddEdgeDef( i1, i2, facing[ i ] );
215 		R_AddEdgeDef( i2, i3, facing[ i ] );
216 		R_AddEdgeDef( i3, i1, facing[ i ] );
217 	}
218 
219 	// draw the silhouette edges
220 
221 	GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
222 	GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
223 	qglColor3f( 0.2f, 0.2f, 0.2f );
224 
225 	// don't write to the color buffer
226 	qglGetBooleanv(GL_COLOR_WRITEMASK, rgba);
227 	qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
228 
229 	qglEnable( GL_STENCIL_TEST );
230 	qglStencilFunc( GL_ALWAYS, 1, 255 );
231 
232 	GL_Cull( CT_BACK_SIDED );
233 	qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
234 
235 	R_RenderShadowEdges();
236 
237 	GL_Cull( CT_FRONT_SIDED );
238 	qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR );
239 
240 	R_RenderShadowEdges();
241 
242 	// reenable writing to the color buffer
243 	qglColorMask(rgba[0], rgba[1], rgba[2], rgba[3]);
244 #endif
245 }
246 
247 
248 /*
249 =================
250 RB_ShadowFinish
251 
252 Darken everything that is is a shadow volume.
253 We have to delay this until everything has been shadowed,
254 because otherwise shadows from different body parts would
255 overlap and double darken.
256 =================
257 */
RB_ShadowFinish(void)258 void RB_ShadowFinish( void ) {
259 	// FIXME: implement this
260 #if 0
261 	if ( r_shadows->integer != 2 ) {
262 		return;
263 	}
264 	if ( glConfig.stencilBits < 4 ) {
265 		return;
266 	}
267 	qglEnable( GL_STENCIL_TEST );
268 	qglStencilFunc( GL_NOTEQUAL, 0, 255 );
269 
270 	GL_Cull( CT_TWO_SIDED );
271 
272 	GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
273 
274 	qglLoadIdentity();
275 
276 	qglColor3f( 0.6f, 0.6f, 0.6f );
277 	GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO );
278 
279 //	qglColor3f( 1, 0, 0 );
280 //	GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
281 
282 	qglBegin( GL_QUADS );
283 	qglVertex3f( -100, 100, -10 );
284 	qglVertex3f( 100, 100, -10 );
285 	qglVertex3f( 100, -100, -10 );
286 	qglVertex3f( -100, -100, -10 );
287 	qglEnd();
288 
289 	qglColor4f( 1,1,1,1 );
290 	qglDisable( GL_STENCIL_TEST );
291 #endif
292 }
293 
294 
295 /*
296 =================
297 RB_ProjectionShadowDeform
298 
299 =================
300 */
RB_ProjectionShadowDeform(void)301 void RB_ProjectionShadowDeform( void ) {
302 	float   *xyz;
303 	int i;
304 	float h;
305 	vec3_t ground;
306 	vec3_t light;
307 	float groundDist;
308 	float d;
309 	vec3_t lightDir;
310 
311 	xyz = ( float * ) tess.xyz;
312 
313 	ground[0] = backEnd.or.axis[0][2];
314 	ground[1] = backEnd.or.axis[1][2];
315 	ground[2] = backEnd.or.axis[2][2];
316 
317 	groundDist = backEnd.or.origin[2] - backEnd.currentEntity->e.shadowPlane;
318 
319 	VectorCopy( backEnd.currentEntity->lightDir, lightDir );
320 	d = DotProduct( lightDir, ground );
321 	// don't let the shadows get too long or go negative
322 	if ( d < 0.5 ) {
323 		VectorMA( lightDir, ( 0.5 - d ), ground, lightDir );
324 		d = DotProduct( lightDir, ground );
325 	}
326 	d = 1.0 / d;
327 
328 	light[0] = lightDir[0] * d;
329 	light[1] = lightDir[1] * d;
330 	light[2] = lightDir[2] * d;
331 
332 	for ( i = 0; i < tess.numVertexes; i++, xyz += 4 ) {
333 		h = DotProduct( xyz, ground ) + groundDist;
334 
335 		xyz[0] -= light[0] * h;
336 		xyz[1] -= light[1] * h;
337 		xyz[2] -= light[2] * h;
338 	}
339 }
340