29 #include "../../../idlib/precompiled.h"
33 #include "../../../renderer/tr_local.h"
106 static const int MAX_SHADOW_TRIS = 32768;
109 static int numOutputTris;
118 static int numSilEdges;
126 static const int MAX_SIL_QUADS = MAX_SHADOW_TRIS*3;
127 static silQuad_t silQuads[MAX_SIL_QUADS];
128 static int numSilQuads;
137 static float EDGE_PLANE_EPSILON = 0.1f;
138 static float UNIQUE_EPSILON = 0.1f;
140 static int numSilPlanes;
144 static int numUniqued;
145 static int numUniquedBeforeProjection;
146 static int maxUniqued;
150 static int maxRetIndexes;
152 static int FindUniqueVert(
idVec3 &
v );
161 static void CreateEdgesForTri(
shadowTri_t *tri ) {
162 for (
int j = 0 ;
j < 3 ;
j++ ) {
172 static const float EDGE_EPSILON = 0.1f;
176 if ( a->
v[0] * b->
edge[0] <= EDGE_EPSILON
177 && a->
v[1] * b->
edge[0] <= EDGE_EPSILON
178 && a->
v[2] * b->
edge[0] <= EDGE_EPSILON ) {
181 if ( a->
v[0] * b->
edge[1] <= EDGE_EPSILON
182 && a->
v[1] * b->
edge[1] <= EDGE_EPSILON
183 && a->
v[2] * b->
edge[1] <= EDGE_EPSILON ) {
186 if ( a->
v[0] * b->
edge[2] <= EDGE_EPSILON
187 && a->
v[1] * b->
edge[2] <= EDGE_EPSILON
188 && a->
v[2] * b->
edge[2] <= EDGE_EPSILON ) {
192 for (
int i = 0 ;
i < 3 ;
i++ ) {
194 for ( j = 0 ; j < 3 ; j++ ) {
195 float d = a->
v[
j] * b->
edge[
i];
196 if ( d > EDGE_EPSILON ) {
232 static int c_removedFragments;
233 static void ClipTriangle_r(
const shadowTri_t *tri,
int startTri,
int skipTri,
int numTris,
const shadowTri_t *tris ) {
237 for (
int i = startTri ;
i < numTris ;
i++ ) {
238 if (
i == skipTri ) {
243 if ( TriOutsideTri( tri, other ) ) {
246 if ( TriOutsideTri( other, tri ) ) {
252 if ( !TriBehindTri( tri, other ) ) {
259 for (
int j = 0 ; j < 4 &&
w ; j++ ) {
273 fragment.
v[0] = (*back)[0].ToVec3();
274 fragment.
v[1] = (*back)[k-1].ToVec3();
275 fragment.
v[2] = (*back)[k].ToVec3();
276 CreateEdgesForTri( &fragment );
277 ClipTriangle_r( &fragment,
i + 1, skipTri, numTris, tris );
289 c_removedFragments++;
295 if ( numOutputTris == MAX_SHADOW_TRIS ) {
296 common->
Error(
"numOutputTris == MAX_SHADOW_TRIS" );
299 outputTris[numOutputTris] = *tri;
312 static void ClipOccluders(
idVec4 *verts,
glIndex_t *indexes,
int numIndexes,
313 idVec3 projectionOrigin ) {
314 int numTris = numIndexes / 3;
319 common->
Printf(
"ClipOccluders: %i triangles\n", numTris );
321 for ( i = 0 ; i < numTris ; i++ ) {
325 tri->
v[0] = verts[indexes[i*3+2]].
ToVec3() - projectionOrigin;
326 tri->
v[1] = verts[indexes[i*3+1]].
ToVec3() - projectionOrigin;
327 tri->
v[2] = verts[indexes[i*3+0]].
ToVec3() - projectionOrigin;
341 CreateEdgesForTri( tri );
350 int numFragmented = 0;
352 for ( i = 0 ; i < numTris ; i++ ) {
353 int oldOutput = numOutputTris;
354 c_removedFragments = 0;
355 ClipTriangle_r( &tris[i], 0, i, numTris, tris );
356 if ( numOutputTris == oldOutput ) {
358 }
else if ( c_removedFragments == 0 ) {
363 numOutputTris = oldOutput+1;
373 numOutputTris = oldOutput+1;
377 common->
Printf(
"%i triangles completely invisible\n", numRemoved );
378 common->
Printf(
"%i triangles completely visible\n", numComplete );
379 common->
Printf(
"%i triangles fragmented\n", numFragmented );
380 common->
Printf(
"%i shadowing fragments before optimization\n", numOutputTris );
390 static void OptimizeOutputTris(
void ) {
397 for ( i = 0 ; i < numOutputTris ; i++ ) {
403 for ( checkGroup = optGroups ; checkGroup ; checkGroup = checkGroup->
nextGroup ) {
404 if ( checkGroup->
planeNum == planeNum ) {
413 optGroups = checkGroup;
418 mtri->
v[0].
xyz = tri->
v[0];
419 mtri->
v[1].
xyz = tri->
v[1];
420 mtri->
v[2].
xyz = tri->
v[2];
428 for ( checkGroup = optGroups ; checkGroup ; checkGroup = checkGroup->
nextGroup ) {
432 tri->
v[0] = mtri->
v[0].
xyz;
433 tri->
v[1] = mtri->
v[1].
xyz;
434 tri->
v[2] = mtri->
v[2].
xyz;
442 static int EdgeSort(
const void *a,
const void *b ) {
443 if ( *(
unsigned *)a < *(
unsigned *)b ) {
446 if ( *(
unsigned *)a > *(
unsigned *)b ) {
462 static void GenerateSilEdges(
void ) {
465 unsigned *edges = (
unsigned *)_alloca( (numOutputTris*3+1)*
sizeof(*edges) );
470 for ( i = 0 ; i < numOutputTris ; i++ ) {
471 int a = outputTris[
i].
index[0];
472 int b = outputTris[
i].
index[1];
473 int c = outputTris[
i].
index[2];
474 if ( a == b || a == c || b == c ) {
478 for ( j = 0 ; j < 3 ; j++ ) {
482 v2 = outputTris[
i].
index[(j+1)%3];
487 edges[numEdges] = ( v1 << 16 ) | ( v2 << 1 );
489 edges[numEdges] = ( v2 << 16 ) | ( v1 << 1 ) | 1;
495 qsort( edges, numEdges,
sizeof( edges[0] ), EdgeSort );
496 edges[numEdges] = -1;
498 for ( i = 0 ; i < numEdges ; i++ ) {
499 if ( ( edges[i] ^ edges[i+1] ) == 1 ) {
507 if ( edges[i] & 1 ) {
509 v1 = ( edges[
i] >> 1 ) & 0x7fff;
512 v2 = ( edges[
i] >> 1 ) & 0x7fff;
518 silEdges[numSilEdges].
index[0] =
v1;
519 silEdges[numSilEdges].
index[1] =
v2;
539 for (
int i = 0 ; i < numSilEdges ; i++ ) {
540 if ( silEdges[i].
index[0] == silEdges[i].
index[1] ) {
549 for ( j = 0 ; j < numSilPlanes ; j++ ) {
550 float d = v1 * silPlanes[
j].
normal;
551 float d2 = v2 * silPlanes[
j].
normal;
553 if ( fabs( d ) < EDGE_PLANE_EPSILON
554 && fabs( d2 ) < EDGE_PLANE_EPSILON ) {
556 silPlanes[
j].
edges = &silEdges[
i];
561 if ( j == numSilPlanes ) {
566 silPlanes[
j].
edges = &silEdges[
i];
582 if ( numSilQuads == MAX_SIL_QUADS ) {
585 silQuads[numSilQuads] = quad;
630 if ( check == skipEdge ) {
635 if ( check->index[0] == check->index[1] ) {
640 for (
int i = 0 ; i < 2 ; i++ ) {
643 plane.
Cross( uniqued[check->index[i]], silPlane->
normal );
646 if ( plane.
Length() < 0.9 ) {
652 if ( uniqued[check->index[!i]] * plane > 0 ) {
656 float d1 = uniqued[quad.
nearV[0]] * plane;
657 float d2 = uniqued[quad.
nearV[1]] * plane;
659 float d3 = uniqued[quad.
farV[0]] * plane;
660 float d4 = uniqued[quad.
farV[1]] * plane;
667 if ( ( d1 > EDGE_PLANE_EPSILON && d3 > EDGE_PLANE_EPSILON && d2 < -EDGE_PLANE_EPSILON && d4 < -EDGE_PLANE_EPSILON )
668 || ( d2 > EDGE_PLANE_EPSILON && d4 > EDGE_PLANE_EPSILON && d1 < -EDGE_PLANE_EPSILON && d3 < -EDGE_PLANE_EPSILON ) ) {
669 float f = d1 / ( d1 - d2 );
670 float f2 = d3 / ( d3 - d4 );
672 if ( f <= 0.0001 || f >= 0.9999 ) {
678 int nearMidIndex = FindUniqueVert( nearMid );
679 idVec3 farMid = (1-
f) * uniqued[quad.
farV[0]] + f * uniqued[quad.
farV[1]];
680 int farMidIndex = FindUniqueVert( farMid );
684 if ( d1 > EDGE_PLANE_EPSILON ) {
685 clipped.
nearV[1] = nearMidIndex;
686 clipped.
farV[1] = farMidIndex;
687 FragmentSilQuad( clipped, silPlane, check->nextEdge, skipEdge );
688 quad.
nearV[0] = nearMidIndex;
689 quad.
farV[0] = farMidIndex;
691 clipped.
nearV[0] = nearMidIndex;
692 clipped.
farV[0] = farMidIndex;
693 FragmentSilQuad( clipped, silPlane, check->nextEdge, skipEdge );
694 quad.
nearV[1] = nearMidIndex;
695 quad.
farV[1] = farMidIndex;
703 idVec3 dir = uniqued[check->index[1]] - uniqued[check->index[0]];
706 separate.
ToVec4()[3] = -(uniqued[check->index[1]] * separate.
Normal());
713 if ( ( d1 < EDGE_PLANE_EPSILON && d2 < EDGE_PLANE_EPSILON )
714 || ( d1 > -EDGE_PLANE_EPSILON && d2 > -EDGE_PLANE_EPSILON ) ) {
719 float f = d1 / ( d1 - d2 );
721 int mid0Index = FindUniqueVert( mid0 );
725 f = d1 / ( d1 - d2 );
726 if ( f < 0 || f > 1 ) {
731 int mid1Index = FindUniqueVert( mid1 );
735 clipped.
nearV[0] = mid0Index;
736 clipped.
nearV[1] = mid1Index;
737 FragmentSilQuad( clipped, silPlane, check->nextEdge, skipEdge );
738 quad.
farV[0] = mid0Index;
739 quad.
farV[1] = mid1Index;
742 SaveQuad( silPlane, quad );
751 static void FragmentSilQuads(
void ) {
758 for (
int i = 0 ; i < numSilPlanes ; i++ ) {
764 quad.
nearV[0] = e1->index[0];
765 quad.
nearV[1] = e1->index[1];
766 if ( e1->index[0] == e1->index[1] ) {
767 common->
Error(
"FragmentSilQuads: degenerate edge" );
769 quad.
farV[0] = e1->index[0] + numUniquedBeforeProjection;
770 quad.
farV[1] = e1->index[1] + numUniquedBeforeProjection;
771 FragmentSilQuad( quad, sil, sil->
edges, e1 );
784 static void EmitFragmentedSilQuads(
void ) {
788 for ( i = 0 ; i < numSilPlanes ; i++ ) {
793 memset( &groups, 0,
sizeof( groups ) );
797 planes[1] = -planes[0];
810 if ( f1->nearV[0] == f2->
nearV[1] && f1->nearV[1] == f2->
nearV[0] ) {
820 mtri->
v[0].
xyz = uniqued[f1->nearV[0]];
821 mtri->
v[1].
xyz = uniqued[f1->nearV[1]];
822 mtri->
v[2].
xyz = uniqued[f1->farV[1]];
824 v1 = mtri->
v[1].
xyz - mtri->
v[0].
xyz;
825 v2 = mtri->
v[2].
xyz - mtri->
v[0].
xyz;
826 normal.
Cross( v2, v1 );
828 if ( normal * planes[0].Normal() > 0 ) {
838 mtri->
v[0].
xyz = uniqued[f1->farV[0]];
839 mtri->
v[1].
xyz = uniqued[f1->nearV[0]];
840 mtri->
v[2].
xyz = uniqued[f1->farV[1]];
848 if ( index + 6 > maxRetIndexes ) {
851 ret.
indexes[index+0] = f1->nearV[0];
852 ret.
indexes[index+1] = f1->nearV[1];
853 ret.
indexes[index+2] = f1->farV[1];
854 ret.
indexes[index+3] = f1->farV[0];
855 ret.
indexes[index+4] = f1->nearV[0];
856 ret.
indexes[index+5] = f1->farV[1];
864 for ( j = 0 ; j < 2 ; j++ ) {
865 if ( !groups[j].triList ) {
872 for ( mtri = groups[j].triList ; mtri ; mtri = mtri->
next ) {
873 for ( k = 0 ; k < 3 ; k++ ) {
894 static void EmitUnoptimizedSilEdges(
void ) {
897 for ( i = 0 ; i < numSilEdges ; i++ ) {
898 int v1 = silEdges[
i].
index[0];
899 int v2 = silEdges[
i].
index[1];
903 ret.
indexes[index+2] = v2+numUniquedBeforeProjection;
904 ret.
indexes[index+3] = v1+numUniquedBeforeProjection;
906 ret.
indexes[index+5] = v2+numUniquedBeforeProjection;
918 static int FindUniqueVert(
idVec3 &
v ) {
921 for ( k = 0 ; k < numUniqued ; k++ ) {
922 idVec3 &check = uniqued[k];
923 if ( fabs( v[0] - check[0] ) < UNIQUE_EPSILON
924 && fabs( v[1] - check[1] ) < UNIQUE_EPSILON
925 && fabs( v[2] - check[2] ) < UNIQUE_EPSILON ) {
929 if ( numUniqued == maxUniqued ) {
930 common->
Error(
"FindUniqueVert: numUniqued == maxUniqued" );
932 uniqued[numUniqued] =
v;
947 static void UniqueVerts(
void ) {
956 for ( i = 0 ; i < numOutputTris ; i++ ) {
957 for ( j = 0 ; j < 3 ; j++ ) {
958 outputTris[
i].
index[
j] = FindUniqueVert( outputTris[i].v[j] );
968 static void ProjectUniqued(
idVec3 projectionOrigin,
idPlane projectionPlane ) {
974 if ( numUniqued * 2 > maxUniqued ) {
975 common->
Error(
"ProjectUniqued: numUniqued * 2 > maxUniqued" );
980 for (
int i = 0 ; i < numUniqued ; i++ ) {
982 idVec3 in = uniqued[
i] + projectionOrigin;
988 w = in * mat[3].
ToVec3() + mat[3][3];
991 out.
x = ( in * mat[0].
ToVec3() + mat[0][3] ) * oow;
992 out.
y = ( in * mat[1].
ToVec3() + mat[1][3] ) * oow;
993 out.
z = ( in * mat[2].
ToVec3() + mat[2][3] ) * oow;
995 uniqued[numUniqued+
i] = out - projectionOrigin;
1012 memset( &ret, 0,
sizeof( ret ) );
1015 ClipOccluders( verts, indexes, numIndexes, projectionOrigin );
1018 OptimizeOutputTris();
1029 numUniquedBeforeProjection = numUniqued;
1030 ProjectUniqued( projectionOrigin, projectionPlane );
1052 for (
int i = 0 ; i < numOutputTris ; i++ ) {
1058 ret.
indexes[(numOutputTris+
i)*3+0] = numUniquedBeforeProjection + outputTris[i].index[0];
1059 ret.
indexes[(numOutputTris+
i)*3+1] = numUniquedBeforeProjection + outputTris[i].index[1];
1060 ret.
indexes[(numOutputTris+
i)*3+2] = numUniquedBeforeProjection + outputTris[i].index[2];
1067 EmitFragmentedSilQuads();
1070 EmitUnoptimizedSilEdges();
1077 for (
int i = 0 ; i < numUniqued ; i++ ) {
1079 ret.
verts[
i] = uniqued[
i] + projectionOrigin;
1107 if ( a == b || a == c || b == c ) {
1111 if ( i < tri->numShadowIndexesNoCaps ) {
1114 if ( i < tri->numShadowIndexesNoFrontCaps ) {
1124 common->
Printf(
"removed %i degenerate triangles from shadow\n", c_removed );
1142 uniqued = (
idVec3 *)_alloca(
sizeof( *uniqued ) * maxUniqued );
1149 common->
Error(
"CleanupOptimizedShadowTris: index out of range" );
1153 for ( i = 0 ; i < tri->
numVerts ; i++ ) {
1157 for ( i = 0 ; i < tri->
numVerts ; i++ ) {
1168 for (
int i = 0 ; i < numSilIndexes ; i+=6 ) {
1170 for ( j = i+6 ; j < numSilIndexes ; j+=6 ) {
1183 if ( j == numSilIndexes ) {
1188 for ( k = i+6 ; k <
j ; k++ ) {
1192 for ( k = j+6 ; k < tri->
numIndexes ; k++ ) {
1195 numSilIndexes -= 12;
1207 RemoveDegenerateTriangles( tri );
1222 common->
Printf(
"----- CreateLightShadow %p -----\n", light );
1256 memset( &cullInfo, 0,
sizeof( cullInfo ) );
void CleanupOptimizedShadowTris(srfTriangles_t *tri)
int numShadowIndexesNoFrontCaps
const idVec3 & Normal(void) const
void GenerateSilPlanes(void)
float Distance(const idVec3 &v) const
void R_LightProjectionMatrix(const idVec3 &origin, const idPlane &rearPlane, idVec4 mat[4])
int FindFloatPlane(const idPlane &plane, bool *fixedDegeneracies=NULL)
const idVec4 & ToVec4(void) const
shadowOptLevel_t shadowOptLevel
idVec3 Cross(const idVec3 &a) const
mapTri_t * MergeTriLists(mapTri_t *a, mapTri_t *b)
void FreeTriList(mapTri_t *a)
void OptimizeGroupList(optimizeGroup_t *groupList)
GLfloat GLfloat GLfloat v2
int GetNumPoints(void) const
GLubyte GLubyte GLubyte GLubyte w
mapTri_t * CopyTriList(const mapTri_t *a)
void R_CleanupTriangles(srfTriangles_t *tri, bool createNormals, bool identifySilEdges, bool useUnsmoothedTangents)
void FreeOptimizeGroupList(optimizeGroup_t *groups)
void R_FreeStaticTriSurf(srfTriangles_t *tri)
struct silQuad_s * nextQuad
optimizedShadow_t SuperOptimizeOccluders(idVec4 *verts, glIndex_t *indexes, int numIndexes, idPlane projectionPlane, idVec3 projectionOrigin)
shadowCache_t * shadowVertexes
srfTriangles_t * ShareMapTriVerts(const mapTri_t *tris)
GLubyte GLubyte GLubyte a
virtual void Printf(const char *fmt,...) id_attribute((format(printf
struct shadowOptEdge_s * nextEdge
struct silQuad_s silQuad_t
srfTriangles_t * R_CreateShadowVolume(const idRenderEntityLocal *ent, const srfTriangles_t *tri, const idRenderLightLocal *light, shadowGen_t optimize, srfCullInfo_t &cullInfo)
int numShadowIndexesNoCaps
int Split(const idPlane &plane, const float epsilon, idWinding **front, idWinding **back) const
silQuad_t * fragmentedQuads
struct optimizeGroup_s * nextGroup
void * Mem_ClearedAlloc(const int size)
void R_FreeInteractionCullInfo(srfCullInfo_t &cullInfo)
const idVec3 & ToVec3(void) const
void * Mem_Alloc(const int size)
srfTriangles_t * CreateLightShadow(optimizeGroup_t *shadowerGroups, const mapLight_t *light)
dmapGlobals_t dmapGlobals
virtual void Error(const char *fmt,...) id_attribute((format(printf
struct shadowOptEdge_s shadowOptEdge_t