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 }