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