aboutsummaryrefslogtreecommitdiff
path: root/mp/src/utils/vrad/vismat.cpp
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /mp/src/utils/vrad/vismat.cpp
parentMark some more files as text. (diff)
downloadsource-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz
source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/utils/vrad/vismat.cpp')
-rw-r--r--mp/src/utils/vrad/vismat.cpp966
1 files changed, 483 insertions, 483 deletions
diff --git a/mp/src/utils/vrad/vismat.cpp b/mp/src/utils/vrad/vismat.cpp
index 7491f69f..ca9398ec 100644
--- a/mp/src/utils/vrad/vismat.cpp
+++ b/mp/src/utils/vrad/vismat.cpp
@@ -1,483 +1,483 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//
-//=============================================================================//
-
-#include "vrad.h"
-#include "vmpi.h"
-#ifdef MPI
-#include "messbuf.h"
-static MessageBuffer mb;
-#endif
-
-#define HALFBIT
-
-extern char source[MAX_PATH];
-extern char vismatfile[_MAX_PATH];
-extern char incrementfile[_MAX_PATH];
-extern qboolean incremental;
-
-/*
-===================================================================
-
-VISIBILITY MATRIX
-
-Determine which patches can see each other
-Use the PVS to accelerate if available
-===================================================================
-*/
-
-#define TEST_EPSILON 0.1
-#define PLANE_TEST_EPSILON 0.01 // patch must be this much in front of the plane to be considered "in front"
-#define PATCH_FACE_OFFSET 0.1 // push patch origins off from the face by this amount to avoid self collisions
-
-#define STREAM_SIZE 512
-
-class CTransferMaker
-{
-public:
-
- CTransferMaker( transfer_t *all_transfers );
- ~CTransferMaker();
-
- FORCEINLINE void TestMakeTransfer( Vector start, Vector stop, int ndxShooter, int ndxReciever )
- {
- g_RtEnv.AddToRayStream( m_RayStream, start, stop, &m_pResults[m_nTests] );
- m_pShooterPatches[m_nTests] = ndxShooter;
- m_pRecieverPatches[m_nTests] = ndxReciever;
- ++m_nTests;
- }
-
- void Finish();
-
-private:
-
- int m_nTests;
- RayTracingSingleResult *m_pResults;
- int *m_pShooterPatches;
- int *m_pRecieverPatches;
- RayStream m_RayStream;
- transfer_t *m_AllTransfers;
-};
-
-CTransferMaker::CTransferMaker( transfer_t *all_transfers ) :
- m_AllTransfers( all_transfers ), m_nTests( 0 )
-{
- m_pResults = (RayTracingSingleResult *)calloc( 1, MAX_PATCHES * sizeof ( RayTracingSingleResult ) );
- m_pShooterPatches = (int *)calloc( 1, MAX_PATCHES * sizeof( int ) );
- m_pRecieverPatches = (int *)calloc( 1, MAX_PATCHES * sizeof( int ) );
-}
-
-CTransferMaker::~CTransferMaker()
-{
- free ( m_pResults );
- free ( m_pShooterPatches );
- free (m_pRecieverPatches );
-}
-
-void CTransferMaker::Finish()
-{
- g_RtEnv.FinishRayStream( m_RayStream );
- for ( int i = 0; i < m_nTests; ++i )
- {
- if ( m_pResults[i].HitID == -1 || m_pResults[i].HitDistance >= m_pResults[i].ray_length )
- {
- MakeTransfer( m_pShooterPatches[i], m_pRecieverPatches[i], m_AllTransfers );
- }
- }
- m_nTests = 0;
-}
-
-
-dleaf_t* PointInLeaf (int iNode, Vector const& point)
-{
- if ( iNode < 0 )
- return &dleafs[ (-1-iNode) ];
-
- dnode_t *node = &dnodes[iNode];
- dplane_t *plane = &dplanes[ node->planenum ];
-
- float dist = DotProduct (point, plane->normal) - plane->dist;
- if ( dist > TEST_EPSILON )
- {
- return PointInLeaf( node->children[0], point );
- }
- else if ( dist < -TEST_EPSILON )
- {
- return PointInLeaf( node->children[1], point );
- }
- else
- {
- dleaf_t *pTest = PointInLeaf( node->children[0], point );
- if ( pTest->cluster != -1 )
- return pTest;
-
- return PointInLeaf( node->children[1], point );
- }
-}
-
-
-int ClusterFromPoint( Vector const& point )
-{
- dleaf_t *leaf = PointInLeaf( 0, point );
-
- return leaf->cluster;
-}
-
-void PvsForOrigin (Vector& org, byte *pvs)
-{
- int visofs;
- int cluster;
-
- if (!visdatasize)
- {
- memset (pvs, 255, (dvis->numclusters+7)/8 );
- return;
- }
-
- cluster = ClusterFromPoint( org );
- if ( cluster < 0 )
- {
- visofs = -1;
- }
- else
- {
- visofs = dvis->bitofs[ cluster ][DVIS_PVS];
- }
-
- if (visofs == -1)
- Error ("visofs == -1");
-
- DecompressVis (&dvisdata[visofs], pvs);
-}
-
-
-void TestPatchToPatch( int ndxPatch1, int ndxPatch2, int head, transfer_t *transfers, CTransferMaker &transferMaker, int iThread )
-{
- Vector tmp;
-
- //
- // get patches
- //
- if( ndxPatch1 == g_Patches.InvalidIndex() || ndxPatch2 == g_Patches.InvalidIndex() )
- return;
-
- CPatch *patch = &g_Patches.Element( ndxPatch1 );
- CPatch *patch2 = &g_Patches.Element( ndxPatch2 );
-
- if (patch2->child1 != g_Patches.InvalidIndex() )
- {
- // check to see if we should use a child node instead
-
- VectorSubtract( patch->origin, patch2->origin, tmp );
- // SQRT( 1/4 )
- // FIXME: should be based on form-factor (ie. include visible angle, etc)
- if ( DotProduct(tmp, tmp) * 0.0625 < patch2->area )
- {
- TestPatchToPatch( ndxPatch1, patch2->child1, head, transfers, transferMaker, iThread );
- TestPatchToPatch( ndxPatch1, patch2->child2, head, transfers, transferMaker, iThread );
- return;
- }
- }
-
- // check vis between patch and patch2
- // if bit has not already been set
- // && v2 is not behind light plane
- // && v2 is visible from v1
- if ( DotProduct( patch2->origin, patch->normal ) > patch->planeDist + PLANE_TEST_EPSILON )
- {
- // push out origins from face so that don't intersect their owners
- Vector p1, p2;
- VectorAdd( patch->origin, patch->normal, p1 );
- VectorAdd( patch2->origin, patch2->normal, p2 );
- transferMaker.TestMakeTransfer( p1, p2, ndxPatch1, ndxPatch2 );
- }
-}
-
-
-/*
-==============
-TestPatchToFace
-
-Sets vis bits for all patches in the face
-==============
-*/
-void TestPatchToFace (unsigned patchnum, int facenum, int head, transfer_t *transfers, CTransferMaker &transferMaker, int iThread )
-{
- if( faceParents.Element( facenum ) == g_Patches.InvalidIndex() || patchnum == g_Patches.InvalidIndex() )
- return;
-
- CPatch *patch = &g_Patches.Element( patchnum );
- CPatch *patch2 = &g_Patches.Element( faceParents.Element( facenum ) );
-
- // if emitter is behind that face plane, skip all patches
-
- CPatch *pNextPatch;
-
- if ( patch2 && DotProduct(patch->origin, patch2->normal) > patch2->planeDist + PLANE_TEST_EPSILON )
- {
- // we need to do a real test
- for( ; patch2; patch2 = pNextPatch )
- {
- // next patch
- pNextPatch = NULL;
- if( patch2->ndxNextParent != g_Patches.InvalidIndex() )
- {
- pNextPatch = &g_Patches.Element( patch2->ndxNextParent );
- }
-
- /*
- // skip patches too far away
- VectorSubtract( patch->origin, patch2->origin, tmp );
- if (DotProduct( tmp, tmp ) > 512 * 512)
- continue;
- */
-
- int ndxPatch2 = patch2 - g_Patches.Base();
- TestPatchToPatch( patchnum, ndxPatch2, head, transfers, transferMaker, iThread );
- }
- }
-}
-
-
-struct ClusterDispList_t
-{
- CUtlVector<int> dispFaces;
-};
-
-static CUtlVector<ClusterDispList_t> g_ClusterDispFaces;
-
-//-----------------------------------------------------------------------------
-// Helps us find all displacements associated with a particular cluster
-//-----------------------------------------------------------------------------
-void AddDispsToClusterTable( void )
-{
- g_ClusterDispFaces.SetCount( g_ClusterLeaves.Count() );
-
- //
- // add displacement faces to the cluster table
- //
- for( int ndxFace = 0; ndxFace < numfaces; ndxFace++ )
- {
- // search for displacement faces
- if( g_pFaces[ndxFace].dispinfo == -1 )
- continue;
-
- //
- // get the clusters associated with the face
- //
- if( g_FacePatches.Element( ndxFace ) != g_FacePatches.InvalidIndex() )
- {
- CPatch *pNextPatch = NULL;
- for( CPatch *pPatch = &g_Patches.Element( g_FacePatches.Element( ndxFace ) ); pPatch; pPatch = pNextPatch )
- {
- // next patch
- pNextPatch = NULL;
- if( pPatch->ndxNext != g_Patches.InvalidIndex() )
- {
- pNextPatch = &g_Patches.Element( pPatch->ndxNext );
- }
-
- if( pPatch->clusterNumber != g_Patches.InvalidIndex() )
- {
- int ndxDisp = g_ClusterDispFaces[pPatch->clusterNumber].dispFaces.Find( ndxFace );
- if( ndxDisp == -1 )
- {
- ndxDisp = g_ClusterDispFaces[pPatch->clusterNumber].dispFaces.AddToTail();
- g_ClusterDispFaces[pPatch->clusterNumber].dispFaces[ndxDisp] = ndxFace;
- }
- }
- }
- }
- }
-}
-
-
-/*
-==============
-BuildVisRow
-
-Calc vis bits from a single patch
-==============
-*/
-void BuildVisRow (int patchnum, byte *pvs, int head, transfer_t *transfers, CTransferMaker &transferMaker, int iThread )
-{
- int j, k, l, leafIndex;
- CPatch *patch;
- dleaf_t *leaf;
- byte face_tested[MAX_MAP_FACES];
- byte disp_tested[MAX_MAP_FACES];
-
- patch = &g_Patches.Element( patchnum );
-
- memset( face_tested, 0, numfaces ) ;
- memset( disp_tested, 0, numfaces );
-
- for (j=0; j<dvis->numclusters; j++)
- {
- if ( ! ( pvs[(j)>>3] & (1<<((j)&7)) ) )
- {
- continue; // not in pvs
- }
-
- for ( leafIndex = 0; leafIndex < g_ClusterLeaves[j].leafCount; leafIndex++ )
- {
- leaf = dleafs + g_ClusterLeaves[j].leafs[leafIndex];
-
- for (k=0 ; k<leaf->numleaffaces; k++)
- {
- l = dleaffaces[leaf->firstleafface + k];
- // faces can be marksurfed by multiple leaves, but
- // don't bother testing again
- if (face_tested[l])
- {
- continue;
- }
- face_tested[l] = 1;
-
- // don't check patches on the same face
- if (patch->faceNumber == l)
- continue;
- TestPatchToFace (patchnum, l, head, transfers, transferMaker, iThread );
- }
- }
-
- int dispCount = g_ClusterDispFaces[j].dispFaces.Size();
- for( int ndxDisp = 0; ndxDisp < dispCount; ndxDisp++ )
- {
- int ndxFace = g_ClusterDispFaces[j].dispFaces[ndxDisp];
- if( disp_tested[ndxFace] )
- continue;
-
- disp_tested[ndxFace] = 1;
-
- // don't check patches on the same face
- if( patch->faceNumber == ndxFace )
- continue;
-
- TestPatchToFace( patchnum, ndxFace, head, transfers, transferMaker, iThread );
- }
- }
-
-
- // Msg("%d) Transfers: %5d\n", patchnum, patch->numtransfers);
-}
-
-
-
-/*
-===========
-BuildVisLeafs
-
- This is run by multiple threads
-===========
-*/
-
-transfer_t* BuildVisLeafs_Start()
-{
- return (transfer_t *)calloc( 1, MAX_PATCHES * sizeof( transfer_t ) );
-}
-
-
-// If PatchCB is non-null, it is called after each row is generated (used by MPI).
-void BuildVisLeafs_Cluster(
- int threadnum,
- transfer_t *transfers,
- int iCluster,
- void (*PatchCB)(int iThread, int patchnum, CPatch *patch)
- )
-{
- byte pvs[(MAX_MAP_CLUSTERS+7)/8];
- CPatch *patch;
- int head;
- unsigned patchnum;
-
- DecompressVis( &dvisdata[ dvis->bitofs[ iCluster ][DVIS_PVS] ], pvs);
- head = 0;
-
- CTransferMaker transferMaker( transfers );
-
- // light every patch in the cluster
- if( clusterChildren.Element( iCluster ) != clusterChildren.InvalidIndex() )
- {
- CPatch *pNextPatch;
- for( patch = &g_Patches.Element( clusterChildren.Element( iCluster ) ); patch; patch = pNextPatch )
- {
- //
- // next patch
- //
- pNextPatch = NULL;
- if( patch->ndxNextClusterChild != g_Patches.InvalidIndex() )
- {
- pNextPatch = &g_Patches.Element( patch->ndxNextClusterChild );
- }
-
- patchnum = patch - g_Patches.Base();
-
- // build to all other world clusters
- BuildVisRow (patchnum, pvs, head, transfers, transferMaker, threadnum );
- transferMaker.Finish();
-
- // do the transfers
- MakeScales( patchnum, transfers );
-
- // Let MPI aggregate the data if it's being used.
- if ( PatchCB )
- PatchCB( threadnum, patchnum, patch );
- }
- }
-}
-
-
-void BuildVisLeafs_End( transfer_t *transfers )
-{
- free( transfers );
-}
-
-
-void BuildVisLeafs( int threadnum, void *pUserData )
-{
- transfer_t *transfers = BuildVisLeafs_Start();
-
- while ( 1 )
- {
- //
- // build a minimal BSP tree that only
- // covers areas relevent to the PVS
- //
- // JAY: Now this returns a cluster index
- int iCluster = GetThreadWork();
- if ( iCluster == -1 )
- break;
-
- BuildVisLeafs_Cluster( threadnum, transfers, iCluster, NULL );
- }
-
- BuildVisLeafs_End( transfers );
-}
-
-
-/*
-==============
-BuildVisMatrix
-==============
-*/
-void BuildVisMatrix (void)
-{
- if ( g_bUseMPI )
- {
- RunMPIBuildVisLeafs();
- }
- else
- {
- RunThreadsOn (dvis->numclusters, true, BuildVisLeafs);
- }
-}
-
-void FreeVisMatrix (void)
-{
-
-}
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+
+#include "vrad.h"
+#include "vmpi.h"
+#ifdef MPI
+#include "messbuf.h"
+static MessageBuffer mb;
+#endif
+
+#define HALFBIT
+
+extern char source[MAX_PATH];
+extern char vismatfile[_MAX_PATH];
+extern char incrementfile[_MAX_PATH];
+extern qboolean incremental;
+
+/*
+===================================================================
+
+VISIBILITY MATRIX
+
+Determine which patches can see each other
+Use the PVS to accelerate if available
+===================================================================
+*/
+
+#define TEST_EPSILON 0.1
+#define PLANE_TEST_EPSILON 0.01 // patch must be this much in front of the plane to be considered "in front"
+#define PATCH_FACE_OFFSET 0.1 // push patch origins off from the face by this amount to avoid self collisions
+
+#define STREAM_SIZE 512
+
+class CTransferMaker
+{
+public:
+
+ CTransferMaker( transfer_t *all_transfers );
+ ~CTransferMaker();
+
+ FORCEINLINE void TestMakeTransfer( Vector start, Vector stop, int ndxShooter, int ndxReciever )
+ {
+ g_RtEnv.AddToRayStream( m_RayStream, start, stop, &m_pResults[m_nTests] );
+ m_pShooterPatches[m_nTests] = ndxShooter;
+ m_pRecieverPatches[m_nTests] = ndxReciever;
+ ++m_nTests;
+ }
+
+ void Finish();
+
+private:
+
+ int m_nTests;
+ RayTracingSingleResult *m_pResults;
+ int *m_pShooterPatches;
+ int *m_pRecieverPatches;
+ RayStream m_RayStream;
+ transfer_t *m_AllTransfers;
+};
+
+CTransferMaker::CTransferMaker( transfer_t *all_transfers ) :
+ m_AllTransfers( all_transfers ), m_nTests( 0 )
+{
+ m_pResults = (RayTracingSingleResult *)calloc( 1, MAX_PATCHES * sizeof ( RayTracingSingleResult ) );
+ m_pShooterPatches = (int *)calloc( 1, MAX_PATCHES * sizeof( int ) );
+ m_pRecieverPatches = (int *)calloc( 1, MAX_PATCHES * sizeof( int ) );
+}
+
+CTransferMaker::~CTransferMaker()
+{
+ free ( m_pResults );
+ free ( m_pShooterPatches );
+ free (m_pRecieverPatches );
+}
+
+void CTransferMaker::Finish()
+{
+ g_RtEnv.FinishRayStream( m_RayStream );
+ for ( int i = 0; i < m_nTests; ++i )
+ {
+ if ( m_pResults[i].HitID == -1 || m_pResults[i].HitDistance >= m_pResults[i].ray_length )
+ {
+ MakeTransfer( m_pShooterPatches[i], m_pRecieverPatches[i], m_AllTransfers );
+ }
+ }
+ m_nTests = 0;
+}
+
+
+dleaf_t* PointInLeaf (int iNode, Vector const& point)
+{
+ if ( iNode < 0 )
+ return &dleafs[ (-1-iNode) ];
+
+ dnode_t *node = &dnodes[iNode];
+ dplane_t *plane = &dplanes[ node->planenum ];
+
+ float dist = DotProduct (point, plane->normal) - plane->dist;
+ if ( dist > TEST_EPSILON )
+ {
+ return PointInLeaf( node->children[0], point );
+ }
+ else if ( dist < -TEST_EPSILON )
+ {
+ return PointInLeaf( node->children[1], point );
+ }
+ else
+ {
+ dleaf_t *pTest = PointInLeaf( node->children[0], point );
+ if ( pTest->cluster != -1 )
+ return pTest;
+
+ return PointInLeaf( node->children[1], point );
+ }
+}
+
+
+int ClusterFromPoint( Vector const& point )
+{
+ dleaf_t *leaf = PointInLeaf( 0, point );
+
+ return leaf->cluster;
+}
+
+void PvsForOrigin (Vector& org, byte *pvs)
+{
+ int visofs;
+ int cluster;
+
+ if (!visdatasize)
+ {
+ memset (pvs, 255, (dvis->numclusters+7)/8 );
+ return;
+ }
+
+ cluster = ClusterFromPoint( org );
+ if ( cluster < 0 )
+ {
+ visofs = -1;
+ }
+ else
+ {
+ visofs = dvis->bitofs[ cluster ][DVIS_PVS];
+ }
+
+ if (visofs == -1)
+ Error ("visofs == -1");
+
+ DecompressVis (&dvisdata[visofs], pvs);
+}
+
+
+void TestPatchToPatch( int ndxPatch1, int ndxPatch2, int head, transfer_t *transfers, CTransferMaker &transferMaker, int iThread )
+{
+ Vector tmp;
+
+ //
+ // get patches
+ //
+ if( ndxPatch1 == g_Patches.InvalidIndex() || ndxPatch2 == g_Patches.InvalidIndex() )
+ return;
+
+ CPatch *patch = &g_Patches.Element( ndxPatch1 );
+ CPatch *patch2 = &g_Patches.Element( ndxPatch2 );
+
+ if (patch2->child1 != g_Patches.InvalidIndex() )
+ {
+ // check to see if we should use a child node instead
+
+ VectorSubtract( patch->origin, patch2->origin, tmp );
+ // SQRT( 1/4 )
+ // FIXME: should be based on form-factor (ie. include visible angle, etc)
+ if ( DotProduct(tmp, tmp) * 0.0625 < patch2->area )
+ {
+ TestPatchToPatch( ndxPatch1, patch2->child1, head, transfers, transferMaker, iThread );
+ TestPatchToPatch( ndxPatch1, patch2->child2, head, transfers, transferMaker, iThread );
+ return;
+ }
+ }
+
+ // check vis between patch and patch2
+ // if bit has not already been set
+ // && v2 is not behind light plane
+ // && v2 is visible from v1
+ if ( DotProduct( patch2->origin, patch->normal ) > patch->planeDist + PLANE_TEST_EPSILON )
+ {
+ // push out origins from face so that don't intersect their owners
+ Vector p1, p2;
+ VectorAdd( patch->origin, patch->normal, p1 );
+ VectorAdd( patch2->origin, patch2->normal, p2 );
+ transferMaker.TestMakeTransfer( p1, p2, ndxPatch1, ndxPatch2 );
+ }
+}
+
+
+/*
+==============
+TestPatchToFace
+
+Sets vis bits for all patches in the face
+==============
+*/
+void TestPatchToFace (unsigned patchnum, int facenum, int head, transfer_t *transfers, CTransferMaker &transferMaker, int iThread )
+{
+ if( faceParents.Element( facenum ) == g_Patches.InvalidIndex() || patchnum == g_Patches.InvalidIndex() )
+ return;
+
+ CPatch *patch = &g_Patches.Element( patchnum );
+ CPatch *patch2 = &g_Patches.Element( faceParents.Element( facenum ) );
+
+ // if emitter is behind that face plane, skip all patches
+
+ CPatch *pNextPatch;
+
+ if ( patch2 && DotProduct(patch->origin, patch2->normal) > patch2->planeDist + PLANE_TEST_EPSILON )
+ {
+ // we need to do a real test
+ for( ; patch2; patch2 = pNextPatch )
+ {
+ // next patch
+ pNextPatch = NULL;
+ if( patch2->ndxNextParent != g_Patches.InvalidIndex() )
+ {
+ pNextPatch = &g_Patches.Element( patch2->ndxNextParent );
+ }
+
+ /*
+ // skip patches too far away
+ VectorSubtract( patch->origin, patch2->origin, tmp );
+ if (DotProduct( tmp, tmp ) > 512 * 512)
+ continue;
+ */
+
+ int ndxPatch2 = patch2 - g_Patches.Base();
+ TestPatchToPatch( patchnum, ndxPatch2, head, transfers, transferMaker, iThread );
+ }
+ }
+}
+
+
+struct ClusterDispList_t
+{
+ CUtlVector<int> dispFaces;
+};
+
+static CUtlVector<ClusterDispList_t> g_ClusterDispFaces;
+
+//-----------------------------------------------------------------------------
+// Helps us find all displacements associated with a particular cluster
+//-----------------------------------------------------------------------------
+void AddDispsToClusterTable( void )
+{
+ g_ClusterDispFaces.SetCount( g_ClusterLeaves.Count() );
+
+ //
+ // add displacement faces to the cluster table
+ //
+ for( int ndxFace = 0; ndxFace < numfaces; ndxFace++ )
+ {
+ // search for displacement faces
+ if( g_pFaces[ndxFace].dispinfo == -1 )
+ continue;
+
+ //
+ // get the clusters associated with the face
+ //
+ if( g_FacePatches.Element( ndxFace ) != g_FacePatches.InvalidIndex() )
+ {
+ CPatch *pNextPatch = NULL;
+ for( CPatch *pPatch = &g_Patches.Element( g_FacePatches.Element( ndxFace ) ); pPatch; pPatch = pNextPatch )
+ {
+ // next patch
+ pNextPatch = NULL;
+ if( pPatch->ndxNext != g_Patches.InvalidIndex() )
+ {
+ pNextPatch = &g_Patches.Element( pPatch->ndxNext );
+ }
+
+ if( pPatch->clusterNumber != g_Patches.InvalidIndex() )
+ {
+ int ndxDisp = g_ClusterDispFaces[pPatch->clusterNumber].dispFaces.Find( ndxFace );
+ if( ndxDisp == -1 )
+ {
+ ndxDisp = g_ClusterDispFaces[pPatch->clusterNumber].dispFaces.AddToTail();
+ g_ClusterDispFaces[pPatch->clusterNumber].dispFaces[ndxDisp] = ndxFace;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/*
+==============
+BuildVisRow
+
+Calc vis bits from a single patch
+==============
+*/
+void BuildVisRow (int patchnum, byte *pvs, int head, transfer_t *transfers, CTransferMaker &transferMaker, int iThread )
+{
+ int j, k, l, leafIndex;
+ CPatch *patch;
+ dleaf_t *leaf;
+ byte face_tested[MAX_MAP_FACES];
+ byte disp_tested[MAX_MAP_FACES];
+
+ patch = &g_Patches.Element( patchnum );
+
+ memset( face_tested, 0, numfaces ) ;
+ memset( disp_tested, 0, numfaces );
+
+ for (j=0; j<dvis->numclusters; j++)
+ {
+ if ( ! ( pvs[(j)>>3] & (1<<((j)&7)) ) )
+ {
+ continue; // not in pvs
+ }
+
+ for ( leafIndex = 0; leafIndex < g_ClusterLeaves[j].leafCount; leafIndex++ )
+ {
+ leaf = dleafs + g_ClusterLeaves[j].leafs[leafIndex];
+
+ for (k=0 ; k<leaf->numleaffaces; k++)
+ {
+ l = dleaffaces[leaf->firstleafface + k];
+ // faces can be marksurfed by multiple leaves, but
+ // don't bother testing again
+ if (face_tested[l])
+ {
+ continue;
+ }
+ face_tested[l] = 1;
+
+ // don't check patches on the same face
+ if (patch->faceNumber == l)
+ continue;
+ TestPatchToFace (patchnum, l, head, transfers, transferMaker, iThread );
+ }
+ }
+
+ int dispCount = g_ClusterDispFaces[j].dispFaces.Size();
+ for( int ndxDisp = 0; ndxDisp < dispCount; ndxDisp++ )
+ {
+ int ndxFace = g_ClusterDispFaces[j].dispFaces[ndxDisp];
+ if( disp_tested[ndxFace] )
+ continue;
+
+ disp_tested[ndxFace] = 1;
+
+ // don't check patches on the same face
+ if( patch->faceNumber == ndxFace )
+ continue;
+
+ TestPatchToFace( patchnum, ndxFace, head, transfers, transferMaker, iThread );
+ }
+ }
+
+
+ // Msg("%d) Transfers: %5d\n", patchnum, patch->numtransfers);
+}
+
+
+
+/*
+===========
+BuildVisLeafs
+
+ This is run by multiple threads
+===========
+*/
+
+transfer_t* BuildVisLeafs_Start()
+{
+ return (transfer_t *)calloc( 1, MAX_PATCHES * sizeof( transfer_t ) );
+}
+
+
+// If PatchCB is non-null, it is called after each row is generated (used by MPI).
+void BuildVisLeafs_Cluster(
+ int threadnum,
+ transfer_t *transfers,
+ int iCluster,
+ void (*PatchCB)(int iThread, int patchnum, CPatch *patch)
+ )
+{
+ byte pvs[(MAX_MAP_CLUSTERS+7)/8];
+ CPatch *patch;
+ int head;
+ unsigned patchnum;
+
+ DecompressVis( &dvisdata[ dvis->bitofs[ iCluster ][DVIS_PVS] ], pvs);
+ head = 0;
+
+ CTransferMaker transferMaker( transfers );
+
+ // light every patch in the cluster
+ if( clusterChildren.Element( iCluster ) != clusterChildren.InvalidIndex() )
+ {
+ CPatch *pNextPatch;
+ for( patch = &g_Patches.Element( clusterChildren.Element( iCluster ) ); patch; patch = pNextPatch )
+ {
+ //
+ // next patch
+ //
+ pNextPatch = NULL;
+ if( patch->ndxNextClusterChild != g_Patches.InvalidIndex() )
+ {
+ pNextPatch = &g_Patches.Element( patch->ndxNextClusterChild );
+ }
+
+ patchnum = patch - g_Patches.Base();
+
+ // build to all other world clusters
+ BuildVisRow (patchnum, pvs, head, transfers, transferMaker, threadnum );
+ transferMaker.Finish();
+
+ // do the transfers
+ MakeScales( patchnum, transfers );
+
+ // Let MPI aggregate the data if it's being used.
+ if ( PatchCB )
+ PatchCB( threadnum, patchnum, patch );
+ }
+ }
+}
+
+
+void BuildVisLeafs_End( transfer_t *transfers )
+{
+ free( transfers );
+}
+
+
+void BuildVisLeafs( int threadnum, void *pUserData )
+{
+ transfer_t *transfers = BuildVisLeafs_Start();
+
+ while ( 1 )
+ {
+ //
+ // build a minimal BSP tree that only
+ // covers areas relevent to the PVS
+ //
+ // JAY: Now this returns a cluster index
+ int iCluster = GetThreadWork();
+ if ( iCluster == -1 )
+ break;
+
+ BuildVisLeafs_Cluster( threadnum, transfers, iCluster, NULL );
+ }
+
+ BuildVisLeafs_End( transfers );
+}
+
+
+/*
+==============
+BuildVisMatrix
+==============
+*/
+void BuildVisMatrix (void)
+{
+ if ( g_bUseMPI )
+ {
+ RunMPIBuildVisLeafs();
+ }
+ else
+ {
+ RunThreadsOn (dvis->numclusters, true, BuildVisLeafs);
+ }
+}
+
+void FreeVisMatrix (void)
+{
+
+}