DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

tr_trisurf.cpp (56101B)


      1 /*
      2 ===========================================================================
      3 
      4 Doom 3 BFG Edition GPL Source Code
      5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 
      6 
      7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  
      8 
      9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
     10 it under the terms of the GNU General Public License as published by
     11 the Free Software Foundation, either version 3 of the License, or
     12 (at your option) any later version.
     13 
     14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
     15 but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 GNU General Public License for more details.
     18 
     19 You should have received a copy of the GNU General Public License
     20 along with Doom 3 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code.  If not, please request a copy in writing from id Software at the address below.
     23 
     24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
     25 
     26 ===========================================================================
     27 */
     28 
     29 #pragma hdrstop
     30 #include "../idlib/precompiled.h"
     31 
     32 #include "tr_local.h"
     33 
     34 /*
     35 ==============================================================================
     36 
     37 TRIANGLE MESH PROCESSING
     38 
     39 The functions in this file have no vertex / index count limits.
     40 
     41 Truly identical vertexes that match in position, normal, and texcoord can
     42 be merged away.
     43 
     44 Vertexes that match in position and texcoord, but have distinct normals will
     45 remain distinct for all purposes.  This is usually a poor choice for models,
     46 as adding a bevel face will not add any more vertexes, and will tend to
     47 look better.
     48 
     49 Match in position and normal, but differ in texcoords are referenced together
     50 for calculating tangent vectors for bump mapping.
     51 Artists should take care to have identical texels in all maps (bump/diffuse/specular)
     52 in this case
     53 
     54 Vertexes that only match in position are merged for shadow edge finding.
     55 
     56 Degenerate triangles.
     57 
     58 Overlapped triangles, even if normals or texcoords differ, must be removed.
     59 for the silhoette based stencil shadow algorithm to function properly.
     60 Is this true???
     61 Is the overlapped triangle problem just an example of the trippled edge problem?
     62 
     63 Interpenetrating triangles are not currently clipped to surfaces.
     64 Do they effect the shadows?
     65 
     66 if vertexes are intended to deform apart, make sure that no vertexes
     67 are on top of each other in the base frame, or the sil edges may be
     68 calculated incorrectly.
     69 
     70 We might be able to identify this from topology.
     71 
     72 Dangling edges are acceptable, but three way edges are not.
     73 
     74 Are any combinations of two way edges unacceptable, like one facing
     75 the backside of the other?
     76 
     77 Topology is determined by a collection of triangle indexes.
     78 
     79 The edge list can be built up from this, and stays valid even under
     80 deformations.
     81 
     82 Somewhat non-intuitively, concave edges cannot be optimized away, or the
     83 stencil shadow algorithm miscounts.
     84 
     85 Face normals are needed for generating shadow volumes and for calculating
     86 the silhouette, but they will change with any deformation.
     87 
     88 Vertex normals and vertex tangents will change with each deformation,
     89 but they may be able to be transformed instead of recalculated.
     90 
     91 bounding volume, both box and sphere will change with deformation.
     92 
     93 silhouette indexes
     94 shade indexes
     95 texture indexes
     96 
     97   shade indexes will only be > silhouette indexes if there is facet shading present
     98 
     99 	lookups from texture to sil and texture to shade?
    100 
    101 The normal and tangent vector smoothing is simple averaging, no attempt is
    102 made to better handle the cases where the distribution around the shared vertex
    103 is highly uneven.
    104 
    105   we may get degenerate triangles even with the uniquing and removal
    106   if the vertexes have different texcoords.
    107 
    108 ==============================================================================
    109 */
    110 
    111 // this shouldn't change anything, but previously renderbumped models seem to need it
    112 #define USE_INVA
    113 
    114 // instead of using the texture T vector, cross the normal and S vector for an orthogonal axis
    115 #define DERIVE_UNSMOOTHED_BITANGENT
    116 
    117 /*
    118 =================
    119 R_TriSurfMemory
    120 
    121 For memory profiling
    122 =================
    123 */
    124 int R_TriSurfMemory( const srfTriangles_t *tri ) {
    125 	int total = 0;
    126 
    127 	if ( tri == NULL ) {
    128 		return total;
    129 	}
    130 
    131 	if ( tri->preLightShadowVertexes != NULL ) {
    132 		total += tri->numVerts * 2 * sizeof( tri->preLightShadowVertexes[0] );
    133 	}
    134 	if ( tri->staticShadowVertexes != NULL ) {
    135 		total += tri->numVerts * 2 * sizeof( tri->staticShadowVertexes[0] );
    136 	}
    137 	if ( tri->verts != NULL ) {
    138 		if ( tri->ambientSurface == NULL || tri->verts != tri->ambientSurface->verts ) {
    139 			total += tri->numVerts * sizeof( tri->verts[0] );
    140 		}
    141 	}
    142 	if ( tri->indexes != NULL ) {
    143 		if ( tri->ambientSurface == NULL || tri->indexes != tri->ambientSurface->indexes ) {
    144 			total += tri->numIndexes * sizeof( tri->indexes[0] );
    145 		}
    146 	}
    147 	if ( tri->silIndexes != NULL ) {
    148 		total += tri->numIndexes * sizeof( tri->silIndexes[0] );
    149 	}
    150 	if ( tri->silEdges != NULL ) {
    151 		total += tri->numSilEdges * sizeof( tri->silEdges[0] );
    152 	}
    153 	if ( tri->dominantTris != NULL ) {
    154 		total += tri->numVerts * sizeof( tri->dominantTris[0] );
    155 	}
    156 	if ( tri->mirroredVerts != NULL ) {
    157 		total += tri->numMirroredVerts * sizeof( tri->mirroredVerts[0] );
    158 	}
    159 	if ( tri->dupVerts != NULL ) {
    160 		total += tri->numDupVerts * sizeof( tri->dupVerts[0] );
    161 	}
    162 
    163 	total += sizeof( *tri );
    164 
    165 	return total;
    166 }
    167 
    168 /*
    169 ==============
    170 R_FreeStaticTriSurfVertexCaches
    171 ==============
    172 */
    173 void R_FreeStaticTriSurfVertexCaches( srfTriangles_t * tri ) {
    174 	// we don't support reclaiming static geometry memory
    175 	// without a level change
    176 	tri->ambientCache = 0;
    177 	tri->indexCache = 0;
    178 	tri->shadowCache = 0;
    179 }
    180 
    181 /*
    182 ==============
    183 R_FreeStaticTriSurf
    184 ==============
    185 */
    186 void R_FreeStaticTriSurf( srfTriangles_t *tri ) {
    187 	if ( !tri ) {
    188 		return;
    189 	}
    190 
    191 	R_FreeStaticTriSurfVertexCaches( tri );
    192 
    193 	if ( !tri->referencedVerts ) {
    194 		if ( tri->verts != NULL ) {
    195 			// R_CreateLightTris points tri->verts at the verts of the ambient surface
    196 			if ( tri->ambientSurface == NULL || tri->verts != tri->ambientSurface->verts ) {
    197 				Mem_Free( tri->verts );
    198 			}
    199 		}
    200 	}
    201 
    202 	if ( !tri->referencedIndexes ) {
    203 		if ( tri->indexes != NULL ) {
    204 			// if a surface is completely inside a light volume R_CreateLightTris points tri->indexes at the indexes of the ambient surface
    205 			if ( tri->ambientSurface == NULL || tri->indexes != tri->ambientSurface->indexes ) {
    206 				Mem_Free( tri->indexes );
    207 			}
    208 		}
    209 		if ( tri->silIndexes != NULL ) {
    210 			Mem_Free( tri->silIndexes );
    211 		}
    212 		if ( tri->silEdges != NULL ) {
    213 			Mem_Free( tri->silEdges );
    214 		}
    215 		if ( tri->dominantTris != NULL ) {
    216 			Mem_Free( tri->dominantTris );
    217 		}
    218 		if ( tri->mirroredVerts != NULL ) {
    219 			Mem_Free( tri->mirroredVerts );
    220 		}
    221 		if ( tri->dupVerts != NULL ) {
    222 			Mem_Free( tri->dupVerts );
    223 		}
    224 	}
    225 
    226 	if ( tri->preLightShadowVertexes != NULL ) {
    227 		Mem_Free( tri->preLightShadowVertexes );
    228 	}
    229 	if ( tri->staticShadowVertexes != NULL ) {
    230 		Mem_Free( tri->staticShadowVertexes );
    231 	}
    232 
    233 	// clear the tri out so we don't retain stale data
    234 	memset( tri, 0, sizeof( srfTriangles_t ) );
    235 
    236 	Mem_Free( tri );
    237 }
    238 
    239 /*
    240 ==============
    241 R_FreeStaticTriSurfVerts
    242 ==============
    243 */
    244 void R_FreeStaticTriSurfVerts( srfTriangles_t *tri ) {
    245 	// we don't support reclaiming static geometry memory
    246 	// without a level change
    247 	tri->ambientCache = 0;
    248 
    249 	if ( tri->verts != NULL ) {
    250 		// R_CreateLightTris points tri->verts at the verts of the ambient surface
    251 		if ( tri->ambientSurface == NULL || tri->verts != tri->ambientSurface->verts ) {
    252 			Mem_Free( tri->verts );
    253 		}
    254 	}
    255 }
    256 
    257 /*
    258 ==============
    259 R_AllocStaticTriSurf
    260 ==============
    261 */
    262 srfTriangles_t *R_AllocStaticTriSurf() {
    263 	srfTriangles_t *tris = (srfTriangles_t *)Mem_ClearedAlloc( sizeof( srfTriangles_t ), TAG_SRFTRIS );
    264 	return tris;
    265 }
    266 
    267 /*
    268 =================
    269 R_CopyStaticTriSurf
    270 
    271 This only duplicates the indexes and verts, not any of the derived data.
    272 =================
    273 */
    274 srfTriangles_t *R_CopyStaticTriSurf( const srfTriangles_t *tri ) {
    275 	srfTriangles_t	*newTri;
    276 
    277 	newTri = R_AllocStaticTriSurf();
    278 	R_AllocStaticTriSurfVerts( newTri, tri->numVerts );
    279 	R_AllocStaticTriSurfIndexes( newTri, tri->numIndexes );
    280 	newTri->numVerts = tri->numVerts;
    281 	newTri->numIndexes = tri->numIndexes;
    282 	memcpy( newTri->verts, tri->verts, tri->numVerts * sizeof( newTri->verts[0] ) );
    283 	memcpy( newTri->indexes, tri->indexes, tri->numIndexes * sizeof( newTri->indexes[0] ) );
    284 
    285 	return newTri;
    286 }
    287 
    288 /*
    289 =================
    290 R_AllocStaticTriSurfVerts
    291 =================
    292 */
    293 void R_AllocStaticTriSurfVerts( srfTriangles_t *tri, int numVerts ) {
    294 	assert( tri->verts == NULL );
    295 	tri->verts = (idDrawVert *)Mem_Alloc16( numVerts * sizeof( idDrawVert ), TAG_TRI_VERTS );
    296 }
    297 
    298 /*
    299 =================
    300 R_AllocStaticTriSurfIndexes
    301 =================
    302 */
    303 void R_AllocStaticTriSurfIndexes( srfTriangles_t *tri, int numIndexes ) {
    304 	assert( tri->indexes == NULL );
    305 	tri->indexes = (triIndex_t *)Mem_Alloc16( numIndexes * sizeof( triIndex_t ), TAG_TRI_INDEXES );
    306 }
    307 
    308 /*
    309 =================
    310 R_AllocStaticTriSurfSilIndexes
    311 =================
    312 */
    313 void R_AllocStaticTriSurfSilIndexes( srfTriangles_t *tri, int numIndexes ) {
    314 	assert( tri->silIndexes == NULL );
    315 	tri->silIndexes = (triIndex_t *)Mem_Alloc16( numIndexes * sizeof( triIndex_t ), TAG_TRI_SIL_INDEXES );
    316 }
    317 
    318 /*
    319 =================
    320 R_AllocStaticTriSurfDominantTris
    321 =================
    322 */
    323 void R_AllocStaticTriSurfDominantTris( srfTriangles_t *tri, int numVerts ) {
    324 	assert( tri->dominantTris == NULL );
    325 	tri->dominantTris = (dominantTri_t *)Mem_Alloc16( numVerts * sizeof( dominantTri_t ), TAG_TRI_DOMINANT_TRIS );
    326 }
    327 
    328 /*
    329 =================
    330 R_AllocStaticTriSurfMirroredVerts
    331 =================
    332 */
    333 void R_AllocStaticTriSurfMirroredVerts( srfTriangles_t *tri, int numMirroredVerts ) {
    334 	assert( tri->mirroredVerts == NULL );
    335 	tri->mirroredVerts = (int *)Mem_Alloc16( numMirroredVerts * sizeof( *tri->mirroredVerts ), TAG_TRI_MIR_VERT );
    336 }
    337 
    338 /*
    339 =================
    340 R_AllocStaticTriSurfDupVerts
    341 =================
    342 */
    343 void R_AllocStaticTriSurfDupVerts( srfTriangles_t *tri, int numDupVerts ) {
    344 	assert( tri->dupVerts == NULL );
    345 	tri->dupVerts = (int *)Mem_Alloc16( numDupVerts * 2 * sizeof( *tri->dupVerts ), TAG_TRI_DUP_VERT );
    346 }
    347 
    348 /*
    349 =================
    350 R_AllocStaticTriSurfSilEdges
    351 =================
    352 */
    353 void R_AllocStaticTriSurfSilEdges( srfTriangles_t *tri, int numSilEdges ) {
    354 	assert( tri->silEdges == NULL );
    355 	tri->silEdges = (silEdge_t *)Mem_Alloc16( numSilEdges * sizeof( silEdge_t ), TAG_TRI_SIL_EDGE );
    356 }
    357 
    358 /*
    359 =================
    360 R_AllocStaticTriSurfPreLightShadowVerts
    361 =================
    362 */
    363 void R_AllocStaticTriSurfPreLightShadowVerts( srfTriangles_t *tri, int numVerts ) {
    364 	assert( tri->preLightShadowVertexes == NULL );
    365 	tri->preLightShadowVertexes = (idShadowVert *)Mem_Alloc16( numVerts * sizeof( idShadowVert ), TAG_TRI_SHADOW );
    366 }
    367 
    368 /*
    369 =================
    370 R_ResizeStaticTriSurfVerts
    371 =================
    372 */
    373 void R_ResizeStaticTriSurfVerts( srfTriangles_t *tri, int numVerts ) {
    374 	idDrawVert * newVerts = (idDrawVert *)Mem_Alloc16( numVerts * sizeof( idDrawVert ), TAG_TRI_VERTS );
    375 	const int copy = std::min( numVerts, tri->numVerts );
    376 	memcpy( newVerts, tri->verts, copy * sizeof( idDrawVert ) );
    377 	Mem_Free( tri->verts );
    378 	tri->verts = newVerts;
    379 }
    380 
    381 /*
    382 =================
    383 R_ResizeStaticTriSurfIndexes
    384 =================
    385 */
    386 void R_ResizeStaticTriSurfIndexes( srfTriangles_t *tri, int numIndexes ) {
    387 	triIndex_t * newIndexes = (triIndex_t *)Mem_Alloc16( numIndexes * sizeof( triIndex_t ), TAG_TRI_INDEXES );
    388 	const int copy = std::min( numIndexes, tri->numIndexes );
    389 	memcpy( newIndexes, tri->indexes, copy * sizeof( triIndex_t ) );
    390 	Mem_Free( tri->indexes );
    391 	tri->indexes = newIndexes;
    392 }
    393 
    394 /*
    395 =================
    396 R_ReferenceStaticTriSurfVerts
    397 =================
    398 */
    399 void R_ReferenceStaticTriSurfVerts( srfTriangles_t *tri, const srfTriangles_t *reference ) {
    400 	tri->verts = reference->verts;
    401 }
    402 
    403 /*
    404 =================
    405 R_ReferenceStaticTriSurfIndexes
    406 =================
    407 */
    408 void R_ReferenceStaticTriSurfIndexes( srfTriangles_t *tri, const srfTriangles_t *reference ) {
    409 	tri->indexes = reference->indexes;
    410 }
    411 
    412 /*
    413 =================
    414 R_FreeStaticTriSurfSilIndexes
    415 =================
    416 */
    417 void R_FreeStaticTriSurfSilIndexes( srfTriangles_t *tri ) {
    418 	Mem_Free( tri->silIndexes );
    419 	tri->silIndexes = NULL;
    420 }
    421 
    422 /*
    423 ===============
    424 R_RangeCheckIndexes
    425 
    426 Check for syntactically incorrect indexes, like out of range values.
    427 Does not check for semantics, like degenerate triangles.
    428 
    429 No vertexes is acceptable if no indexes.
    430 No indexes is acceptable.
    431 More vertexes than are referenced by indexes are acceptable.
    432 ===============
    433 */
    434 void R_RangeCheckIndexes( const srfTriangles_t *tri ) {
    435 	int		i;
    436 
    437 	if ( tri->numIndexes < 0 ) {
    438 		common->Error( "R_RangeCheckIndexes: numIndexes < 0" );
    439 	}
    440 	if ( tri->numVerts < 0 ) {
    441 		common->Error( "R_RangeCheckIndexes: numVerts < 0" );
    442 	}
    443 
    444 	// must specify an integral number of triangles
    445 	if ( tri->numIndexes % 3 != 0 ) {
    446 		common->Error( "R_RangeCheckIndexes: numIndexes %% 3" );
    447 	}
    448 
    449 	for ( i = 0; i < tri->numIndexes; i++ ) {
    450 		if ( tri->indexes[i] >= tri->numVerts ) {
    451 			common->Error( "R_RangeCheckIndexes: index out of range" );
    452 		}
    453 	}
    454 
    455 	// this should not be possible unless there are unused verts
    456 	if ( tri->numVerts > tri->numIndexes ) {
    457 		// FIXME: find the causes of these
    458 		// common->Printf( "R_RangeCheckIndexes: tri->numVerts > tri->numIndexes\n" );
    459 	}
    460 }
    461 
    462 /*
    463 =================
    464 R_BoundTriSurf
    465 =================
    466 */
    467 void R_BoundTriSurf( srfTriangles_t *tri ) {
    468 	SIMDProcessor->MinMax( tri->bounds[0], tri->bounds[1], tri->verts, tri->numVerts );
    469 }
    470 
    471 /*
    472 =================
    473 R_CreateSilRemap
    474 =================
    475 */
    476 static int *R_CreateSilRemap( const srfTriangles_t *tri ) {
    477 	int		c_removed, c_unique;
    478 	int		*remap;
    479 	int		i, j, hashKey;
    480 	const idDrawVert *v1, *v2;
    481 
    482 	remap = (int *)R_ClearedStaticAlloc( tri->numVerts * sizeof( remap[0] ) );
    483 
    484 	if ( !r_useSilRemap.GetBool() ) {
    485 		for ( i = 0; i < tri->numVerts; i++ ) {
    486 			remap[i] = i;
    487 		}
    488 		return remap;
    489 	}
    490 
    491 	idHashIndex		hash( 1024, tri->numVerts );
    492 
    493 	c_removed = 0;
    494 	c_unique = 0;
    495 	for ( i = 0; i < tri->numVerts; i++ ) {
    496 		v1 = &tri->verts[i];
    497 
    498 		// see if there is an earlier vert that it can map to
    499 		hashKey = hash.GenerateKey( v1->xyz );
    500 		for ( j = hash.First( hashKey ); j >= 0; j = hash.Next( j ) ) {
    501 			v2 = &tri->verts[j];
    502 			if ( v2->xyz[0] == v1->xyz[0]
    503 				&& v2->xyz[1] == v1->xyz[1]
    504 				&& v2->xyz[2] == v1->xyz[2] ) {
    505 				c_removed++;
    506 				remap[i] = j;
    507 				break;
    508 			}
    509 		}
    510 		if ( j < 0 ) {
    511 			c_unique++;
    512 			remap[i] = i;
    513 			hash.Add( hashKey, i );
    514 		}
    515 	}
    516 
    517 	return remap;
    518 }
    519 
    520 /*
    521 =================
    522 R_CreateSilIndexes
    523 
    524 Uniquing vertexes only on xyz before creating sil edges reduces
    525 the edge count by about 20% on Q3 models
    526 =================
    527 */
    528 void R_CreateSilIndexes( srfTriangles_t *tri ) {
    529 	int		i;
    530 	int		*remap;
    531 
    532 	if ( tri->silIndexes ) {
    533 		Mem_Free( tri->silIndexes );
    534 		tri->silIndexes = NULL;
    535 	}
    536 
    537 	remap = R_CreateSilRemap( tri );
    538 
    539 	// remap indexes to the first one
    540 	R_AllocStaticTriSurfSilIndexes( tri, tri->numIndexes );
    541 	assert( tri->silIndexes != NULL );
    542 	for ( i = 0; i < tri->numIndexes; i++ ) {
    543 		tri->silIndexes[i] = remap[tri->indexes[i]];
    544 	}
    545 
    546 	R_StaticFree( remap );
    547 }
    548 
    549 /*
    550 =====================
    551 R_CreateDupVerts
    552 =====================
    553 */
    554 void R_CreateDupVerts( srfTriangles_t *tri ) {
    555 	int i;
    556 
    557 	idTempArray<int> remap( tri->numVerts );
    558 
    559 	// initialize vertex remap in case there are unused verts
    560 	for ( i = 0; i < tri->numVerts; i++ ) {
    561 		remap[i] = i;
    562 	}
    563 
    564 	// set the remap based on how the silhouette indexes are remapped
    565 	for ( i = 0; i < tri->numIndexes; i++ ) {
    566 		remap[tri->indexes[i]] = tri->silIndexes[i];
    567 	}
    568 
    569 	// create duplicate vertex index based on the vertex remap
    570 	idTempArray<int> tempDupVerts( tri->numVerts * 2 );
    571 	tri->numDupVerts = 0;
    572 	for ( i = 0; i < tri->numVerts; i++ ) {
    573 		if ( remap[i] != i ) {
    574 			tempDupVerts[tri->numDupVerts*2+0] = i;
    575 			tempDupVerts[tri->numDupVerts*2+1] = remap[i];
    576 			tri->numDupVerts++;
    577 		}
    578 	}
    579 
    580 	R_AllocStaticTriSurfDupVerts( tri, tri->numDupVerts );
    581 	memcpy( tri->dupVerts, tempDupVerts.Ptr(), tri->numDupVerts * 2 * sizeof( tri->dupVerts[0] ) );
    582 }
    583 
    584 /*
    585 ===============
    586 R_DefineEdge
    587 ===============
    588 */
    589 static int c_duplicatedEdges, c_tripledEdges;
    590 static const int MAX_SIL_EDGES			= 0x7ffff;
    591 
    592 static void R_DefineEdge( const int v1, const int v2, const int planeNum, const int numPlanes,
    593 	idList<silEdge_t> & silEdges, idHashIndex	& silEdgeHash ) {
    594 	int		i, hashKey;
    595 
    596 	// check for degenerate edge
    597 	if ( v1 == v2 ) {
    598 		return;
    599 	}
    600 	hashKey = silEdgeHash.GenerateKey( v1, v2 );
    601 	// search for a matching other side
    602 	for ( i = silEdgeHash.First( hashKey ); i >= 0 && i < MAX_SIL_EDGES; i = silEdgeHash.Next( i ) ) {
    603 		if ( silEdges[i].v1 == v1 && silEdges[i].v2 == v2 ) {
    604 			c_duplicatedEdges++;
    605 			// allow it to still create a new edge
    606 			continue;
    607 		}
    608 		if ( silEdges[i].v2 == v1 && silEdges[i].v1 == v2 ) {
    609 			if ( silEdges[i].p2 != numPlanes )  {
    610 				c_tripledEdges++;
    611 				// allow it to still create a new edge
    612 				continue;
    613 			}
    614 			// this is a matching back side
    615 			silEdges[i].p2 = planeNum;
    616 			return;
    617 		}
    618 
    619 	}
    620 
    621 	// define the new edge
    622 	silEdgeHash.Add( hashKey, silEdges.Num() );
    623 
    624 	silEdge_t silEdge;
    625 
    626 	silEdge.p1 = planeNum;
    627 	silEdge.p2 = numPlanes;
    628 	silEdge.v1 = v1;
    629 	silEdge.v2 = v2;
    630 
    631 	silEdges.Append( silEdge );
    632 }
    633 
    634 /*
    635 =================
    636 SilEdgeSort
    637 =================
    638 */
    639 static int SilEdgeSort( const void *a, const void *b ) {
    640 	if ( ((silEdge_t *)a)->p1 < ((silEdge_t *)b)->p1 ) {
    641 		return -1;
    642 	}
    643 	if ( ((silEdge_t *)a)->p1 > ((silEdge_t *)b)->p1 ) {
    644 		return 1;
    645 	}
    646 	if ( ((silEdge_t *)a)->p2 < ((silEdge_t *)b)->p2 ) {
    647 		return -1;
    648 	}
    649 	if ( ((silEdge_t *)a)->p2 > ((silEdge_t *)b)->p2 ) {
    650 		return 1;
    651 	}
    652 	return 0;
    653 }
    654 
    655 /*
    656 =================
    657 R_IdentifySilEdges
    658 
    659 If the surface will not deform, coplanar edges (polygon interiors)
    660 can never create silhouette plains, and can be omited
    661 =================
    662 */
    663 int	c_coplanarSilEdges;
    664 int	c_totalSilEdges;
    665 
    666 void R_IdentifySilEdges( srfTriangles_t *tri, bool omitCoplanarEdges ) {
    667 	int		i;
    668 	int		shared, single;
    669 
    670 	omitCoplanarEdges = false;	// optimization doesn't work for some reason
    671 
    672 	static const int SILEDGE_HASH_SIZE		= 1024;
    673 
    674 	const int numTris = tri->numIndexes / 3;
    675 
    676 	idList<silEdge_t>	silEdges( MAX_SIL_EDGES );
    677 	idHashIndex	silEdgeHash( SILEDGE_HASH_SIZE, MAX_SIL_EDGES );
    678 	int			numPlanes = numTris;
    679 
    680 
    681 	silEdgeHash.Clear();
    682 
    683 	c_duplicatedEdges = 0;
    684 	c_tripledEdges = 0;
    685 
    686 	for ( i = 0; i < numTris; i++ ) {
    687 		int		i1, i2, i3;
    688 
    689 		i1 = tri->silIndexes[ i*3 + 0 ];
    690 		i2 = tri->silIndexes[ i*3 + 1 ];
    691 		i3 = tri->silIndexes[ i*3 + 2 ];
    692 
    693 		// create the edges
    694 		R_DefineEdge( i1, i2, i, numPlanes, silEdges, silEdgeHash );
    695 		R_DefineEdge( i2, i3, i, numPlanes, silEdges, silEdgeHash );
    696 		R_DefineEdge( i3, i1, i, numPlanes, silEdges, silEdgeHash );
    697 	}
    698 
    699 	if ( c_duplicatedEdges || c_tripledEdges ) {
    700 		common->DWarning( "%i duplicated edge directions, %i tripled edges", c_duplicatedEdges, c_tripledEdges );
    701 	}
    702 
    703 	// if we know that the vertexes aren't going
    704 	// to deform, we can remove interior triangulation edges
    705 	// on otherwise planar polygons.
    706 	// I earlier believed that I could also remove concave
    707 	// edges, because they are never silhouettes in the conventional sense,
    708 	// but they are still needed to balance out all the true sil edges
    709 	// for the shadow algorithm to function
    710 	int		c_coplanarCulled;
    711 
    712 	c_coplanarCulled = 0;
    713 	if ( omitCoplanarEdges ) {
    714 		for ( i = 0; i < silEdges.Num(); i++ ) {
    715 			int			i1, i2, i3;
    716 			idPlane		plane;
    717 			int			base;
    718 			int			j;
    719 			float		d;
    720 
    721 			if ( silEdges[i].p2 == numPlanes ) {	// the fake dangling edge
    722 				continue;
    723 			}
    724 
    725 			base = silEdges[i].p1 * 3;
    726 			i1 = tri->silIndexes[ base + 0 ];
    727 			i2 = tri->silIndexes[ base + 1 ];
    728 			i3 = tri->silIndexes[ base + 2 ];
    729 
    730 			plane.FromPoints( tri->verts[i1].xyz, tri->verts[i2].xyz, tri->verts[i3].xyz );
    731 
    732 			// check to see if points of second triangle are not coplanar
    733 			base = silEdges[i].p2 * 3;
    734 			for ( j = 0; j < 3; j++ ) {
    735 				i1 = tri->silIndexes[ base + j ];
    736 				d = plane.Distance( tri->verts[i1].xyz );
    737 				if ( d != 0 ) {		// even a small epsilon causes problems
    738 					break;
    739 				}
    740 			}
    741 
    742 			if ( j == 3 ) {
    743 				// we can cull this sil edge
    744 				memmove( &silEdges[i], &silEdges[i+1], (silEdges.Num()-i-1) * sizeof( silEdges[i] ) );
    745 				c_coplanarCulled++;
    746 				silEdges.SetNum( silEdges.Num() - 1 );
    747 				i--;
    748 			}
    749 		}
    750 		if ( c_coplanarCulled ) {
    751 			c_coplanarSilEdges += c_coplanarCulled;
    752 //			common->Printf( "%i of %i sil edges coplanar culled\n", c_coplanarCulled,
    753 //				c_coplanarCulled + numSilEdges );
    754 		}
    755 	}
    756 	c_totalSilEdges += silEdges.Num();
    757 
    758 	// sort the sil edges based on plane number
    759 	qsort( silEdges.Ptr(), silEdges.Num(), sizeof( silEdges[0] ), SilEdgeSort );
    760 
    761 	// count up the distribution.
    762 	// a perfectly built model should only have shared
    763 	// edges, but most models will have some interpenetration
    764 	// and dangling edges
    765 	shared = 0;
    766 	single = 0;
    767 	for ( i = 0; i < silEdges.Num(); i++ ) {
    768 		if ( silEdges[i].p2 == numPlanes ) {
    769 			single++;
    770 		} else {
    771 			shared++;
    772 		}
    773 	}
    774 
    775 	if ( !single ) {
    776 		tri->perfectHull = true;
    777 	} else {
    778 		tri->perfectHull = false;
    779 	}
    780 
    781 	tri->numSilEdges = silEdges.Num();
    782 	R_AllocStaticTriSurfSilEdges( tri, silEdges.Num() );
    783 	memcpy( tri->silEdges, silEdges.Ptr(), silEdges.Num() * sizeof( tri->silEdges[0] ) );
    784 }
    785 
    786 /*
    787 ===============
    788 R_FaceNegativePolarity
    789 
    790 Returns true if the texture polarity of the face is negative, false if it is positive or zero
    791 ===============
    792 */
    793 static bool R_FaceNegativePolarity( const srfTriangles_t *tri, int firstIndex ) {
    794 	const idDrawVert * a = tri->verts + tri->indexes[firstIndex + 0];
    795 	const idDrawVert * b = tri->verts + tri->indexes[firstIndex + 1];
    796 	const idDrawVert * c = tri->verts + tri->indexes[firstIndex + 2];
    797 
    798 	const idVec2 aST = a->GetTexCoord();
    799 	const idVec2 bST = b->GetTexCoord();
    800 	const idVec2 cST = c->GetTexCoord();
    801 
    802 	float d0[5];
    803 	d0[3] = bST[0] - aST[0];
    804 	d0[4] = bST[1] - aST[1];
    805 
    806 	float d1[5];
    807 	d1[3] = cST[0] - aST[0];
    808 	d1[4] = cST[1] - aST[1];
    809 
    810 	const float area = d0[3] * d1[4] - d0[4] * d1[3];
    811 	if ( area >= 0 ) {
    812 		return false;
    813 	}
    814 	return true;
    815 }
    816 
    817 /*
    818 ===================
    819 R_DuplicateMirroredVertexes
    820 
    821 Modifies the surface to bust apart any verts that are shared by both positive and
    822 negative texture polarities, so tangent space smoothing at the vertex doesn't
    823 degenerate.
    824 
    825 This will create some identical vertexes (which will eventually get different tangent
    826 vectors), so never optimize the resulting mesh, or it will get the mirrored edges back.
    827 
    828 Reallocates tri->verts and changes tri->indexes in place
    829 Silindexes are unchanged by this.
    830 
    831 sets mirroredVerts and mirroredVerts[]
    832 ===================
    833 */
    834 struct tangentVert_t {
    835 	bool	polarityUsed[2];
    836 	int		negativeRemap;
    837 };
    838 
    839 static void	R_DuplicateMirroredVertexes( srfTriangles_t *tri ) {
    840 	tangentVert_t	*vert;
    841 	int				i, j;
    842 	int				totalVerts;
    843 	int				numMirror;
    844 
    845 	idTempArray<tangentVert_t> tverts( tri->numVerts );
    846 	tverts.Zero();
    847 
    848 	// determine texture polarity of each surface
    849 
    850 	// mark each vert with the polarities it uses
    851 	for ( i = 0; i < tri->numIndexes; i+=3 ) {
    852 		int	polarity = R_FaceNegativePolarity( tri, i );
    853 		for ( j = 0; j < 3; j++ ) {
    854 			tverts[tri->indexes[i+j]].polarityUsed[ polarity ] = true;
    855 		}
    856 	}
    857 
    858 	// now create new vertex indices as needed
    859 	totalVerts = tri->numVerts;
    860 	for ( i = 0; i < tri->numVerts; i++ ) {
    861 		vert = &tverts[i];
    862 		if ( vert->polarityUsed[0] && vert->polarityUsed[1] ) {
    863 			vert->negativeRemap = totalVerts;
    864 			totalVerts++;
    865 		}
    866 	}
    867 
    868 	tri->numMirroredVerts = totalVerts - tri->numVerts;
    869 
    870 	if ( tri->numMirroredVerts == 0 ) {
    871 		tri->mirroredVerts = NULL;
    872 		return;
    873 	}
    874 
    875 	// now create the new list
    876 	R_AllocStaticTriSurfMirroredVerts( tri, tri->numMirroredVerts );
    877 	R_ResizeStaticTriSurfVerts( tri, totalVerts );
    878 
    879 	// create the duplicates
    880 	numMirror = 0;
    881 	for ( i = 0; i < tri->numVerts; i++ ) {
    882 		j = tverts[i].negativeRemap;
    883 		if ( j ) {
    884 			tri->verts[j] = tri->verts[i];
    885 			tri->mirroredVerts[numMirror] = i;
    886 			numMirror++;
    887 		}
    888 	}
    889 	tri->numVerts = totalVerts;
    890 
    891 	// change the indexes
    892 	for ( i = 0; i < tri->numIndexes; i++ ) {
    893 		if ( tverts[tri->indexes[i]].negativeRemap && R_FaceNegativePolarity( tri, 3 * ( i / 3 ) ) ) {
    894 			tri->indexes[i] = tverts[tri->indexes[i]].negativeRemap;
    895 		}
    896 	}
    897 }
    898 
    899 /*
    900 ============
    901 R_DeriveNormalsAndTangents
    902 
    903 Derives the normal and orthogonal tangent vectors for the triangle vertices.
    904 For each vertex the normal and tangent vectors are derived from all triangles
    905 using the vertex which results in smooth tangents across the mesh.
    906 ============
    907 */
    908 void R_DeriveNormalsAndTangents( srfTriangles_t *tri ) {
    909 	idTempArray< idVec3 > vertexNormals( tri->numVerts );
    910 	idTempArray< idVec3 > vertexTangents( tri->numVerts );
    911 	idTempArray< idVec3 > vertexBitangents( tri->numVerts );
    912 
    913 	vertexNormals.Zero();
    914 	vertexTangents.Zero();
    915 	vertexBitangents.Zero();
    916 
    917 	for ( int i = 0; i < tri->numIndexes; i += 3 ) {
    918 		const int v0 = tri->indexes[i + 0];
    919 		const int v1 = tri->indexes[i + 1];
    920 		const int v2 = tri->indexes[i + 2];
    921 
    922 		const idDrawVert * a = tri->verts + v0;
    923 		const idDrawVert * b = tri->verts + v1;
    924 		const idDrawVert * c = tri->verts + v2;
    925 
    926 		const idVec2 aST = a->GetTexCoord();
    927 		const idVec2 bST = b->GetTexCoord();
    928 		const idVec2 cST = c->GetTexCoord();
    929 
    930 		float d0[5];
    931 		d0[0] = b->xyz[0] - a->xyz[0];
    932 		d0[1] = b->xyz[1] - a->xyz[1];
    933 		d0[2] = b->xyz[2] - a->xyz[2];
    934 		d0[3] = bST[0] - aST[0];
    935 		d0[4] = bST[1] - aST[1];
    936 
    937 		float d1[5];
    938 		d1[0] = c->xyz[0] - a->xyz[0];
    939 		d1[1] = c->xyz[1] - a->xyz[1];
    940 		d1[2] = c->xyz[2] - a->xyz[2];
    941 		d1[3] = cST[0] - aST[0];
    942 		d1[4] = cST[1] - aST[1];
    943 
    944 		idVec3 normal;
    945 		normal[0] = d1[1] * d0[2] - d1[2] * d0[1];
    946 		normal[1] = d1[2] * d0[0] - d1[0] * d0[2];
    947 		normal[2] = d1[0] * d0[1] - d1[1] * d0[0];
    948 
    949 		const float f0 = idMath::InvSqrt( normal.x * normal.x + normal.y * normal.y + normal.z * normal.z );
    950 
    951 		normal.x *= f0;
    952 		normal.y *= f0;
    953 		normal.z *= f0;
    954 
    955 		// area sign bit
    956 		const float area = d0[3] * d1[4] - d0[4] * d1[3];
    957 		unsigned int signBit = ( *(unsigned int *)&area ) & ( 1 << 31 );
    958 
    959 		idVec3 tangent;
    960 		tangent[0] = d0[0] * d1[4] - d0[4] * d1[0];
    961 		tangent[1] = d0[1] * d1[4] - d0[4] * d1[1];
    962 		tangent[2] = d0[2] * d1[4] - d0[4] * d1[2];
    963 
    964 		const float f1 = idMath::InvSqrt( tangent.x * tangent.x + tangent.y * tangent.y + tangent.z * tangent.z );
    965 		*(unsigned int *)&f1 ^= signBit;
    966 
    967 		tangent.x *= f1;
    968 		tangent.y *= f1;
    969 		tangent.z *= f1;
    970 
    971 		idVec3 bitangent;
    972 		bitangent[0] = d0[3] * d1[0] - d0[0] * d1[3];
    973 		bitangent[1] = d0[3] * d1[1] - d0[1] * d1[3];
    974 		bitangent[2] = d0[3] * d1[2] - d0[2] * d1[3];
    975 
    976 		const float f2 = idMath::InvSqrt( bitangent.x * bitangent.x + bitangent.y * bitangent.y + bitangent.z * bitangent.z );
    977 		*(unsigned int *)&f2 ^= signBit;
    978 
    979 		bitangent.x *= f2;
    980 		bitangent.y *= f2;
    981 		bitangent.z *= f2;
    982 
    983 		vertexNormals[v0] += normal;
    984 		vertexTangents[v0] += tangent;
    985 		vertexBitangents[v0] += bitangent;
    986 
    987 		vertexNormals[v1] += normal;
    988 		vertexTangents[v1] += tangent;
    989 		vertexBitangents[v1] += bitangent;
    990 
    991 		vertexNormals[v2] += normal;
    992 		vertexTangents[v2] += tangent;
    993 		vertexBitangents[v2] += bitangent;
    994 	}
    995 
    996 	// add the normal of a duplicated vertex to the normal of the first vertex with the same XYZ
    997 	for ( int i = 0; i < tri->numDupVerts; i++ ) {
    998 		vertexNormals[tri->dupVerts[i*2+0]] += vertexNormals[tri->dupVerts[i*2+1]];
    999 	}
   1000 
   1001 	// copy vertex normals to duplicated vertices
   1002 	for ( int i = 0; i < tri->numDupVerts; i++ ) {
   1003 		vertexNormals[tri->dupVerts[i*2+1]] = vertexNormals[tri->dupVerts[i*2+0]];
   1004 	}
   1005 
   1006 	// Project the summed vectors onto the normal plane and normalize.
   1007 	// The tangent vectors will not necessarily be orthogonal to each
   1008 	// other, but they will be orthogonal to the surface normal.
   1009 	for ( int i = 0; i < tri->numVerts; i++ ) {
   1010 		const float normalScale = idMath::InvSqrt( vertexNormals[i].x * vertexNormals[i].x + vertexNormals[i].y * vertexNormals[i].y + vertexNormals[i].z * vertexNormals[i].z );
   1011 		vertexNormals[i].x *= normalScale;
   1012 		vertexNormals[i].y *= normalScale;
   1013 		vertexNormals[i].z *= normalScale;
   1014 
   1015 		vertexTangents[i] -= ( vertexTangents[i] * vertexNormals[i] ) * vertexNormals[i];
   1016 		vertexBitangents[i] -= ( vertexBitangents[i] * vertexNormals[i] ) * vertexNormals[i];
   1017 
   1018 		const float tangentScale = idMath::InvSqrt( vertexTangents[i].x * vertexTangents[i].x + vertexTangents[i].y * vertexTangents[i].y + vertexTangents[i].z * vertexTangents[i].z );
   1019 		vertexTangents[i].x *= tangentScale;
   1020 		vertexTangents[i].y *= tangentScale;
   1021 		vertexTangents[i].z *= tangentScale;
   1022 
   1023 		const float bitangentScale = idMath::InvSqrt( vertexBitangents[i].x * vertexBitangents[i].x + vertexBitangents[i].y * vertexBitangents[i].y + vertexBitangents[i].z * vertexBitangents[i].z );
   1024 		vertexBitangents[i].x *= bitangentScale;
   1025 		vertexBitangents[i].y *= bitangentScale;
   1026 		vertexBitangents[i].z *= bitangentScale;
   1027 	}
   1028 
   1029 	// compress the normals and tangents
   1030 	for ( int i = 0; i < tri->numVerts; i++ ) {
   1031 		tri->verts[i].SetNormal( vertexNormals[i] );
   1032 		tri->verts[i].SetTangent( vertexTangents[i] );
   1033 		tri->verts[i].SetBiTangent( vertexBitangents[i] );
   1034 	}
   1035 }
   1036 
   1037 /*
   1038 ============
   1039 R_DeriveUnsmoothedNormalsAndTangents
   1040 ============
   1041 */
   1042 void R_DeriveUnsmoothedNormalsAndTangents( srfTriangles_t * tri ) {
   1043 	for ( int i = 0; i < tri->numVerts; i++ ) {
   1044 		float d0, d1, d2, d3, d4;
   1045 		float d5, d6, d7, d8, d9;
   1046 		float s0, s1, s2;
   1047 		float n0, n1, n2;
   1048 		float t0, t1, t2;
   1049 		float t3, t4, t5;
   1050 
   1051 		const dominantTri_t &dt = tri->dominantTris[i];
   1052 
   1053 		idDrawVert *a = tri->verts + i;
   1054 		idDrawVert *b = tri->verts + dt.v2;
   1055 		idDrawVert *c = tri->verts + dt.v3;
   1056 
   1057 		const idVec2 aST = a->GetTexCoord();
   1058 		const idVec2 bST = b->GetTexCoord();
   1059 		const idVec2 cST = c->GetTexCoord();
   1060 
   1061 		d0 = b->xyz[0] - a->xyz[0];
   1062 		d1 = b->xyz[1] - a->xyz[1];
   1063 		d2 = b->xyz[2] - a->xyz[2];
   1064 		d3 = bST[0] - aST[0];
   1065 		d4 = bST[1] - aST[1];
   1066 
   1067 		d5 = c->xyz[0] - a->xyz[0];
   1068 		d6 = c->xyz[1] - a->xyz[1];
   1069 		d7 = c->xyz[2] - a->xyz[2];
   1070 		d8 = cST[0] - aST[0];
   1071 		d9 = cST[1] - aST[1];
   1072 
   1073 		s0 = dt.normalizationScale[0];
   1074 		s1 = dt.normalizationScale[1];
   1075 		s2 = dt.normalizationScale[2];
   1076 
   1077 		n0 = s2 * ( d6 * d2 - d7 * d1 );
   1078 		n1 = s2 * ( d7 * d0 - d5 * d2 );
   1079 		n2 = s2 * ( d5 * d1 - d6 * d0 );
   1080 
   1081 		t0 = s0 * ( d0 * d9 - d4 * d5 );
   1082 		t1 = s0 * ( d1 * d9 - d4 * d6 );
   1083 		t2 = s0 * ( d2 * d9 - d4 * d7 );
   1084 
   1085 #ifndef DERIVE_UNSMOOTHED_BITANGENT
   1086 		t3 = s1 * ( d3 * d5 - d0 * d8 );
   1087 		t4 = s1 * ( d3 * d6 - d1 * d8 );
   1088 		t5 = s1 * ( d3 * d7 - d2 * d8 );
   1089 #else
   1090 		t3 = s1 * ( n2 * t1 - n1 * t2 );
   1091 		t4 = s1 * ( n0 * t2 - n2 * t0 );
   1092 		t5 = s1 * ( n1 * t0 - n0 * t1 );
   1093 #endif
   1094 
   1095 		a->SetNormal( n0, n1, n2 );
   1096 		a->SetTangent( t0, t1, t2 );
   1097 		a->SetBiTangent( t3, t4, t5 );
   1098 	}
   1099 }
   1100 
   1101 /*
   1102 =====================
   1103 R_CreateVertexNormals
   1104 
   1105 Averages together the contributions of all faces that are
   1106 used by a vertex, creating drawVert->normal
   1107 =====================
   1108 */
   1109 void R_CreateVertexNormals( srfTriangles_t *tri ) {
   1110 	if ( tri->silIndexes == NULL ) {
   1111 		R_CreateSilIndexes( tri );
   1112 	}
   1113 
   1114 	idTempArray< idVec3 > vertexNormals( tri->numVerts );
   1115 	vertexNormals.Zero();
   1116 
   1117 	assert( tri->silIndexes != NULL );
   1118 	for ( int i = 0; i < tri->numIndexes; i += 3 ) {
   1119 		const int i0 = tri->silIndexes[i + 0];
   1120 		const int i1 = tri->silIndexes[i + 1];
   1121 		const int i2 = tri->silIndexes[i + 2];
   1122 
   1123 		const idDrawVert & v0 = tri->verts[i0];
   1124 		const idDrawVert & v1 = tri->verts[i1];
   1125 		const idDrawVert & v2 = tri->verts[i2];
   1126 
   1127 		const idPlane plane( v0.xyz, v1.xyz, v2.xyz );
   1128 
   1129 		vertexNormals[i0] += plane.Normal();
   1130 		vertexNormals[i1] += plane.Normal();
   1131 		vertexNormals[i2] += plane.Normal();
   1132 	}
   1133 
   1134 	// replicate from silIndexes to all indexes
   1135 	for ( int i = 0; i < tri->numIndexes; i++ ) {
   1136 		vertexNormals[tri->indexes[i]] = vertexNormals[tri->silIndexes[i]];
   1137 	}
   1138 
   1139 	// normalize
   1140 	for ( int i = 0; i < tri->numVerts; i++ ) {
   1141 		vertexNormals[i].Normalize();
   1142 	}
   1143 
   1144 	// compress the normals
   1145 	for ( int i = 0; i < tri->numVerts; i++ ) {
   1146 		tri->verts[i].SetNormal( vertexNormals[i] );
   1147 	}
   1148 }
   1149 
   1150 /*
   1151 =================
   1152 R_DeriveTangentsWithoutNormals
   1153 
   1154 Build texture space tangents for bump mapping
   1155 If a surface is deformed, this must be recalculated
   1156 
   1157 This assumes that any mirrored vertexes have already been duplicated, so
   1158 any shared vertexes will have the tangent spaces smoothed across.
   1159 
   1160 Texture wrapping slightly complicates this, but as long as the normals
   1161 are shared, and the tangent vectors are projected onto the normals, the
   1162 separate vertexes should wind up with identical tangent spaces.
   1163 
   1164 mirroring a normalmap WILL cause a slightly visible seam unless the normals
   1165 are completely flat around the edge's full bilerp support.
   1166 
   1167 Vertexes which are smooth shaded must have their tangent vectors
   1168 in the same plane, which will allow a seamless
   1169 rendering as long as the normal map is even on both sides of the
   1170 seam.
   1171 
   1172 A smooth shaded surface may have multiple tangent vectors at a vertex
   1173 due to texture seams or mirroring, but it should only have a single
   1174 normal vector.
   1175 
   1176 Each triangle has a pair of tangent vectors in it's plane
   1177 
   1178 Should we consider having vertexes point at shared tangent spaces
   1179 to save space or speed transforms?
   1180 
   1181 this version only handles bilateral symetry
   1182 =================
   1183 */
   1184 void R_DeriveTangentsWithoutNormals( srfTriangles_t *tri ) {
   1185 	idTempArray< idVec3 > triangleTangents( tri->numIndexes / 3 );
   1186 	idTempArray< idVec3 > triangleBitangents( tri->numIndexes / 3 );
   1187 
   1188 	//
   1189 	// calculate tangent vectors for each face in isolation
   1190 	//
   1191 	int c_positive = 0;
   1192 	int c_negative = 0;
   1193 	int c_textureDegenerateFaces = 0;
   1194 	for ( int i = 0; i < tri->numIndexes; i += 3 ) {
   1195 		idVec3	temp;
   1196 
   1197 		idDrawVert * a = tri->verts + tri->indexes[i + 0];
   1198 		idDrawVert * b = tri->verts + tri->indexes[i + 1];
   1199 		idDrawVert * c = tri->verts + tri->indexes[i + 2];
   1200 
   1201 		const idVec2 aST = a->GetTexCoord();
   1202 		const idVec2 bST = b->GetTexCoord();
   1203 		const idVec2 cST = c->GetTexCoord();
   1204 
   1205 		float d0[5];
   1206 		d0[0] = b->xyz[0] - a->xyz[0];
   1207 		d0[1] = b->xyz[1] - a->xyz[1];
   1208 		d0[2] = b->xyz[2] - a->xyz[2];
   1209 		d0[3] = bST[0] - aST[0];
   1210 		d0[4] = bST[1] - aST[1];
   1211 
   1212 		float d1[5];
   1213 		d1[0] = c->xyz[0] - a->xyz[0];
   1214 		d1[1] = c->xyz[1] - a->xyz[1];
   1215 		d1[2] = c->xyz[2] - a->xyz[2];
   1216 		d1[3] = cST[0] - aST[0];
   1217 		d1[4] = cST[1] - aST[1];
   1218 
   1219 		const float area = d0[3] * d1[4] - d0[4] * d1[3];
   1220 		if ( fabs( area ) < 1e-20f ) {
   1221 			triangleTangents[i / 3].Zero();
   1222 			triangleBitangents[i / 3].Zero();
   1223 			c_textureDegenerateFaces++;
   1224 			continue;
   1225 		}
   1226 		if ( area > 0.0f ) {
   1227 			c_positive++;
   1228 		} else {
   1229 			c_negative++;
   1230 		}
   1231 
   1232 #ifdef USE_INVA
   1233 		float inva = ( area < 0.0f ) ? -1.0f : 1.0f;		// was = 1.0f / area;
   1234 
   1235         temp[0] = ( d0[0] * d1[4] - d0[4] * d1[0] ) * inva;
   1236         temp[1] = ( d0[1] * d1[4] - d0[4] * d1[1] ) * inva;
   1237         temp[2] = ( d0[2] * d1[4] - d0[4] * d1[2] ) * inva;
   1238 		temp.Normalize();
   1239 		triangleTangents[i / 3] = temp;
   1240         
   1241         temp[0] = ( d0[3] * d1[0] - d0[0] * d1[3] ) * inva;
   1242         temp[1] = ( d0[3] * d1[1] - d0[1] * d1[3] ) * inva;
   1243         temp[2] = ( d0[3] * d1[2] - d0[2] * d1[3] ) * inva;
   1244 		temp.Normalize();
   1245 		triangleBitangents[i / 3] = temp;
   1246 #else
   1247         temp[0] = ( d0[0] * d1[4] - d0[4] * d1[0] );
   1248         temp[1] = ( d0[1] * d1[4] - d0[4] * d1[1] );
   1249         temp[2] = ( d0[2] * d1[4] - d0[4] * d1[2] );
   1250 		temp.Normalize();
   1251 		triangleTangents[i / 3] = temp;
   1252         
   1253         temp[0] = ( d0[3] * d1[0] - d0[0] * d1[3] );
   1254         temp[1] = ( d0[3] * d1[1] - d0[1] * d1[3] );
   1255         temp[2] = ( d0[3] * d1[2] - d0[2] * d1[3] );
   1256 		temp.Normalize();
   1257 		triangleBitangents[i / 3] = temp;
   1258 #endif
   1259 	}
   1260 
   1261 	idTempArray< idVec3 > vertexTangents( tri->numVerts );
   1262 	idTempArray< idVec3 > vertexBitangents( tri->numVerts );
   1263 
   1264 	// clear the tangents
   1265 	for ( int i = 0; i < tri->numVerts; ++i ) {
   1266 		vertexTangents[i].Zero();
   1267 		vertexBitangents[i].Zero();
   1268 	}
   1269 
   1270 	// sum up the neighbors
   1271 	for ( int i = 0; i < tri->numIndexes; i += 3 ) {
   1272 		// for each vertex on this face
   1273 		for ( int j = 0; j < 3; j++ ) {
   1274 			vertexTangents[tri->indexes[i+j]] += triangleTangents[i / 3];
   1275 			vertexBitangents[tri->indexes[i+j]] += triangleBitangents[i / 3];
   1276 		}
   1277 	}
   1278 
   1279 	// Project the summed vectors onto the normal plane and normalize.
   1280 	// The tangent vectors will not necessarily be orthogonal to each
   1281 	// other, but they will be orthogonal to the surface normal.
   1282 	for ( int i = 0; i < tri->numVerts; i++ ) {
   1283 		idVec3 normal = tri->verts[i].GetNormal();
   1284 		normal.Normalize();
   1285 
   1286 		vertexTangents[i] -= ( vertexTangents[i] * normal ) * normal;
   1287 		vertexTangents[i].Normalize();
   1288 
   1289 		vertexBitangents[i] -= ( vertexBitangents[i] * normal ) * normal;
   1290 		vertexBitangents[i].Normalize();
   1291 	}
   1292 
   1293 	for ( int i = 0; i < tri->numVerts; i++ ) {
   1294 		tri->verts[i].SetTangent( vertexTangents[i] );
   1295 		tri->verts[i].SetBiTangent( vertexBitangents[i] );
   1296 	}
   1297 
   1298 	tri->tangentsCalculated = true;
   1299 }
   1300 
   1301 /*
   1302 ===================
   1303 R_BuildDominantTris
   1304 
   1305 Find the largest triangle that uses each vertex
   1306 ===================
   1307 */
   1308 typedef struct {
   1309 	int		vertexNum;
   1310 	int		faceNum;
   1311 } indexSort_t;
   1312 
   1313 static int IndexSort( const void *a, const void *b ) {
   1314 	if ( ((indexSort_t *)a)->vertexNum < ((indexSort_t *)b)->vertexNum ) {
   1315 		return -1;
   1316 	}
   1317 	if ( ((indexSort_t *)a)->vertexNum > ((indexSort_t *)b)->vertexNum ) {
   1318 		return 1;
   1319 	}
   1320 	return 0;
   1321 }
   1322 
   1323 void R_BuildDominantTris( srfTriangles_t *tri ) {
   1324 	int i, j;
   1325 	dominantTri_t *dt;
   1326 	const int numIndexes = tri->numIndexes;
   1327 	indexSort_t *ind = (indexSort_t *)R_StaticAlloc( numIndexes * sizeof( indexSort_t ) );
   1328 	if ( ind == NULL ) {
   1329 		idLib::Error( "Couldn't allocate index sort array" );
   1330 		return;
   1331 	}
   1332 
   1333 	for ( i = 0; i < tri->numIndexes; i++ ) {
   1334 		ind[i].vertexNum = tri->indexes[i];
   1335 		ind[i].faceNum = i / 3;
   1336 	}
   1337 	qsort( ind, tri->numIndexes, sizeof( *ind ), IndexSort );
   1338 
   1339 	R_AllocStaticTriSurfDominantTris( tri, tri->numVerts );
   1340 	dt = tri->dominantTris;
   1341 	memset( dt, 0, tri->numVerts * sizeof( dt[0] ) );
   1342 
   1343 	for ( i = 0; i < numIndexes; i += j ) {
   1344 		float	maxArea = 0;
   1345 #pragma warning( disable: 6385 ) // This is simply to get pass a false defect for /analyze -- if you can figure out a better way, please let Shawn know...
   1346 		int		vertNum = ind[i].vertexNum;
   1347 #pragma warning( default: 6385 )
   1348 		for ( j = 0; i + j < tri->numIndexes && ind[i+j].vertexNum == vertNum; j++ ) {
   1349 			float		d0[5], d1[5];
   1350 			idDrawVert	*a, *b, *c;
   1351 			idVec3		normal, tangent, bitangent;
   1352 
   1353 			int	i1 = tri->indexes[ind[i+j].faceNum * 3 + 0];
   1354 			int	i2 = tri->indexes[ind[i+j].faceNum * 3 + 1];
   1355 			int	i3 = tri->indexes[ind[i+j].faceNum * 3 + 2];
   1356 			
   1357 			a = tri->verts + i1;
   1358 			b = tri->verts + i2;
   1359 			c = tri->verts + i3;
   1360 
   1361 			const idVec2 aST = a->GetTexCoord();
   1362 			const idVec2 bST = b->GetTexCoord();
   1363 			const idVec2 cST = c->GetTexCoord();
   1364 
   1365 			d0[0] = b->xyz[0] - a->xyz[0];
   1366 			d0[1] = b->xyz[1] - a->xyz[1];
   1367 			d0[2] = b->xyz[2] - a->xyz[2];
   1368 			d0[3] = bST[0] - aST[0];
   1369 			d0[4] = bST[1] - aST[1];
   1370 
   1371 			d1[0] = c->xyz[0] - a->xyz[0];
   1372 			d1[1] = c->xyz[1] - a->xyz[1];
   1373 			d1[2] = c->xyz[2] - a->xyz[2];
   1374 			d1[3] = cST[0] - aST[0];
   1375 			d1[4] = cST[1] - aST[1];
   1376 
   1377 			normal[0] = ( d1[1] * d0[2] - d1[2] * d0[1] );
   1378 			normal[1] = ( d1[2] * d0[0] - d1[0] * d0[2] );
   1379 			normal[2] = ( d1[0] * d0[1] - d1[1] * d0[0] );
   1380 
   1381 			float area = normal.Length();
   1382 
   1383 			// if this is smaller than what we already have, skip it
   1384 			if ( area < maxArea ) {
   1385 				continue;
   1386 			}
   1387 			maxArea = area;
   1388 
   1389 			if ( i1 == vertNum ) {
   1390 				dt[vertNum].v2 = i2;
   1391 				dt[vertNum].v3 = i3;
   1392 			} else if ( i2 == vertNum ) {
   1393 				dt[vertNum].v2 = i3;
   1394 				dt[vertNum].v3 = i1;
   1395 			} else {
   1396 				dt[vertNum].v2 = i1;
   1397 				dt[vertNum].v3 = i2;
   1398 			}
   1399 
   1400 			float	len = area;
   1401 			if ( len < 0.001f ) {
   1402 				len = 0.001f;
   1403 			}
   1404 			dt[vertNum].normalizationScale[2] = 1.0f / len;		// normal
   1405 
   1406 			// texture area
   1407 			area = d0[3] * d1[4] - d0[4] * d1[3];
   1408 
   1409 			tangent[0] = ( d0[0] * d1[4] - d0[4] * d1[0] );
   1410 			tangent[1] = ( d0[1] * d1[4] - d0[4] * d1[1] );
   1411 			tangent[2] = ( d0[2] * d1[4] - d0[4] * d1[2] );
   1412 			len = tangent.Length();
   1413 			if ( len < 0.001f ) {
   1414 				len = 0.001f;
   1415 			}
   1416 			dt[vertNum].normalizationScale[0] = ( area > 0 ? 1 : -1 ) / len;	// tangents[0]
   1417 	        
   1418 			bitangent[0] = ( d0[3] * d1[0] - d0[0] * d1[3] );
   1419 			bitangent[1] = ( d0[3] * d1[1] - d0[1] * d1[3] );
   1420 			bitangent[2] = ( d0[3] * d1[2] - d0[2] * d1[3] );
   1421 			len = bitangent.Length();
   1422 			if ( len < 0.001f ) {
   1423 				len = 0.001f;
   1424 			}
   1425 #ifdef DERIVE_UNSMOOTHED_BITANGENT
   1426 			dt[vertNum].normalizationScale[1] = ( area > 0 ? 1 : -1 );
   1427 #else
   1428 			dt[vertNum].normalizationScale[1] = ( area > 0 ? 1 : -1 ) / len;	// tangents[1]
   1429 #endif
   1430 		}
   1431 	}
   1432 
   1433 	R_StaticFree( ind );
   1434 }
   1435 
   1436 /*
   1437 ==================
   1438 R_DeriveTangents
   1439 
   1440 This is called once for static surfaces, and every frame for deforming surfaces
   1441 
   1442 Builds tangents, normals, and face planes
   1443 ==================
   1444 */
   1445 void R_DeriveTangents( srfTriangles_t *tri ) {
   1446 	if ( tri->tangentsCalculated ) {
   1447 		return;
   1448 	}
   1449 
   1450 	tr.pc.c_tangentIndexes += tri->numIndexes;
   1451 
   1452 	if ( tri->dominantTris != NULL ) {
   1453 		R_DeriveUnsmoothedNormalsAndTangents( tri );
   1454 	} else {
   1455 		R_DeriveNormalsAndTangents( tri );
   1456 	}
   1457 	tri->tangentsCalculated = true;
   1458 }
   1459 
   1460 /*
   1461 =================
   1462 R_RemoveDuplicatedTriangles
   1463 
   1464 silIndexes must have already been calculated
   1465 
   1466 silIndexes are used instead of indexes, because duplicated
   1467 triangles could have different texture coordinates.
   1468 =================
   1469 */
   1470 void R_RemoveDuplicatedTriangles( srfTriangles_t *tri ) {
   1471 	int		c_removed;
   1472 	int		i, j, r;
   1473 	int		a, b, c;
   1474 
   1475 	c_removed = 0;
   1476 
   1477 	// check for completely duplicated triangles
   1478 	// any rotation of the triangle is still the same, but a mirroring
   1479 	// is considered different
   1480 	for ( i = 0; i < tri->numIndexes; i+=3 ) {
   1481 		for ( r = 0; r < 3; r++ ) {
   1482 			a = tri->silIndexes[i+r];
   1483 			b = tri->silIndexes[i+(r+1)%3];
   1484 			c = tri->silIndexes[i+(r+2)%3];
   1485 			for ( j = i + 3; j < tri->numIndexes; j+=3 ) {
   1486 				if ( tri->silIndexes[j] == a && tri->silIndexes[j+1] == b && tri->silIndexes[j+2] == c ) {
   1487 					c_removed++;
   1488 					memmove( tri->indexes + j, tri->indexes + j + 3, ( tri->numIndexes - j - 3 ) * sizeof( tri->indexes[0] ) );
   1489 					memmove( tri->silIndexes + j, tri->silIndexes + j + 3, ( tri->numIndexes - j - 3 ) * sizeof( tri->silIndexes[0] ) );
   1490 					tri->numIndexes -= 3;
   1491 					j -= 3;
   1492 				}
   1493 			}
   1494 		}
   1495 	}
   1496 
   1497 	if ( c_removed ) {
   1498 		common->Printf( "removed %i duplicated triangles\n", c_removed );
   1499 	}
   1500 }
   1501 
   1502 /*
   1503 =================
   1504 R_RemoveDegenerateTriangles
   1505 
   1506 silIndexes must have already been calculated
   1507 =================
   1508 */
   1509 void R_RemoveDegenerateTriangles( srfTriangles_t *tri ) {
   1510 	int		c_removed;
   1511 	int		i;
   1512 	int		a, b, c;
   1513 
   1514 	assert( tri->silIndexes != NULL );
   1515 
   1516 	// check for completely degenerate triangles
   1517 	c_removed = 0;
   1518 	for ( i = 0; i < tri->numIndexes; i += 3 ) {
   1519 		a = tri->silIndexes[i];
   1520 		b = tri->silIndexes[i+1];
   1521 		c = tri->silIndexes[i+2];
   1522 		if ( a == b || a == c || b == c ) {
   1523 			c_removed++;
   1524 			memmove( tri->indexes + i, tri->indexes + i + 3, ( tri->numIndexes - i - 3 ) * sizeof( tri->indexes[0] ) );
   1525 			memmove( tri->silIndexes + i, tri->silIndexes + i + 3, ( tri->numIndexes - i - 3 ) * sizeof( tri->silIndexes[0] ) );
   1526 			tri->numIndexes -= 3;
   1527 			i -= 3;
   1528 		}
   1529 	}
   1530 
   1531 	// this doesn't free the memory used by the unused verts
   1532 
   1533 	if ( c_removed ) {
   1534 		common->Printf( "removed %i degenerate triangles\n", c_removed );
   1535 	}
   1536 }
   1537 
   1538 /*
   1539 =================
   1540 R_TestDegenerateTextureSpace
   1541 =================
   1542 */
   1543 void R_TestDegenerateTextureSpace( srfTriangles_t *tri ) {
   1544 	int		c_degenerate;
   1545 	int		i;
   1546 
   1547 	// check for triangles with a degenerate texture space
   1548 	c_degenerate = 0;
   1549 	for ( i = 0; i < tri->numIndexes; i += 3 ) {
   1550 		const idDrawVert &a = tri->verts[tri->indexes[i+0]];
   1551 		const idDrawVert &b = tri->verts[tri->indexes[i+1]];
   1552 		const idDrawVert &c = tri->verts[tri->indexes[i+2]];
   1553 
   1554 		if ( a.st == b.st || b.st == c.st || c.st == a.st ) {
   1555 			c_degenerate++;
   1556 		}
   1557 	}
   1558 
   1559 	if ( c_degenerate ) {
   1560 //		common->Printf( "%d triangles with a degenerate texture space\n", c_degenerate );
   1561 	}
   1562 }
   1563 
   1564 /*
   1565 =================
   1566 R_RemoveUnusedVerts
   1567 =================
   1568 */
   1569 void R_RemoveUnusedVerts( srfTriangles_t *tri ) {
   1570 	int		i;
   1571 	int		*mark;
   1572 	int		index;
   1573 	int		used;
   1574 
   1575 	mark = (int *)R_ClearedStaticAlloc( tri->numVerts * sizeof( *mark ) );
   1576 
   1577 	for ( i = 0; i < tri->numIndexes; i++ ) {
   1578 		index = tri->indexes[i];
   1579 		if ( index < 0 || index >= tri->numVerts ) {
   1580 			common->Error( "R_RemoveUnusedVerts: bad index" );
   1581 		}
   1582 		mark[ index ] = 1;
   1583 
   1584 		if ( tri->silIndexes ) {
   1585 			index = tri->silIndexes[i];
   1586 			if ( index < 0 || index >= tri->numVerts ) {
   1587 				common->Error( "R_RemoveUnusedVerts: bad index" );
   1588 			}
   1589 			mark[ index ] = 1;
   1590 		}
   1591 	}
   1592 
   1593 	used = 0;
   1594 	for ( i = 0; i < tri->numVerts; i++ ) {
   1595 		if ( !mark[i] ) {
   1596 			continue;
   1597 		}
   1598 		mark[i] = used + 1;
   1599 		used++;
   1600 	}
   1601 
   1602 	if ( used != tri->numVerts ) {
   1603 		for ( i = 0; i < tri->numIndexes; i++ ) {
   1604 			tri->indexes[i] = mark[ tri->indexes[i] ] - 1;
   1605 			if ( tri->silIndexes ) {
   1606 				tri->silIndexes[i] = mark[ tri->silIndexes[i] ] - 1;
   1607 			}
   1608 		}
   1609 		tri->numVerts = used;
   1610 
   1611 		for ( i = 0; i < tri->numVerts; i++ ) {
   1612 			index = mark[ i ];
   1613 			if ( !index ) {
   1614 				continue;
   1615 			}
   1616 			tri->verts[ index - 1 ] = tri->verts[i];
   1617 		}
   1618 
   1619 		// this doesn't realloc the arrays to save the memory used by the unused verts
   1620 	}
   1621 
   1622 	R_StaticFree( mark );
   1623 }
   1624 
   1625 /*
   1626 =================
   1627 R_MergeSurfaceList
   1628 
   1629 Only deals with vertexes and indexes, not silhouettes, planes, etc.
   1630 Does NOT perform a cleanup triangles, so there may be duplicated verts in the result.
   1631 =================
   1632 */
   1633 srfTriangles_t * R_MergeSurfaceList( const srfTriangles_t **surfaces, int numSurfaces ) {
   1634 	srfTriangles_t	*newTri;
   1635 	const srfTriangles_t	*tri;
   1636 	int				i, j;
   1637 	int				totalVerts;
   1638 	int				totalIndexes;
   1639 
   1640 	totalVerts = 0;
   1641 	totalIndexes = 0;
   1642 	for ( i = 0; i < numSurfaces; i++ ) {
   1643 		totalVerts += surfaces[i]->numVerts;
   1644 		totalIndexes += surfaces[i]->numIndexes;
   1645 	}
   1646 
   1647 	newTri = R_AllocStaticTriSurf();
   1648 	newTri->numVerts = totalVerts;
   1649 	newTri->numIndexes = totalIndexes;
   1650 	R_AllocStaticTriSurfVerts( newTri, newTri->numVerts );
   1651 	R_AllocStaticTriSurfIndexes( newTri, newTri->numIndexes );
   1652 
   1653 	totalVerts = 0;
   1654 	totalIndexes = 0;
   1655 	for ( i = 0; i < numSurfaces; i++ ) {
   1656 		tri = surfaces[i];
   1657 		memcpy( newTri->verts + totalVerts, tri->verts, tri->numVerts * sizeof( *tri->verts ) );
   1658 		for ( j = 0; j < tri->numIndexes; j++ ) {
   1659 			newTri->indexes[ totalIndexes + j ] = totalVerts + tri->indexes[j];
   1660 		}
   1661 		totalVerts += tri->numVerts;
   1662 		totalIndexes += tri->numIndexes;
   1663 	}
   1664 
   1665 	return newTri;
   1666 }
   1667 
   1668 /*
   1669 =================
   1670 R_MergeTriangles
   1671 
   1672 Only deals with vertexes and indexes, not silhouettes, planes, etc.
   1673 Does NOT perform a cleanup triangles, so there may be duplicated verts in the result.
   1674 =================
   1675 */
   1676 srfTriangles_t * R_MergeTriangles( const srfTriangles_t *tri1, const srfTriangles_t *tri2 ) {
   1677 	const srfTriangles_t	*tris[2];
   1678 
   1679 	tris[0] = tri1;
   1680 	tris[1] = tri2;
   1681 
   1682 	return R_MergeSurfaceList( tris, 2 );
   1683 }
   1684 
   1685 /*
   1686 =================
   1687 R_ReverseTriangles
   1688 
   1689 Lit two sided surfaces need to have the triangles actually duplicated,
   1690 they can't just turn on two sided lighting, because the normal and tangents
   1691 are wrong on the other sides.
   1692 
   1693 This should be called before R_CleanupTriangles
   1694 =================
   1695 */
   1696 void R_ReverseTriangles( srfTriangles_t *tri ) {
   1697 	int			i;
   1698 
   1699 	// flip the normal on each vertex
   1700 	// If the surface is going to have generated normals, this won't matter,
   1701 	// but if it has explicit normals, this will keep it on the correct side
   1702 	for ( i = 0; i < tri->numVerts; i++ ) {
   1703 		tri->verts[i].SetNormal( vec3_origin - tri->verts[i].GetNormal() );
   1704 	}
   1705 
   1706 	// flip the index order to make them back sided
   1707 	for ( i = 0; i < tri->numIndexes; i+= 3 ) {
   1708 		triIndex_t	temp;
   1709 
   1710 		temp = tri->indexes[ i + 0 ];
   1711 		tri->indexes[ i + 0 ] = tri->indexes[ i + 1 ];
   1712 		tri->indexes[ i + 1 ] = temp;
   1713 	}
   1714 }
   1715 
   1716 /*
   1717 =================
   1718 R_CleanupTriangles
   1719 
   1720 FIXME: allow createFlat and createSmooth normals, as well as explicit
   1721 =================
   1722 */
   1723 void R_CleanupTriangles( srfTriangles_t *tri, bool createNormals, bool identifySilEdges, bool useUnsmoothedTangents ) {
   1724 	R_RangeCheckIndexes( tri );
   1725 
   1726 	R_CreateSilIndexes( tri );
   1727 
   1728 //	R_RemoveDuplicatedTriangles( tri );	// this may remove valid overlapped transparent triangles
   1729 
   1730 	R_RemoveDegenerateTriangles( tri );
   1731 
   1732 	R_TestDegenerateTextureSpace( tri );
   1733 
   1734 //	R_RemoveUnusedVerts( tri );
   1735 
   1736 	if ( identifySilEdges ) {
   1737 		R_IdentifySilEdges( tri, true );	// assume it is non-deformable, and omit coplanar edges
   1738 	}
   1739 
   1740 	// bust vertexes that share a mirrored edge into separate vertexes
   1741 	R_DuplicateMirroredVertexes( tri );
   1742 
   1743 	R_CreateDupVerts( tri );
   1744 
   1745 	R_BoundTriSurf( tri );
   1746 
   1747 	if ( useUnsmoothedTangents ) {
   1748 		R_BuildDominantTris( tri );
   1749 		R_DeriveTangents( tri );
   1750 	} else if ( !createNormals ) {
   1751 		R_DeriveTangentsWithoutNormals( tri );
   1752 	} else {
   1753 		R_DeriveTangents( tri );
   1754 	}
   1755 }
   1756 
   1757 /*
   1758 ===================================================================================
   1759 
   1760 DEFORMED SURFACES
   1761 
   1762 ===================================================================================
   1763 */
   1764 
   1765 /*
   1766 ===================
   1767 R_BuildDeformInfo
   1768 ===================
   1769 */
   1770 deformInfo_t *R_BuildDeformInfo( int numVerts, const idDrawVert *verts, int numIndexes, const int *indexes, 
   1771 									bool useUnsmoothedTangents ) {
   1772 	srfTriangles_t	tri;
   1773 	memset( &tri, 0, sizeof( srfTriangles_t ) );
   1774 
   1775 	tri.numVerts = numVerts;
   1776 	R_AllocStaticTriSurfVerts( &tri, tri.numVerts );
   1777 	SIMDProcessor->Memcpy( tri.verts, verts, tri.numVerts * sizeof( tri.verts[0] ) );
   1778 
   1779 	tri.numIndexes = numIndexes;
   1780 	R_AllocStaticTriSurfIndexes( &tri, tri.numIndexes );
   1781 
   1782 	// don't memcpy, so we can change the index type from int to short without changing the interface
   1783 	for ( int i = 0; i < tri.numIndexes; i++ ) {
   1784 		tri.indexes[i] = indexes[i];
   1785 	}
   1786 
   1787 	R_RangeCheckIndexes( &tri );
   1788 	R_CreateSilIndexes( &tri );
   1789 	R_IdentifySilEdges( &tri, false );			// we cannot remove coplanar edges, because they can deform to silhouettes
   1790 	R_DuplicateMirroredVertexes( &tri );		// split mirror points into multiple points
   1791 	R_CreateDupVerts( &tri );
   1792 	if ( useUnsmoothedTangents ) {
   1793 		R_BuildDominantTris( &tri );
   1794 	}
   1795 	R_DeriveTangents( &tri );
   1796 
   1797 	deformInfo_t * deform = (deformInfo_t *)R_ClearedStaticAlloc( sizeof( *deform ) );
   1798 
   1799 	deform->numSourceVerts = numVerts;
   1800 	deform->numOutputVerts = tri.numVerts;
   1801 	deform->verts = tri.verts;
   1802 
   1803 	deform->numIndexes = numIndexes;
   1804 	deform->indexes = tri.indexes;
   1805 
   1806 	deform->silIndexes = tri.silIndexes;
   1807 
   1808 	deform->numSilEdges = tri.numSilEdges;
   1809 	deform->silEdges = tri.silEdges;
   1810 
   1811 	deform->numMirroredVerts = tri.numMirroredVerts;
   1812 	deform->mirroredVerts = tri.mirroredVerts;
   1813 
   1814 	deform->numDupVerts = tri.numDupVerts;
   1815 	deform->dupVerts = tri.dupVerts;
   1816 
   1817 	if ( tri.dominantTris != NULL ) {
   1818 		Mem_Free( tri.dominantTris );
   1819 		tri.dominantTris = NULL;
   1820 	}
   1821 
   1822 	idShadowVertSkinned * shadowVerts = (idShadowVertSkinned *) Mem_Alloc16( ALIGN( deform->numOutputVerts * 2 * sizeof( idShadowVertSkinned ), 16 ), TAG_MODEL );
   1823 	idShadowVertSkinned::CreateShadowCache( shadowVerts, deform->verts, deform->numOutputVerts );
   1824 
   1825 	deform->staticAmbientCache = vertexCache.AllocStaticVertex( deform->verts, ALIGN( deform->numOutputVerts * sizeof( idDrawVert ), VERTEX_CACHE_ALIGN ) );
   1826 	deform->staticIndexCache = vertexCache.AllocStaticIndex( deform->indexes, ALIGN( deform->numIndexes * sizeof( triIndex_t ), INDEX_CACHE_ALIGN ) );
   1827 	deform->staticShadowCache = vertexCache.AllocStaticVertex( shadowVerts, ALIGN( deform->numOutputVerts * 2 * sizeof( idShadowVertSkinned ), VERTEX_CACHE_ALIGN ) );
   1828 
   1829 	Mem_Free( shadowVerts );
   1830 
   1831 	return deform;
   1832 }
   1833 
   1834 /*
   1835 ===================
   1836 R_FreeDeformInfo
   1837 ===================
   1838 */
   1839 void R_FreeDeformInfo( deformInfo_t *deformInfo ) {
   1840 	if ( deformInfo->verts != NULL ) {
   1841 		Mem_Free( deformInfo->verts );
   1842 	}
   1843 	if ( deformInfo->indexes != NULL ) {
   1844 		Mem_Free( deformInfo->indexes );
   1845 	}
   1846 	if ( deformInfo->silIndexes != NULL ) {
   1847 		Mem_Free( deformInfo->silIndexes );
   1848 	}
   1849 	if ( deformInfo->silEdges != NULL ) {
   1850 		Mem_Free( deformInfo->silEdges );
   1851 	}
   1852 	if ( deformInfo->mirroredVerts != NULL ) {
   1853 		Mem_Free( deformInfo->mirroredVerts );
   1854 	}
   1855 	if ( deformInfo->dupVerts != NULL ) {
   1856 		Mem_Free( deformInfo->dupVerts );
   1857 	}
   1858 	R_StaticFree( deformInfo );
   1859 }
   1860 
   1861 /*
   1862 ===================
   1863 R_DeformInfoMemoryUsed
   1864 ===================
   1865 */
   1866 int R_DeformInfoMemoryUsed( deformInfo_t *deformInfo ) {
   1867 	int total = 0;
   1868 
   1869 	if ( deformInfo->verts != NULL ) {
   1870 		total += deformInfo->numOutputVerts * sizeof( deformInfo->verts[0] );
   1871 	}
   1872 	if ( deformInfo->indexes != NULL ) {
   1873 		total += deformInfo->numIndexes * sizeof( deformInfo->indexes[0] );
   1874 	}
   1875 	if ( deformInfo->mirroredVerts != NULL ) {
   1876 		total += deformInfo->numMirroredVerts * sizeof( deformInfo->mirroredVerts[0] );
   1877 	}
   1878 	if ( deformInfo->dupVerts != NULL ) {
   1879 		total += deformInfo->numDupVerts * sizeof( deformInfo->dupVerts[0] );
   1880 	}
   1881 	if ( deformInfo->silIndexes != NULL ) {
   1882 		total += deformInfo->numIndexes * sizeof( deformInfo->silIndexes[0] );
   1883 	}
   1884 	if ( deformInfo->silEdges != NULL ) {
   1885 		total += deformInfo->numSilEdges * sizeof( deformInfo->silEdges[0] );
   1886 	}
   1887 
   1888 	total += sizeof( *deformInfo );
   1889 	return total;
   1890 }
   1891 
   1892 /*
   1893 ===================================================================================
   1894 
   1895 VERTEX / INDEX CACHING
   1896 
   1897 ===================================================================================
   1898 */
   1899 
   1900 /*
   1901 ===================
   1902 R_InitDrawSurfFromTri
   1903 ===================
   1904 */
   1905 void R_InitDrawSurfFromTri( drawSurf_t & ds, srfTriangles_t & tri ) {
   1906 	if ( tri.numIndexes == 0 ) {
   1907 		ds.numIndexes = 0;
   1908 		return;
   1909 	}
   1910 
   1911 	// copy verts and indexes to this frame's hardware memory if they aren't already there
   1912 	//
   1913 	// deformed surfaces will not have any vertices but the ambient cache will have already
   1914 	// been created for them.
   1915 	if ( ( tri.verts == NULL ) && !tri.referencedIndexes ) {
   1916 		// pre-generated shadow models will not have any verts, just shadowVerts
   1917 		tri.ambientCache = 0;
   1918 	} else if ( !vertexCache.CacheIsCurrent( tri.ambientCache ) ) {
   1919 		tri.ambientCache = vertexCache.AllocVertex( tri.verts, ALIGN( tri.numVerts * sizeof( tri.verts[0] ), VERTEX_CACHE_ALIGN ) );
   1920 	}
   1921 	if ( !vertexCache.CacheIsCurrent( tri.indexCache ) ) {
   1922 		tri.indexCache = vertexCache.AllocIndex( tri.indexes, ALIGN( tri.numIndexes * sizeof( tri.indexes[0] ), INDEX_CACHE_ALIGN ) );
   1923 	}
   1924 
   1925 	ds.numIndexes = tri.numIndexes;
   1926 	ds.ambientCache = tri.ambientCache;
   1927 	ds.indexCache = tri.indexCache;
   1928 	ds.shadowCache = tri.shadowCache;
   1929 	ds.jointCache = 0;
   1930 }
   1931 
   1932 /*
   1933 ===================
   1934 R_CreateStaticBuffersForTri
   1935 
   1936 For static surfaces, the indexes, ambient, and shadow buffers can be pre-created at load
   1937 time, rather than being re-created each frame in the frame temporary buffers.
   1938 ===================
   1939 */
   1940 void R_CreateStaticBuffersForTri( srfTriangles_t & tri ) {
   1941 	tri.indexCache = 0;
   1942 	tri.ambientCache = 0;
   1943 	tri.shadowCache = 0;
   1944 
   1945 	// index cache
   1946 	if ( tri.indexes != NULL ) {
   1947 		tri.indexCache = vertexCache.AllocStaticIndex( tri.indexes, ALIGN( tri.numIndexes * sizeof( tri.indexes[0] ), INDEX_CACHE_ALIGN ) );
   1948 	}
   1949 
   1950 	// vertex cache
   1951 	if ( tri.verts != NULL ) {
   1952 		tri.ambientCache = vertexCache.AllocStaticVertex( tri.verts, ALIGN( tri.numVerts * sizeof( tri.verts[0] ), VERTEX_CACHE_ALIGN ) );
   1953 	}
   1954 
   1955 	// shadow cache
   1956 	if ( tri.preLightShadowVertexes != NULL ) {
   1957 		// this should only be true for the _prelight<NAME> pre-calculated shadow volumes
   1958 		assert( tri.verts == NULL );	// pre-light shadow volume surfaces don't have ambient vertices
   1959 		const int shadowSize = ALIGN( tri.numVerts * 2 * sizeof( idShadowVert ), VERTEX_CACHE_ALIGN );
   1960 		tri.shadowCache = vertexCache.AllocStaticVertex( tri.preLightShadowVertexes, shadowSize );
   1961 	} else if ( tri.verts != NULL ) {
   1962 		// the shadowVerts for normal models include all the xyz values duplicated
   1963 		// for a W of 1 (near cap) and a W of 0 (end cap, projected to infinity)
   1964 		const int shadowSize = ALIGN( tri.numVerts * 2 * sizeof( idShadowVert ), VERTEX_CACHE_ALIGN );
   1965 		if ( tri.staticShadowVertexes == NULL ) {
   1966 			tri.staticShadowVertexes = (idShadowVert *) Mem_Alloc16( shadowSize, TAG_TEMP );
   1967 			idShadowVert::CreateShadowCache( tri.staticShadowVertexes, tri.verts, tri.numVerts );
   1968 		}
   1969 		tri.shadowCache = vertexCache.AllocStaticVertex( tri.staticShadowVertexes, shadowSize );
   1970 
   1971 #if !defined( KEEP_INTERACTION_CPU_DATA )
   1972 		Mem_Free( tri.staticShadowVertexes );
   1973 		tri.staticShadowVertexes = NULL;
   1974 #endif
   1975 	}
   1976 }