Counter Strike : Global Offensive Source Code
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.

520 lines
12 KiB

  1. //========= Copyright � 1996-2005, 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. struct ClusterPatchList_t
  245. {
  246. CUtlVector<int> patches;
  247. };
  248. static CUtlVector<ClusterPatchList_t> g_ClusterStaticPropPatches;
  249. void AddStaticPropPatchesToClusterTable()
  250. {
  251. g_ClusterStaticPropPatches.SetCount( g_ClusterLeaves.Count() );
  252. for ( int i = 0; i < g_Patches.Count(); i++ )
  253. {
  254. const CPatch &patch = g_Patches[ i ];
  255. if ( patch.faceNumber >= 0 || patch.clusterNumber < 0 )
  256. {
  257. continue;
  258. }
  259. g_ClusterStaticPropPatches[ patch.clusterNumber ].patches.AddToTail( i );
  260. }
  261. }
  262. /*
  263. ==============
  264. BuildVisRow
  265. Calc vis bits from a single patch
  266. ==============
  267. */
  268. void BuildVisRow (int patchnum, byte *pvs, int head, transfer_t *transfers, CTransferMaker &transferMaker, int iThread )
  269. {
  270. int j, k, l, leafIndex;
  271. CPatch *patch;
  272. dleaf_t *leaf;
  273. byte face_tested[MAX_MAP_FACES];
  274. byte disp_tested[MAX_MAP_FACES];
  275. patch = &g_Patches.Element( patchnum );
  276. memset( face_tested, 0, numfaces ) ;
  277. memset( disp_tested, 0, numfaces );
  278. for (j=0; j<dvis->numclusters; j++)
  279. {
  280. if ( ! ( pvs[(j)>>3] & (1<<((j)&7)) ) )
  281. {
  282. continue; // not in pvs
  283. }
  284. for ( leafIndex = 0; leafIndex < g_ClusterLeaves[j].leafCount; leafIndex++ )
  285. {
  286. leaf = dleafs + g_ClusterLeaves[j].leafs[leafIndex];
  287. for (k=0 ; k<leaf->numleaffaces; k++)
  288. {
  289. l = dleaffaces[leaf->firstleafface + k];
  290. // faces can be marksurfed by multiple leaves, but
  291. // don't bother testing again
  292. if (face_tested[l])
  293. {
  294. continue;
  295. }
  296. face_tested[l] = 1;
  297. // don't check patches on the same face
  298. if (patch->faceNumber == l)
  299. continue;
  300. TestPatchToFace (patchnum, l, head, transfers, transferMaker, iThread );
  301. }
  302. }
  303. int dispCount = g_ClusterDispFaces[j].dispFaces.Count();
  304. for( int ndxDisp = 0; ndxDisp < dispCount; ndxDisp++ )
  305. {
  306. int ndxFace = g_ClusterDispFaces[j].dispFaces[ndxDisp];
  307. if( disp_tested[ndxFace] )
  308. continue;
  309. disp_tested[ndxFace] = 1;
  310. // don't check patches on the same face
  311. if( patch->faceNumber == ndxFace )
  312. continue;
  313. TestPatchToFace( patchnum, ndxFace, head, transfers, transferMaker, iThread );
  314. }
  315. if ( g_bStaticPropBounce )
  316. {
  317. // Test static prop patches
  318. int staticPropPatchCount = g_ClusterStaticPropPatches[ j ].patches.Count();
  319. for ( int i = 0; i < staticPropPatchCount; i++ )
  320. {
  321. int nPatchIdx = g_ClusterStaticPropPatches[ j ].patches[ i ];
  322. if ( nPatchIdx != patchnum )
  323. {
  324. TestPatchToPatch( patchnum, nPatchIdx, head, transfers, transferMaker, iThread );
  325. }
  326. }
  327. }
  328. }
  329. // Msg("%d) Transfers: %5d\n", patchnum, patch->numtransfers);
  330. }
  331. /*
  332. ===========
  333. BuildVisLeafs
  334. This is run by multiple threads
  335. ===========
  336. */
  337. transfer_t* BuildVisLeafs_Start()
  338. {
  339. return (transfer_t *)calloc( 1, MAX_PATCHES * sizeof( transfer_t ) );
  340. }
  341. // If PatchCB is non-null, it is called after each row is generated (used by MPI).
  342. void BuildVisLeafs_Cluster(
  343. int threadnum,
  344. transfer_t *transfers,
  345. int iCluster,
  346. void (*PatchCB)(int iThread, int patchnum, CPatch *patch)
  347. )
  348. {
  349. byte pvs[(MAX_MAP_CLUSTERS+7)/8];
  350. CPatch *patch;
  351. int head;
  352. unsigned patchnum;
  353. DecompressVis( &dvisdata[ dvis->bitofs[ iCluster ][DVIS_PVS] ], pvs);
  354. head = 0;
  355. CTransferMaker transferMaker( transfers );
  356. // light every patch in the cluster
  357. if( clusterChildren.Element( iCluster ) != clusterChildren.InvalidIndex() )
  358. {
  359. CPatch *pNextPatch;
  360. for( patch = &g_Patches.Element( clusterChildren.Element( iCluster ) ); patch; patch = pNextPatch )
  361. {
  362. //
  363. // next patch
  364. //
  365. pNextPatch = NULL;
  366. if( patch->ndxNextClusterChild != g_Patches.InvalidIndex() )
  367. {
  368. pNextPatch = &g_Patches.Element( patch->ndxNextClusterChild );
  369. }
  370. patchnum = patch - g_Patches.Base();
  371. // build to all other world clusters
  372. BuildVisRow (patchnum, pvs, head, transfers, transferMaker, threadnum );
  373. transferMaker.Finish();
  374. // do the transfers
  375. MakeScales( patchnum, transfers );
  376. // Let MPI aggregate the data if it's being used.
  377. if ( PatchCB )
  378. PatchCB( threadnum, patchnum, patch );
  379. }
  380. }
  381. }
  382. void BuildVisLeafs_End( transfer_t *transfers )
  383. {
  384. free( transfers );
  385. }
  386. void BuildVisLeafs( int threadnum, void *pUserData )
  387. {
  388. transfer_t *transfers = BuildVisLeafs_Start();
  389. while ( 1 )
  390. {
  391. //
  392. // build a minimal BSP tree that only
  393. // covers areas relevent to the PVS
  394. //
  395. // JAY: Now this returns a cluster index
  396. int iCluster = GetThreadWork();
  397. if ( iCluster == -1 )
  398. break;
  399. BuildVisLeafs_Cluster( threadnum, transfers, iCluster, NULL );
  400. }
  401. BuildVisLeafs_End( transfers );
  402. }
  403. /*
  404. ==============
  405. BuildVisMatrix
  406. ==============
  407. */
  408. void BuildVisMatrix (void)
  409. {
  410. if ( g_bUseMPI )
  411. {
  412. RunMPIBuildVisLeafs();
  413. }
  414. else
  415. {
  416. RunThreadsOn (dvis->numclusters, true, BuildVisLeafs);
  417. }
  418. }
  419. void FreeVisMatrix (void)
  420. {
  421. }