Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

483 lines
11 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "vrad.h"
  9. #include "vmpi.h"
  10. #ifdef MPI
  11. #include "messbuf.h"
  12. static MessageBuffer mb;
  13. #endif
  14. #define HALFBIT
  15. extern char source[MAX_PATH];
  16. extern char vismatfile[_MAX_PATH];
  17. extern char incrementfile[_MAX_PATH];
  18. extern qboolean incremental;
  19. /*
  20. ===================================================================
  21. VISIBILITY MATRIX
  22. Determine which patches can see each other
  23. Use the PVS to accelerate if available
  24. ===================================================================
  25. */
  26. #define TEST_EPSILON 0.1
  27. #define PLANE_TEST_EPSILON 0.01 // patch must be this much in front of the plane to be considered "in front"
  28. #define PATCH_FACE_OFFSET 0.1 // push patch origins off from the face by this amount to avoid self collisions
  29. #define STREAM_SIZE 512
  30. class CTransferMaker
  31. {
  32. public:
  33. CTransferMaker( transfer_t *all_transfers );
  34. ~CTransferMaker();
  35. FORCEINLINE void TestMakeTransfer( Vector start, Vector stop, int ndxShooter, int ndxReciever )
  36. {
  37. g_RtEnv.AddToRayStream( m_RayStream, start, stop, &m_pResults[m_nTests] );
  38. m_pShooterPatches[m_nTests] = ndxShooter;
  39. m_pRecieverPatches[m_nTests] = ndxReciever;
  40. ++m_nTests;
  41. }
  42. void Finish();
  43. private:
  44. int m_nTests;
  45. RayTracingSingleResult *m_pResults;
  46. int *m_pShooterPatches;
  47. int *m_pRecieverPatches;
  48. RayStream m_RayStream;
  49. transfer_t *m_AllTransfers;
  50. };
  51. CTransferMaker::CTransferMaker( transfer_t *all_transfers ) :
  52. m_AllTransfers( all_transfers ), m_nTests( 0 )
  53. {
  54. m_pResults = (RayTracingSingleResult *)calloc( 1, MAX_PATCHES * sizeof ( RayTracingSingleResult ) );
  55. m_pShooterPatches = (int *)calloc( 1, MAX_PATCHES * sizeof( int ) );
  56. m_pRecieverPatches = (int *)calloc( 1, MAX_PATCHES * sizeof( int ) );
  57. }
  58. CTransferMaker::~CTransferMaker()
  59. {
  60. free ( m_pResults );
  61. free ( m_pShooterPatches );
  62. free (m_pRecieverPatches );
  63. }
  64. void CTransferMaker::Finish()
  65. {
  66. g_RtEnv.FinishRayStream( m_RayStream );
  67. for ( int i = 0; i < m_nTests; ++i )
  68. {
  69. if ( m_pResults[i].HitID == -1 || m_pResults[i].HitDistance >= m_pResults[i].ray_length )
  70. {
  71. MakeTransfer( m_pShooterPatches[i], m_pRecieverPatches[i], m_AllTransfers );
  72. }
  73. }
  74. m_nTests = 0;
  75. }
  76. dleaf_t* PointInLeaf (int iNode, Vector const& point)
  77. {
  78. if ( iNode < 0 )
  79. return &dleafs[ (-1-iNode) ];
  80. dnode_t *node = &dnodes[iNode];
  81. dplane_t *plane = &dplanes[ node->planenum ];
  82. float dist = DotProduct (point, plane->normal) - plane->dist;
  83. if ( dist > TEST_EPSILON )
  84. {
  85. return PointInLeaf( node->children[0], point );
  86. }
  87. else if ( dist < -TEST_EPSILON )
  88. {
  89. return PointInLeaf( node->children[1], point );
  90. }
  91. else
  92. {
  93. dleaf_t *pTest = PointInLeaf( node->children[0], point );
  94. if ( pTest->cluster != -1 )
  95. return pTest;
  96. return PointInLeaf( node->children[1], point );
  97. }
  98. }
  99. int ClusterFromPoint( Vector const& point )
  100. {
  101. dleaf_t *leaf = PointInLeaf( 0, point );
  102. return leaf->cluster;
  103. }
  104. void PvsForOrigin (Vector& org, byte *pvs)
  105. {
  106. int visofs;
  107. int cluster;
  108. if (!visdatasize)
  109. {
  110. memset (pvs, 255, (dvis->numclusters+7)/8 );
  111. return;
  112. }
  113. cluster = ClusterFromPoint( org );
  114. if ( cluster < 0 )
  115. {
  116. visofs = -1;
  117. }
  118. else
  119. {
  120. visofs = dvis->bitofs[ cluster ][DVIS_PVS];
  121. }
  122. if (visofs == -1)
  123. Error ("visofs == -1");
  124. DecompressVis (&dvisdata[visofs], pvs);
  125. }
  126. void TestPatchToPatch( int ndxPatch1, int ndxPatch2, int head, transfer_t *transfers, CTransferMaker &transferMaker, int iThread )
  127. {
  128. Vector tmp;
  129. //
  130. // get patches
  131. //
  132. if( ndxPatch1 == g_Patches.InvalidIndex() || ndxPatch2 == g_Patches.InvalidIndex() )
  133. return;
  134. CPatch *patch = &g_Patches.Element( ndxPatch1 );
  135. CPatch *patch2 = &g_Patches.Element( ndxPatch2 );
  136. if (patch2->child1 != g_Patches.InvalidIndex() )
  137. {
  138. // check to see if we should use a child node instead
  139. VectorSubtract( patch->origin, patch2->origin, tmp );
  140. // SQRT( 1/4 )
  141. // FIXME: should be based on form-factor (ie. include visible angle, etc)
  142. if ( DotProduct(tmp, tmp) * 0.0625 < patch2->area )
  143. {
  144. TestPatchToPatch( ndxPatch1, patch2->child1, head, transfers, transferMaker, iThread );
  145. TestPatchToPatch( ndxPatch1, patch2->child2, head, transfers, transferMaker, iThread );
  146. return;
  147. }
  148. }
  149. // check vis between patch and patch2
  150. // if bit has not already been set
  151. // && v2 is not behind light plane
  152. // && v2 is visible from v1
  153. if ( DotProduct( patch2->origin, patch->normal ) > patch->planeDist + PLANE_TEST_EPSILON )
  154. {
  155. // push out origins from face so that don't intersect their owners
  156. Vector p1, p2;
  157. VectorAdd( patch->origin, patch->normal, p1 );
  158. VectorAdd( patch2->origin, patch2->normal, p2 );
  159. transferMaker.TestMakeTransfer( p1, p2, ndxPatch1, ndxPatch2 );
  160. }
  161. }
  162. /*
  163. ==============
  164. TestPatchToFace
  165. Sets vis bits for all patches in the face
  166. ==============
  167. */
  168. void TestPatchToFace (unsigned patchnum, int facenum, int head, transfer_t *transfers, CTransferMaker &transferMaker, int iThread )
  169. {
  170. if( faceParents.Element( facenum ) == g_Patches.InvalidIndex() || patchnum == g_Patches.InvalidIndex() )
  171. return;
  172. CPatch *patch = &g_Patches.Element( patchnum );
  173. CPatch *patch2 = &g_Patches.Element( faceParents.Element( facenum ) );
  174. // if emitter is behind that face plane, skip all patches
  175. CPatch *pNextPatch;
  176. if ( patch2 && DotProduct(patch->origin, patch2->normal) > patch2->planeDist + PLANE_TEST_EPSILON )
  177. {
  178. // we need to do a real test
  179. for( ; patch2; patch2 = pNextPatch )
  180. {
  181. // next patch
  182. pNextPatch = NULL;
  183. if( patch2->ndxNextParent != g_Patches.InvalidIndex() )
  184. {
  185. pNextPatch = &g_Patches.Element( patch2->ndxNextParent );
  186. }
  187. /*
  188. // skip patches too far away
  189. VectorSubtract( patch->origin, patch2->origin, tmp );
  190. if (DotProduct( tmp, tmp ) > 512 * 512)
  191. continue;
  192. */
  193. int ndxPatch2 = patch2 - g_Patches.Base();
  194. TestPatchToPatch( patchnum, ndxPatch2, head, transfers, transferMaker, iThread );
  195. }
  196. }
  197. }
  198. struct ClusterDispList_t
  199. {
  200. CUtlVector<int> dispFaces;
  201. };
  202. static CUtlVector<ClusterDispList_t> g_ClusterDispFaces;
  203. //-----------------------------------------------------------------------------
  204. // Helps us find all displacements associated with a particular cluster
  205. //-----------------------------------------------------------------------------
  206. void AddDispsToClusterTable( void )
  207. {
  208. g_ClusterDispFaces.SetCount( g_ClusterLeaves.Count() );
  209. //
  210. // add displacement faces to the cluster table
  211. //
  212. for( int ndxFace = 0; ndxFace < numfaces; ndxFace++ )
  213. {
  214. // search for displacement faces
  215. if( g_pFaces[ndxFace].dispinfo == -1 )
  216. continue;
  217. //
  218. // get the clusters associated with the face
  219. //
  220. if( g_FacePatches.Element( ndxFace ) != g_FacePatches.InvalidIndex() )
  221. {
  222. CPatch *pNextPatch = NULL;
  223. for( CPatch *pPatch = &g_Patches.Element( g_FacePatches.Element( ndxFace ) ); pPatch; pPatch = pNextPatch )
  224. {
  225. // next patch
  226. pNextPatch = NULL;
  227. if( pPatch->ndxNext != g_Patches.InvalidIndex() )
  228. {
  229. pNextPatch = &g_Patches.Element( pPatch->ndxNext );
  230. }
  231. if( pPatch->clusterNumber != g_Patches.InvalidIndex() )
  232. {
  233. int ndxDisp = g_ClusterDispFaces[pPatch->clusterNumber].dispFaces.Find( ndxFace );
  234. if( ndxDisp == -1 )
  235. {
  236. ndxDisp = g_ClusterDispFaces[pPatch->clusterNumber].dispFaces.AddToTail();
  237. g_ClusterDispFaces[pPatch->clusterNumber].dispFaces[ndxDisp] = ndxFace;
  238. }
  239. }
  240. }
  241. }
  242. }
  243. }
  244. /*
  245. ==============
  246. BuildVisRow
  247. Calc vis bits from a single patch
  248. ==============
  249. */
  250. void BuildVisRow (int patchnum, byte *pvs, int head, transfer_t *transfers, CTransferMaker &transferMaker, int iThread )
  251. {
  252. int j, k, l, leafIndex;
  253. CPatch *patch;
  254. dleaf_t *leaf;
  255. byte face_tested[MAX_MAP_FACES];
  256. byte disp_tested[MAX_MAP_FACES];
  257. patch = &g_Patches.Element( patchnum );
  258. memset( face_tested, 0, numfaces ) ;
  259. memset( disp_tested, 0, numfaces );
  260. for (j=0; j<dvis->numclusters; j++)
  261. {
  262. if ( ! ( pvs[(j)>>3] & (1<<((j)&7)) ) )
  263. {
  264. continue; // not in pvs
  265. }
  266. for ( leafIndex = 0; leafIndex < g_ClusterLeaves[j].leafCount; leafIndex++ )
  267. {
  268. leaf = dleafs + g_ClusterLeaves[j].leafs[leafIndex];
  269. for (k=0 ; k<leaf->numleaffaces; k++)
  270. {
  271. l = dleaffaces[leaf->firstleafface + k];
  272. // faces can be marksurfed by multiple leaves, but
  273. // don't bother testing again
  274. if (face_tested[l])
  275. {
  276. continue;
  277. }
  278. face_tested[l] = 1;
  279. // don't check patches on the same face
  280. if (patch->faceNumber == l)
  281. continue;
  282. TestPatchToFace (patchnum, l, head, transfers, transferMaker, iThread );
  283. }
  284. }
  285. int dispCount = g_ClusterDispFaces[j].dispFaces.Size();
  286. for( int ndxDisp = 0; ndxDisp < dispCount; ndxDisp++ )
  287. {
  288. int ndxFace = g_ClusterDispFaces[j].dispFaces[ndxDisp];
  289. if( disp_tested[ndxFace] )
  290. continue;
  291. disp_tested[ndxFace] = 1;
  292. // don't check patches on the same face
  293. if( patch->faceNumber == ndxFace )
  294. continue;
  295. TestPatchToFace( patchnum, ndxFace, head, transfers, transferMaker, iThread );
  296. }
  297. }
  298. // Msg("%d) Transfers: %5d\n", patchnum, patch->numtransfers);
  299. }
  300. /*
  301. ===========
  302. BuildVisLeafs
  303. This is run by multiple threads
  304. ===========
  305. */
  306. transfer_t* BuildVisLeafs_Start()
  307. {
  308. return (transfer_t *)calloc( 1, MAX_PATCHES * sizeof( transfer_t ) );
  309. }
  310. // If PatchCB is non-null, it is called after each row is generated (used by MPI).
  311. void BuildVisLeafs_Cluster(
  312. int threadnum,
  313. transfer_t *transfers,
  314. int iCluster,
  315. void (*PatchCB)(int iThread, int patchnum, CPatch *patch)
  316. )
  317. {
  318. byte pvs[(MAX_MAP_CLUSTERS+7)/8];
  319. CPatch *patch;
  320. int head;
  321. unsigned patchnum;
  322. DecompressVis( &dvisdata[ dvis->bitofs[ iCluster ][DVIS_PVS] ], pvs);
  323. head = 0;
  324. CTransferMaker transferMaker( transfers );
  325. // light every patch in the cluster
  326. if( clusterChildren.Element( iCluster ) != clusterChildren.InvalidIndex() )
  327. {
  328. CPatch *pNextPatch;
  329. for( patch = &g_Patches.Element( clusterChildren.Element( iCluster ) ); patch; patch = pNextPatch )
  330. {
  331. //
  332. // next patch
  333. //
  334. pNextPatch = NULL;
  335. if( patch->ndxNextClusterChild != g_Patches.InvalidIndex() )
  336. {
  337. pNextPatch = &g_Patches.Element( patch->ndxNextClusterChild );
  338. }
  339. patchnum = patch - g_Patches.Base();
  340. // build to all other world clusters
  341. BuildVisRow (patchnum, pvs, head, transfers, transferMaker, threadnum );
  342. transferMaker.Finish();
  343. // do the transfers
  344. MakeScales( patchnum, transfers );
  345. // Let MPI aggregate the data if it's being used.
  346. if ( PatchCB )
  347. PatchCB( threadnum, patchnum, patch );
  348. }
  349. }
  350. }
  351. void BuildVisLeafs_End( transfer_t *transfers )
  352. {
  353. free( transfers );
  354. }
  355. void BuildVisLeafs( int threadnum, void *pUserData )
  356. {
  357. transfer_t *transfers = BuildVisLeafs_Start();
  358. while ( 1 )
  359. {
  360. //
  361. // build a minimal BSP tree that only
  362. // covers areas relevent to the PVS
  363. //
  364. // JAY: Now this returns a cluster index
  365. int iCluster = GetThreadWork();
  366. if ( iCluster == -1 )
  367. break;
  368. BuildVisLeafs_Cluster( threadnum, transfers, iCluster, NULL );
  369. }
  370. BuildVisLeafs_End( transfers );
  371. }
  372. /*
  373. ==============
  374. BuildVisMatrix
  375. ==============
  376. */
  377. void BuildVisMatrix (void)
  378. {
  379. if ( g_bUseMPI )
  380. {
  381. RunMPIBuildVisLeafs();
  382. }
  383. else
  384. {
  385. RunThreadsOn (dvis->numclusters, true, BuildVisLeafs);
  386. }
  387. }
  388. void FreeVisMatrix (void)
  389. {
  390. }