1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4 Copyright (C) 2006 Robert Beckebans <trebor_7@users.sourceforge.net>
5 
6 This file is part of XreaL source code.
7 
8 XreaL source code is free software; you can redistribute it
9 and/or modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the License,
11 or (at your option) any later version.
12 
13 XreaL source code is distributed in the hope that it will be
14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with XreaL source code; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21 ===========================================================================
22 */
23 // tr_surface.c
24 #include "tr_local.h"
25 
26 /*
27 ==============================================================================
28 THIS ENTIRE FILE IS BACK END!
29 
30 backEnd.currentEntity will be valid.
31 
32 Tess_Begin has already been called for the surface's shader.
33 
34 The modelview matrix will be set.
35 
36 It is safe to actually issue drawing commands here if you don't want to
37 use the shader system.
38 ==============================================================================
39 */
40 
41 /*
42 ==============
43 Tess_EndBegin
44 ==============
45 */
Tess_EndBegin()46 void Tess_EndBegin()
47 {
48 	Tess_End();
49 	Tess_Begin(tess.surfaceShader, tess.lightShader, tess.lightmapNum, tess.fogNum, tess.skipTangentSpaces,
50 					tess.shadowVolume);
51 }
52 
53 /*
54 ==============
55 Tess_CheckOverflow
56 ==============
57 */
Tess_CheckOverflow(int verts,int indexes)58 void Tess_CheckOverflow(int verts, int indexes)
59 {
60 	if(glConfig2.vertexBufferObjectAvailable && (tess.indexesVBO || tess.vertexesVBO))
61 	{
62 		Tess_EndBegin();
63 		return;
64 	}
65 
66 	if(tess.numVertexes + verts < SHADER_MAX_VERTEXES && tess.numIndexes + indexes < SHADER_MAX_INDEXES)
67 	{
68 		return;
69 	}
70 
71 	if(r_logFile->integer)
72 	{
73 		// don't just call LogComment, or we will get
74 		// a call to va() every frame!
75 		GLimp_LogComment(va
76 						 ("--- Tess_CheckOverflow(%i + %i vertices, %i + %i triangles ) ---\n", tess.numVertexes, verts,
77 						  (tess.numIndexes / 3), indexes));
78 	}
79 
80 	Tess_End();
81 
82 	if(verts >= SHADER_MAX_VERTEXES)
83 	{
84 		ri.Error(ERR_DROP, "Tess_CheckOverflow: verts > MAX (%d > %d)", verts, SHADER_MAX_VERTEXES);
85 	}
86 	if(indexes >= SHADER_MAX_INDEXES)
87 	{
88 		ri.Error(ERR_DROP, "Tess_CheckOverflow: indices > MAX (%d > %d)", indexes, SHADER_MAX_INDEXES);
89 	}
90 
91 	Tess_Begin(tess.surfaceShader, tess.lightShader, tess.lightmapNum, tess.fogNum, tess.skipTangentSpaces,
92 					tess.shadowVolume);
93 }
94 
95 
96 /*
97 ==============
98 Tess_AddQuadStampExt
99 ==============
100 */
Tess_AddQuadStampExt(vec3_t origin,vec3_t left,vec3_t up,byte * color,float s1,float t1,float s2,float t2)101 void Tess_AddQuadStampExt(vec3_t origin, vec3_t left, vec3_t up, byte * color, float s1, float t1, float s2, float t2)
102 {
103 	vec3_t          normal;
104 	int             ndx;
105 
106 	GLimp_LogComment("--- Tess_AddQuadStampExt ---\n");
107 
108 	Tess_CheckOverflow(4, 6);
109 
110 	ndx = tess.numVertexes;
111 
112 	// triangle indexes for a simple quad
113 	tess.indexes[tess.numIndexes] = ndx;
114 	tess.indexes[tess.numIndexes + 1] = ndx + 1;
115 	tess.indexes[tess.numIndexes + 2] = ndx + 3;
116 
117 	tess.indexes[tess.numIndexes + 3] = ndx + 3;
118 	tess.indexes[tess.numIndexes + 4] = ndx + 1;
119 	tess.indexes[tess.numIndexes + 5] = ndx + 2;
120 
121 	tess.xyz[ndx][0] = origin[0] + left[0] + up[0];
122 	tess.xyz[ndx][1] = origin[1] + left[1] + up[1];
123 	tess.xyz[ndx][2] = origin[2] + left[2] + up[2];
124 	tess.xyz[ndx][3] = 1;
125 
126 	tess.xyz[ndx + 1][0] = origin[0] - left[0] + up[0];
127 	tess.xyz[ndx + 1][1] = origin[1] - left[1] + up[1];
128 	tess.xyz[ndx + 1][2] = origin[2] - left[2] + up[2];
129 	tess.xyz[ndx + 1][3] = 1;
130 
131 	tess.xyz[ndx + 2][0] = origin[0] - left[0] - up[0];
132 	tess.xyz[ndx + 2][1] = origin[1] - left[1] - up[1];
133 	tess.xyz[ndx + 2][2] = origin[2] - left[2] - up[2];
134 	tess.xyz[ndx + 2][3] = 1;
135 
136 	tess.xyz[ndx + 3][0] = origin[0] + left[0] - up[0];
137 	tess.xyz[ndx + 3][1] = origin[1] + left[1] - up[1];
138 	tess.xyz[ndx + 3][2] = origin[2] + left[2] - up[2];
139 	tess.xyz[ndx + 3][3] = 1;
140 
141 
142 	// constant normal all the way around
143 	VectorSubtract(vec3_origin, backEnd.viewParms.or.axis[0], normal);
144 
145 	tess.normals[ndx][0] = tess.normals[ndx + 1][0] = tess.normals[ndx + 2][0] = tess.normals[ndx + 3][0] = normal[0];
146 	tess.normals[ndx][1] = tess.normals[ndx + 1][1] = tess.normals[ndx + 2][1] = tess.normals[ndx + 3][1] = normal[1];
147 	tess.normals[ndx][2] = tess.normals[ndx + 1][2] = tess.normals[ndx + 2][2] = tess.normals[ndx + 3][2] = normal[2];
148 
149 	// standard square texture coordinates
150 	tess.texCoords[ndx][0][0] = tess.texCoords[ndx][1][0] = s1;
151 	tess.texCoords[ndx][0][1] = tess.texCoords[ndx][1][1] = t1;
152 
153 	tess.texCoords[ndx + 1][0][0] = tess.texCoords[ndx + 1][1][0] = s2;
154 	tess.texCoords[ndx + 1][0][1] = tess.texCoords[ndx + 1][1][1] = t1;
155 
156 	tess.texCoords[ndx + 2][0][0] = tess.texCoords[ndx + 2][1][0] = s2;
157 	tess.texCoords[ndx + 2][0][1] = tess.texCoords[ndx + 2][1][1] = t2;
158 
159 	tess.texCoords[ndx + 3][0][0] = tess.texCoords[ndx + 3][1][0] = s1;
160 	tess.texCoords[ndx + 3][0][1] = tess.texCoords[ndx + 3][1][1] = t2;
161 
162 	// constant color all the way around
163 	// should this be identity and let the shader specify from entity?
164 	*(unsigned int *)&tess.colors[ndx] =
165 		*(unsigned int *)&tess.colors[ndx + 1] =
166 		*(unsigned int *)&tess.colors[ndx + 2] = *(unsigned int *)&tess.colors[ndx + 3] = *(unsigned int *)color;
167 
168 
169 	tess.numVertexes += 4;
170 	tess.numIndexes += 6;
171 }
172 
173 /*
174 ==============
175 Tess_AddQuadStamp
176 ==============
177 */
Tess_AddQuadStamp(vec3_t origin,vec3_t left,vec3_t up,byte * color)178 void Tess_AddQuadStamp(vec3_t origin, vec3_t left, vec3_t up, byte * color)
179 {
180 	Tess_AddQuadStampExt(origin, left, up, color, 0, 0, 1, 1);
181 }
182 
183 /*
184 ==============
185 Tess_SurfaceSprite
186 ==============
187 */
Tess_SurfaceSprite(void)188 static void Tess_SurfaceSprite(void)
189 {
190 	vec3_t          left, up;
191 	float           radius;
192 
193 	GLimp_LogComment("--- Tess_SurfaceSprite ---\n");
194 
195 	// calculate the xyz locations for the four corners
196 	radius = backEnd.currentEntity->e.radius;
197 	if(backEnd.currentEntity->e.rotation == 0)
198 	{
199 		VectorScale(backEnd.viewParms.or.axis[1], radius, left);
200 		VectorScale(backEnd.viewParms.or.axis[2], radius, up);
201 	}
202 	else
203 	{
204 		float           s, c;
205 		float           ang;
206 
207 		ang = M_PI * backEnd.currentEntity->e.rotation / 180;
208 		s = sin(ang);
209 		c = cos(ang);
210 
211 		VectorScale(backEnd.viewParms.or.axis[1], c * radius, left);
212 		VectorMA(left, -s * radius, backEnd.viewParms.or.axis[2], left);
213 
214 		VectorScale(backEnd.viewParms.or.axis[2], c * radius, up);
215 		VectorMA(up, s * radius, backEnd.viewParms.or.axis[1], up);
216 	}
217 	if(backEnd.viewParms.isMirror)
218 	{
219 		VectorSubtract(vec3_origin, left, left);
220 	}
221 
222 	Tess_AddQuadStamp(backEnd.currentEntity->e.origin, left, up, backEnd.currentEntity->e.shaderRGBA);
223 }
224 
225 
226 /*
227 =============
228 Tess_SurfacePolychain
229 =============
230 */
Tess_SurfacePolychain(srfPoly_t * p,int numLightIndexes,int * lightIndexes,int numShadowIndexes,int * shadowIndexes)231 static void Tess_SurfacePolychain(srfPoly_t * p, int numLightIndexes, int *lightIndexes, int numShadowIndexes, int *shadowIndexes)
232 {
233 	int             i;
234 	int             numv;
235 
236 	GLimp_LogComment("--- Tess_SurfacePolychain ---\n");
237 
238 	if(tess.shadowVolume)
239 	{
240 		return;
241 	}
242 
243 	Tess_CheckOverflow(p->numVerts, 3 * (p->numVerts - 2));
244 
245 	// fan triangles into the tess array
246 	numv = tess.numVertexes;
247 	for(i = 0; i < p->numVerts; i++)
248 	{
249 		VectorCopy(p->verts[i].xyz, tess.xyz[numv]);
250 		tess.xyz[numv][3] = 1;
251 		tess.texCoords[numv][0][0] = p->verts[i].st[0];
252 		tess.texCoords[numv][0][1] = p->verts[i].st[1];
253 		*(int *)&tess.colors[numv] = *(int *)p->verts[i].modulate;
254 
255 		numv++;
256 	}
257 
258 	// generate fan indexes into the tess array
259 	for(i = 0; i < p->numVerts - 2; i++)
260 	{
261 		tess.indexes[tess.numIndexes + 0] = tess.numVertexes;
262 		tess.indexes[tess.numIndexes + 1] = tess.numVertexes + i + 1;
263 		tess.indexes[tess.numIndexes + 2] = tess.numVertexes + i + 2;
264 		tess.numIndexes += 3;
265 	}
266 
267 	tess.numVertexes = numv;
268 }
269 
270 /*
271 ==============
272 Tess_SurfaceFace
273 ==============
274 */
Tess_SurfaceFace(srfSurfaceFace_t * cv,int numLightIndexes,int * lightIndexes,int numShadowIndexes,int * shadowIndexes)275 static void Tess_SurfaceFace(srfSurfaceFace_t * cv, int numLightIndexes, int *lightIndexes, int numShadowIndexes, int *shadowIndexes)
276 {
277 	int             i;
278 	srfTriangle_t  *tri;
279 	srfVert_t      *dv;
280 	float          *xyz, *tangent, *binormal, *normal, *texCoords;
281 	byte           *color;
282 	vec3_t          lightOrigin;
283 	float           d;
284 
285 	GLimp_LogComment("--- Tess_SurfaceFace ---\n");
286 
287 	if(tess.shadowVolume)
288 	{
289 		VectorCopy(backEnd.currentLight->transformed, lightOrigin);
290 
291 		if(numShadowIndexes)
292 		{
293 			// this case is always zfail with light and dark caps
294 			Tess_CheckOverflow(cv->numVerts, numShadowIndexes);
295 
296 			for(i = 0; i < numShadowIndexes; i++)
297 			{
298 				tess.indexes[tess.numIndexes + i] = tess.numVertexes + shadowIndexes[i];
299 			}
300 
301 			tess.numIndexes += numShadowIndexes;
302 			backEnd.pc.c_shadowIndexes += numShadowIndexes;
303 		}
304 		else
305 		{
306 			// decide which triangles face the light
307 			sh.numFacing = 0;
308 			for(i = 0, tri = cv->triangles; i < cv->numTriangles; i++, tri++)
309 			{
310 				d = DotProduct(tri->plane, lightOrigin) - tri->plane[3];
311 				if(d > 0 && !tess.surfaceShader->cullType == CT_BACK_SIDED)
312 				{
313 					sh.facing[i] = qtrue;
314 					sh.numFacing++;
315 				}
316 				else
317 				{
318 					sh.facing[i] = qfalse;
319 				}
320 			}
321 
322 			if(backEnd.currentEntity->needZFail)
323 			{
324 				Tess_CheckOverflow(cv->numVerts * 2, sh.numFacing * (6 + 2) * 3);
325 			}
326 			else
327 			{
328 				Tess_CheckOverflow(cv->numVerts * 2, sh.numFacing * 6 * 3);
329 			}
330 
331 			// set up indices for silhouette edges
332 			for(i = 0, tri = cv->triangles; i < cv->numTriangles; i++, tri++)
333 			{
334 				if(!sh.facing[i])
335 				{
336 					continue;
337 				}
338 
339 				if((tri->neighbors[0] < 0) || (tri->neighbors[0] >= 0 && !sh.facing[tri->neighbors[0]]))
340 				{
341 					tess.indexes[tess.numIndexes + 0] = tess.numVertexes + tri->indexes[1];
342 					tess.indexes[tess.numIndexes + 1] = tess.numVertexes + tri->indexes[0];
343 					tess.indexes[tess.numIndexes + 2] = tess.numVertexes + tri->indexes[0] + cv->numVerts;
344 
345 					tess.indexes[tess.numIndexes + 3] = tess.numVertexes + tri->indexes[1];
346 					tess.indexes[tess.numIndexes + 4] = tess.numVertexes + tri->indexes[0] + cv->numVerts;
347 					tess.indexes[tess.numIndexes + 5] = tess.numVertexes + tri->indexes[1] + cv->numVerts;
348 
349 					tess.numIndexes += 6;
350 					backEnd.pc.c_shadowIndexes += 6;
351 				}
352 
353 				if((tri->neighbors[1] < 0) || (tri->neighbors[1] >= 0 && !sh.facing[tri->neighbors[1]]))
354 				{
355 					tess.indexes[tess.numIndexes + 0] = tess.numVertexes + tri->indexes[2];
356 					tess.indexes[tess.numIndexes + 1] = tess.numVertexes + tri->indexes[1];
357 					tess.indexes[tess.numIndexes + 2] = tess.numVertexes + tri->indexes[1] + cv->numVerts;
358 
359 					tess.indexes[tess.numIndexes + 3] = tess.numVertexes + tri->indexes[2];
360 					tess.indexes[tess.numIndexes + 4] = tess.numVertexes + tri->indexes[1] + cv->numVerts;
361 					tess.indexes[tess.numIndexes + 5] = tess.numVertexes + tri->indexes[2] + cv->numVerts;
362 
363 					tess.numIndexes += 6;
364 					backEnd.pc.c_shadowIndexes += 6;
365 				}
366 
367 				if((tri->neighbors[2] < 0) || (tri->neighbors[2] >= 0 && !sh.facing[tri->neighbors[2]]))
368 				{
369 					tess.indexes[tess.numIndexes + 0] = tess.numVertexes + tri->indexes[0];
370 					tess.indexes[tess.numIndexes + 1] = tess.numVertexes + tri->indexes[2];
371 					tess.indexes[tess.numIndexes + 2] = tess.numVertexes + tri->indexes[2] + cv->numVerts;
372 
373 					tess.indexes[tess.numIndexes + 3] = tess.numVertexes + tri->indexes[0];
374 					tess.indexes[tess.numIndexes + 4] = tess.numVertexes + tri->indexes[2] + cv->numVerts;
375 					tess.indexes[tess.numIndexes + 5] = tess.numVertexes + tri->indexes[0] + cv->numVerts;
376 
377 					tess.numIndexes += 6;
378 					backEnd.pc.c_shadowIndexes += 6;
379 				}
380 			}
381 
382 			// set up indices for light and dark caps
383 			if(backEnd.currentEntity->needZFail)
384 			{
385 				for(i = 0, tri = cv->triangles; i < cv->numTriangles; i++, tri++)
386 				{
387 					if(!sh.facing[i])
388 					{
389 						continue;
390 					}
391 
392 					// light cap
393 					tess.indexes[tess.numIndexes + 0] = tess.numVertexes + tri->indexes[0];
394 					tess.indexes[tess.numIndexes + 1] = tess.numVertexes + tri->indexes[1];
395 					tess.indexes[tess.numIndexes + 2] = tess.numVertexes + tri->indexes[2];
396 
397 					// dark cap
398 					tess.indexes[tess.numIndexes + 3] = tess.numVertexes + tri->indexes[2] + cv->numVerts;
399 					tess.indexes[tess.numIndexes + 4] = tess.numVertexes + tri->indexes[1] + cv->numVerts;
400 					tess.indexes[tess.numIndexes + 5] = tess.numVertexes + tri->indexes[0] + cv->numVerts;
401 
402 					tess.numIndexes += 6;
403 					backEnd.pc.c_shadowIndexes += 6;
404 				}
405 			}
406 		}
407 
408 		// copy vertexes and extrude to infinity
409 		for(i = 0, dv = cv->verts, xyz = tess.xyz[tess.numVertexes]; i < cv->numVerts; i++, dv++, xyz += 4)
410 		{
411 			xyz[0] = dv->xyz[0];
412 			xyz[1] = dv->xyz[1];
413 			xyz[2] = dv->xyz[2];
414 			xyz[3] = 1.0;
415 		}
416 
417 		for(i = 0, dv = cv->verts, xyz = tess.xyz[tess.numVertexes + cv->numVerts]; i < cv->numVerts; i++, dv++, xyz += 4)
418 		{
419 			#if 1
420 			xyz[0] = dv->xyz[0];
421 			xyz[1] = dv->xyz[1];
422 			xyz[2] = dv->xyz[2];
423 			#else
424 			xyz[0] = dv->xyz[0] - lightOrigin[0];
425 			xyz[1] = dv->xyz[1] - lightOrigin[1];
426 			xyz[2] = dv->xyz[2] - lightOrigin[2];
427 			#endif
428 			xyz[3] = 0.0;
429 		}
430 
431 		tess.numVertexes += cv->numVerts * 2;
432 		backEnd.pc.c_shadowVertexes += cv->numVerts * 2;
433 
434 		backEnd.pc.c_shadowSurfaces++;
435 	}
436 	else
437 	{
438 		if(glConfig2.vertexBufferObjectAvailable && (cv->indexesVBO || cv->vertsVBO) && r_vboFaces->integer)
439 		{
440 			Tess_EndBegin();
441 		}
442 
443 		if(glConfig2.vertexBufferObjectAvailable && cv->indexesVBO && r_vboFaces->integer)
444 		{
445 			Tess_CheckOverflow(cv->numVerts, cv->numTriangles * 3);
446 
447 			tess.indexesVBO = cv->indexesVBO;
448 			qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, tess.indexesVBO);
449 
450 			tess.numIndexes += cv->numTriangles * 3;
451 		}
452 		else
453 		{
454 			if(numLightIndexes)
455 			{
456 				Tess_CheckOverflow(cv->numVerts, numLightIndexes);
457 
458 				for(i = 0; i < numLightIndexes; i++)
459 				{
460 					tess.indexes[tess.numIndexes + i] = tess.numVertexes + lightIndexes[i];
461 				}
462 
463 				tess.numIndexes += numLightIndexes;
464 			}
465 			else
466 			{
467 				Tess_CheckOverflow(cv->numVerts, cv->numTriangles * 3);
468 
469 				for(i = 0, tri = cv->triangles; i < cv->numTriangles; i++, tri++)
470 				{
471 					tess.indexes[tess.numIndexes + i * 3 + 0] = tess.numVertexes + tri->indexes[0];
472 					tess.indexes[tess.numIndexes + i * 3 + 1] = tess.numVertexes + tri->indexes[1];
473 					tess.indexes[tess.numIndexes + i * 3 + 2] = tess.numVertexes + tri->indexes[2];
474 				}
475 
476 				tess.numIndexes += cv->numTriangles * 3;
477 			}
478 		}
479 
480 		if(glConfig2.vertexBufferObjectAvailable && cv->vertsVBO && r_vboFaces->integer)
481 		{
482 			tess.vertexesVBO = cv->vertsVBO;
483 			tess.ofsXYZ = cv->ofsXYZ;
484 			tess.ofsTexCoords = cv->ofsTexCoords;
485 			tess.ofsTexCoords2 = cv->ofsTexCoords2;
486 			tess.ofsTangents = cv->ofsTangents;
487 			tess.ofsBinormals = cv->ofsBinormals;
488 			tess.ofsNormals = cv->ofsNormals;
489 			tess.ofsColors = cv->ofsColors;
490 
491 			qglBindBufferARB(GL_ARRAY_BUFFER_ARB, tess.vertexesVBO);
492 		}
493 		else
494 		{
495 			dv = cv->verts;
496 			xyz = tess.xyz[tess.numVertexes];
497 			tangent = tess.tangents[tess.numVertexes];
498 			binormal = tess.binormals[tess.numVertexes];
499 			normal = tess.normals[tess.numVertexes];
500 			texCoords = tess.texCoords[tess.numVertexes][0];
501 			color = tess.colors[tess.numVertexes];
502 
503 			for(i = 0; i < cv->numVerts;
504 				i++, dv++, xyz += 4, tangent += 4, binormal += 4, normal += 4, texCoords += 4, color += 4)
505 			{
506 				xyz[0] = dv->xyz[0];
507 				xyz[1] = dv->xyz[1];
508 				xyz[2] = dv->xyz[2];
509 				xyz[3] = 1;
510 
511 				if(!tess.skipTangentSpaces)
512 				{
513 					tangent[0] = dv->tangent[0];
514 					tangent[1] = dv->tangent[1];
515 					tangent[2] = dv->tangent[2];
516 
517 					binormal[0] = dv->binormal[0];
518 					binormal[1] = dv->binormal[1];
519 					binormal[2] = dv->binormal[2];
520 
521 					normal[0] = dv->normal[0];
522 					normal[1] = dv->normal[1];
523 					normal[2] = dv->normal[2];
524 				}
525 
526 				texCoords[0] = dv->st[0];
527 				texCoords[1] = dv->st[1];
528 
529 				texCoords[2] = dv->lightmap[0];
530 				texCoords[3] = dv->lightmap[1];
531 
532 				*(int *)color = *(int *)dv->color;
533 			}
534 		}
535 
536 		tess.numVertexes += cv->numVerts;
537 	}
538 }
539 
540 /*
541 =============
542 Tess_SurfaceGrid
543 =============
544 */
Tess_SurfaceGrid(srfGridMesh_t * cv,int numLightIndexes,int * lightIndexes,int numShadowIndexes,int * shadowIndexes)545 static void Tess_SurfaceGrid(srfGridMesh_t * cv, int numLightIndexes, int *lightIndexes, int numShadowIndexes, int *shadowIndexes)
546 {
547 	int             i;
548 	srfTriangle_t  *tri;
549 	srfVert_t      *dv;
550 	float          *xyz, *tangent, *binormal, *normal, *texCoords;
551 	byte           *color;
552 	vec3_t          lightOrigin;
553 	float           d;
554 
555 	GLimp_LogComment("--- Tess_SurfaceGrid ---\n");
556 
557 	if(tess.shadowVolume)
558 	{
559 		VectorCopy(backEnd.currentLight->transformed, lightOrigin);
560 
561 		if(numShadowIndexes)
562 		{
563 			// this case is always zfail with light and dark caps
564 			Tess_CheckOverflow(cv->numVerts, numShadowIndexes);
565 
566 			for(i = 0; i < numShadowIndexes; i++)
567 			{
568 				tess.indexes[tess.numIndexes + i] = tess.numVertexes + shadowIndexes[i];
569 			}
570 
571 			tess.numIndexes += numShadowIndexes;
572 			backEnd.pc.c_shadowIndexes += numShadowIndexes;
573 		}
574 		else
575 		{
576 			// decide which triangles face the light
577 			sh.numFacing = 0;
578 			for(i = 0, tri = cv->triangles; i < cv->numTriangles; i++, tri++)
579 			{
580 				d = DotProduct(tri->plane, lightOrigin) - tri->plane[3];
581 				if(d > 0 && !tess.surfaceShader->cullType == CT_BACK_SIDED)
582 				{
583 					sh.facing[i] = qtrue;
584 					sh.numFacing++;
585 				}
586 				else
587 				{
588 					sh.facing[i] = qfalse;
589 				}
590 			}
591 
592 			if(backEnd.currentEntity->needZFail)
593 			{
594 				Tess_CheckOverflow(cv->numVerts * 2, sh.numFacing * (6 + 2) * 3);
595 			}
596 			else
597 			{
598 				Tess_CheckOverflow(cv->numVerts * 2, sh.numFacing * 6 * 3);
599 			}
600 
601 			// set up indices for silhouette edges
602 			for(i = 0, tri = cv->triangles; i < cv->numTriangles; i++, tri++)
603 			{
604 				if(!sh.facing[i])
605 				{
606 					continue;
607 				}
608 
609 				if((tri->neighbors[0] < 0) || (tri->neighbors[0] >= 0 && !sh.facing[tri->neighbors[0]]))
610 				{
611 					tess.indexes[tess.numIndexes + 0] = tess.numVertexes + tri->indexes[1];
612 					tess.indexes[tess.numIndexes + 1] = tess.numVertexes + tri->indexes[0];
613 					tess.indexes[tess.numIndexes + 2] = tess.numVertexes + tri->indexes[0] + cv->numVerts;
614 
615 					tess.indexes[tess.numIndexes + 3] = tess.numVertexes + tri->indexes[1];
616 					tess.indexes[tess.numIndexes + 4] = tess.numVertexes + tri->indexes[0] + cv->numVerts;
617 					tess.indexes[tess.numIndexes + 5] = tess.numVertexes + tri->indexes[1] + cv->numVerts;
618 
619 					tess.numIndexes += 6;
620 					backEnd.pc.c_shadowIndexes += 6;
621 				}
622 
623 				if((tri->neighbors[1] < 0) || (tri->neighbors[1] >= 0 && !sh.facing[tri->neighbors[1]]))
624 				{
625 					tess.indexes[tess.numIndexes + 0] = tess.numVertexes + tri->indexes[2];
626 					tess.indexes[tess.numIndexes + 1] = tess.numVertexes + tri->indexes[1];
627 					tess.indexes[tess.numIndexes + 2] = tess.numVertexes + tri->indexes[1] + cv->numVerts;
628 
629 					tess.indexes[tess.numIndexes + 3] = tess.numVertexes + tri->indexes[2];
630 					tess.indexes[tess.numIndexes + 4] = tess.numVertexes + tri->indexes[1] + cv->numVerts;
631 					tess.indexes[tess.numIndexes + 5] = tess.numVertexes + tri->indexes[2] + cv->numVerts;
632 
633 					tess.numIndexes += 6;
634 					backEnd.pc.c_shadowIndexes += 6;
635 				}
636 
637 				if((tri->neighbors[2] < 0) || (tri->neighbors[2] >= 0 && !sh.facing[tri->neighbors[2]]))
638 				{
639 					tess.indexes[tess.numIndexes + 0] = tess.numVertexes + tri->indexes[0];
640 					tess.indexes[tess.numIndexes + 1] = tess.numVertexes + tri->indexes[2];
641 					tess.indexes[tess.numIndexes + 2] = tess.numVertexes + tri->indexes[2] + cv->numVerts;
642 
643 					tess.indexes[tess.numIndexes + 3] = tess.numVertexes + tri->indexes[0];
644 					tess.indexes[tess.numIndexes + 4] = tess.numVertexes + tri->indexes[2] + cv->numVerts;
645 					tess.indexes[tess.numIndexes + 5] = tess.numVertexes + tri->indexes[0] + cv->numVerts;
646 
647 					tess.numIndexes += 6;
648 					backEnd.pc.c_shadowIndexes += 6;
649 				}
650 			}
651 
652 			// set up indices for light and dark caps
653 			if(backEnd.currentEntity->needZFail)
654 			{
655 				for(i = 0, tri = cv->triangles; i < cv->numTriangles; i++, tri++)
656 				{
657 					if(!sh.facing[i])
658 					{
659 						continue;
660 					}
661 
662 					// light cap
663 					tess.indexes[tess.numIndexes + 0] = tess.numVertexes + tri->indexes[0];
664 					tess.indexes[tess.numIndexes + 1] = tess.numVertexes + tri->indexes[1];
665 					tess.indexes[tess.numIndexes + 2] = tess.numVertexes + tri->indexes[2];
666 
667 					// dark cap
668 					tess.indexes[tess.numIndexes + 3] = tess.numVertexes + tri->indexes[2] + cv->numVerts;
669 					tess.indexes[tess.numIndexes + 4] = tess.numVertexes + tri->indexes[1] + cv->numVerts;
670 					tess.indexes[tess.numIndexes + 5] = tess.numVertexes + tri->indexes[0] + cv->numVerts;
671 
672 					tess.numIndexes += 6;
673 					backEnd.pc.c_shadowIndexes += 6;
674 				}
675 			}
676 		}
677 
678 		// copy vertexes and extrude to infinity
679 		for(i = 0, dv = cv->verts, xyz = tess.xyz[tess.numVertexes]; i < cv->numVerts; i++, dv++, xyz += 4)
680 		{
681 			xyz[0] = dv->xyz[0];
682 			xyz[1] = dv->xyz[1];
683 			xyz[2] = dv->xyz[2];
684 			xyz[3] = 1.0;
685 		}
686 
687 		for(i = 0, dv = cv->verts, xyz = tess.xyz[tess.numVertexes + cv->numVerts]; i < cv->numVerts; i++, dv++, xyz += 4)
688 		{
689 			#if 1
690 			xyz[0] = dv->xyz[0];
691 			xyz[1] = dv->xyz[1];
692 			xyz[2] = dv->xyz[2];
693 			#else
694 			xyz[0] = dv->xyz[0] - lightOrigin[0];
695 			xyz[1] = dv->xyz[1] - lightOrigin[1];
696 			xyz[2] = dv->xyz[2] - lightOrigin[2];
697 			#endif
698 			xyz[3] = 0.0;
699 		}
700 
701 		tess.numVertexes += cv->numVerts * 2;
702 		backEnd.pc.c_shadowVertexes += cv->numVerts * 2;
703 
704 		backEnd.pc.c_shadowSurfaces++;
705 	}
706 	else
707 	{
708 		if(glConfig2.vertexBufferObjectAvailable && (cv->indexesVBO || cv->vertsVBO) && r_vboCurves->integer)
709 		{
710 			Tess_EndBegin();
711 		}
712 
713 		if(glConfig2.vertexBufferObjectAvailable && cv->indexesVBO && r_vboCurves->integer)
714 		{
715 			Tess_CheckOverflow(cv->numVerts, cv->numTriangles * 3);
716 
717 			tess.indexesVBO = cv->indexesVBO;
718 			qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, tess.indexesVBO);
719 
720 			tess.numIndexes += cv->numTriangles * 3;
721 		}
722 		else
723 		{
724 			if(numLightIndexes)
725 			{
726 				Tess_CheckOverflow(cv->numVerts, numLightIndexes);
727 
728 				for(i = 0; i < numLightIndexes; i++)
729 				{
730 					tess.indexes[tess.numIndexes + i] = tess.numVertexes + lightIndexes[i];
731 				}
732 
733 				tess.numIndexes += numLightIndexes;
734 			}
735 			else
736 			{
737 				Tess_CheckOverflow(cv->numVerts, cv->numTriangles * 3);
738 
739 				for(i = 0, tri = cv->triangles; i < cv->numTriangles; i++, tri++)
740 				{
741 					tess.indexes[tess.numIndexes + i * 3 + 0] = tess.numVertexes + tri->indexes[0];
742 					tess.indexes[tess.numIndexes + i * 3 + 1] = tess.numVertexes + tri->indexes[1];
743 					tess.indexes[tess.numIndexes + i * 3 + 2] = tess.numVertexes + tri->indexes[2];
744 				}
745 
746 				tess.numIndexes += cv->numTriangles * 3;
747 			}
748 		}
749 
750 		if(glConfig2.vertexBufferObjectAvailable && cv->vertsVBO && r_vboCurves->integer)
751 		{
752 			tess.vertexesVBO = cv->vertsVBO;
753 			tess.ofsXYZ = cv->ofsXYZ;
754 			tess.ofsTexCoords = cv->ofsTexCoords;
755 			tess.ofsTexCoords2 = cv->ofsTexCoords2;
756 			tess.ofsTangents = cv->ofsTangents;
757 			tess.ofsBinormals = cv->ofsBinormals;
758 			tess.ofsNormals = cv->ofsNormals;
759 			tess.ofsColors = cv->ofsColors;
760 
761 			qglBindBufferARB(GL_ARRAY_BUFFER_ARB, tess.vertexesVBO);
762 		}
763 		else
764 		{
765 			dv = cv->verts;
766 			xyz = tess.xyz[tess.numVertexes];
767 			tangent = tess.tangents[tess.numVertexes];
768 			binormal = tess.binormals[tess.numVertexes];
769 			normal = tess.normals[tess.numVertexes];
770 			texCoords = tess.texCoords[tess.numVertexes][0];
771 			color = tess.colors[tess.numVertexes];
772 
773 			for(i = 0; i < cv->numVerts;
774 				i++, dv++, xyz += 4, tangent += 4, binormal += 4, normal += 4, texCoords += 4, color += 4)
775 			{
776 				xyz[0] = dv->xyz[0];
777 				xyz[1] = dv->xyz[1];
778 				xyz[2] = dv->xyz[2];
779 				xyz[3] = 1;
780 
781 				if(!tess.skipTangentSpaces)
782 				{
783 					tangent[0] = dv->tangent[0];
784 					tangent[1] = dv->tangent[1];
785 					tangent[2] = dv->tangent[2];
786 
787 					binormal[0] = dv->binormal[0];
788 					binormal[1] = dv->binormal[1];
789 					binormal[2] = dv->binormal[2];
790 
791 					normal[0] = dv->normal[0];
792 					normal[1] = dv->normal[1];
793 					normal[2] = dv->normal[2];
794 				}
795 
796 				texCoords[0] = dv->st[0];
797 				texCoords[1] = dv->st[1];
798 
799 				texCoords[2] = dv->lightmap[0];
800 				texCoords[3] = dv->lightmap[1];
801 
802 				*(int *)color = *(int *)dv->color;
803 			}
804 		}
805 
806 		tess.numVertexes += cv->numVerts;
807 	}
808 }
809 
810 /*
811 =============
812 Tess_SurfaceTriangles
813 =============
814 */
Tess_SurfaceTriangles(srfTriangles_t * cv,int numLightIndexes,int * lightIndexes,int numShadowIndexes,int * shadowIndexes)815 static void Tess_SurfaceTriangles(srfTriangles_t * cv, int numLightIndexes, int *lightIndexes, int numShadowIndexes, int *shadowIndexes)
816 {
817 	int             i;
818 	srfTriangle_t  *tri;
819 	srfVert_t      *dv;
820 	float          *xyz, *tangent, *binormal, *normal, *texCoords;
821 	byte           *color;
822 	vec3_t          lightOrigin;
823 	float           d;
824 
825 	GLimp_LogComment("--- Tess_SurfaceTriangles ---\n");
826 
827 	if(tess.shadowVolume)
828 	{
829 		VectorCopy(backEnd.currentLight->transformed, lightOrigin);
830 
831 		if(numShadowIndexes)
832 		{
833 			// this case is always zfail with light and dark caps
834 			Tess_CheckOverflow(cv->numVerts, numShadowIndexes);
835 
836 			for(i = 0; i < numShadowIndexes; i++)
837 			{
838 				tess.indexes[tess.numIndexes + i] = tess.numVertexes + shadowIndexes[i];
839 			}
840 
841 			tess.numIndexes += numShadowIndexes;
842 			backEnd.pc.c_shadowIndexes += numShadowIndexes;
843 		}
844 		else
845 		{
846 			// decide which triangles face the light
847 			sh.numFacing = 0;
848 			for(i = 0, tri = cv->triangles; i < cv->numTriangles; i++, tri++)
849 			{
850 				d = DotProduct(tri->plane, lightOrigin) - tri->plane[3];
851 				if(d > 0 && !tess.surfaceShader->cullType == CT_BACK_SIDED)
852 				{
853 					sh.facing[i] = qtrue;
854 					sh.numFacing++;
855 				}
856 				else
857 				{
858 					sh.facing[i] = qfalse;
859 				}
860 			}
861 
862 			if(backEnd.currentEntity->needZFail)
863 			{
864 				Tess_CheckOverflow(cv->numVerts * 2, sh.numFacing * (6 + 2) * 3);
865 			}
866 			else
867 			{
868 				Tess_CheckOverflow(cv->numVerts * 2, sh.numFacing * 6 * 3);
869 			}
870 
871 			// set up indices for silhouette edges
872 			for(i = 0, tri = cv->triangles; i < cv->numTriangles; i++, tri++)
873 			{
874 				if(!sh.facing[i])
875 				{
876 					continue;
877 				}
878 
879 				if((tri->neighbors[0] < 0) || (tri->neighbors[0] >= 0 && !sh.facing[tri->neighbors[0]]))
880 				{
881 					tess.indexes[tess.numIndexes + 0] = tess.numVertexes + tri->indexes[1];
882 					tess.indexes[tess.numIndexes + 1] = tess.numVertexes + tri->indexes[0];
883 					tess.indexes[tess.numIndexes + 2] = tess.numVertexes + tri->indexes[0] + cv->numVerts;
884 
885 					tess.indexes[tess.numIndexes + 3] = tess.numVertexes + tri->indexes[1];
886 					tess.indexes[tess.numIndexes + 4] = tess.numVertexes + tri->indexes[0] + cv->numVerts;
887 					tess.indexes[tess.numIndexes + 5] = tess.numVertexes + tri->indexes[1] + cv->numVerts;
888 
889 					tess.numIndexes += 6;
890 					backEnd.pc.c_shadowIndexes += 6;
891 				}
892 
893 				if((tri->neighbors[1] < 0) || (tri->neighbors[1] >= 0 && !sh.facing[tri->neighbors[1]]))
894 				{
895 					tess.indexes[tess.numIndexes + 0] = tess.numVertexes + tri->indexes[2];
896 					tess.indexes[tess.numIndexes + 1] = tess.numVertexes + tri->indexes[1];
897 					tess.indexes[tess.numIndexes + 2] = tess.numVertexes + tri->indexes[1] + cv->numVerts;
898 
899 					tess.indexes[tess.numIndexes + 3] = tess.numVertexes + tri->indexes[2];
900 					tess.indexes[tess.numIndexes + 4] = tess.numVertexes + tri->indexes[1] + cv->numVerts;
901 					tess.indexes[tess.numIndexes + 5] = tess.numVertexes + tri->indexes[2] + cv->numVerts;
902 
903 					tess.numIndexes += 6;
904 					backEnd.pc.c_shadowIndexes += 6;
905 				}
906 
907 				if((tri->neighbors[2] < 0) || (tri->neighbors[2] >= 0 && !sh.facing[tri->neighbors[2]]))
908 				{
909 					tess.indexes[tess.numIndexes + 0] = tess.numVertexes + tri->indexes[0];
910 					tess.indexes[tess.numIndexes + 1] = tess.numVertexes + tri->indexes[2];
911 					tess.indexes[tess.numIndexes + 2] = tess.numVertexes + tri->indexes[2] + cv->numVerts;
912 
913 					tess.indexes[tess.numIndexes + 3] = tess.numVertexes + tri->indexes[0];
914 					tess.indexes[tess.numIndexes + 4] = tess.numVertexes + tri->indexes[2] + cv->numVerts;
915 					tess.indexes[tess.numIndexes + 5] = tess.numVertexes + tri->indexes[0] + cv->numVerts;
916 
917 					tess.numIndexes += 6;
918 					backEnd.pc.c_shadowIndexes += 6;
919 				}
920 			}
921 
922 			// set up indices for light and dark caps
923 			if(backEnd.currentEntity->needZFail)
924 			{
925 				for(i = 0, tri = cv->triangles; i < cv->numTriangles; i++, tri++)
926 				{
927 					if(!sh.facing[i])
928 					{
929 						continue;
930 					}
931 
932 					// light cap
933 					tess.indexes[tess.numIndexes + 0] = tess.numVertexes + tri->indexes[0];
934 					tess.indexes[tess.numIndexes + 1] = tess.numVertexes + tri->indexes[1];
935 					tess.indexes[tess.numIndexes + 2] = tess.numVertexes + tri->indexes[2];
936 
937 					// dark cap
938 					tess.indexes[tess.numIndexes + 3] = tess.numVertexes + tri->indexes[2] + cv->numVerts;
939 					tess.indexes[tess.numIndexes + 4] = tess.numVertexes + tri->indexes[1] + cv->numVerts;
940 					tess.indexes[tess.numIndexes + 5] = tess.numVertexes + tri->indexes[0] + cv->numVerts;
941 
942 					tess.numIndexes += 6;
943 					backEnd.pc.c_shadowIndexes += 6;
944 				}
945 			}
946 		}
947 
948 		// copy vertexes and extrude to infinity
949 		for(i = 0, dv = cv->verts, xyz = tess.xyz[tess.numVertexes]; i < cv->numVerts; i++, dv++, xyz += 4)
950 		{
951 			xyz[0] = dv->xyz[0];
952 			xyz[1] = dv->xyz[1];
953 			xyz[2] = dv->xyz[2];
954 			xyz[3] = 1.0;
955 		}
956 
957 		for(i = 0, dv = cv->verts, xyz = tess.xyz[tess.numVertexes + cv->numVerts]; i < cv->numVerts; i++, dv++, xyz += 4)
958 		{
959 			#if 1
960 			xyz[0] = dv->xyz[0];
961 			xyz[1] = dv->xyz[1];
962 			xyz[2] = dv->xyz[2];
963 			#else
964 			xyz[0] = dv->xyz[0] - lightOrigin[0];
965 			xyz[1] = dv->xyz[1] - lightOrigin[1];
966 			xyz[2] = dv->xyz[2] - lightOrigin[2];
967 			#endif
968 			xyz[3] = 0.0;
969 		}
970 
971 		tess.numVertexes += cv->numVerts * 2;
972 		backEnd.pc.c_shadowVertexes += cv->numVerts * 2;
973 
974 		backEnd.pc.c_shadowSurfaces++;
975 	}
976 	else
977 	{
978 		if(glConfig2.vertexBufferObjectAvailable && (cv->indexesVBO || cv->vertsVBO) && r_vboTriangles->integer)
979 		{
980 			Tess_EndBegin();
981 		}
982 
983 		if(glConfig2.vertexBufferObjectAvailable && cv->indexesVBO && r_vboTriangles->integer)
984 		{
985 			Tess_CheckOverflow(cv->numVerts, cv->numTriangles * 3);
986 
987 			tess.indexesVBO = cv->indexesVBO;
988 			qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, tess.indexesVBO);
989 
990 			tess.numIndexes += cv->numTriangles * 3;
991 		}
992 		else
993 		{
994 			if(numLightIndexes)
995 			{
996 				Tess_CheckOverflow(cv->numVerts, numLightIndexes);
997 
998 				for(i = 0; i < numLightIndexes; i++)
999 				{
1000 					tess.indexes[tess.numIndexes + i] = tess.numVertexes + lightIndexes[i];
1001 				}
1002 
1003 				tess.numIndexes += numLightIndexes;
1004 			}
1005 			else
1006 			{
1007 				Tess_CheckOverflow(cv->numVerts, cv->numTriangles * 3);
1008 
1009 				for(i = 0, tri = cv->triangles; i < cv->numTriangles; i++, tri++)
1010 				{
1011 					tess.indexes[tess.numIndexes + i * 3 + 0] = tess.numVertexes + tri->indexes[0];
1012 					tess.indexes[tess.numIndexes + i * 3 + 1] = tess.numVertexes + tri->indexes[1];
1013 					tess.indexes[tess.numIndexes + i * 3 + 2] = tess.numVertexes + tri->indexes[2];
1014 				}
1015 
1016 				tess.numIndexes += cv->numTriangles * 3;
1017 			}
1018 		}
1019 
1020 		if(glConfig2.vertexBufferObjectAvailable && cv->vertsVBO && r_vboTriangles->integer)
1021 		{
1022 			tess.vertexesVBO = cv->vertsVBO;
1023 			tess.ofsXYZ = cv->ofsXYZ;
1024 			tess.ofsTexCoords = cv->ofsTexCoords;
1025 			tess.ofsTexCoords2 = cv->ofsTexCoords;
1026 			tess.ofsTangents = cv->ofsTangents;
1027 			tess.ofsBinormals = cv->ofsBinormals;
1028 			tess.ofsNormals = cv->ofsNormals;
1029 			tess.ofsColors = cv->ofsColors;
1030 
1031 			qglBindBufferARB(GL_ARRAY_BUFFER_ARB, tess.vertexesVBO);
1032 		}
1033 		else
1034 		{
1035 			dv = cv->verts;
1036 			xyz = tess.xyz[tess.numVertexes];
1037 			tangent = tess.tangents[tess.numVertexes];
1038 			binormal = tess.binormals[tess.numVertexes];
1039 			normal = tess.normals[tess.numVertexes];
1040 			texCoords = tess.texCoords[tess.numVertexes][0];
1041 			color = tess.colors[tess.numVertexes];
1042 
1043 			for(i = 0; i < cv->numVerts;
1044 				i++, dv++, xyz += 4, tangent += 4, binormal += 4, normal += 4, texCoords += 4, color += 4)
1045 			{
1046 				xyz[0] = dv->xyz[0];
1047 				xyz[1] = dv->xyz[1];
1048 				xyz[2] = dv->xyz[2];
1049 				xyz[3] = 1;
1050 
1051 				if(!tess.skipTangentSpaces)
1052 				{
1053 					tangent[0] = dv->tangent[0];
1054 					tangent[1] = dv->tangent[1];
1055 					tangent[2] = dv->tangent[2];
1056 
1057 					binormal[0] = dv->binormal[0];
1058 					binormal[1] = dv->binormal[1];
1059 					binormal[2] = dv->binormal[2];
1060 
1061 					normal[0] = dv->normal[0];
1062 					normal[1] = dv->normal[1];
1063 					normal[2] = dv->normal[2];
1064 				}
1065 
1066 				texCoords[0] = dv->st[0];
1067 				texCoords[1] = dv->st[1];
1068 
1069 				texCoords[2] = dv->st[0];
1070 				texCoords[3] = dv->st[1];
1071 
1072 				*(int *)color = *(int *)dv->color;
1073 			}
1074 		}
1075 
1076 		tess.numVertexes += cv->numVerts;
1077 	}
1078 }
1079 
1080 
1081 
1082 /*
1083 ==============
1084 Tess_SurfaceBeam
1085 ==============
1086 */
Tess_SurfaceBeam(void)1087 static void Tess_SurfaceBeam(void)
1088 {
1089 #define NUM_BEAM_SEGS 6
1090 	refEntity_t *e;
1091 	int             i;
1092 	vec3_t          perpvec;
1093 	vec3_t          direction, normalized_direction;
1094 	vec3_t          start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS];
1095 	vec3_t          oldorigin, origin;
1096 
1097 	GLimp_LogComment("--- Tess_SurfaceBeam ---\n");
1098 
1099 	e = &backEnd.currentEntity->e;
1100 
1101 	oldorigin[0] = e->oldorigin[0];
1102 	oldorigin[1] = e->oldorigin[1];
1103 	oldorigin[2] = e->oldorigin[2];
1104 
1105 	origin[0] = e->origin[0];
1106 	origin[1] = e->origin[1];
1107 	origin[2] = e->origin[2];
1108 
1109 	normalized_direction[0] = direction[0] = oldorigin[0] - origin[0];
1110 	normalized_direction[1] = direction[1] = oldorigin[1] - origin[1];
1111 	normalized_direction[2] = direction[2] = oldorigin[2] - origin[2];
1112 
1113 	if(VectorNormalize(normalized_direction) == 0)
1114 		return;
1115 
1116 	PerpendicularVector(perpvec, normalized_direction);
1117 
1118 	VectorScale(perpvec, 4, perpvec);
1119 
1120 	for(i = 0; i < NUM_BEAM_SEGS; i++)
1121 	{
1122 		RotatePointAroundVector(start_points[i], normalized_direction, perpvec, (360.0 / NUM_BEAM_SEGS) * i);
1123 //      VectorAdd( start_points[i], origin, start_points[i] );
1124 		VectorAdd(start_points[i], direction, end_points[i]);
1125 	}
1126 
1127 	GL_Program(0);
1128 	GL_SelectTexture(0);
1129 	GL_Bind(tr.whiteImage);
1130 
1131 	GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
1132 
1133 	qglColor3f(1, 0, 0);
1134 
1135 	qglBegin(GL_TRIANGLE_STRIP);
1136 	for(i = 0; i <= NUM_BEAM_SEGS; i++)
1137 	{
1138 		qglVertex3fv(start_points[i % NUM_BEAM_SEGS]);
1139 		qglVertex3fv(end_points[i % NUM_BEAM_SEGS]);
1140 	}
1141 	qglEnd();
1142 }
1143 
1144 //================================================================================
1145 
Tess_DoRailCore(const vec3_t start,const vec3_t end,const vec3_t up,float len,float spanWidth)1146 static void Tess_DoRailCore(const vec3_t start, const vec3_t end, const vec3_t up, float len, float spanWidth)
1147 {
1148 	float           spanWidth2;
1149 	int             vbase;
1150 	float           t = len / 256.0f;
1151 
1152 	vbase = tess.numVertexes;
1153 
1154 	spanWidth2 = -spanWidth;
1155 
1156 	// FIXME: use quad stamp?
1157 	VectorMA(start, spanWidth, up, tess.xyz[tess.numVertexes]);
1158 	tess.xyz[tess.numVertexes][3] = 1;
1159 	tess.texCoords[tess.numVertexes][0][0] = 0;
1160 	tess.texCoords[tess.numVertexes][0][1] = 0;
1161 	tess.colors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 0.25;
1162 	tess.colors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 0.25;
1163 	tess.colors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 0.25;
1164 	tess.numVertexes++;
1165 
1166 	VectorMA(start, spanWidth2, up, tess.xyz[tess.numVertexes]);
1167 	tess.xyz[tess.numVertexes][3] = 1;
1168 	tess.texCoords[tess.numVertexes][0][0] = 0;
1169 	tess.texCoords[tess.numVertexes][0][1] = 1;
1170 	tess.colors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0];
1171 	tess.colors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1];
1172 	tess.colors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2];
1173 	tess.numVertexes++;
1174 
1175 	VectorMA(end, spanWidth, up, tess.xyz[tess.numVertexes]);
1176 	tess.xyz[tess.numVertexes][3] = 1;
1177 	tess.texCoords[tess.numVertexes][0][0] = t;
1178 	tess.texCoords[tess.numVertexes][0][1] = 0;
1179 	tess.colors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0];
1180 	tess.colors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1];
1181 	tess.colors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2];
1182 	tess.numVertexes++;
1183 
1184 	VectorMA(end, spanWidth2, up, tess.xyz[tess.numVertexes]);
1185 	tess.xyz[tess.numVertexes][3] = 1;
1186 	tess.texCoords[tess.numVertexes][0][0] = t;
1187 	tess.texCoords[tess.numVertexes][0][1] = 1;
1188 	tess.colors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0];
1189 	tess.colors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1];
1190 	tess.colors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2];
1191 	tess.numVertexes++;
1192 
1193 	tess.indexes[tess.numIndexes++] = vbase;
1194 	tess.indexes[tess.numIndexes++] = vbase + 1;
1195 	tess.indexes[tess.numIndexes++] = vbase + 2;
1196 
1197 	tess.indexes[tess.numIndexes++] = vbase + 2;
1198 	tess.indexes[tess.numIndexes++] = vbase + 1;
1199 	tess.indexes[tess.numIndexes++] = vbase + 3;
1200 }
1201 
Tess_DoRailDiscs(int numSegs,const vec3_t start,const vec3_t dir,const vec3_t right,const vec3_t up)1202 static void Tess_DoRailDiscs(int numSegs, const vec3_t start, const vec3_t dir, const vec3_t right, const vec3_t up)
1203 {
1204 	int             i;
1205 	vec3_t          pos[4];
1206 	vec3_t          v;
1207 	int             spanWidth = r_railWidth->integer;
1208 	float           c, s;
1209 	float           scale;
1210 
1211 	if(numSegs > 1)
1212 		numSegs--;
1213 	if(!numSegs)
1214 		return;
1215 
1216 	scale = 0.25;
1217 
1218 	for(i = 0; i < 4; i++)
1219 	{
1220 		c = cos(DEG2RAD(45 + i * 90));
1221 		s = sin(DEG2RAD(45 + i * 90));
1222 		v[0] = (right[0] * c + up[0] * s) * scale * spanWidth;
1223 		v[1] = (right[1] * c + up[1] * s) * scale * spanWidth;
1224 		v[2] = (right[2] * c + up[2] * s) * scale * spanWidth;
1225 		VectorAdd(start, v, pos[i]);
1226 
1227 		if(numSegs > 1)
1228 		{
1229 			// offset by 1 segment if we're doing a long distance shot
1230 			VectorAdd(pos[i], dir, pos[i]);
1231 		}
1232 	}
1233 
1234 	for(i = 0; i < numSegs; i++)
1235 	{
1236 		int             j;
1237 
1238 		Tess_CheckOverflow(4, 6);
1239 
1240 		for(j = 0; j < 4; j++)
1241 		{
1242 			VectorCopy(pos[j], tess.xyz[tess.numVertexes]);
1243 			tess.xyz[tess.numVertexes][3] = 1;
1244 			tess.texCoords[tess.numVertexes][0][0] = (j < 2);
1245 			tess.texCoords[tess.numVertexes][0][1] = (j && j != 3);
1246 			tess.colors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0];
1247 			tess.colors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1];
1248 			tess.colors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2];
1249 			tess.numVertexes++;
1250 
1251 			VectorAdd(pos[j], dir, pos[j]);
1252 		}
1253 
1254 		tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 0;
1255 		tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1;
1256 		tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3;
1257 		tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3;
1258 		tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1;
1259 		tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 2;
1260 	}
1261 }
1262 
1263 /*
1264 ==============
1265 Tess_SurfaceRailRings
1266 ==============
1267 */
Tess_SurfaceRailRings(void)1268 static void Tess_SurfaceRailRings(void)
1269 {
1270 	refEntity_t *e;
1271 	int             numSegs;
1272 	int             len;
1273 	vec3_t          vec;
1274 	vec3_t          right, up;
1275 	vec3_t          start, end;
1276 
1277 	GLimp_LogComment("--- Tess_SurfaceRailRings ---\n");
1278 
1279 	e = &backEnd.currentEntity->e;
1280 
1281 	VectorCopy(e->oldorigin, start);
1282 	VectorCopy(e->origin, end);
1283 
1284 	// compute variables
1285 	VectorSubtract(end, start, vec);
1286 	len = VectorNormalize(vec);
1287 	MakeNormalVectors(vec, right, up);
1288 	numSegs = (len) / r_railSegmentLength->value;
1289 	if(numSegs <= 0)
1290 	{
1291 		numSegs = 1;
1292 	}
1293 
1294 	VectorScale(vec, r_railSegmentLength->value, vec);
1295 
1296 	Tess_DoRailDiscs(numSegs, start, vec, right, up);
1297 }
1298 
1299 /*
1300 ==============
1301 Tess_SurfaceRailCore
1302 ==============
1303 */
Tess_SurfaceRailCore(void)1304 static void Tess_SurfaceRailCore(void)
1305 {
1306 	refEntity_t *e;
1307 	int             len;
1308 	vec3_t          right;
1309 	vec3_t          vec;
1310 	vec3_t          start, end;
1311 	vec3_t          v1, v2;
1312 
1313 	GLimp_LogComment("--- Tess_SurfaceRailCore ---\n");
1314 
1315 	e = &backEnd.currentEntity->e;
1316 
1317 	VectorCopy(e->oldorigin, start);
1318 	VectorCopy(e->origin, end);
1319 
1320 	VectorSubtract(end, start, vec);
1321 	len = VectorNormalize(vec);
1322 
1323 	// compute side vector
1324 	VectorSubtract(start, backEnd.viewParms.or.origin, v1);
1325 	VectorNormalize(v1);
1326 	VectorSubtract(end, backEnd.viewParms.or.origin, v2);
1327 	VectorNormalize(v2);
1328 	CrossProduct(v1, v2, right);
1329 	VectorNormalize(right);
1330 
1331 	Tess_DoRailCore(start, end, right, len, r_railCoreWidth->integer);
1332 }
1333 
1334 /*
1335 ==============
1336 Tess_SurfaceLightningBolt
1337 ==============
1338 */
Tess_SurfaceLightningBolt(void)1339 static void Tess_SurfaceLightningBolt(void)
1340 {
1341 	refEntity_t *e;
1342 	int             len;
1343 	vec3_t          right;
1344 	vec3_t          vec;
1345 	vec3_t          start, end;
1346 	vec3_t          v1, v2;
1347 	int             i;
1348 
1349 	GLimp_LogComment("--- Tess_SurfaceLightningBolt ---\n");
1350 
1351 	e = &backEnd.currentEntity->e;
1352 
1353 	VectorCopy(e->oldorigin, end);
1354 	VectorCopy(e->origin, start);
1355 
1356 	// compute variables
1357 	VectorSubtract(end, start, vec);
1358 	len = VectorNormalize(vec);
1359 
1360 	// compute side vector
1361 	VectorSubtract(start, backEnd.viewParms.or.origin, v1);
1362 	VectorNormalize(v1);
1363 	VectorSubtract(end, backEnd.viewParms.or.origin, v2);
1364 	VectorNormalize(v2);
1365 	CrossProduct(v1, v2, right);
1366 	VectorNormalize(right);
1367 
1368 	for(i = 0; i < 4; i++)
1369 	{
1370 		vec3_t          temp;
1371 
1372 		Tess_DoRailCore(start, end, right, len, 8);
1373 		RotatePointAroundVector(temp, vec, right, 45);
1374 		VectorCopy(temp, right);
1375 	}
1376 }
1377 
1378 /*
1379 ==============
1380 VectorArrayNormalize
1381 
1382 The inputs to this routing seem to always be close to length = 1.0 (about 0.6 to 2.0)
1383 This means that we don't have to worry about zero length or enormously long vectors.
1384 ==============
1385 */
VectorArrayNormalize(vec4_t * normals,unsigned int count)1386 static void VectorArrayNormalize(vec4_t * normals, unsigned int count)
1387 {
1388 //    assert(count);
1389 
1390 #if idppc
1391 	{
1392 		register float  half = 0.5;
1393 		register float  one = 1.0;
1394 		float          *components = (float *)normals;
1395 
1396 		// Vanilla PPC code, but since PPC has a reciprocal square root estimate instruction,
1397 		// runs *much* faster than calling sqrt().  We'll use a single Newton-Raphson
1398 		// refinement step to get a little more precision.  This seems to yeild results
1399 		// that are correct to 3 decimal places and usually correct to at least 4 (sometimes 5).
1400 		// (That is, for the given input range of about 0.6 to 2.0).
1401 		do
1402 		{
1403 			float           x, y, z;
1404 			float           B, y0, y1;
1405 
1406 			x = components[0];
1407 			y = components[1];
1408 			z = components[2];
1409 			components += 4;
1410 			B = x * x + y * y + z * z;
1411 
1412 #ifdef __GNUC__
1413 		  asm("frsqrte %0,%1": "=f"(y0):"f"(B));
1414 #else
1415 			y0 = __frsqrte(B);
1416 #endif
1417 			y1 = y0 + half * y0 * (one - B * y0 * y0);
1418 
1419 			x = x * y1;
1420 			y = y * y1;
1421 			components[-4] = x;
1422 			z = z * y1;
1423 			components[-3] = y;
1424 			components[-2] = z;
1425 		} while(count--);
1426 	}
1427 #else							// No assembly version for this architecture, or C_ONLY defined
1428 	// given the input, it's safe to call VectorNormalizeFast
1429 	while(count--)
1430 	{
1431 		VectorNormalizeFast(normals[0]);
1432 		normals++;
1433 	}
1434 #endif
1435 
1436 }
1437 
1438 /*
1439 =============
1440 Tess_SurfaceMDX
1441 =============
1442 */
Tess_SurfaceMDX(mdxSurface_t * srf,int numLightIndexes,int * lightIndexes,int numShadowIndexes,int * shadowIndexes)1443 void Tess_SurfaceMDX(mdxSurface_t * srf, int numLightIndexes, int *lightIndexes, int numShadowIndexes, int *shadowIndexes)
1444 {
1445 	int             i, j;
1446 	int             numIndexes = 0;
1447 	int             numVertexes;
1448 	mdxModel_t     *model;
1449 	mdxVertex_t    *oldVert, *newVert;
1450 	mdxSt_t        *st;
1451 	srfTriangle_t  *tri;
1452 	vec3_t          lightOrigin;
1453 	float           backlerp;
1454 	float           oldXyzScale, newXyzScale;
1455 
1456 	GLimp_LogComment("--- Tess_SurfaceMDX ---\n");
1457 
1458 	if(backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame)
1459 	{
1460 		backlerp = 0;
1461 	}
1462 	else
1463 	{
1464 		backlerp = backEnd.currentEntity->e.backlerp;
1465 	}
1466 
1467 	newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp);
1468 	oldXyzScale = MD3_XYZ_SCALE * backlerp;
1469 
1470 	if(tess.shadowVolume)
1471 	{
1472 		if(backEnd.currentEntity->needZFail)
1473 		{
1474 			Tess_CheckOverflow(srf->numVerts * 2, srf->numTriangles * (6 + 2) * 3);
1475 		}
1476 		else
1477 		{
1478 			Tess_CheckOverflow(srf->numVerts * 2, srf->numTriangles * 6 * 3);
1479 		}
1480 
1481 		model = srf->model;
1482 
1483 		VectorCopy(backEnd.currentLight->transformed, lightOrigin);
1484 
1485 		// lerp vertices and extrude to infinity
1486 		newVert = srf->verts + (backEnd.currentEntity->e.frame * srf->numVerts);
1487 		oldVert = srf->verts + (backEnd.currentEntity->e.oldframe * srf->numVerts);
1488 
1489 		numVertexes = srf->numVerts;
1490 		for(j = 0; j < numVertexes; j++, newVert++, oldVert++)
1491 		{
1492 			vec3_t          tmpVert;
1493 
1494 			if(backlerp == 0)
1495 			{
1496 				// just copy
1497 				tmpVert[0] = newVert->xyz[0] * newXyzScale;
1498 				tmpVert[1] = newVert->xyz[1] * newXyzScale;
1499 				tmpVert[2] = newVert->xyz[2] * newXyzScale;
1500 			}
1501 			else
1502 			{
1503 				// interpolate the xyz
1504 				tmpVert[0] = oldVert->xyz[0] * oldXyzScale + newVert->xyz[0] * newXyzScale;
1505 				tmpVert[1] = oldVert->xyz[1] * oldXyzScale + newVert->xyz[1] * newXyzScale;
1506 				tmpVert[2] = oldVert->xyz[2] * oldXyzScale + newVert->xyz[2] * newXyzScale;
1507 			}
1508 
1509 			tess.xyz[tess.numVertexes + j][0] = tmpVert[0];
1510 			tess.xyz[tess.numVertexes + j][1] = tmpVert[1];
1511 			tess.xyz[tess.numVertexes + j][2] = tmpVert[2];
1512 			tess.xyz[tess.numVertexes + j][3] = 1;
1513 
1514 			#if 1
1515 			tess.xyz[tess.numVertexes + numVertexes + j][0] = tmpVert[0];
1516 			tess.xyz[tess.numVertexes + numVertexes + j][1] = tmpVert[1];
1517 			tess.xyz[tess.numVertexes + numVertexes + j][2] = tmpVert[2];
1518 			tess.xyz[tess.numVertexes + numVertexes + j][3] = 0;
1519 			#else
1520 			tess.xyz[tess.numVertexes + numVertexes + j][0] = tmpVert[0] - lightOrigin[0];
1521 			tess.xyz[tess.numVertexes + numVertexes + j][1] = tmpVert[1] - lightOrigin[1];
1522 			tess.xyz[tess.numVertexes + numVertexes + j][2] = tmpVert[2] - lightOrigin[2];
1523 			tess.xyz[tess.numVertexes + numVertexes + j][3] = 0;
1524 			#endif
1525 		}
1526 
1527 		// decide which triangles face the light
1528 		for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
1529 		{
1530 			float          *v1, *v2, *v3;
1531 			vec3_t          d1, d2;
1532 			vec4_t          plane;
1533 			float           d;
1534 
1535 			v1 = tess.xyz[tess.numVertexes + tri->indexes[0]];
1536 			v2 = tess.xyz[tess.numVertexes + tri->indexes[1]];
1537 			v3 = tess.xyz[tess.numVertexes + tri->indexes[2]];
1538 
1539 			VectorSubtract(v2, v1, d1);
1540 			VectorSubtract(v3, v1, d2);
1541 
1542 			CrossProduct(d2, d1, plane);
1543 			plane[3] = DotProduct(plane, v1);
1544 
1545 			d = DotProduct(plane, lightOrigin) - plane[3];
1546 			if(d > 0 && !tess.surfaceShader->cullType == CT_BACK_SIDED)
1547 			{
1548 				sh.facing[i] = qtrue;
1549 			}
1550 			else
1551 			{
1552 				sh.facing[i] = qfalse;
1553 			}
1554 		}
1555 
1556 		// set up indices for silhouette edges
1557 		for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
1558 		{
1559 			if(!sh.facing[i])
1560 			{
1561 				continue;
1562 			}
1563 
1564 			if((tri->neighbors[0] < 0) || (tri->neighbors[0] >= 0 && !sh.facing[tri->neighbors[0]]))
1565 			{
1566 				tess.indexes[tess.numIndexes + 0] = tess.numVertexes + tri->indexes[1];
1567 				tess.indexes[tess.numIndexes + 1] = tess.numVertexes + tri->indexes[0];
1568 				tess.indexes[tess.numIndexes + 2] = tess.numVertexes + tri->indexes[0] + srf->numVerts;
1569 
1570 				tess.indexes[tess.numIndexes + 3] = tess.numVertexes + tri->indexes[1];
1571 				tess.indexes[tess.numIndexes + 4] = tess.numVertexes + tri->indexes[0] + srf->numVerts;
1572 				tess.indexes[tess.numIndexes + 5] = tess.numVertexes + tri->indexes[1] + srf->numVerts;
1573 
1574 				tess.numIndexes += 6;
1575 				backEnd.pc.c_shadowIndexes += 6;
1576 			}
1577 
1578 			if((tri->neighbors[1] < 0) || (tri->neighbors[1] >= 0 && !sh.facing[tri->neighbors[1]]))
1579 			{
1580 				tess.indexes[tess.numIndexes + 0] = tess.numVertexes + tri->indexes[2];
1581 				tess.indexes[tess.numIndexes + 1] = tess.numVertexes + tri->indexes[1];
1582 				tess.indexes[tess.numIndexes + 2] = tess.numVertexes + tri->indexes[1] + srf->numVerts;
1583 
1584 				tess.indexes[tess.numIndexes + 3] = tess.numVertexes + tri->indexes[2];
1585 				tess.indexes[tess.numIndexes + 4] = tess.numVertexes + tri->indexes[1] + srf->numVerts;
1586 				tess.indexes[tess.numIndexes + 5] = tess.numVertexes + tri->indexes[2] + srf->numVerts;
1587 
1588 				tess.numIndexes += 6;
1589 				backEnd.pc.c_shadowIndexes += 6;
1590 			}
1591 
1592 			if((tri->neighbors[2] < 0) || (tri->neighbors[2] >= 0 && !sh.facing[tri->neighbors[2]]))
1593 			{
1594 				tess.indexes[tess.numIndexes + 0] = tess.numVertexes + tri->indexes[0];
1595 				tess.indexes[tess.numIndexes + 1] = tess.numVertexes + tri->indexes[2];
1596 				tess.indexes[tess.numIndexes + 2] = tess.numVertexes + tri->indexes[2] + srf->numVerts;
1597 
1598 				tess.indexes[tess.numIndexes + 3] = tess.numVertexes + tri->indexes[0];
1599 				tess.indexes[tess.numIndexes + 4] = tess.numVertexes + tri->indexes[2] + srf->numVerts;
1600 				tess.indexes[tess.numIndexes + 5] = tess.numVertexes + tri->indexes[0] + srf->numVerts;
1601 
1602 				tess.numIndexes += 6;
1603 				backEnd.pc.c_shadowIndexes += 6;
1604 			}
1605 		}
1606 
1607 		// set up indices for light and dark caps
1608 		if(backEnd.currentEntity->needZFail)
1609 		{
1610 			for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
1611 			{
1612 				if(!sh.facing[i])
1613 				{
1614 					continue;
1615 				}
1616 
1617 				// light cap
1618 				tess.indexes[tess.numIndexes + 0] = tess.numVertexes + tri->indexes[0];
1619 				tess.indexes[tess.numIndexes + 1] = tess.numVertexes + tri->indexes[1];
1620 				tess.indexes[tess.numIndexes + 2] = tess.numVertexes + tri->indexes[2];
1621 
1622 				// dark cap
1623 				tess.indexes[tess.numIndexes + 3] = tess.numVertexes + tri->indexes[2] + srf->numVerts;
1624 				tess.indexes[tess.numIndexes + 4] = tess.numVertexes + tri->indexes[1] + srf->numVerts;
1625 				tess.indexes[tess.numIndexes + 5] = tess.numVertexes + tri->indexes[0] + srf->numVerts;
1626 
1627 				tess.numIndexes += 6;
1628 				backEnd.pc.c_shadowIndexes += 6;
1629 			}
1630 		}
1631 
1632 		tess.numVertexes += srf->numVerts * 2;
1633 		backEnd.pc.c_shadowVertexes += srf->numVerts * 2;
1634 
1635 		backEnd.pc.c_shadowSurfaces++;
1636 	}
1637 	else
1638 	{
1639 		Tess_CheckOverflow(srf->numVerts, srf->numTriangles * 3);
1640 
1641 		model = srf->model;
1642 
1643 		numIndexes = srf->numTriangles * 3;
1644 		for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
1645 		{
1646 			tess.indexes[tess.numIndexes + i * 3 + 0] = tess.numVertexes + tri->indexes[0];
1647 			tess.indexes[tess.numIndexes + i * 3 + 1] = tess.numVertexes + tri->indexes[1];
1648 			tess.indexes[tess.numIndexes + i * 3 + 2] = tess.numVertexes + tri->indexes[2];
1649 		}
1650 
1651 		newVert = srf->verts + (backEnd.currentEntity->e.frame * srf->numVerts);
1652 		oldVert = srf->verts + (backEnd.currentEntity->e.oldframe * srf->numVerts);
1653 		st = srf->st;
1654 
1655 		numVertexes = srf->numVerts;
1656 		for(j = 0; j < numVertexes; j++, newVert++, oldVert++, st++)
1657 		{
1658 			vec3_t          tmpVert;
1659 
1660 			if(backlerp == 0)
1661 			{
1662 				// just copy
1663 				tmpVert[0] = newVert->xyz[0] * newXyzScale;
1664 				tmpVert[1] = newVert->xyz[1] * newXyzScale;
1665 				tmpVert[2] = newVert->xyz[2] * newXyzScale;
1666 			}
1667 			else
1668 			{
1669 				// interpolate the xyz
1670 				tmpVert[0] = oldVert->xyz[0] * oldXyzScale + newVert->xyz[0] * newXyzScale;
1671 				tmpVert[1] = oldVert->xyz[1] * oldXyzScale + newVert->xyz[1] * newXyzScale;
1672 				tmpVert[2] = oldVert->xyz[2] * oldXyzScale + newVert->xyz[2] * newXyzScale;
1673 			}
1674 
1675 			tess.xyz[tess.numVertexes + j][0] = tmpVert[0];
1676 			tess.xyz[tess.numVertexes + j][1] = tmpVert[1];
1677 			tess.xyz[tess.numVertexes + j][2] = tmpVert[2];
1678 			tess.xyz[tess.numVertexes + j][3] = 1;
1679 
1680 			tess.texCoords[tess.numVertexes + j][0][0] = st->st[0];
1681 			tess.texCoords[tess.numVertexes + j][0][1] = st->st[1];
1682 		}
1683 
1684 		// calc tangent spaces
1685 		if(!tess.skipTangentSpaces)
1686 		{
1687 			int             i;
1688 			vec3_t          faceNormal;
1689 			float          *v;
1690 			const float    *v0, *v1, *v2;
1691 			const float    *t0, *t1, *t2;
1692 			vec3_t          tangent;
1693 			vec3_t          binormal;
1694 			vec3_t          normal;
1695 			int            *indices;
1696 
1697 			for(i = 0; i < numVertexes; i++)
1698 			{
1699 				VectorClear(tess.tangents[tess.numVertexes + i]);
1700 				VectorClear(tess.binormals[tess.numVertexes + i]);
1701 				VectorClear(tess.normals[tess.numVertexes + i]);
1702 			}
1703 
1704 			for(i = 0, indices = tess.indexes + tess.numIndexes; i < numIndexes; i += 3, indices += 3)
1705 			{
1706 				v0 = tess.xyz[indices[0]];
1707 				v1 = tess.xyz[indices[1]];
1708 				v2 = tess.xyz[indices[2]];
1709 
1710 				t0 = tess.texCoords[indices[0]][0];
1711 				t1 = tess.texCoords[indices[1]][0];
1712 				t2 = tess.texCoords[indices[2]][0];
1713 #if 1
1714 				R_CalcNormalForTriangle(faceNormal, v0, v1, v2);
1715 				R_CalcTangentSpace(tangent, binormal, normal, v0, v1, v2, t0, t1, t2, faceNormal);
1716 #else
1717 				R_CalcNormalForTriangle(normal, v0, v1, v2);
1718 				R_CalcTangentsForTriangle(tangent, binormal, v0, v1, v2, t0, t1, t2);
1719 #endif
1720 				for(j = 0; j < 3; j++)
1721 				{
1722 					v = tess.tangents[indices[j]];
1723 					VectorAdd(v, tangent, v);
1724 					v = tess.binormals[indices[j]];
1725 					VectorAdd(v, binormal, v);
1726 					v = tess.normals[indices[j]];
1727 					VectorAdd(v, normal, v);
1728 				}
1729 			}
1730 
1731 			VectorArrayNormalize((vec4_t *) tess.tangents[tess.numVertexes], numVertexes);
1732 			VectorArrayNormalize((vec4_t *) tess.binormals[tess.numVertexes], numVertexes);
1733 			VectorArrayNormalize((vec4_t *) tess.normals[tess.numVertexes], numVertexes);
1734 		}
1735 
1736 		tess.numIndexes += numIndexes;
1737 		tess.numVertexes += numVertexes;
1738 	}
1739 }
1740 
1741 /*
1742 ==============
1743 Tess_SurfaceMD5
1744 ==============
1745 */
Tess_SurfaceMD5(md5Surface_t * srf,int numLightIndexes,int * lightIndexes,int numShadowIndexes,int * shadowIndexes)1746 void Tess_SurfaceMD5(md5Surface_t * srf, int numLightIndexes, int *lightIndexes, int numShadowIndexes, int *shadowIndexes)
1747 {
1748 	int             i, j, k;
1749 	int             numIndexes = 0;
1750 	int             numVertexes;
1751 	md5Model_t     *model;
1752 	md5Vertex_t    *v;
1753 	md5Bone_t      *bone;
1754 	srfTriangle_t  *tri;
1755 	vec3_t          offsetVec;
1756 	vec3_t          lightOrigin;
1757 	float          *xyzw, *xyzw2;
1758 
1759 	GLimp_LogComment("--- Tess_SurfaceMD5 ---\n");
1760 
1761 	if(tess.shadowVolume)
1762 	{
1763 		if(backEnd.currentEntity->needZFail)
1764 		{
1765 			Tess_CheckOverflow(srf->numVerts * 2, srf->numTriangles * (6 + 2) * 3);
1766 		}
1767 		else
1768 		{
1769 			Tess_CheckOverflow(srf->numVerts * 2, srf->numTriangles * 6 * 3);
1770 		}
1771 
1772 		model = srf->model;
1773 
1774 		VectorCopy(backEnd.currentLight->transformed, lightOrigin);
1775 
1776 		// deform the vertexes by the lerped bones and extrude to infinity
1777 		numVertexes = srf->numVerts;
1778 		xyzw = tess.xyz[tess.numVertexes];
1779 		xyzw2 = tess.xyz[tess.numVertexes + srf->numVerts];
1780 		for(j = 0, v = srf->verts; j < numVertexes; j++, v++, xyzw += 4, xyzw2 += 4)
1781 		{
1782 			vec3_t          tmpVert;
1783 			md5Weight_t    *w;
1784 
1785 			VectorClear(tmpVert);
1786 
1787 			for(k = 0, w = v->weights[0]; k < v->numWeights; k++, w++)
1788 			{
1789 				bone = &model->bones[w->boneIndex];
1790 
1791 				if(backEnd.currentEntity->e.skeleton.type == SK_ABSOLUTE)
1792 				{
1793 					QuatTransformVector(backEnd.currentEntity->e.skeleton.bones[w->boneIndex].rotation, w->offset, offsetVec);
1794 
1795 					offsetVec[0] *= backEnd.currentEntity->e.skeleton.scale[0];
1796 					offsetVec[1] *= backEnd.currentEntity->e.skeleton.scale[1];
1797 					offsetVec[2] *= backEnd.currentEntity->e.skeleton.scale[2];
1798 
1799 					VectorAdd(backEnd.currentEntity->e.skeleton.bones[w->boneIndex].origin, offsetVec, offsetVec);
1800 				}
1801 				else
1802 				{
1803 					QuatTransformVector(bone->rotation, w->offset, offsetVec);
1804 					VectorAdd(bone->origin, offsetVec, offsetVec);
1805 				}
1806 
1807 				VectorMA(tmpVert, w->boneWeight, offsetVec, tmpVert);
1808 			}
1809 
1810 			xyzw[0] = tmpVert[0];
1811 			xyzw[1] = tmpVert[1];
1812 			xyzw[2] = tmpVert[2];
1813 			xyzw[3] = 1;
1814 
1815 			#if 1
1816 			xyzw2[0] = tmpVert[0];
1817 			xyzw2[1] = tmpVert[1];
1818 			xyzw2[2] = tmpVert[2];
1819 			#else
1820 			xyzw2[0] = tmpVert[0] - lightOrigin[0];
1821 			xyzw2[1] = tmpVert[1] - lightOrigin[1];
1822 			xyzw2[2] = tmpVert[2] - lightOrigin[2];
1823 			#endif
1824 			xyzw2[3] = 0;
1825 		}
1826 
1827 		// decide which triangles face the light
1828 		for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
1829 		{
1830 			float          *v1, *v2, *v3;
1831 			vec3_t          d1, d2;
1832 			vec4_t          plane;
1833 			float           d;
1834 
1835 			v1 = tess.xyz[tess.numVertexes + tri->indexes[0]];
1836 			v2 = tess.xyz[tess.numVertexes + tri->indexes[1]];
1837 			v3 = tess.xyz[tess.numVertexes + tri->indexes[2]];
1838 
1839 			VectorSubtract(v2, v1, d1);
1840 			VectorSubtract(v3, v1, d2);
1841 
1842 			CrossProduct(d2, d1, plane);
1843 			plane[3] = DotProduct(plane, v1);
1844 
1845 			d = DotProduct(plane, lightOrigin) - plane[3];
1846 			if(d > 0 && !tess.surfaceShader->cullType == CT_BACK_SIDED)
1847 			{
1848 				sh.facing[i] = qtrue;
1849 			}
1850 			else
1851 			{
1852 				sh.facing[i] = qfalse;
1853 			}
1854 		}
1855 
1856 		// set up indices for silhouette edges
1857 		for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
1858 		{
1859 			if(!sh.facing[i])
1860 			{
1861 				continue;
1862 			}
1863 
1864 			if((tri->neighbors[0] < 0) || (tri->neighbors[0] >= 0 && !sh.facing[tri->neighbors[0]]))
1865 			{
1866 				tess.indexes[tess.numIndexes + 0] = tess.numVertexes + tri->indexes[1];
1867 				tess.indexes[tess.numIndexes + 1] = tess.numVertexes + tri->indexes[0];
1868 				tess.indexes[tess.numIndexes + 2] = tess.numVertexes + tri->indexes[0] + srf->numVerts;
1869 
1870 				tess.indexes[tess.numIndexes + 3] = tess.numVertexes + tri->indexes[1];
1871 				tess.indexes[tess.numIndexes + 4] = tess.numVertexes + tri->indexes[0] + srf->numVerts;
1872 				tess.indexes[tess.numIndexes + 5] = tess.numVertexes + tri->indexes[1] + srf->numVerts;
1873 
1874 				tess.numIndexes += 6;
1875 				backEnd.pc.c_shadowIndexes += 6;
1876 			}
1877 
1878 			if((tri->neighbors[1] < 0) || (tri->neighbors[1] >= 0 && !sh.facing[tri->neighbors[1]]))
1879 			{
1880 				tess.indexes[tess.numIndexes + 0] = tess.numVertexes + tri->indexes[2];
1881 				tess.indexes[tess.numIndexes + 1] = tess.numVertexes + tri->indexes[1];
1882 				tess.indexes[tess.numIndexes + 2] = tess.numVertexes + tri->indexes[1] + srf->numVerts;
1883 
1884 				tess.indexes[tess.numIndexes + 3] = tess.numVertexes + tri->indexes[2];
1885 				tess.indexes[tess.numIndexes + 4] = tess.numVertexes + tri->indexes[1] + srf->numVerts;
1886 				tess.indexes[tess.numIndexes + 5] = tess.numVertexes + tri->indexes[2] + srf->numVerts;
1887 
1888 				tess.numIndexes += 6;
1889 				backEnd.pc.c_shadowIndexes += 6;
1890 			}
1891 
1892 			if((tri->neighbors[2] < 0) || (tri->neighbors[2] >= 0 && !sh.facing[tri->neighbors[2]]))
1893 			{
1894 				tess.indexes[tess.numIndexes + 0] = tess.numVertexes + tri->indexes[0];
1895 				tess.indexes[tess.numIndexes + 1] = tess.numVertexes + tri->indexes[2];
1896 				tess.indexes[tess.numIndexes + 2] = tess.numVertexes + tri->indexes[2] + srf->numVerts;
1897 
1898 				tess.indexes[tess.numIndexes + 3] = tess.numVertexes + tri->indexes[0];
1899 				tess.indexes[tess.numIndexes + 4] = tess.numVertexes + tri->indexes[2] + srf->numVerts;
1900 				tess.indexes[tess.numIndexes + 5] = tess.numVertexes + tri->indexes[0] + srf->numVerts;
1901 
1902 				tess.numIndexes += 6;
1903 				backEnd.pc.c_shadowIndexes += 6;
1904 			}
1905 		}
1906 
1907 		// set up indices for light and dark caps
1908 		if(backEnd.currentEntity->needZFail)
1909 		{
1910 			for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
1911 			{
1912 				if(!sh.facing[i])
1913 				{
1914 					continue;
1915 				}
1916 
1917 				// light cap
1918 				tess.indexes[tess.numIndexes + 0] = tess.numVertexes + tri->indexes[0];
1919 				tess.indexes[tess.numIndexes + 1] = tess.numVertexes + tri->indexes[1];
1920 				tess.indexes[tess.numIndexes + 2] = tess.numVertexes + tri->indexes[2];
1921 
1922 				// dark cap
1923 				tess.indexes[tess.numIndexes + 3] = tess.numVertexes + tri->indexes[2] + srf->numVerts;
1924 				tess.indexes[tess.numIndexes + 4] = tess.numVertexes + tri->indexes[1] + srf->numVerts;
1925 				tess.indexes[tess.numIndexes + 5] = tess.numVertexes + tri->indexes[0] + srf->numVerts;
1926 
1927 				tess.numIndexes += 6;
1928 				backEnd.pc.c_shadowIndexes += 6;
1929 			}
1930 		}
1931 
1932 		tess.numVertexes += srf->numVerts * 2;
1933 		backEnd.pc.c_shadowVertexes += srf->numVerts * 2;
1934 
1935 		backEnd.pc.c_shadowSurfaces++;
1936 	}
1937 	else
1938 	{
1939 		Tess_CheckOverflow(srf->numVerts, srf->numTriangles * 3);
1940 
1941 		model = srf->model;
1942 
1943 		numIndexes = srf->numTriangles * 3;
1944 		for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
1945 		{
1946 			tess.indexes[tess.numIndexes + i * 3 + 0] = tess.numVertexes + tri->indexes[0];
1947 			tess.indexes[tess.numIndexes + i * 3 + 1] = tess.numVertexes + tri->indexes[1];
1948 			tess.indexes[tess.numIndexes + i * 3 + 2] = tess.numVertexes + tri->indexes[2];
1949 		}
1950 
1951 		// deform the vertexes by the lerped bones
1952 		numVertexes = srf->numVerts;
1953 		for(j = 0, v = srf->verts; j < numVertexes; j++, v++)
1954 		{
1955 			vec3_t          tmpVert;
1956 			md5Weight_t    *w;
1957 
1958 			VectorClear(tmpVert);
1959 
1960 			for(k = 0, w = v->weights[0]; k < v->numWeights; k++, w++)
1961 			{
1962 				bone = &model->bones[w->boneIndex];
1963 
1964 				if(backEnd.currentEntity->e.skeleton.type == SK_ABSOLUTE)
1965 				{
1966 					QuatTransformVector(backEnd.currentEntity->e.skeleton.bones[w->boneIndex].rotation, w->offset, offsetVec);
1967 
1968 					offsetVec[0] *= backEnd.currentEntity->e.skeleton.scale[0];
1969 					offsetVec[1] *= backEnd.currentEntity->e.skeleton.scale[1];
1970 					offsetVec[2] *= backEnd.currentEntity->e.skeleton.scale[2];
1971 
1972 					VectorAdd(backEnd.currentEntity->e.skeleton.bones[w->boneIndex].origin, offsetVec, offsetVec);
1973 				}
1974 				else
1975 				{
1976 					QuatTransformVector(bone->rotation, w->offset, offsetVec);
1977 					VectorAdd(bone->origin, offsetVec, offsetVec);
1978 				}
1979 
1980 				VectorMA(tmpVert, w->boneWeight, offsetVec, tmpVert);
1981 			}
1982 
1983 			tess.xyz[tess.numVertexes + j][0] = tmpVert[0];
1984 			tess.xyz[tess.numVertexes + j][1] = tmpVert[1];
1985 			tess.xyz[tess.numVertexes + j][2] = tmpVert[2];
1986 			tess.xyz[tess.numVertexes + j][3] = 1;
1987 
1988 			tess.texCoords[tess.numVertexes + j][0][0] = v->texCoords[0];
1989 			tess.texCoords[tess.numVertexes + j][0][1] = v->texCoords[1];
1990 		}
1991 
1992 		// calc tangent spaces
1993 		if(!tess.skipTangentSpaces)
1994 		{
1995 			int             i;
1996 			vec3_t          faceNormal;
1997 			float          *v;
1998 			const float    *v0, *v1, *v2;
1999 			const float    *t0, *t1, *t2;
2000 			vec3_t          tangent;
2001 			vec3_t          binormal;
2002 			vec3_t          normal;
2003 			int            *indices;
2004 
2005 			for(i = 0; i < numVertexes; i++)
2006 			{
2007 				VectorClear(tess.tangents[tess.numVertexes + i]);
2008 				VectorClear(tess.binormals[tess.numVertexes + i]);
2009 				VectorClear(tess.normals[tess.numVertexes + i]);
2010 			}
2011 
2012 			for(i = 0, indices = tess.indexes + tess.numIndexes; i < numIndexes; i += 3, indices += 3)
2013 			{
2014 				v0 = tess.xyz[indices[0]];
2015 				v1 = tess.xyz[indices[1]];
2016 				v2 = tess.xyz[indices[2]];
2017 
2018 				t0 = tess.texCoords[indices[0]][0];
2019 				t1 = tess.texCoords[indices[1]][0];
2020 				t2 = tess.texCoords[indices[2]][0];
2021 #if 1
2022 				R_CalcNormalForTriangle(faceNormal, v0, v1, v2);
2023 				R_CalcTangentSpace(tangent, binormal, normal, v0, v1, v2, t0, t1, t2, faceNormal);
2024 #else
2025 				R_CalcNormalForTriangle(normal, v0, v1, v2);
2026 				R_CalcTangentsForTriangle(tangent, binormal, v0, v1, v2, t0, t1, t2);
2027 #endif
2028 				for(j = 0; j < 3; j++)
2029 				{
2030 					v = tess.tangents[indices[j]];
2031 					VectorAdd(v, tangent, v);
2032 					v = tess.binormals[indices[j]];
2033 					VectorAdd(v, binormal, v);
2034 					v = tess.normals[indices[j]];
2035 					VectorAdd(v, normal, v);
2036 				}
2037 			}
2038 
2039 			VectorArrayNormalize((vec4_t *) tess.tangents[tess.numVertexes], numVertexes);
2040 			VectorArrayNormalize((vec4_t *) tess.binormals[tess.numVertexes], numVertexes);
2041 			VectorArrayNormalize((vec4_t *) tess.normals[tess.numVertexes], numVertexes);
2042 		}
2043 
2044 		tess.numIndexes += numIndexes;
2045 		tess.numVertexes += numVertexes;
2046 	}
2047 }
2048 
2049 /*
2050 ===========================================================================
2051 
2052 NULL MODEL
2053 
2054 ===========================================================================
2055 */
2056 
2057 /*
2058 ===================
2059 Tess_SurfaceAxis
2060 
2061 Draws x/y/z lines from the origin for orientation debugging
2062 ===================
2063 */
Tess_SurfaceAxis(void)2064 static void Tess_SurfaceAxis(void)
2065 {
2066 	GLimp_LogComment("--- Tess_SurfaceAxis ---\n");
2067 
2068 	GL_Program(0);
2069 	GL_SelectTexture(0);
2070 	GL_Bind(tr.whiteImage);
2071 
2072 	qglLineWidth(3);
2073 	qglBegin(GL_LINES);
2074 	qglColor3f(1, 0, 0);
2075 	qglVertex3f(0, 0, 0);
2076 	qglVertex3f(16, 0, 0);
2077 	qglColor3f(0, 1, 0);
2078 	qglVertex3f(0, 0, 0);
2079 	qglVertex3f(0, 16, 0);
2080 	qglColor3f(0, 0, 1);
2081 	qglVertex3f(0, 0, 0);
2082 	qglVertex3f(0, 0, 16);
2083 	qglEnd();
2084 	qglLineWidth(1);
2085 }
2086 
2087 //===========================================================================
2088 
2089 /*
2090 ====================
2091 Tess_SurfaceEntity
2092 
2093 Entities that have a single procedurally generated surface
2094 ====================
2095 */
Tess_SurfaceEntity(surfaceType_t * surfType,int numLightIndexes,int * lightIndexes,int numShadowIndexes,int * shadowIndexes)2096 static void Tess_SurfaceEntity(surfaceType_t * surfType, int numLightIndexes, int *lightIndexes, int numShadowIndexes, int *shadowIndexes)
2097 {
2098 	GLimp_LogComment("--- Tess_SurfaceEntity ---\n");
2099 
2100 	if(tess.shadowVolume)
2101 	{
2102 		return;
2103 	}
2104 
2105 	switch (backEnd.currentEntity->e.reType)
2106 	{
2107 		case RT_SPRITE:
2108 			Tess_SurfaceSprite();
2109 			break;
2110 		case RT_BEAM:
2111 			Tess_SurfaceBeam();
2112 			break;
2113 		case RT_RAIL_CORE:
2114 			Tess_SurfaceRailCore();
2115 			break;
2116 		case RT_RAIL_RINGS:
2117 			Tess_SurfaceRailRings();
2118 			break;
2119 		case RT_LIGHTNING:
2120 			Tess_SurfaceLightningBolt();
2121 			break;
2122 		default:
2123 			Tess_SurfaceAxis();
2124 			break;
2125 	}
2126 	return;
2127 }
2128 
Tess_SurfaceBad(surfaceType_t * surfType,int numLightIndexes,int * lightIndexes,int numShadowIndexes,int * shadowIndexes)2129 static void Tess_SurfaceBad(surfaceType_t * surfType, int numLightIndexes, int *lightIndexes, int numShadowIndexes, int *shadowIndexes)
2130 {
2131 	GLimp_LogComment("--- Tess_SurfaceBad ---\n");
2132 
2133 	ri.Printf(PRINT_ALL, "Bad surface tesselated.\n");
2134 }
2135 
Tess_SurfaceFlare(srfFlare_t * surf,int numLightIndexes,int * lightIndexes,int numShadowIndexes,int * shadowIndexes)2136 static void Tess_SurfaceFlare(srfFlare_t * surf, int numLightIndexes, int *lightIndexes, int numShadowIndexes, int *shadowIndexes)
2137 {
2138 	if(!r_drawFlares->integer)
2139 		return;
2140 
2141 	GLimp_LogComment("--- Tess_SurfaceFlare ---\n");
2142 
2143 
2144 	if(tess.shadowVolume)
2145 		return;
2146 
2147 	RB_AddFlare((void *)surf, tess.fogNum, surf->origin, surf->color, surf->normal);
2148 }
2149 
Tess_SurfaceSkip(void * surf,int numLightIndexes,int * lightIndexes,int numShadowIndexes,int * shadowIndexes)2150 static void Tess_SurfaceSkip(void *surf, int numLightIndexes, int *lightIndexes, int numShadowIndexes, int *shadowIndexes)
2151 {
2152 }
2153 
2154 
2155 void            (*tess_surfaceTable[SF_NUM_SURFACE_TYPES]) (void *, int numLightIndexes, int *lightIndexes, int numShadowIndexes,
2156 														  int *shadowIndexes) =
2157 {
2158 	(void (*)(void *, int, int *, int, int *))Tess_SurfaceBad,	// SF_BAD,
2159 		(void (*)(void *, int, int *, int, int *))Tess_SurfaceSkip,	// SF_SKIP,
2160 		(void (*)(void *, int, int *, int, int *))Tess_SurfaceFace,	// SF_FACE,
2161 		(void (*)(void *, int, int *, int, int *))Tess_SurfaceGrid,	// SF_GRID,
2162 		(void (*)(void *, int, int *, int, int *))Tess_SurfaceTriangles,	// SF_TRIANGLES,
2163 		(void (*)(void *, int, int *, int, int *))Tess_SurfacePolychain,	// SF_POLY,
2164 		(void (*)(void *, int, int *, int, int *))Tess_SurfaceMDX,	// SF_MDX,
2165 		(void (*)(void *, int, int *, int, int *))Tess_SurfaceMD5,	// SF_MD5,
2166 		(void (*)(void *, int, int *, int, int *))Tess_SurfaceFlare,	// SF_FLARE,
2167 		(void (*)(void *, int, int *, int, int *))Tess_SurfaceEntity	// SF_ENTITY
2168 };
2169