2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 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.
14 Doom 3 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.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 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 Source Code. If not, please request a copy in writing from id Software at the address below.
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.
26 ===========================================================================
29 #include "../idlib/precompiled.h"
35 ==============================================================================
37 TRIANGLE MESH PROCESSING
39 The functions in this file have no vertex / index count limits.
41 Truly identical vertexes that match in position, normal, and texcoord can
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
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)
54 Vertexes that only match in position are merged for shadow edge finding.
58 Overlapped triangles, even if normals or texcoords differ, must be removed.
59 for the silhoette based stencil shadow algorithm to function properly.
61 Is the overlapped triangle problem just an example of the trippled edge problem?
63 Interpenetrating triangles are not currently clipped to surfaces.
64 Do they effect the shadows?
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.
70 We might be able to identify this from topology.
72 Dangling edges are acceptable, but three way edges are not.
74 Are any combinations of two way edges unacceptable, like one facing
75 the backside of the other?
78 Topology is determined by a collection of triangle indexes.
80 The edge list can be built up from this, and stays valid even under
83 Somewhat non-intuitively, concave edges cannot be optimized away, or the
84 stencil shadow algorithm miscounts.
86 Face normals are needed for generating shadow volumes and for calculating
87 the silhouette, but they will change with any deformation.
89 Vertex normals and vertex tangents will change with each deformation,
90 but they may be able to be transformed instead of recalculated.
92 bounding volume, both box and sphere will change with deformation.
98 shade indexes will only be > silhouette indexes if there is facet shading present
100 lookups from texture to sil and texture to shade?
102 The normal and tangent vector smoothing is simple averaging, no attempt is
103 made to better handle the cases where the distribution around the shared vertex
107 we may get degenerate triangles even with the uniquing and removal
108 if the vertexes have different texcoords.
110 ==============================================================================
113 // this shouldn't change anything, but previously renderbumped models seem to need it
116 // instead of using the texture T vector, cross the normal and S vector for an orthogonal axis
117 #define DERIVE_UNSMOOTHED_BITANGENT
119 const int MAX_SIL_EDGES = 0x10000;
120 const int SILEDGE_HASH_SIZE = 1024;
122 static int numSilEdges;
123 static silEdge_t * silEdges;
124 static idHashIndex silEdgeHash( SILEDGE_HASH_SIZE, MAX_SIL_EDGES );
125 static int numPlanes;
127 static idBlockAlloc<srfTriangles_t, 1<<8> srfTrianglesAllocator;
129 #ifdef USE_TRI_DATA_ALLOCATOR
130 static idDynamicBlockAlloc<idDrawVert, 1<<20, 1<<10> triVertexAllocator;
131 static idDynamicBlockAlloc<glIndex_t, 1<<18, 1<<10> triIndexAllocator;
132 static idDynamicBlockAlloc<shadowCache_t, 1<<18, 1<<10> triShadowVertexAllocator;
133 static idDynamicBlockAlloc<idPlane, 1<<17, 1<<10> triPlaneAllocator;
134 static idDynamicBlockAlloc<glIndex_t, 1<<17, 1<<10> triSilIndexAllocator;
135 static idDynamicBlockAlloc<silEdge_t, 1<<17, 1<<10> triSilEdgeAllocator;
136 static idDynamicBlockAlloc<dominantTri_t, 1<<16, 1<<10> triDominantTrisAllocator;
137 static idDynamicBlockAlloc<int, 1<<16, 1<<10> triMirroredVertAllocator;
138 static idDynamicBlockAlloc<int, 1<<16, 1<<10> triDupVertAllocator;
140 static idDynamicAlloc<idDrawVert, 1<<20, 1<<10> triVertexAllocator;
141 static idDynamicAlloc<glIndex_t, 1<<18, 1<<10> triIndexAllocator;
142 static idDynamicAlloc<shadowCache_t, 1<<18, 1<<10> triShadowVertexAllocator;
143 static idDynamicAlloc<idPlane, 1<<17, 1<<10> triPlaneAllocator;
144 static idDynamicAlloc<glIndex_t, 1<<17, 1<<10> triSilIndexAllocator;
145 static idDynamicAlloc<silEdge_t, 1<<17, 1<<10> triSilEdgeAllocator;
146 static idDynamicAlloc<dominantTri_t, 1<<16, 1<<10> triDominantTrisAllocator;
147 static idDynamicAlloc<int, 1<<16, 1<<10> triMirroredVertAllocator;
148 static idDynamicAlloc<int, 1<<16, 1<<10> triDupVertAllocator;
157 void R_InitTriSurfData( void ) {
158 silEdges = (silEdge_t *)R_StaticAlloc( MAX_SIL_EDGES * sizeof( silEdges[0] ) );
160 // initialize allocators for triangle surfaces
161 triVertexAllocator.Init();
162 triIndexAllocator.Init();
163 triShadowVertexAllocator.Init();
164 triPlaneAllocator.Init();
165 triSilIndexAllocator.Init();
166 triSilEdgeAllocator.Init();
167 triDominantTrisAllocator.Init();
168 triMirroredVertAllocator.Init();
169 triDupVertAllocator.Init();
171 // never swap out triangle surfaces
172 triVertexAllocator.SetLockMemory( true );
173 triIndexAllocator.SetLockMemory( true );
174 triShadowVertexAllocator.SetLockMemory( true );
175 triPlaneAllocator.SetLockMemory( true );
176 triSilIndexAllocator.SetLockMemory( true );
177 triSilEdgeAllocator.SetLockMemory( true );
178 triDominantTrisAllocator.SetLockMemory( true );
179 triMirroredVertAllocator.SetLockMemory( true );
180 triDupVertAllocator.SetLockMemory( true );
185 R_ShutdownTriSurfData
188 void R_ShutdownTriSurfData( void ) {
189 R_StaticFree( silEdges );
191 srfTrianglesAllocator.Shutdown();
192 triVertexAllocator.Shutdown();
193 triIndexAllocator.Shutdown();
194 triShadowVertexAllocator.Shutdown();
195 triPlaneAllocator.Shutdown();
196 triSilIndexAllocator.Shutdown();
197 triSilEdgeAllocator.Shutdown();
198 triDominantTrisAllocator.Shutdown();
199 triMirroredVertAllocator.Shutdown();
200 triDupVertAllocator.Shutdown();
208 void R_PurgeTriSurfData( frameData_t *frame ) {
209 // free deferred triangle surfaces
210 R_FreeDeferredTriSurfs( frame );
212 // free empty base blocks
213 triVertexAllocator.FreeEmptyBaseBlocks();
214 triIndexAllocator.FreeEmptyBaseBlocks();
215 triShadowVertexAllocator.FreeEmptyBaseBlocks();
216 triPlaneAllocator.FreeEmptyBaseBlocks();
217 triSilIndexAllocator.FreeEmptyBaseBlocks();
218 triSilEdgeAllocator.FreeEmptyBaseBlocks();
219 triDominantTrisAllocator.FreeEmptyBaseBlocks();
220 triMirroredVertAllocator.FreeEmptyBaseBlocks();
221 triDupVertAllocator.FreeEmptyBaseBlocks();
229 void R_ShowTriSurfMemory_f( const idCmdArgs &args ) {
230 common->Printf( "%6d kB in %d triangle surfaces\n",
231 ( srfTrianglesAllocator.GetAllocCount() * sizeof( srfTriangles_t ) ) >> 10,
232 srfTrianglesAllocator.GetAllocCount() );
234 common->Printf( "%6d kB vertex memory (%d kB free in %d blocks, %d empty base blocks)\n",
235 triVertexAllocator.GetBaseBlockMemory() >> 10, triVertexAllocator.GetFreeBlockMemory() >> 10,
236 triVertexAllocator.GetNumFreeBlocks(), triVertexAllocator.GetNumEmptyBaseBlocks() );
238 common->Printf( "%6d kB index memory (%d kB free in %d blocks, %d empty base blocks)\n",
239 triIndexAllocator.GetBaseBlockMemory() >> 10, triIndexAllocator.GetFreeBlockMemory() >> 10,
240 triIndexAllocator.GetNumFreeBlocks(), triIndexAllocator.GetNumEmptyBaseBlocks() );
242 common->Printf( "%6d kB shadow vert memory (%d kB free in %d blocks, %d empty base blocks)\n",
243 triShadowVertexAllocator.GetBaseBlockMemory() >> 10, triShadowVertexAllocator.GetFreeBlockMemory() >> 10,
244 triShadowVertexAllocator.GetNumFreeBlocks(), triShadowVertexAllocator.GetNumEmptyBaseBlocks() );
246 common->Printf( "%6d kB tri plane memory (%d kB free in %d blocks, %d empty base blocks)\n",
247 triPlaneAllocator.GetBaseBlockMemory() >> 10, triPlaneAllocator.GetFreeBlockMemory() >> 10,
248 triPlaneAllocator.GetNumFreeBlocks(), triPlaneAllocator.GetNumEmptyBaseBlocks() );
250 common->Printf( "%6d kB sil index memory (%d kB free in %d blocks, %d empty base blocks)\n",
251 triSilIndexAllocator.GetBaseBlockMemory() >> 10, triSilIndexAllocator.GetFreeBlockMemory() >> 10,
252 triSilIndexAllocator.GetNumFreeBlocks(), triSilIndexAllocator.GetNumEmptyBaseBlocks() );
254 common->Printf( "%6d kB sil edge memory (%d kB free in %d blocks, %d empty base blocks)\n",
255 triSilEdgeAllocator.GetBaseBlockMemory() >> 10, triSilEdgeAllocator.GetFreeBlockMemory() >> 10,
256 triSilEdgeAllocator.GetNumFreeBlocks(), triSilEdgeAllocator.GetNumEmptyBaseBlocks() );
258 common->Printf( "%6d kB dominant tri memory (%d kB free in %d blocks, %d empty base blocks)\n",
259 triDominantTrisAllocator.GetBaseBlockMemory() >> 10, triDominantTrisAllocator.GetFreeBlockMemory() >> 10,
260 triDominantTrisAllocator.GetNumFreeBlocks(), triDominantTrisAllocator.GetNumEmptyBaseBlocks() );
262 common->Printf( "%6d kB mirror vert memory (%d kB free in %d blocks, %d empty base blocks)\n",
263 triMirroredVertAllocator.GetBaseBlockMemory() >> 10, triMirroredVertAllocator.GetFreeBlockMemory() >> 10,
264 triMirroredVertAllocator.GetNumFreeBlocks(), triMirroredVertAllocator.GetNumEmptyBaseBlocks() );
266 common->Printf( "%6d kB dup vert memory (%d kB free in %d blocks, %d empty base blocks)\n",
267 triDupVertAllocator.GetBaseBlockMemory() >> 10, triDupVertAllocator.GetFreeBlockMemory() >> 10,
268 triDupVertAllocator.GetNumFreeBlocks(), triDupVertAllocator.GetNumEmptyBaseBlocks() );
270 common->Printf( "%6d kB total triangle memory\n",
271 ( srfTrianglesAllocator.GetAllocCount() * sizeof( srfTriangles_t ) +
272 triVertexAllocator.GetBaseBlockMemory() +
273 triIndexAllocator.GetBaseBlockMemory() +
274 triShadowVertexAllocator.GetBaseBlockMemory() +
275 triPlaneAllocator.GetBaseBlockMemory() +
276 triSilIndexAllocator.GetBaseBlockMemory() +
277 triSilEdgeAllocator.GetBaseBlockMemory() +
278 triDominantTrisAllocator.GetBaseBlockMemory() +
279 triMirroredVertAllocator.GetBaseBlockMemory() +
280 triDupVertAllocator.GetBaseBlockMemory() ) >> 10 );
290 int R_TriSurfMemory( const srfTriangles_t *tri ) {
297 // used as a flag in interations
298 if ( tri == LIGHT_TRIS_DEFERRED ) {
302 if ( tri->shadowVertexes != NULL ) {
303 total += tri->numVerts * sizeof( tri->shadowVertexes[0] );
304 } else if ( tri->verts != NULL ) {
305 if ( tri->ambientSurface == NULL || tri->verts != tri->ambientSurface->verts ) {
306 total += tri->numVerts * sizeof( tri->verts[0] );
309 if ( tri->facePlanes != NULL ) {
310 total += tri->numIndexes / 3 * sizeof( tri->facePlanes[0] );
312 if ( tri->indexes != NULL ) {
313 if ( tri->ambientSurface == NULL || tri->indexes != tri->ambientSurface->indexes ) {
314 total += tri->numIndexes * sizeof( tri->indexes[0] );
317 if ( tri->silIndexes != NULL ) {
318 total += tri->numIndexes * sizeof( tri->silIndexes[0] );
320 if ( tri->silEdges != NULL ) {
321 total += tri->numSilEdges * sizeof( tri->silEdges[0] );
323 if ( tri->dominantTris != NULL ) {
324 total += tri->numVerts * sizeof( tri->dominantTris[0] );
326 if ( tri->mirroredVerts != NULL ) {
327 total += tri->numMirroredVerts * sizeof( tri->mirroredVerts[0] );
329 if ( tri->dupVerts != NULL ) {
330 total += tri->numDupVerts * sizeof( tri->dupVerts[0] );
333 total += sizeof( *tri );
340 R_FreeStaticTriSurfVertexCaches
343 void R_FreeStaticTriSurfVertexCaches( srfTriangles_t *tri ) {
344 if ( tri->ambientSurface == NULL ) {
345 // this is a real model surface
346 vertexCache.Free( tri->ambientCache );
347 tri->ambientCache = NULL;
349 // this is a light interaction surface that references
350 // a different ambient model surface
351 vertexCache.Free( tri->lightingCache );
352 tri->lightingCache = NULL;
354 if ( tri->indexCache ) {
355 vertexCache.Free( tri->indexCache );
356 tri->indexCache = NULL;
358 if ( tri->shadowCache && ( tri->shadowVertexes != NULL || tri->verts != NULL ) ) {
359 // if we don't have tri->shadowVertexes, these are a reference to a
360 // shadowCache on the original surface, which a vertex program
361 // will take care of making unique for each light
362 vertexCache.Free( tri->shadowCache );
363 tri->shadowCache = NULL;
369 R_ReallyFreeStaticTriSurf
371 This does the actual free
374 void R_ReallyFreeStaticTriSurf( srfTriangles_t *tri ) {
379 R_FreeStaticTriSurfVertexCaches( tri );
381 if ( tri->verts != NULL ) {
382 // R_CreateLightTris points tri->verts at the verts of the ambient surface
383 if ( tri->ambientSurface == NULL || tri->verts != tri->ambientSurface->verts ) {
384 triVertexAllocator.Free( tri->verts );
388 if ( !tri->deformedSurface ) {
389 if ( tri->indexes != NULL ) {
390 // if a surface is completely inside a light volume R_CreateLightTris points tri->indexes at the indexes of the ambient surface
391 if ( tri->ambientSurface == NULL || tri->indexes != tri->ambientSurface->indexes ) {
392 triIndexAllocator.Free( tri->indexes );
395 if ( tri->silIndexes != NULL ) {
396 triSilIndexAllocator.Free( tri->silIndexes );
398 if ( tri->silEdges != NULL ) {
399 triSilEdgeAllocator.Free( tri->silEdges );
401 if ( tri->dominantTris != NULL ) {
402 triDominantTrisAllocator.Free( tri->dominantTris );
404 if ( tri->mirroredVerts != NULL ) {
405 triMirroredVertAllocator.Free( tri->mirroredVerts );
407 if ( tri->dupVerts != NULL ) {
408 triDupVertAllocator.Free( tri->dupVerts );
412 if ( tri->facePlanes != NULL ) {
413 triPlaneAllocator.Free( tri->facePlanes );
416 if ( tri->shadowVertexes != NULL ) {
417 triShadowVertexAllocator.Free( tri->shadowVertexes );
421 memset( tri, 0, sizeof( srfTriangles_t ) );
424 srfTrianglesAllocator.Free( tri );
429 R_CheckStaticTriSurfMemory
432 void R_CheckStaticTriSurfMemory( const srfTriangles_t *tri ) {
437 if ( tri->verts != NULL ) {
438 // R_CreateLightTris points tri->verts at the verts of the ambient surface
439 if ( tri->ambientSurface == NULL || tri->verts != tri->ambientSurface->verts ) {
440 const char *error = triVertexAllocator.CheckMemory( tri->verts );
441 assert( error == NULL );
445 if ( !tri->deformedSurface ) {
446 if ( tri->indexes != NULL ) {
447 // if a surface is completely inside a light volume R_CreateLightTris points tri->indexes at the indexes of the ambient surface
448 if ( tri->ambientSurface == NULL || tri->indexes != tri->ambientSurface->indexes ) {
449 const char *error = triIndexAllocator.CheckMemory( tri->indexes );
450 assert( error == NULL );
455 if ( tri->shadowVertexes != NULL ) {
456 const char *error = triShadowVertexAllocator.CheckMemory( tri->shadowVertexes );
457 assert( error == NULL );
463 R_FreeDeferredTriSurfs
466 void R_FreeDeferredTriSurfs( frameData_t *frame ) {
467 srfTriangles_t *tri, *next;
473 for ( tri = frame->firstDeferredFreeTriSurf; tri; tri = next ) {
474 next = tri->nextDeferredFree;
475 R_ReallyFreeStaticTriSurf( tri );
478 frame->firstDeferredFreeTriSurf = NULL;
479 frame->lastDeferredFreeTriSurf = NULL;
486 This will defer the free until the current frame has run through the back end.
489 void R_FreeStaticTriSurf( srfTriangles_t *tri ) {
496 if ( tri->nextDeferredFree ) {
497 common->Error( "R_FreeStaticTriSurf: freed a freed triangle" );
502 // command line utility, or rendering in editor preview mode ( force )
503 R_ReallyFreeStaticTriSurf( tri );
505 #ifdef ID_DEBUG_MEMORY
506 R_CheckStaticTriSurfMemory( tri );
508 tri->nextDeferredFree = NULL;
509 if ( frame->lastDeferredFreeTriSurf ) {
510 frame->lastDeferredFreeTriSurf->nextDeferredFree = tri;
512 frame->firstDeferredFreeTriSurf = tri;
514 frame->lastDeferredFreeTriSurf = tri;
523 srfTriangles_t *R_AllocStaticTriSurf( void ) {
524 srfTriangles_t *tris = srfTrianglesAllocator.Alloc();
525 memset( tris, 0, sizeof( srfTriangles_t ) );
533 This only duplicates the indexes and verts, not any of the derived data.
536 srfTriangles_t *R_CopyStaticTriSurf( const srfTriangles_t *tri ) {
537 srfTriangles_t *newTri;
539 newTri = R_AllocStaticTriSurf();
540 R_AllocStaticTriSurfVerts( newTri, tri->numVerts );
541 R_AllocStaticTriSurfIndexes( newTri, tri->numIndexes );
542 newTri->numVerts = tri->numVerts;
543 newTri->numIndexes = tri->numIndexes;
544 memcpy( newTri->verts, tri->verts, tri->numVerts * sizeof( newTri->verts[0] ) );
545 memcpy( newTri->indexes, tri->indexes, tri->numIndexes * sizeof( newTri->indexes[0] ) );
552 R_AllocStaticTriSurfVerts
555 void R_AllocStaticTriSurfVerts( srfTriangles_t *tri, int numVerts ) {
556 assert( tri->verts == NULL );
557 tri->verts = triVertexAllocator.Alloc( numVerts );
562 R_AllocStaticTriSurfIndexes
565 void R_AllocStaticTriSurfIndexes( srfTriangles_t *tri, int numIndexes ) {
566 assert( tri->indexes == NULL );
567 tri->indexes = triIndexAllocator.Alloc( numIndexes );
572 R_AllocStaticTriSurfShadowVerts
575 void R_AllocStaticTriSurfShadowVerts( srfTriangles_t *tri, int numVerts ) {
576 assert( tri->shadowVertexes == NULL );
577 tri->shadowVertexes = triShadowVertexAllocator.Alloc( numVerts );
582 R_AllocStaticTriSurfPlanes
585 void R_AllocStaticTriSurfPlanes( srfTriangles_t *tri, int numIndexes ) {
586 if ( tri->facePlanes ) {
587 triPlaneAllocator.Free( tri->facePlanes );
589 tri->facePlanes = triPlaneAllocator.Alloc( numIndexes / 3 );
594 R_ResizeStaticTriSurfVerts
597 void R_ResizeStaticTriSurfVerts( srfTriangles_t *tri, int numVerts ) {
598 #ifdef USE_TRI_DATA_ALLOCATOR
599 tri->verts = triVertexAllocator.Resize( tri->verts, numVerts );
607 R_ResizeStaticTriSurfIndexes
610 void R_ResizeStaticTriSurfIndexes( srfTriangles_t *tri, int numIndexes ) {
611 #ifdef USE_TRI_DATA_ALLOCATOR
612 tri->indexes = triIndexAllocator.Resize( tri->indexes, numIndexes );
620 R_ResizeStaticTriSurfShadowVerts
623 void R_ResizeStaticTriSurfShadowVerts( srfTriangles_t *tri, int numVerts ) {
624 #ifdef USE_TRI_DATA_ALLOCATOR
625 tri->shadowVertexes = triShadowVertexAllocator.Resize( tri->shadowVertexes, numVerts );
633 R_ReferenceStaticTriSurfVerts
636 void R_ReferenceStaticTriSurfVerts( srfTriangles_t *tri, const srfTriangles_t *reference ) {
637 tri->verts = reference->verts;
642 R_ReferenceStaticTriSurfIndexes
645 void R_ReferenceStaticTriSurfIndexes( srfTriangles_t *tri, const srfTriangles_t *reference ) {
646 tri->indexes = reference->indexes;
651 R_FreeStaticTriSurfSilIndexes
654 void R_FreeStaticTriSurfSilIndexes( srfTriangles_t *tri ) {
655 triSilIndexAllocator.Free( tri->silIndexes );
656 tri->silIndexes = NULL;
663 Check for syntactically incorrect indexes, like out of range values.
664 Does not check for semantics, like degenerate triangles.
666 No vertexes is acceptable if no indexes.
667 No indexes is acceptable.
668 More vertexes than are referenced by indexes are acceptable.
671 void R_RangeCheckIndexes( const srfTriangles_t *tri ) {
674 if ( tri->numIndexes < 0 ) {
675 common->Error( "R_RangeCheckIndexes: numIndexes < 0" );
677 if ( tri->numVerts < 0 ) {
678 common->Error( "R_RangeCheckIndexes: numVerts < 0" );
681 // must specify an integral number of triangles
682 if ( tri->numIndexes % 3 != 0 ) {
683 common->Error( "R_RangeCheckIndexes: numIndexes %% 3" );
686 for ( i = 0 ; i < tri->numIndexes ; i++ ) {
687 if ( tri->indexes[i] < 0 || tri->indexes[i] >= tri->numVerts ) {
688 common->Error( "R_RangeCheckIndexes: index out of range" );
692 // this should not be possible unless there are unused verts
693 if ( tri->numVerts > tri->numIndexes ) {
694 // FIXME: find the causes of these
695 // common->Printf( "R_RangeCheckIndexes: tri->numVerts > tri->numIndexes\n" );
704 void R_BoundTriSurf( srfTriangles_t *tri ) {
705 SIMDProcessor->MinMax( tri->bounds[0], tri->bounds[1], tri->verts, tri->numVerts );
713 static int *R_CreateSilRemap( const srfTriangles_t *tri ) {
714 int c_removed, c_unique;
717 const idDrawVert *v1, *v2;
719 remap = (int *)R_ClearedStaticAlloc( tri->numVerts * sizeof( remap[0] ) );
721 if ( !r_useSilRemap.GetBool() ) {
722 for ( i = 0 ; i < tri->numVerts ; i++ ) {
728 idHashIndex hash( 1024, tri->numVerts );
732 for ( i = 0 ; i < tri->numVerts ; i++ ) {
735 // see if there is an earlier vert that it can map to
736 hashKey = hash.GenerateKey( v1->xyz );
737 for ( j = hash.First( hashKey ); j >= 0; j = hash.Next( j ) ) {
739 if ( v2->xyz[0] == v1->xyz[0]
740 && v2->xyz[1] == v1->xyz[1]
741 && v2->xyz[2] == v1->xyz[2] ) {
750 hash.Add( hashKey, i );
761 Uniquing vertexes only on xyz before creating sil edges reduces
762 the edge count by about 20% on Q3 models
765 void R_CreateSilIndexes( srfTriangles_t *tri ) {
769 if ( tri->silIndexes ) {
770 triSilIndexAllocator.Free( tri->silIndexes );
771 tri->silIndexes = NULL;
774 remap = R_CreateSilRemap( tri );
776 // remap indexes to the first one
777 tri->silIndexes = triSilIndexAllocator.Alloc( tri->numIndexes );
778 for ( i = 0; i < tri->numIndexes; i++ ) {
779 tri->silIndexes[i] = remap[tri->indexes[i]];
782 R_StaticFree( remap );
786 =====================
788 =====================
790 void R_CreateDupVerts( srfTriangles_t *tri ) {
793 int *remap = (int *) _alloca16( tri->numVerts * sizeof( remap[0] ) );
795 // initialize vertex remap in case there are unused verts
796 for ( i = 0; i < tri->numVerts; i++ ) {
800 // set the remap based on how the silhouette indexes are remapped
801 for ( i = 0; i < tri->numIndexes; i++ ) {
802 remap[tri->indexes[i]] = tri->silIndexes[i];
805 // create duplicate vertex index based on the vertex remap
806 int * tempDupVerts = (int *) _alloca16( tri->numVerts * 2 * sizeof( tempDupVerts[0] ) );
807 tri->numDupVerts = 0;
808 for ( i = 0; i < tri->numVerts; i++ ) {
809 if ( remap[i] != i ) {
810 tempDupVerts[tri->numDupVerts*2+0] = i;
811 tempDupVerts[tri->numDupVerts*2+1] = remap[i];
816 tri->dupVerts = triDupVertAllocator.Alloc( tri->numDupVerts * 2 );
817 memcpy( tri->dupVerts, tempDupVerts, tri->numDupVerts * 2 * sizeof( tri->dupVerts[0] ) );
821 =====================
824 Writes the facePlanes values, overwriting existing ones if present
825 =====================
827 void R_DeriveFacePlanes( srfTriangles_t *tri ) {
830 if ( !tri->facePlanes ) {
831 R_AllocStaticTriSurfPlanes( tri, tri->numIndexes );
833 planes = tri->facePlanes;
837 SIMDProcessor->DeriveTriPlanes( planes, tri->verts, tri->numVerts, tri->indexes, tri->numIndexes );
841 for ( int i = 0; i < tri->numIndexes; i+= 3, planes++ ) {
843 idVec3 d1, d2, normal;
844 idVec3 *v1, *v2, *v3;
846 i1 = tri->indexes[i + 0];
847 i2 = tri->indexes[i + 1];
848 i3 = tri->indexes[i + 2];
850 v1 = &tri->verts[i1].xyz;
851 v2 = &tri->verts[i2].xyz;
852 v3 = &tri->verts[i3].xyz;
854 d1[0] = v2->x - v1->x;
855 d1[1] = v2->y - v1->y;
856 d1[2] = v2->z - v1->z;
858 d2[0] = v3->x - v1->x;
859 d2[1] = v3->y - v1->y;
860 d2[2] = v3->z - v1->z;
862 normal[0] = d2.y * d1.z - d2.z * d1.y;
863 normal[1] = d2.z * d1.x - d2.x * d1.z;
864 normal[2] = d2.x * d1.y - d2.y * d1.x;
866 float sqrLength, invLength;
868 sqrLength = normal.x * normal.x + normal.y * normal.y + normal.z * normal.z;
869 invLength = idMath::RSqrt( sqrLength );
871 (*planes)[0] = normal[0] * invLength;
872 (*planes)[1] = normal[1] * invLength;
873 (*planes)[2] = normal[2] * invLength;
875 planes->FitThroughPoint( *v1 );
880 tri->facePlanesCalculated = true;
884 =====================
885 R_CreateVertexNormals
887 Averages together the contributions of all faces that are
888 used by a vertex, creating drawVert->normal
889 =====================
891 void R_CreateVertexNormals( srfTriangles_t *tri ) {
893 const idPlane *planes;
895 for ( i = 0 ; i < tri->numVerts ; i++ ) {
896 tri->verts[i].normal.Zero();
899 if ( !tri->facePlanes || !tri->facePlanesCalculated ) {
900 R_DeriveFacePlanes( tri );
902 if ( !tri->silIndexes ) {
903 R_CreateSilIndexes( tri );
905 planes = tri->facePlanes;
906 for ( i = 0 ; i < tri->numIndexes ; i += 3, planes++ ) {
907 for ( j = 0 ; j < 3 ; j++ ) {
908 int index = tri->silIndexes[i+j];
909 tri->verts[index].normal += planes->Normal();
913 // normalize and replicate from silIndexes to all indexes
914 for ( i = 0 ; i < tri->numIndexes ; i++ ) {
915 tri->verts[tri->indexes[i]].normal = tri->verts[tri->silIndexes[i]].normal;
916 tri->verts[tri->indexes[i]].normal.Normalize();
925 static int c_duplicatedEdges, c_tripledEdges;
927 static void R_DefineEdge( int v1, int v2, int planeNum ) {
930 // check for degenerate edge
934 hashKey = silEdgeHash.GenerateKey( v1, v2 );
935 // search for a matching other side
936 for ( i = silEdgeHash.First( hashKey ); i >= 0 && i < MAX_SIL_EDGES; i = silEdgeHash.Next( i ) ) {
937 if ( silEdges[i].v1 == v1 && silEdges[i].v2 == v2 ) {
939 // allow it to still create a new edge
942 if ( silEdges[i].v2 == v1 && silEdges[i].v1 == v2 ) {
943 if ( silEdges[i].p2 != numPlanes ) {
945 // allow it to still create a new edge
948 // this is a matching back side
949 silEdges[i].p2 = planeNum;
955 // define the new edge
956 if ( numSilEdges == MAX_SIL_EDGES ) {
957 common->DWarning( "MAX_SIL_EDGES" );
961 silEdgeHash.Add( hashKey, numSilEdges );
963 silEdges[numSilEdges].p1 = planeNum;
964 silEdges[numSilEdges].p2 = numPlanes;
965 silEdges[numSilEdges].v1 = v1;
966 silEdges[numSilEdges].v2 = v2;
976 static int SilEdgeSort( const void *a, const void *b ) {
977 if ( ((silEdge_t *)a)->p1 < ((silEdge_t *)b)->p1 ) {
980 if ( ((silEdge_t *)a)->p1 > ((silEdge_t *)b)->p1 ) {
983 if ( ((silEdge_t *)a)->p2 < ((silEdge_t *)b)->p2 ) {
986 if ( ((silEdge_t *)a)->p2 > ((silEdge_t *)b)->p2 ) {
996 If the surface will not deform, coplanar edges (polygon interiors)
997 can never create silhouette plains, and can be omited
1000 int c_coplanarSilEdges;
1001 int c_totalSilEdges;
1003 void R_IdentifySilEdges( srfTriangles_t *tri, bool omitCoplanarEdges ) {
1008 omitCoplanarEdges = false; // optimization doesn't work for some reason
1010 numTris = tri->numIndexes / 3;
1013 silEdgeHash.Clear();
1014 numPlanes = numTris;
1016 c_duplicatedEdges = 0;
1019 for ( i = 0 ; i < numTris ; i++ ) {
1022 i1 = tri->silIndexes[ i*3 + 0 ];
1023 i2 = tri->silIndexes[ i*3 + 1 ];
1024 i3 = tri->silIndexes[ i*3 + 2 ];
1027 R_DefineEdge( i1, i2, i );
1028 R_DefineEdge( i2, i3, i );
1029 R_DefineEdge( i3, i1, i );
1032 if ( c_duplicatedEdges || c_tripledEdges ) {
1033 common->DWarning( "%i duplicated edge directions, %i tripled edges", c_duplicatedEdges, c_tripledEdges );
1036 // if we know that the vertexes aren't going
1037 // to deform, we can remove interior triangulation edges
1038 // on otherwise planar polygons.
1039 // I earlier believed that I could also remove concave
1040 // edges, because they are never silhouettes in the conventional sense,
1041 // but they are still needed to balance out all the true sil edges
1042 // for the shadow algorithm to function
1043 int c_coplanarCulled;
1045 c_coplanarCulled = 0;
1046 if ( omitCoplanarEdges ) {
1047 for ( i = 0 ; i < numSilEdges ; i++ ) {
1054 if ( silEdges[i].p2 == numPlanes ) { // the fake dangling edge
1058 base = silEdges[i].p1 * 3;
1059 i1 = tri->silIndexes[ base + 0 ];
1060 i2 = tri->silIndexes[ base + 1 ];
1061 i3 = tri->silIndexes[ base + 2 ];
1063 plane.FromPoints( tri->verts[i1].xyz, tri->verts[i2].xyz, tri->verts[i3].xyz );
1065 // check to see if points of second triangle are not coplanar
1066 base = silEdges[i].p2 * 3;
1067 for ( j = 0 ; j < 3 ; j++ ) {
1068 i1 = tri->silIndexes[ base + j ];
1069 d = plane.Distance( tri->verts[i1].xyz );
1070 if ( d != 0 ) { // even a small epsilon causes problems
1076 // we can cull this sil edge
1077 memmove( &silEdges[i], &silEdges[i+1], (numSilEdges-i-1) * sizeof( silEdges[i] ) );
1083 if ( c_coplanarCulled ) {
1084 c_coplanarSilEdges += c_coplanarCulled;
1085 // common->Printf( "%i of %i sil edges coplanar culled\n", c_coplanarCulled,
1086 // c_coplanarCulled + numSilEdges );
1089 c_totalSilEdges += numSilEdges;
1091 // sort the sil edges based on plane number
1092 qsort( silEdges, numSilEdges, sizeof( silEdges[0] ), SilEdgeSort );
1094 // count up the distribution.
1095 // a perfectly built model should only have shared
1096 // edges, but most models will have some interpenetration
1097 // and dangling edges
1100 for ( i = 0 ; i < numSilEdges ; i++ ) {
1101 if ( silEdges[i].p2 == numPlanes ) {
1109 tri->perfectHull = true;
1111 tri->perfectHull = false;
1114 tri->numSilEdges = numSilEdges;
1115 tri->silEdges = triSilEdgeAllocator.Alloc( numSilEdges );
1116 memcpy( tri->silEdges, silEdges, numSilEdges * sizeof( tri->silEdges[0] ) );
1121 R_FaceNegativePolarity
1123 Returns true if the texture polarity of the face is negative, false if it is positive or zero
1126 static bool R_FaceNegativePolarity( const srfTriangles_t *tri, int firstIndex ) {
1127 idDrawVert *a, *b, *c;
1131 a = tri->verts + tri->indexes[firstIndex + 0];
1132 b = tri->verts + tri->indexes[firstIndex + 1];
1133 c = tri->verts + tri->indexes[firstIndex + 2];
1135 d0[3] = b->st[0] - a->st[0];
1136 d0[4] = b->st[1] - a->st[1];
1138 d1[3] = c->st[0] - a->st[0];
1139 d1[4] = c->st[1] - a->st[1];
1141 area = d0[3] * d1[4] - d0[4] * d1[3];
1150 R_DeriveFaceTangents
1155 bool negativePolarity;
1159 static void R_DeriveFaceTangents( const srfTriangles_t *tri, faceTangents_t *faceTangents ) {
1161 int c_textureDegenerateFaces;
1162 int c_positive, c_negative;
1164 idDrawVert *a, *b, *c;
1167 // calculate tangent vectors for each face in isolation
1171 c_textureDegenerateFaces = 0;
1172 for ( i = 0 ; i < tri->numIndexes ; i+=3 ) {
1177 ft = &faceTangents[i/3];
1179 a = tri->verts + tri->indexes[i + 0];
1180 b = tri->verts + tri->indexes[i + 1];
1181 c = tri->verts + tri->indexes[i + 2];
1183 d0[0] = b->xyz[0] - a->xyz[0];
1184 d0[1] = b->xyz[1] - a->xyz[1];
1185 d0[2] = b->xyz[2] - a->xyz[2];
1186 d0[3] = b->st[0] - a->st[0];
1187 d0[4] = b->st[1] - a->st[1];
1189 d1[0] = c->xyz[0] - a->xyz[0];
1190 d1[1] = c->xyz[1] - a->xyz[1];
1191 d1[2] = c->xyz[2] - a->xyz[2];
1192 d1[3] = c->st[0] - a->st[0];
1193 d1[4] = c->st[1] - a->st[1];
1195 area = d0[3] * d1[4] - d0[4] * d1[3];
1196 if ( fabs( area ) < 1e-20f ) {
1197 ft->negativePolarity = false;
1198 ft->degenerate = true;
1199 ft->tangents[0].Zero();
1200 ft->tangents[1].Zero();
1201 c_textureDegenerateFaces++;
1204 if ( area > 0.0f ) {
1205 ft->negativePolarity = false;
1208 ft->negativePolarity = true;
1211 ft->degenerate = false;
1214 float inva = area < 0.0f ? -1 : 1; // was = 1.0f / area;
1216 temp[0] = (d0[0] * d1[4] - d0[4] * d1[0]) * inva;
1217 temp[1] = (d0[1] * d1[4] - d0[4] * d1[1]) * inva;
1218 temp[2] = (d0[2] * d1[4] - d0[4] * d1[2]) * inva;
1220 ft->tangents[0] = temp;
1222 temp[0] = (d0[3] * d1[0] - d0[0] * d1[3]) * inva;
1223 temp[1] = (d0[3] * d1[1] - d0[1] * d1[3]) * inva;
1224 temp[2] = (d0[3] * d1[2] - d0[2] * d1[3]) * inva;
1226 ft->tangents[1] = temp;
1228 temp[0] = (d0[0] * d1[4] - d0[4] * d1[0]);
1229 temp[1] = (d0[1] * d1[4] - d0[4] * d1[1]);
1230 temp[2] = (d0[2] * d1[4] - d0[4] * d1[2]);
1232 ft->tangents[0] = temp;
1234 temp[0] = (d0[3] * d1[0] - d0[0] * d1[3]);
1235 temp[1] = (d0[3] * d1[1] - d0[1] * d1[3]);
1236 temp[2] = (d0[3] * d1[2] - d0[2] * d1[3]);
1238 ft->tangents[1] = temp;
1247 R_DuplicateMirroredVertexes
1249 Modifies the surface to bust apart any verts that are shared by both positive and
1250 negative texture polarities, so tangent space smoothing at the vertex doesn't
1253 This will create some identical vertexes (which will eventually get different tangent
1254 vectors), so never optimize the resulting mesh, or it will get the mirrored edges back.
1256 Reallocates tri->verts and changes tri->indexes in place
1257 Silindexes are unchanged by this.
1259 sets mirroredVerts and mirroredVerts[]
1264 bool polarityUsed[2];
1268 static void R_DuplicateMirroredVertexes( srfTriangles_t *tri ) {
1269 tangentVert_t *tverts, *vert;
1274 tverts = (tangentVert_t *)_alloca16( tri->numVerts * sizeof( *tverts ) );
1275 memset( tverts, 0, tri->numVerts * sizeof( *tverts ) );
1277 // determine texture polarity of each surface
1279 // mark each vert with the polarities it uses
1280 for ( i = 0 ; i < tri->numIndexes ; i+=3 ) {
1283 polarity = R_FaceNegativePolarity( tri, i );
1284 for ( j = 0 ; j < 3 ; j++ ) {
1285 tverts[tri->indexes[i+j]].polarityUsed[ polarity ] = true;
1289 // now create new verts as needed
1290 totalVerts = tri->numVerts;
1291 for ( i = 0 ; i < tri->numVerts ; i++ ) {
1293 if ( vert->polarityUsed[0] && vert->polarityUsed[1] ) {
1294 vert->negativeRemap = totalVerts;
1299 tri->numMirroredVerts = totalVerts - tri->numVerts;
1301 // now create the new list
1302 if ( totalVerts == tri->numVerts ) {
1303 tri->mirroredVerts = NULL;
1307 tri->mirroredVerts = triMirroredVertAllocator.Alloc( tri->numMirroredVerts );
1309 #ifdef USE_TRI_DATA_ALLOCATOR
1310 tri->verts = triVertexAllocator.Resize( tri->verts, totalVerts );
1312 idDrawVert *oldVerts = tri->verts;
1313 R_AllocStaticTriSurfVerts( tri, totalVerts );
1314 memcpy( tri->verts, oldVerts, tri->numVerts * sizeof( tri->verts[0] ) );
1315 triVertexAllocator.Free( oldVerts );
1318 // create the duplicates
1320 for ( i = 0 ; i < tri->numVerts ; i++ ) {
1321 j = tverts[i].negativeRemap;
1323 tri->verts[j] = tri->verts[i];
1324 tri->mirroredVerts[numMirror] = i;
1329 tri->numVerts = totalVerts;
1330 // change the indexes
1331 for ( i = 0 ; i < tri->numIndexes ; i++ ) {
1332 if ( tverts[tri->indexes[i]].negativeRemap &&
1333 R_FaceNegativePolarity( tri, 3*(i/3) ) ) {
1334 tri->indexes[i] = tverts[tri->indexes[i]].negativeRemap;
1338 tri->numVerts = totalVerts;
1343 R_DeriveTangentsWithoutNormals
1345 Build texture space tangents for bump mapping
1346 If a surface is deformed, this must be recalculated
1348 This assumes that any mirrored vertexes have already been duplicated, so
1349 any shared vertexes will have the tangent spaces smoothed across.
1351 Texture wrapping slightly complicates this, but as long as the normals
1352 are shared, and the tangent vectors are projected onto the normals, the
1353 separate vertexes should wind up with identical tangent spaces.
1355 mirroring a normalmap WILL cause a slightly visible seam unless the normals
1356 are completely flat around the edge's full bilerp support.
1358 Vertexes which are smooth shaded must have their tangent vectors
1359 in the same plane, which will allow a seamless
1360 rendering as long as the normal map is even on both sides of the
1363 A smooth shaded surface may have multiple tangent vectors at a vertex
1364 due to texture seams or mirroring, but it should only have a single
1367 Each triangle has a pair of tangent vectors in it's plane
1369 Should we consider having vertexes point at shared tangent spaces
1370 to save space or speed transforms?
1372 this version only handles bilateral symetry
1375 void R_DeriveTangentsWithoutNormals( srfTriangles_t *tri ) {
1377 faceTangents_t *faceTangents;
1381 faceTangents = (faceTangents_t *)_alloca16( sizeof(faceTangents[0]) * tri->numIndexes/3 );
1382 R_DeriveFaceTangents( tri, faceTangents );
1384 // clear the tangents
1385 for ( i = 0 ; i < tri->numVerts ; i++ ) {
1386 tri->verts[i].tangents[0].Zero();
1387 tri->verts[i].tangents[1].Zero();
1390 // sum up the neighbors
1391 for ( i = 0 ; i < tri->numIndexes ; i+=3 ) {
1392 ft = &faceTangents[i/3];
1394 // for each vertex on this face
1395 for ( j = 0 ; j < 3 ; j++ ) {
1396 vert = &tri->verts[tri->indexes[i+j]];
1398 vert->tangents[0] += ft->tangents[0];
1399 vert->tangents[1] += ft->tangents[1];
1404 // sum up both sides of the mirrored verts
1405 // so the S vectors exactly mirror, and the T vectors are equal
1406 for ( i = 0 ; i < tri->numMirroredVerts ; i++ ) {
1407 idDrawVert *v1, *v2;
1409 v1 = &tri->verts[ tri->numVerts - tri->numMirroredVerts + i ];
1410 v2 = &tri->verts[ tri->mirroredVerts[i] ];
1412 v1->tangents[0] -= v2->tangents[0];
1413 v1->tangents[1] += v2->tangents[1];
1415 v2->tangents[0] = vec3_origin - v1->tangents[0];
1416 v2->tangents[1] = v1->tangents[1];
1421 // project the summed vectors onto the normal plane
1422 // and normalize. The tangent vectors will not necessarily
1423 // be orthogonal to each other, but they will be orthogonal
1424 // to the surface normal.
1425 for ( i = 0 ; i < tri->numVerts ; i++ ) {
1426 vert = &tri->verts[i];
1427 for ( j = 0 ; j < 2 ; j++ ) {
1430 d = vert->tangents[j] * vert->normal;
1431 vert->tangents[j] = vert->tangents[j] - d * vert->normal;
1432 vert->tangents[j].Normalize();
1436 tri->tangentsCalculated = true;
1439 static ID_INLINE void VectorNormalizeFast2( const idVec3 &v, idVec3 &out) {
1442 ilength = idMath::RSqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] );
1443 out[0] = v[0] * ilength;
1444 out[1] = v[1] * ilength;
1445 out[2] = v[2] * ilength;
1452 Find the largest triangle that uses each vertex
1460 static int IndexSort( const void *a, const void *b ) {
1461 if ( ((indexSort_t *)a)->vertexNum < ((indexSort_t *)b)->vertexNum ) {
1464 if ( ((indexSort_t *)a)->vertexNum > ((indexSort_t *)b)->vertexNum ) {
1470 void R_BuildDominantTris( srfTriangles_t *tri ) {
1473 indexSort_t *ind = (indexSort_t *)R_StaticAlloc( tri->numIndexes * sizeof( *ind ) );
1475 for ( i = 0; i < tri->numIndexes; i++ ) {
1476 ind[i].vertexNum = tri->indexes[i];
1477 ind[i].faceNum = i / 3;
1479 qsort( ind, tri->numIndexes, sizeof( *ind ), IndexSort );
1481 tri->dominantTris = dt = triDominantTrisAllocator.Alloc( tri->numVerts );
1482 memset( dt, 0, tri->numVerts * sizeof( dt[0] ) );
1484 for ( i = 0; i < tri->numIndexes; i += j ) {
1486 int vertNum = ind[i].vertexNum;
1487 for ( j = 0; i + j < tri->numIndexes && ind[i+j].vertexNum == vertNum; j++ ) {
1489 idDrawVert *a, *b, *c;
1490 idVec3 normal, tangent, bitangent;
1492 int i1 = tri->indexes[ind[i+j].faceNum * 3 + 0];
1493 int i2 = tri->indexes[ind[i+j].faceNum * 3 + 1];
1494 int i3 = tri->indexes[ind[i+j].faceNum * 3 + 2];
1496 a = tri->verts + i1;
1497 b = tri->verts + i2;
1498 c = tri->verts + i3;
1500 d0[0] = b->xyz[0] - a->xyz[0];
1501 d0[1] = b->xyz[1] - a->xyz[1];
1502 d0[2] = b->xyz[2] - a->xyz[2];
1503 d0[3] = b->st[0] - a->st[0];
1504 d0[4] = b->st[1] - a->st[1];
1506 d1[0] = c->xyz[0] - a->xyz[0];
1507 d1[1] = c->xyz[1] - a->xyz[1];
1508 d1[2] = c->xyz[2] - a->xyz[2];
1509 d1[3] = c->st[0] - a->st[0];
1510 d1[4] = c->st[1] - a->st[1];
1512 normal[0] = ( d1[1] * d0[2] - d1[2] * d0[1] );
1513 normal[1] = ( d1[2] * d0[0] - d1[0] * d0[2] );
1514 normal[2] = ( d1[0] * d0[1] - d1[1] * d0[0] );
1516 float area = normal.Length();
1518 // if this is smaller than what we already have, skip it
1519 if ( area < maxArea ) {
1524 if ( i1 == vertNum ) {
1525 dt[vertNum].v2 = i2;
1526 dt[vertNum].v3 = i3;
1527 } else if ( i2 == vertNum ) {
1528 dt[vertNum].v2 = i3;
1529 dt[vertNum].v3 = i1;
1531 dt[vertNum].v2 = i1;
1532 dt[vertNum].v3 = i2;
1536 if ( len < 0.001f ) {
1539 dt[vertNum].normalizationScale[2] = 1.0f / len; // normal
1542 area = d0[3] * d1[4] - d0[4] * d1[3];
1544 tangent[0] = ( d0[0] * d1[4] - d0[4] * d1[0] );
1545 tangent[1] = ( d0[1] * d1[4] - d0[4] * d1[1] );
1546 tangent[2] = ( d0[2] * d1[4] - d0[4] * d1[2] );
1547 len = tangent.Length();
1548 if ( len < 0.001f ) {
1551 dt[vertNum].normalizationScale[0] = ( area > 0 ? 1 : -1 ) / len; // tangents[0]
1553 bitangent[0] = ( d0[3] * d1[0] - d0[0] * d1[3] );
1554 bitangent[1] = ( d0[3] * d1[1] - d0[1] * d1[3] );
1555 bitangent[2] = ( d0[3] * d1[2] - d0[2] * d1[3] );
1556 len = bitangent.Length();
1557 if ( len < 0.001f ) {
1560 #ifdef DERIVE_UNSMOOTHED_BITANGENT
1561 dt[vertNum].normalizationScale[1] = ( area > 0 ? 1 : -1 );
1563 dt[vertNum].normalizationScale[1] = ( area > 0 ? 1 : -1 ) / len; // tangents[1]
1568 R_StaticFree( ind );
1572 ====================
1573 R_DeriveUnsmoothedTangents
1575 Uses the single largest area triangle for each vertex, instead of smoothing over all
1576 ====================
1578 void R_DeriveUnsmoothedTangents( srfTriangles_t *tri ) {
1579 if ( tri->tangentsCalculated ) {
1585 SIMDProcessor->DeriveUnsmoothedTangents( tri->verts, tri->dominantTris, tri->numVerts );
1589 for ( int i = 0 ; i < tri->numVerts ; i++ ) {
1592 idDrawVert *a, *b, *c;
1593 dominantTri_t *dt = &tri->dominantTris[i];
1596 b = tri->verts + dt->v2;
1597 c = tri->verts + dt->v3;
1599 d0[0] = b->xyz[0] - a->xyz[0];
1600 d0[1] = b->xyz[1] - a->xyz[1];
1601 d0[2] = b->xyz[2] - a->xyz[2];
1602 d0[3] = b->st[0] - a->st[0];
1603 d0[4] = b->st[1] - a->st[1];
1605 d1[0] = c->xyz[0] - a->xyz[0];
1606 d1[1] = c->xyz[1] - a->xyz[1];
1607 d1[2] = c->xyz[2] - a->xyz[2];
1608 d1[3] = c->st[0] - a->st[0];
1609 d1[4] = c->st[1] - a->st[1];
1611 a->normal[0] = dt->normalizationScale[2] * ( d1[1] * d0[2] - d1[2] * d0[1] );
1612 a->normal[1] = dt->normalizationScale[2] * ( d1[2] * d0[0] - d1[0] * d0[2] );
1613 a->normal[2] = dt->normalizationScale[2] * ( d1[0] * d0[1] - d1[1] * d0[0] );
1615 a->tangents[0][0] = dt->normalizationScale[0] * ( d0[0] * d1[4] - d0[4] * d1[0] );
1616 a->tangents[0][1] = dt->normalizationScale[0] * ( d0[1] * d1[4] - d0[4] * d1[1] );
1617 a->tangents[0][2] = dt->normalizationScale[0] * ( d0[2] * d1[4] - d0[4] * d1[2] );
1619 #ifdef DERIVE_UNSMOOTHED_BITANGENT
1620 // derive the bitangent for a completely orthogonal axis,
1621 // instead of using the texture T vector
1622 a->tangents[1][0] = dt->normalizationScale[1] * ( a->normal[2] * a->tangents[0][1] - a->normal[1] * a->tangents[0][2] );
1623 a->tangents[1][1] = dt->normalizationScale[1] * ( a->normal[0] * a->tangents[0][2] - a->normal[2] * a->tangents[0][0] );
1624 a->tangents[1][2] = dt->normalizationScale[1] * ( a->normal[1] * a->tangents[0][0] - a->normal[0] * a->tangents[0][1] );
1626 // calculate the bitangent from the texture T vector
1627 a->tangents[1][0] = dt->normalizationScale[1] * ( d0[3] * d1[0] - d0[0] * d1[3] );
1628 a->tangents[1][1] = dt->normalizationScale[1] * ( d0[3] * d1[1] - d0[1] * d1[3] );
1629 a->tangents[1][2] = dt->normalizationScale[1] * ( d0[3] * d1[2] - d0[2] * d1[3] );
1635 tri->tangentsCalculated = true;
1642 This is called once for static surfaces, and every frame for deforming surfaces
1644 Builds tangents, normals, and face planes
1647 void R_DeriveTangents( srfTriangles_t *tri, bool allocFacePlanes ) {
1651 if ( tri->dominantTris != NULL ) {
1652 R_DeriveUnsmoothedTangents( tri );
1656 if ( tri->tangentsCalculated ) {
1660 tr.pc.c_tangentIndexes += tri->numIndexes;
1662 if ( !tri->facePlanes && allocFacePlanes ) {
1663 R_AllocStaticTriSurfPlanes( tri, tri->numIndexes );
1665 planes = tri->facePlanes;
1670 planes = (idPlane *)_alloca16( ( tri->numIndexes / 3 ) * sizeof( planes[0] ) );
1673 SIMDProcessor->DeriveTangents( planes, tri->verts, tri->numVerts, tri->indexes, tri->numIndexes );
1677 for ( i = 0; i < tri->numVerts; i++ ) {
1678 tri->verts[i].normal.Zero();
1679 tri->verts[i].tangents[0].Zero();
1680 tri->verts[i].tangents[1].Zero();
1683 for ( i = 0; i < tri->numIndexes; i += 3 ) {
1684 // make face tangents
1686 idDrawVert *a, *b, *c;
1687 idVec3 temp, normal, tangents[2];
1689 a = tri->verts + tri->indexes[i + 0];
1690 b = tri->verts + tri->indexes[i + 1];
1691 c = tri->verts + tri->indexes[i + 2];
1693 d0[0] = b->xyz[0] - a->xyz[0];
1694 d0[1] = b->xyz[1] - a->xyz[1];
1695 d0[2] = b->xyz[2] - a->xyz[2];
1696 d0[3] = b->st[0] - a->st[0];
1697 d0[4] = b->st[1] - a->st[1];
1699 d1[0] = c->xyz[0] - a->xyz[0];
1700 d1[1] = c->xyz[1] - a->xyz[1];
1701 d1[2] = c->xyz[2] - a->xyz[2];
1702 d1[3] = c->st[0] - a->st[0];
1703 d1[4] = c->st[1] - a->st[1];
1706 temp[0] = d1[1] * d0[2] - d1[2] * d0[1];
1707 temp[1] = d1[2] * d0[0] - d1[0] * d0[2];
1708 temp[2] = d1[0] * d0[1] - d1[1] * d0[0];
1709 VectorNormalizeFast2( temp, normal );
1712 float area = d0[3] * d1[4] - d0[4] * d1[3];
1713 float inva = area < 0.0f ? -1 : 1; // was = 1.0f / area;
1715 temp[0] = (d0[0] * d1[4] - d0[4] * d1[0]) * inva;
1716 temp[1] = (d0[1] * d1[4] - d0[4] * d1[1]) * inva;
1717 temp[2] = (d0[2] * d1[4] - d0[4] * d1[2]) * inva;
1718 VectorNormalizeFast2( temp, tangents[0] );
1720 temp[0] = (d0[3] * d1[0] - d0[0] * d1[3]) * inva;
1721 temp[1] = (d0[3] * d1[1] - d0[1] * d1[3]) * inva;
1722 temp[2] = (d0[3] * d1[2] - d0[2] * d1[3]) * inva;
1723 VectorNormalizeFast2( temp, tangents[1] );
1725 temp[0] = (d0[0] * d1[4] - d0[4] * d1[0]);
1726 temp[1] = (d0[1] * d1[4] - d0[4] * d1[1]);
1727 temp[2] = (d0[2] * d1[4] - d0[4] * d1[2]);
1728 VectorNormalizeFast2( temp, tangents[0] );
1730 temp[0] = (d0[3] * d1[0] - d0[0] * d1[3]);
1731 temp[1] = (d0[3] * d1[1] - d0[1] * d1[3]);
1732 temp[2] = (d0[3] * d1[2] - d0[2] * d1[3]);
1733 VectorNormalizeFast2( temp, tangents[1] );
1736 // sum up the tangents and normals for each vertex on this face
1737 for ( int j = 0 ; j < 3 ; j++ ) {
1738 vert = &tri->verts[tri->indexes[i+j]];
1739 vert->normal += normal;
1740 vert->tangents[0] += tangents[0];
1741 vert->tangents[1] += tangents[1];
1745 planes->Normal() = normal;
1746 planes->FitThroughPoint( a->xyz );
1755 if ( tri->silIndexes != NULL ) {
1756 for ( i = 0; i < tri->numVerts; i++ ) {
1757 tri->verts[i].normal.Zero();
1759 for ( i = 0; i < tri->numIndexes; i++ ) {
1760 tri->verts[tri->silIndexes[i]].normal += planes[i/3].Normal();
1762 for ( i = 0 ; i < tri->numIndexes ; i++ ) {
1763 tri->verts[tri->indexes[i]].normal = tri->verts[tri->silIndexes[i]].normal;
1769 int *dupVerts = tri->dupVerts;
1770 idDrawVert *verts = tri->verts;
1772 // add the normal of a duplicated vertex to the normal of the first vertex with the same XYZ
1773 for ( i = 0; i < tri->numDupVerts; i++ ) {
1774 verts[dupVerts[i*2+0]].normal += verts[dupVerts[i*2+1]].normal;
1777 // copy vertex normals to duplicated vertices
1778 for ( i = 0; i < tri->numDupVerts; i++ ) {
1779 verts[dupVerts[i*2+1]].normal = verts[dupVerts[i*2+0]].normal;
1785 // sum up both sides of the mirrored verts
1786 // so the S vectors exactly mirror, and the T vectors are equal
1787 for ( i = 0 ; i < tri->numMirroredVerts ; i++ ) {
1788 idDrawVert *v1, *v2;
1790 v1 = &tri->verts[ tri->numVerts - tri->numMirroredVerts + i ];
1791 v2 = &tri->verts[ tri->mirroredVerts[i] ];
1793 v1->tangents[0] -= v2->tangents[0];
1794 v1->tangents[1] += v2->tangents[1];
1796 v2->tangents[0] = vec3_origin - v1->tangents[0];
1797 v2->tangents[1] = v1->tangents[1];
1801 // project the summed vectors onto the normal plane
1802 // and normalize. The tangent vectors will not necessarily
1803 // be orthogonal to each other, but they will be orthogonal
1804 // to the surface normal.
1807 SIMDProcessor->NormalizeTangents( tri->verts, tri->numVerts );
1811 for ( i = 0 ; i < tri->numVerts ; i++ ) {
1812 idDrawVert *vert = &tri->verts[i];
1814 VectorNormalizeFast2( vert->normal, vert->normal );
1816 // project the tangent vectors
1817 for ( int j = 0 ; j < 2 ; j++ ) {
1820 d = vert->tangents[j] * vert->normal;
1821 vert->tangents[j] = vert->tangents[j] - d * vert->normal;
1822 VectorNormalizeFast2( vert->tangents[j], vert->tangents[j] );
1828 tri->tangentsCalculated = true;
1829 tri->facePlanesCalculated = true;
1834 R_RemoveDuplicatedTriangles
1836 silIndexes must have already been calculated
1838 silIndexes are used instead of indexes, because duplicated
1839 triangles could have different texture coordinates.
1842 void R_RemoveDuplicatedTriangles( srfTriangles_t *tri ) {
1849 // check for completely duplicated triangles
1850 // any rotation of the triangle is still the same, but a mirroring
1851 // is considered different
1852 for ( i = 0 ; i < tri->numIndexes ; i+=3 ) {
1853 for ( r = 0 ; r < 3 ; r++ ) {
1854 a = tri->silIndexes[i+r];
1855 b = tri->silIndexes[i+(r+1)%3];
1856 c = tri->silIndexes[i+(r+2)%3];
1857 for ( j = i + 3 ; j < tri->numIndexes ; j+=3 ) {
1858 if ( tri->silIndexes[j] == a && tri->silIndexes[j+1] == b && tri->silIndexes[j+2] == c ) {
1860 memmove( tri->indexes + j, tri->indexes + j + 3, ( tri->numIndexes - j - 3 ) * sizeof( tri->indexes[0] ) );
1861 memmove( tri->silIndexes + j, tri->silIndexes + j + 3, ( tri->numIndexes - j - 3 ) * sizeof( tri->silIndexes[0] ) );
1862 tri->numIndexes -= 3;
1870 common->Printf( "removed %i duplicated triangles\n", c_removed );
1877 R_RemoveDegenerateTriangles
1879 silIndexes must have already been calculated
1882 void R_RemoveDegenerateTriangles( srfTriangles_t *tri ) {
1887 // check for completely degenerate triangles
1889 for ( i = 0; i < tri->numIndexes; i += 3 ) {
1890 a = tri->silIndexes[i];
1891 b = tri->silIndexes[i+1];
1892 c = tri->silIndexes[i+2];
1893 if ( a == b || a == c || b == c ) {
1895 memmove( tri->indexes + i, tri->indexes + i + 3, ( tri->numIndexes - i - 3 ) * sizeof( tri->indexes[0] ) );
1896 if ( tri->silIndexes ) {
1897 memmove( tri->silIndexes + i, tri->silIndexes + i + 3, ( tri->numIndexes - i - 3 ) * sizeof( tri->silIndexes[0] ) );
1899 tri->numIndexes -= 3;
1904 // this doesn't free the memory used by the unused verts
1907 common->Printf( "removed %i degenerate triangles\n", c_removed );
1913 R_TestDegenerateTextureSpace
1916 void R_TestDegenerateTextureSpace( srfTriangles_t *tri ) {
1920 // check for triangles with a degenerate texture space
1922 for ( i = 0; i < tri->numIndexes; i += 3 ) {
1923 const idDrawVert &a = tri->verts[tri->indexes[i+0]];
1924 const idDrawVert &b = tri->verts[tri->indexes[i+1]];
1925 const idDrawVert &c = tri->verts[tri->indexes[i+2]];
1927 if ( a.st == b.st || b.st == c.st || c.st == a.st ) {
1932 if ( c_degenerate ) {
1933 // common->Printf( "%d triangles with a degenerate texture space\n", c_degenerate );
1942 void R_RemoveUnusedVerts( srfTriangles_t *tri ) {
1948 mark = (int *)R_ClearedStaticAlloc( tri->numVerts * sizeof( *mark ) );
1950 for ( i = 0 ; i < tri->numIndexes ; i++ ) {
1951 index = tri->indexes[i];
1952 if ( index < 0 || index >= tri->numVerts ) {
1953 common->Error( "R_RemoveUnusedVerts: bad index" );
1957 if ( tri->silIndexes ) {
1958 index = tri->silIndexes[i];
1959 if ( index < 0 || index >= tri->numVerts ) {
1960 common->Error( "R_RemoveUnusedVerts: bad index" );
1967 for ( i = 0 ; i < tri->numVerts ; i++ ) {
1975 if ( used != tri->numVerts ) {
1976 for ( i = 0 ; i < tri->numIndexes ; i++ ) {
1977 tri->indexes[i] = mark[ tri->indexes[i] ] - 1;
1978 if ( tri->silIndexes ) {
1979 tri->silIndexes[i] = mark[ tri->silIndexes[i] ] - 1;
1982 tri->numVerts = used;
1984 for ( i = 0 ; i < tri->numVerts ; i++ ) {
1989 tri->verts[ index - 1 ] = tri->verts[i];
1992 // this doesn't realloc the arrays to save the memory used by the unused verts
1995 R_StaticFree( mark );
2002 Only deals with vertexes and indexes, not silhouettes, planes, etc.
2003 Does NOT perform a cleanup triangles, so there may be duplicated verts in the result.
2006 srfTriangles_t *R_MergeSurfaceList( const srfTriangles_t **surfaces, int numSurfaces ) {
2007 srfTriangles_t *newTri;
2008 const srfTriangles_t *tri;
2015 for ( i = 0 ; i < numSurfaces ; i++ ) {
2016 totalVerts += surfaces[i]->numVerts;
2017 totalIndexes += surfaces[i]->numIndexes;
2020 newTri = R_AllocStaticTriSurf();
2021 newTri->numVerts = totalVerts;
2022 newTri->numIndexes = totalIndexes;
2023 R_AllocStaticTriSurfVerts( newTri, newTri->numVerts );
2024 R_AllocStaticTriSurfIndexes( newTri, newTri->numIndexes );
2028 for ( i = 0 ; i < numSurfaces ; i++ ) {
2030 memcpy( newTri->verts + totalVerts, tri->verts, tri->numVerts * sizeof( *tri->verts ) );
2031 for ( j = 0 ; j < tri->numIndexes ; j++ ) {
2032 newTri->indexes[ totalIndexes + j ] = totalVerts + tri->indexes[j];
2034 totalVerts += tri->numVerts;
2035 totalIndexes += tri->numIndexes;
2045 Only deals with vertexes and indexes, not silhouettes, planes, etc.
2046 Does NOT perform a cleanup triangles, so there may be duplicated verts in the result.
2049 srfTriangles_t *R_MergeTriangles( const srfTriangles_t *tri1, const srfTriangles_t *tri2 ) {
2050 const srfTriangles_t *tris[2];
2055 return R_MergeSurfaceList( tris, 2 );
2062 Lit two sided surfaces need to have the triangles actually duplicated,
2063 they can't just turn on two sided lighting, because the normal and tangents
2064 are wrong on the other sides.
2066 This should be called before R_CleanupTriangles
2069 void R_ReverseTriangles( srfTriangles_t *tri ) {
2072 // flip the normal on each vertex
2073 // If the surface is going to have generated normals, this won't matter,
2074 // but if it has explicit normals, this will keep it on the correct side
2075 for ( i = 0 ; i < tri->numVerts ; i++ ) {
2076 tri->verts[i].normal = vec3_origin - tri->verts[i].normal;
2079 // flip the index order to make them back sided
2080 for ( i = 0 ; i < tri->numIndexes ; i+= 3 ) {
2083 temp = tri->indexes[ i + 0 ];
2084 tri->indexes[ i + 0 ] = tri->indexes[ i + 1 ];
2085 tri->indexes[ i + 1 ] = temp;
2093 FIXME: allow createFlat and createSmooth normals, as well as explicit
2096 void R_CleanupTriangles( srfTriangles_t *tri, bool createNormals, bool identifySilEdges, bool useUnsmoothedTangents ) {
2097 R_RangeCheckIndexes( tri );
2099 R_CreateSilIndexes( tri );
2101 // R_RemoveDuplicatedTriangles( tri ); // this may remove valid overlapped transparent triangles
2103 R_RemoveDegenerateTriangles( tri );
2105 R_TestDegenerateTextureSpace( tri );
2107 // R_RemoveUnusedVerts( tri );
2109 if ( identifySilEdges ) {
2110 R_IdentifySilEdges( tri, true ); // assume it is non-deformable, and omit coplanar edges
2113 // bust vertexes that share a mirrored edge into separate vertexes
2114 R_DuplicateMirroredVertexes( tri );
2116 // optimize the index order (not working?)
2117 // R_OrderIndexes( tri->numIndexes, tri->indexes );
2119 R_CreateDupVerts( tri );
2121 R_BoundTriSurf( tri );
2123 if ( useUnsmoothedTangents ) {
2124 R_BuildDominantTris( tri );
2125 R_DeriveUnsmoothedTangents( tri );
2126 } else if ( !createNormals ) {
2127 R_DeriveFacePlanes( tri );
2128 R_DeriveTangentsWithoutNormals( tri );
2130 R_DeriveTangents( tri );
2135 ===================================================================================
2139 ===================================================================================
2147 deformInfo_t *R_BuildDeformInfo( int numVerts, const idDrawVert *verts, int numIndexes, const int *indexes, bool useUnsmoothedTangents ) {
2148 deformInfo_t *deform;
2152 memset( &tri, 0, sizeof( tri ) );
2154 tri.numVerts = numVerts;
2155 R_AllocStaticTriSurfVerts( &tri, tri.numVerts );
2156 SIMDProcessor->Memcpy( tri.verts, verts, tri.numVerts * sizeof( tri.verts[0] ) );
2158 tri.numIndexes = numIndexes;
2159 R_AllocStaticTriSurfIndexes( &tri, tri.numIndexes );
2161 // don't memcpy, so we can change the index type from int to short without changing the interface
2162 for ( i = 0 ; i < tri.numIndexes ; i++ ) {
2163 tri.indexes[i] = indexes[i];
2166 R_RangeCheckIndexes( &tri );
2167 R_CreateSilIndexes( &tri );
2169 // should we order the indexes here?
2171 // R_RemoveDuplicatedTriangles( &tri );
2172 // R_RemoveDegenerateTriangles( &tri );
2173 // R_RemoveUnusedVerts( &tri );
2174 R_IdentifySilEdges( &tri, false ); // we cannot remove coplanar edges, because
2175 // they can deform to silhouettes
2177 R_DuplicateMirroredVertexes( &tri ); // split mirror points into multiple points
2179 R_CreateDupVerts( &tri );
2181 if ( useUnsmoothedTangents ) {
2182 R_BuildDominantTris( &tri );
2185 deform = (deformInfo_t *)R_ClearedStaticAlloc( sizeof( *deform ) );
2187 deform->numSourceVerts = numVerts;
2188 deform->numOutputVerts = tri.numVerts;
2190 deform->numIndexes = numIndexes;
2191 deform->indexes = tri.indexes;
2193 deform->silIndexes = tri.silIndexes;
2195 deform->numSilEdges = tri.numSilEdges;
2196 deform->silEdges = tri.silEdges;
2198 deform->dominantTris = tri.dominantTris;
2200 deform->numMirroredVerts = tri.numMirroredVerts;
2201 deform->mirroredVerts = tri.mirroredVerts;
2203 deform->numDupVerts = tri.numDupVerts;
2204 deform->dupVerts = tri.dupVerts;
2207 triVertexAllocator.Free( tri.verts );
2210 if ( tri.facePlanes ) {
2211 triPlaneAllocator.Free( tri.facePlanes );
2222 void R_FreeDeformInfo( deformInfo_t *deformInfo ) {
2223 if ( deformInfo->indexes != NULL ) {
2224 triIndexAllocator.Free( deformInfo->indexes );
2226 if ( deformInfo->silIndexes != NULL ) {
2227 triSilIndexAllocator.Free( deformInfo->silIndexes );
2229 if ( deformInfo->silEdges != NULL ) {
2230 triSilEdgeAllocator.Free( deformInfo->silEdges );
2232 if ( deformInfo->dominantTris != NULL ) {
2233 triDominantTrisAllocator.Free( deformInfo->dominantTris );
2235 if ( deformInfo->mirroredVerts != NULL ) {
2236 triMirroredVertAllocator.Free( deformInfo->mirroredVerts );
2238 if ( deformInfo->dupVerts != NULL ) {
2239 triDupVertAllocator.Free( deformInfo->dupVerts );
2241 R_StaticFree( deformInfo );
2246 R_DeformInfoMemoryUsed
2249 int R_DeformInfoMemoryUsed( deformInfo_t *deformInfo ) {
2252 if ( deformInfo->indexes != NULL ) {
2253 total += deformInfo->numIndexes * sizeof( deformInfo->indexes[0] );
2255 if ( deformInfo->silIndexes != NULL ) {
2256 total += deformInfo->numIndexes * sizeof( deformInfo->silIndexes[0] );
2258 if ( deformInfo->silEdges != NULL ) {
2259 total += deformInfo->numSilEdges * sizeof( deformInfo->silEdges[0] );
2261 if ( deformInfo->dominantTris != NULL ) {
2262 total += deformInfo->numSourceVerts * sizeof( deformInfo->dominantTris[0] );
2264 if ( deformInfo->mirroredVerts != NULL ) {
2265 total += deformInfo->numMirroredVerts * sizeof( deformInfo->mirroredVerts[0] );
2267 if ( deformInfo->dupVerts != NULL ) {
2268 total += deformInfo->numDupVerts * sizeof( deformInfo->dupVerts[0] );
2271 total += sizeof( *deformInfo );