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.

1081 lines
32 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "vrad.h"
  8. #include "VRAD_DispColl.h"
  9. #include "DispColl_Common.h"
  10. #include "radial.h"
  11. #include "CollisionUtils.h"
  12. #include "tier0\dbg.h"
  13. #define SAMPLE_BBOX_SLOP 5.0f
  14. #define TRIEDGE_EPSILON 0.001f
  15. float g_flMaxDispSampleSize = 512.0f;
  16. static FileHandle_t pDispFile = FILESYSTEM_INVALID_HANDLE;
  17. //-----------------------------------------------------------------------------
  18. //-----------------------------------------------------------------------------
  19. CVRADDispColl::CVRADDispColl()
  20. {
  21. m_iParent = -1;
  22. m_flSampleRadius2 = 0.0f;
  23. m_flPatchSampleRadius2 = 0.0f;
  24. m_flSampleWidth = 0.0f;
  25. m_flSampleHeight = 0.0f;
  26. m_aLuxelCoords.Purge();
  27. m_aVertNormals.Purge();
  28. }
  29. //-----------------------------------------------------------------------------
  30. //-----------------------------------------------------------------------------
  31. CVRADDispColl::~CVRADDispColl()
  32. {
  33. m_aLuxelCoords.Purge();
  34. m_aVertNormals.Purge();
  35. }
  36. //-----------------------------------------------------------------------------
  37. //-----------------------------------------------------------------------------
  38. bool CVRADDispColl::Create( CCoreDispInfo *pDisp )
  39. {
  40. // Base class create.
  41. if( !CDispCollTree::Create( pDisp ) )
  42. return false;
  43. // Allocate VRad specific memory.
  44. m_aLuxelCoords.SetSize( GetSize() );
  45. m_aVertNormals.SetSize( GetSize() );
  46. // VRad specific base surface data.
  47. CCoreDispSurface *pSurf = pDisp->GetSurface();
  48. m_iParent = pSurf->GetHandle();
  49. // VRad specific displacement surface data.
  50. for ( int iVert = 0; iVert < m_aVerts.Count(); ++iVert )
  51. {
  52. pDisp->GetNormal( iVert, m_aVertNormals[iVert] );
  53. pDisp->GetLuxelCoord( 0, iVert, m_aLuxelCoords[iVert] );
  54. }
  55. // Re-calculate the lightmap size (in uv) so that the luxels give
  56. // a better world-space uniform approx. due to the non-linear nature
  57. // of the displacement surface in uv-space
  58. dface_t *pFace = &g_pFaces[m_iParent];
  59. if( pFace )
  60. {
  61. CalcSampleRadius2AndBox( pFace );
  62. }
  63. return true;
  64. }
  65. //-----------------------------------------------------------------------------
  66. // Purpose:
  67. //-----------------------------------------------------------------------------
  68. void CVRADDispColl::CalcSampleRadius2AndBox( dface_t *pFace )
  69. {
  70. // Get the luxel sample size.
  71. texinfo_t *pTexInfo = &texinfo[pFace->texinfo];
  72. Assert ( pTexInfo );
  73. if ( !pTexInfo )
  74. return;
  75. // Todo: Width = Height now, should change all the code to look at one value.
  76. Vector vecTmp( pTexInfo->lightmapVecsLuxelsPerWorldUnits[0][0],
  77. pTexInfo->lightmapVecsLuxelsPerWorldUnits[0][1],
  78. pTexInfo->lightmapVecsLuxelsPerWorldUnits[0][2] );
  79. float flWidth = 1.0f / VectorLength( vecTmp );
  80. float flHeight = flWidth;
  81. // Save off the sample width and height.
  82. m_flSampleWidth = flWidth;
  83. m_flSampleHeight = flHeight;
  84. // Calculate the sample radius squared.
  85. float flSampleRadius = sqrt( ( ( flWidth * flWidth ) + ( flHeight * flHeight ) ) ); // * 2.2f;//RADIALDIST2; // AV - Removing the 2.2 scalar since 1.0 works better with CS:GO
  86. if ( flSampleRadius > g_flMaxDispSampleSize )
  87. {
  88. flSampleRadius = g_flMaxDispSampleSize;
  89. }
  90. m_flSampleRadius2 = flSampleRadius * flSampleRadius;
  91. // Calculate the patch radius - the max sample edge length * the number of luxels per edge "chop."
  92. float flSampleSize = max( m_flSampleWidth, m_flSampleHeight );
  93. float flPatchSampleRadius = flSampleSize * dispchop * ( g_bLargeDispSampleRadius ? 2.2f : 1.0f ); // AV - Removing the 2.2 scalar since 1.0 works better with CS:GO. TS - It fixes lighting artefacts in maps with many small displacements.
  94. if ( flPatchSampleRadius > g_MaxDispPatchRadius )
  95. {
  96. flPatchSampleRadius = g_MaxDispPatchRadius;
  97. Warning( "Patch Sample Radius Clamped!\n" );
  98. }
  99. m_flPatchSampleRadius2 = flPatchSampleRadius * flPatchSampleRadius;
  100. }
  101. //-----------------------------------------------------------------------------
  102. // Purpose: Get the min/max of the displacement surface.
  103. //-----------------------------------------------------------------------------
  104. void CVRADDispColl::GetSurfaceMinMax( Vector &boxMin, Vector &boxMax )
  105. {
  106. // Initialize the minimum and maximum box
  107. boxMin = m_aVerts[0];
  108. boxMax = m_aVerts[0];
  109. for( int i = 1; i < m_aVerts.Count(); i++ )
  110. {
  111. if( m_aVerts[i].x < boxMin.x ) { boxMin.x = m_aVerts[i].x; }
  112. if( m_aVerts[i].y < boxMin.y ) { boxMin.y = m_aVerts[i].y; }
  113. if( m_aVerts[i].z < boxMin.z ) { boxMin.z = m_aVerts[i].z; }
  114. if( m_aVerts[i].x > boxMax.x ) { boxMax.x = m_aVerts[i].x; }
  115. if( m_aVerts[i].y > boxMax.y ) { boxMax.y = m_aVerts[i].y; }
  116. if( m_aVerts[i].z > boxMax.z ) { boxMax.z = m_aVerts[i].z; }
  117. }
  118. }
  119. //-----------------------------------------------------------------------------
  120. // Purpose: Find the minor projection axes based on the given normal.
  121. //-----------------------------------------------------------------------------
  122. void CVRADDispColl::GetMinorAxes( Vector const &vecNormal, int &nAxis0, int &nAxis1 )
  123. {
  124. nAxis0 = 0;
  125. nAxis1 = 1;
  126. if( FloatMakePositive( vecNormal.x ) > FloatMakePositive( vecNormal.y ) )
  127. {
  128. if( FloatMakePositive( vecNormal.x ) > FloatMakePositive( vecNormal.z ) )
  129. {
  130. nAxis0 = 1;
  131. nAxis1 = 2;
  132. }
  133. }
  134. else
  135. {
  136. if( FloatMakePositive( vecNormal.y ) > FloatMakePositive( vecNormal.z ) )
  137. {
  138. nAxis0 = 0;
  139. nAxis1 = 2;
  140. }
  141. }
  142. }
  143. //-----------------------------------------------------------------------------
  144. //-----------------------------------------------------------------------------
  145. void CVRADDispColl::BaseFacePlaneToDispUV( Vector const &vecPlanePt, Vector2D &dispUV )
  146. {
  147. PointInQuadToBarycentric( m_vecSurfPoints[0], m_vecSurfPoints[3], m_vecSurfPoints[2], m_vecSurfPoints[1], vecPlanePt, dispUV );
  148. }
  149. //-----------------------------------------------------------------------------
  150. //-----------------------------------------------------------------------------
  151. void CVRADDispColl::DispUVToSurfPoint( Vector2D const &dispUV, Vector &vecPoint, float flPushEps )
  152. {
  153. // Check to see that the point is on the surface.
  154. if ( dispUV.x < 0.0f || dispUV.x > 1.0f || dispUV.y < 0.0f || dispUV.y > 1.0f )
  155. return;
  156. // Get the displacement power.
  157. int nWidth = ( ( 1 << m_nPower ) + 1 );
  158. int nHeight = nWidth;
  159. // Scale the U, V coordinates to the displacement grid size.
  160. float flU = dispUV.x * static_cast<float>( nWidth - 1.000001f );
  161. float flV = dispUV.y * static_cast<float>( nHeight - 1.000001f );
  162. // Find the base U, V.
  163. int nSnapU = static_cast<int>( flU );
  164. int nSnapV = static_cast<int>( flV );
  165. // Use this to get the triangle orientation.
  166. bool bOdd = ( ( ( nSnapV * nWidth ) + nSnapU ) % 2 == 1 );
  167. // Top Left to Bottom Right
  168. if( bOdd )
  169. {
  170. DispUVToSurf_TriTLToBR( vecPoint, flPushEps, flU, flV, nSnapU, nSnapV, nWidth, nHeight );
  171. }
  172. // Bottom Left to Top Right
  173. else
  174. {
  175. DispUVToSurf_TriBLToTR( vecPoint, flPushEps, flU, flV, nSnapU, nSnapV, nWidth, nHeight );
  176. }
  177. }
  178. //-----------------------------------------------------------------------------
  179. // Purpose:
  180. //-----------------------------------------------------------------------------
  181. void CVRADDispColl::DispUVToSurf_TriTLToBR( Vector &vecPoint, float flPushEps,
  182. float flU, float flV, int nSnapU, int nSnapV,
  183. int nWidth, int nHeight )
  184. {
  185. int nNextU = nSnapU + 1;
  186. int nNextV = nSnapV + 1;
  187. if ( nNextU == nWidth) { --nNextU; }
  188. if ( nNextV == nHeight ) { --nNextV; }
  189. float flFracU = flU - static_cast<float>( nSnapU );
  190. float flFracV = flV - static_cast<float>( nSnapV );
  191. if( ( flFracU + flFracV ) >= ( 1.0f + TRIEDGE_EPSILON ) )
  192. {
  193. int nIndices[3];
  194. nIndices[0] = nNextV * nWidth + nSnapU;
  195. nIndices[1] = nNextV * nWidth + nNextU;
  196. nIndices[2] = nSnapV * nWidth + nNextU;
  197. Vector edgeU = m_aVerts[nIndices[0]] - m_aVerts[nIndices[1]];
  198. Vector edgeV = m_aVerts[nIndices[2]] - m_aVerts[nIndices[1]];
  199. vecPoint = m_aVerts[nIndices[1]] + edgeU * ( 1.0f - flFracU ) + edgeV * ( 1.0f - flFracV );
  200. if ( flPushEps != 0.0f )
  201. {
  202. Vector vecNormal;
  203. vecNormal = CrossProduct( edgeU, edgeV );
  204. VectorNormalize( vecNormal );
  205. vecPoint += ( vecNormal * flPushEps );
  206. }
  207. }
  208. else
  209. {
  210. int nIndices[3];
  211. nIndices[0] = nSnapV * nWidth + nSnapU;
  212. nIndices[1] = nNextV * nWidth + nSnapU;
  213. nIndices[2] = nSnapV * nWidth + nNextU;
  214. Vector edgeU = m_aVerts[nIndices[2]] - m_aVerts[nIndices[0]];
  215. Vector edgeV = m_aVerts[nIndices[1]] - m_aVerts[nIndices[0]];
  216. vecPoint = m_aVerts[nIndices[0]] + edgeU * flFracU + edgeV * flFracV;
  217. if ( flPushEps != 0.0f )
  218. {
  219. Vector vecNormal;
  220. vecNormal = CrossProduct( edgeU, edgeV );
  221. VectorNormalize( vecNormal );
  222. vecPoint += ( vecNormal * flPushEps );
  223. }
  224. }
  225. }
  226. //-----------------------------------------------------------------------------
  227. // Purpose:
  228. //-----------------------------------------------------------------------------
  229. void CVRADDispColl::DispUVToSurf_TriBLToTR( Vector &vecPoint, float flPushEps,
  230. float flU, float flV, int nSnapU, int nSnapV,
  231. int nWidth, int nHeight )
  232. {
  233. int nNextU = nSnapU + 1;
  234. int nNextV = nSnapV + 1;
  235. if ( nNextU == nWidth) { --nNextU; }
  236. if ( nNextV == nHeight ) { --nNextV; }
  237. float flFracU = flU - static_cast<float>( nSnapU );
  238. float flFracV = flV - static_cast<float>( nSnapV );
  239. if( flFracU < flFracV )
  240. {
  241. int nIndices[3];
  242. nIndices[0] = nSnapV * nWidth + nSnapU;
  243. nIndices[1] = nNextV * nWidth + nSnapU;
  244. nIndices[2] = nNextV * nWidth + nNextU;
  245. Vector edgeU = m_aVerts[nIndices[2]] - m_aVerts[nIndices[1]];
  246. Vector edgeV = m_aVerts[nIndices[0]] - m_aVerts[nIndices[1]];
  247. vecPoint = m_aVerts[nIndices[1]] + edgeU * flFracU + edgeV * ( 1.0f - flFracV );
  248. if ( flPushEps != 0.0f )
  249. {
  250. Vector vecNormal;
  251. vecNormal = CrossProduct( edgeV, edgeU );
  252. VectorNormalize( vecNormal );
  253. vecPoint += ( vecNormal * flPushEps );
  254. }
  255. }
  256. else
  257. {
  258. int nIndices[3];
  259. nIndices[0] = nSnapV * nWidth + nSnapU;
  260. nIndices[1] = nNextV * nWidth + nNextU;
  261. nIndices[2] = nSnapV * nWidth + nNextU;
  262. Vector edgeU = m_aVerts[nIndices[0]] - m_aVerts[nIndices[2]];
  263. Vector edgeV = m_aVerts[nIndices[1]] - m_aVerts[nIndices[2]];
  264. vecPoint = m_aVerts[nIndices[2]] + edgeU * ( 1.0f - flFracU ) + edgeV * flFracV;
  265. if ( flPushEps != 0.0f )
  266. {
  267. Vector vecNormal;
  268. vecNormal = CrossProduct( edgeV, edgeU );
  269. VectorNormalize( vecNormal );
  270. vecPoint += ( vecNormal * flPushEps );
  271. }
  272. }
  273. }
  274. //-----------------------------------------------------------------------------
  275. //-----------------------------------------------------------------------------
  276. void CVRADDispColl::DispUVToSurfNormal( Vector2D const &dispUV, Vector &vecNormal )
  277. {
  278. // Check to see that the point is on the surface.
  279. if ( dispUV.x < 0.0f || dispUV.x > 1.0f || dispUV.y < 0.0f || dispUV.y > 1.0f )
  280. return;
  281. // Get the displacement power.
  282. int nWidth = ( ( 1 << m_nPower ) + 1 );
  283. int nHeight = nWidth;
  284. // Scale the U, V coordinates to the displacement grid size.
  285. float flU = dispUV.x * static_cast<float>( nWidth - 1.000001f );
  286. float flV = dispUV.y * static_cast<float>( nHeight - 1.000001f );
  287. // Find the base U, V.
  288. int nSnapU = static_cast<int>( flU );
  289. int nSnapV = static_cast<int>( flV );
  290. int nNextU = nSnapU + 1;
  291. int nNextV = nSnapV + 1;
  292. if ( nNextU == nWidth) { --nNextU; }
  293. if ( nNextV == nHeight ) { --nNextV; }
  294. float flFracU = flU - static_cast<float>( nSnapU );
  295. float flFracV = flV - static_cast<float>( nSnapV );
  296. // Get the four normals "around" the "spot"
  297. int iQuad[VRAD_QUAD_SIZE];
  298. iQuad[0] = ( nSnapV * nWidth ) + nSnapU;
  299. iQuad[1] = ( nNextV * nWidth ) + nSnapU;
  300. iQuad[2] = ( nNextV * nWidth ) + nNextU;
  301. iQuad[3] = ( nSnapV * nWidth ) + nNextU;
  302. // Find the blended normal (bi-linear).
  303. Vector vecTmpNormals[2], vecBlendedNormals[2], vecDispNormals[4];
  304. for ( int iVert = 0; iVert < VRAD_QUAD_SIZE; ++iVert )
  305. {
  306. GetVertNormal( iQuad[iVert], vecDispNormals[iVert] );
  307. }
  308. vecTmpNormals[0] = vecDispNormals[0] * ( 1.0f - flFracU );
  309. vecTmpNormals[1] = vecDispNormals[3] * flFracU;
  310. vecBlendedNormals[0] = vecTmpNormals[0] + vecTmpNormals[1];
  311. VectorNormalize( vecBlendedNormals[0] );
  312. vecTmpNormals[0] = vecDispNormals[1] * ( 1.0f - flFracU );
  313. vecTmpNormals[1] = vecDispNormals[2] * flFracU;
  314. vecBlendedNormals[1] = vecTmpNormals[0] + vecTmpNormals[1];
  315. VectorNormalize( vecBlendedNormals[1] );
  316. vecTmpNormals[0] = vecBlendedNormals[0] * ( 1.0f - flFracV );
  317. vecTmpNormals[1] = vecBlendedNormals[1] * flFracV;
  318. vecNormal = vecTmpNormals[0] + vecTmpNormals[1];
  319. VectorNormalize( vecNormal );
  320. }
  321. //-----------------------------------------------------------------------------
  322. // Purpose:
  323. // Output : float
  324. //-----------------------------------------------------------------------------
  325. float CVRADDispColl::CreateParentPatches( void )
  326. {
  327. // Save the total surface area of the displacement.
  328. float flTotalArea = 0.0f;
  329. // Get the number of displacement subdivisions.
  330. int nInterval = GetWidth();
  331. Vector vecPoints[4];
  332. vecPoints[0].Init( m_aVerts[0].x, m_aVerts[0].y, m_aVerts[0].z );
  333. vecPoints[1].Init( m_aVerts[(nInterval*(nInterval-1))].x, m_aVerts[(nInterval*(nInterval-1))].y, m_aVerts[(nInterval*(nInterval-1))].z );
  334. vecPoints[2].Init( m_aVerts[((nInterval*nInterval)-1)].x, m_aVerts[((nInterval*nInterval)-1)].y, m_aVerts[((nInterval*nInterval)-1)].z );
  335. vecPoints[3].Init( m_aVerts[(nInterval-1)].x, m_aVerts[(nInterval-1)].y, m_aVerts[(nInterval-1)].z );
  336. // Create and initialize the patch.
  337. int iPatch = g_Patches.AddToTail();
  338. if ( iPatch == g_Patches.InvalidIndex() )
  339. return flTotalArea;
  340. // Keep track of the area of the patches.
  341. float flArea = 0.0f;
  342. if ( !InitParentPatch( iPatch, vecPoints, flArea ) )
  343. {
  344. g_Patches.Remove( iPatch );
  345. flArea = 0.0f;
  346. }
  347. // Return the displacement area.
  348. return flArea;
  349. }
  350. //-----------------------------------------------------------------------------
  351. // Purpose:
  352. // Input : iParentPatch -
  353. // nLevel -
  354. //-----------------------------------------------------------------------------
  355. void CVRADDispColl::CreateChildPatchesFromRoot( int iParentPatch, int *pChildPatch )
  356. {
  357. // Initialize the child patch indices.
  358. pChildPatch[0] = g_Patches.InvalidIndex();
  359. pChildPatch[1] = g_Patches.InvalidIndex();
  360. // Get the number of displacement subdivisions.
  361. int nInterval = GetWidth();
  362. // Get the parent patch.
  363. CPatch *pParentPatch = &g_Patches[iParentPatch];
  364. if ( !pParentPatch )
  365. return;
  366. // Split along the longest edge.
  367. Vector vecEdges[4];
  368. vecEdges[0] = pParentPatch->winding->p[1] - pParentPatch->winding->p[0];
  369. vecEdges[1] = pParentPatch->winding->p[2] - pParentPatch->winding->p[1];
  370. vecEdges[2] = pParentPatch->winding->p[3] - pParentPatch->winding->p[2];
  371. vecEdges[3] = pParentPatch->winding->p[3] - pParentPatch->winding->p[0];
  372. // Should the patch be subdivided - check the area.
  373. float flMaxLength = max( m_flSampleWidth, m_flSampleHeight );
  374. float flMinEdgeLength = flMaxLength * dispchop;
  375. // Find the longest edge.
  376. float flEdgeLength = 0.0f;
  377. int iLongEdge = -1;
  378. for ( int iEdge = 0; iEdge < 4; ++iEdge )
  379. {
  380. float flLength = vecEdges[iEdge].Length();
  381. if ( flEdgeLength < flLength )
  382. {
  383. flEdgeLength = vecEdges[iEdge].Length();
  384. iLongEdge = iEdge;
  385. }
  386. }
  387. // Small enough already, return.
  388. if ( flEdgeLength < flMinEdgeLength )
  389. return;
  390. // Test area as well so we don't allow slivers.
  391. float flMinArea = ( dispchop * flMaxLength ) * ( dispchop * flMaxLength );
  392. Vector vecNormal = vecEdges[3].Cross( vecEdges[0] );
  393. float flTestArea = VectorNormalize( vecNormal );
  394. if ( flTestArea < flMinArea )
  395. return;
  396. // Get the points for the first triangle.
  397. int iPoints[3];
  398. Vector vecPoints[3];
  399. float flArea;
  400. iPoints[0] = ( nInterval * nInterval ) - 1;
  401. iPoints[1] = 0;
  402. iPoints[2] = nInterval * ( nInterval - 1 );
  403. for ( int iPoint = 0; iPoint < 3; ++iPoint )
  404. {
  405. VectorCopy( m_aVerts[iPoints[iPoint]], vecPoints[iPoint] );
  406. }
  407. // Create and initialize the patch.
  408. pChildPatch[0] = g_Patches.AddToTail();
  409. if ( pChildPatch[0] == g_Patches.InvalidIndex() )
  410. return;
  411. if ( !InitPatch( pChildPatch[0], iParentPatch, 0, vecPoints, iPoints, flArea ) )
  412. {
  413. g_Patches.Remove( pChildPatch[0] );
  414. pChildPatch[0] = g_Patches.InvalidIndex();
  415. return;
  416. }
  417. // Get the points for the second triangle.
  418. iPoints[0] = 0;
  419. iPoints[1] = ( nInterval * nInterval ) - 1;
  420. iPoints[2] = nInterval - 1;
  421. for ( int iPoint = 0; iPoint < 3; ++iPoint )
  422. {
  423. VectorCopy( m_aVerts[iPoints[iPoint]], vecPoints[iPoint] );
  424. }
  425. // Create and initialize the patch.
  426. pChildPatch[1] = g_Patches.AddToTail();
  427. if ( pChildPatch[1] == g_Patches.InvalidIndex() )
  428. {
  429. g_Patches.Remove( pChildPatch[0] );
  430. pChildPatch[0] = g_Patches.InvalidIndex();
  431. return;
  432. }
  433. if ( !InitPatch( pChildPatch[1], iParentPatch, 1, vecPoints, iPoints, flArea ) )
  434. {
  435. g_Patches.Remove( pChildPatch[0] );
  436. pChildPatch[0] = g_Patches.InvalidIndex();
  437. g_Patches.Remove( pChildPatch[1] );
  438. pChildPatch[1] = g_Patches.InvalidIndex();
  439. return;
  440. }
  441. }
  442. //-----------------------------------------------------------------------------
  443. // Purpose:
  444. // Input : flMinArea -
  445. // Output : float
  446. //-----------------------------------------------------------------------------
  447. void CVRADDispColl::CreateChildPatches( int iParentPatch, int nLevel )
  448. {
  449. // Get the parent patch.
  450. CPatch *pParentPatch = &g_Patches[iParentPatch];
  451. if ( !pParentPatch )
  452. return;
  453. // The root face is a quad - special case.
  454. if ( pParentPatch->winding->numpoints == 4 )
  455. {
  456. int iChildPatch[2];
  457. CreateChildPatchesFromRoot( iParentPatch, iChildPatch );
  458. if ( iChildPatch[0] != g_Patches.InvalidIndex() && iChildPatch[1] != g_Patches.InvalidIndex() )
  459. {
  460. CreateChildPatches( iChildPatch[0], 0 );
  461. CreateChildPatches( iChildPatch[1], 0 );
  462. }
  463. return;
  464. }
  465. // Calculate the the area of the patch (triangle!).
  466. Assert( pParentPatch->winding->numpoints == 3 );
  467. if ( pParentPatch->winding->numpoints != 3 )
  468. return;
  469. // Should the patch be subdivided - check the area.
  470. float flMaxLength = max( m_flSampleWidth, m_flSampleHeight );
  471. float flMinEdgeLength = flMaxLength * dispchop;
  472. // Split along the longest edge.
  473. Vector vecEdges[3];
  474. vecEdges[0] = pParentPatch->winding->p[1] - pParentPatch->winding->p[0];
  475. vecEdges[1] = pParentPatch->winding->p[2] - pParentPatch->winding->p[0];
  476. vecEdges[2] = pParentPatch->winding->p[2] - pParentPatch->winding->p[1];
  477. // Find the longest edge.
  478. float flEdgeLength = 0.0f;
  479. int iLongEdge = -1;
  480. for ( int iEdge = 0; iEdge < 3; ++iEdge )
  481. {
  482. if ( flEdgeLength < vecEdges[iEdge].Length() )
  483. {
  484. flEdgeLength = vecEdges[iEdge].Length();
  485. iLongEdge = iEdge;
  486. }
  487. }
  488. // Small enough already, return.
  489. if ( flEdgeLength < flMinEdgeLength )
  490. return;
  491. // Test area as well so we don't allow slivers.
  492. float flMinArea = ( dispchop * flMaxLength ) * ( dispchop * flMaxLength ) * 0.5f;
  493. Vector vecNormal = vecEdges[1].Cross( vecEdges[0] );
  494. float flTestArea = VectorNormalize( vecNormal );
  495. flTestArea *= 0.5f;
  496. if ( flTestArea < flMinArea )
  497. return;
  498. // Check to see if any more displacement verts exist - go to subdivision if not.
  499. if ( nLevel >= ( m_nPower * 2 ) )
  500. {
  501. CreateChildPatchesSub( iParentPatch );
  502. return;
  503. }
  504. int nChildIndices[2][3];
  505. int nNewIndex = ( pParentPatch->indices[1] + pParentPatch->indices[0] ) / 2;
  506. nChildIndices[0][0] = pParentPatch->indices[2];
  507. nChildIndices[0][1] = pParentPatch->indices[0];
  508. nChildIndices[0][2] = nNewIndex;
  509. nChildIndices[1][0] = pParentPatch->indices[1];
  510. nChildIndices[1][1] = pParentPatch->indices[2];
  511. nChildIndices[1][2] = nNewIndex;
  512. Vector vecChildPoints[2][3];
  513. for ( int iTri = 0; iTri < 2; ++iTri )
  514. {
  515. for ( int iPoint = 0; iPoint < 3; ++iPoint )
  516. {
  517. VectorCopy( m_aVerts[nChildIndices[iTri][iPoint]], vecChildPoints[iTri][iPoint] );
  518. }
  519. }
  520. // Create and initialize the children patches.
  521. int iChildPatch[2] = { -1, -1 };
  522. for ( int iChild = 0; iChild < 2; ++iChild )
  523. {
  524. iChildPatch[iChild] = g_Patches.AddToTail();
  525. float flArea = 0.0f;
  526. if ( !InitPatch( iChildPatch[iChild], iParentPatch, iChild, vecChildPoints[iChild], nChildIndices[iChild], flArea ) )
  527. {
  528. if ( iChild == 0 )
  529. {
  530. pParentPatch->child1 = g_Patches.InvalidIndex();
  531. g_Patches.Remove( iChildPatch[iChild] );
  532. break;
  533. }
  534. else
  535. {
  536. pParentPatch->child1 = g_Patches.InvalidIndex();
  537. pParentPatch->child2 = g_Patches.InvalidIndex();
  538. g_Patches.Remove( iChildPatch[iChild] );
  539. g_Patches.Remove( iChildPatch[0] );
  540. }
  541. }
  542. }
  543. // Continue creating children patches.
  544. int nNewLevel = ++nLevel;
  545. CreateChildPatches( iChildPatch[0], nNewLevel );
  546. CreateChildPatches( iChildPatch[1], nNewLevel );
  547. }
  548. //-----------------------------------------------------------------------------
  549. // Purpose:
  550. // Input : flMinArea -
  551. // Output : float
  552. //-----------------------------------------------------------------------------
  553. void CVRADDispColl::CreateChildPatchesSub( int iParentPatch )
  554. {
  555. // Get the parent patch.
  556. CPatch *pParentPatch = &g_Patches[iParentPatch];
  557. if ( !pParentPatch )
  558. return;
  559. // Calculate the the area of the patch (triangle!).
  560. Assert( pParentPatch->winding->numpoints == 3 );
  561. if ( pParentPatch->winding->numpoints != 3 )
  562. return;
  563. // Should the patch be subdivided - check the area.
  564. float flMaxLength = max( m_flSampleWidth, m_flSampleHeight );
  565. float flMinEdgeLength = flMaxLength * dispchop;
  566. // Split along the longest edge.
  567. Vector vecEdges[3];
  568. vecEdges[0] = pParentPatch->winding->p[1] - pParentPatch->winding->p[0];
  569. vecEdges[1] = pParentPatch->winding->p[2] - pParentPatch->winding->p[0];
  570. vecEdges[2] = pParentPatch->winding->p[2] - pParentPatch->winding->p[1];
  571. // Find the longest edge.
  572. float flEdgeLength = 0.0f;
  573. int iLongEdge = -1;
  574. for ( int iEdge = 0; iEdge < 3; ++iEdge )
  575. {
  576. if ( flEdgeLength < vecEdges[iEdge].Length() )
  577. {
  578. flEdgeLength = vecEdges[iEdge].Length();
  579. iLongEdge = iEdge;
  580. }
  581. }
  582. // Small enough already, return.
  583. if ( flEdgeLength < flMinEdgeLength )
  584. return;
  585. // Test area as well so we don't allow slivers.
  586. float flMinArea = ( dispchop * flMaxLength ) * ( dispchop * flMaxLength ) * 0.5f;
  587. Vector vecNormal = vecEdges[1].Cross( vecEdges[0] );
  588. float flTestArea = VectorNormalize( vecNormal );
  589. flTestArea *= 0.5f;
  590. if ( flTestArea < flMinArea )
  591. return;
  592. // Create children patchs - 2 of them.
  593. Vector vecChildPoints[2][3];
  594. switch ( iLongEdge )
  595. {
  596. case 0:
  597. {
  598. vecChildPoints[0][0] = pParentPatch->winding->p[0];
  599. vecChildPoints[0][1] = ( pParentPatch->winding->p[0] + pParentPatch->winding->p[1] ) * 0.5f;
  600. vecChildPoints[0][2] = pParentPatch->winding->p[2];
  601. vecChildPoints[1][0] = ( pParentPatch->winding->p[0] + pParentPatch->winding->p[1] ) * 0.5f;
  602. vecChildPoints[1][1] = pParentPatch->winding->p[1];
  603. vecChildPoints[1][2] = pParentPatch->winding->p[2];
  604. break;
  605. }
  606. case 1:
  607. {
  608. vecChildPoints[0][0] = pParentPatch->winding->p[0];
  609. vecChildPoints[0][1] = pParentPatch->winding->p[1];
  610. vecChildPoints[0][2] = ( pParentPatch->winding->p[1] + pParentPatch->winding->p[2] ) * 0.5f;
  611. vecChildPoints[1][0] = ( pParentPatch->winding->p[1] + pParentPatch->winding->p[2] ) * 0.5f;
  612. vecChildPoints[1][1] = pParentPatch->winding->p[2];
  613. vecChildPoints[1][2] = pParentPatch->winding->p[0];
  614. break;
  615. }
  616. case 2:
  617. {
  618. vecChildPoints[0][0] = pParentPatch->winding->p[0];
  619. vecChildPoints[0][1] = pParentPatch->winding->p[1];
  620. vecChildPoints[0][2] = ( pParentPatch->winding->p[0] + pParentPatch->winding->p[2] ) * 0.5f;
  621. vecChildPoints[1][0] = ( pParentPatch->winding->p[0] + pParentPatch->winding->p[2] ) * 0.5f;
  622. vecChildPoints[1][1] = pParentPatch->winding->p[1];
  623. vecChildPoints[1][2] = pParentPatch->winding->p[2];
  624. break;
  625. }
  626. }
  627. // Create and initialize the children patches.
  628. int iChildPatch[2] = { 0, 0 };
  629. int nChildIndices[3] = { -1, -1, -1 };
  630. for ( int iChild = 0; iChild < 2; ++iChild )
  631. {
  632. iChildPatch[iChild] = g_Patches.AddToTail();
  633. float flArea = 0.0f;
  634. if ( !InitPatch( iChildPatch[iChild], iParentPatch, iChild, vecChildPoints[iChild], nChildIndices, flArea ) )
  635. {
  636. if ( iChild == 0 )
  637. {
  638. pParentPatch->child1 = g_Patches.InvalidIndex();
  639. g_Patches.Remove( iChildPatch[iChild] );
  640. break;
  641. }
  642. else
  643. {
  644. pParentPatch->child1 = g_Patches.InvalidIndex();
  645. pParentPatch->child2 = g_Patches.InvalidIndex();
  646. g_Patches.Remove( iChildPatch[iChild] );
  647. g_Patches.Remove( iChildPatch[0] );
  648. }
  649. }
  650. }
  651. // Continue creating children patches.
  652. CreateChildPatchesSub( iChildPatch[0] );
  653. CreateChildPatchesSub( iChildPatch[1] );
  654. }
  655. int PlaneTypeForNormal (Vector& normal)
  656. {
  657. vec_t ax, ay, az;
  658. // NOTE: should these have an epsilon around 1.0?
  659. if (normal[0] == 1.0 || normal[0] == -1.0)
  660. return PLANE_X;
  661. if (normal[1] == 1.0 || normal[1] == -1.0)
  662. return PLANE_Y;
  663. if (normal[2] == 1.0 || normal[2] == -1.0)
  664. return PLANE_Z;
  665. ax = fabs(normal[0]);
  666. ay = fabs(normal[1]);
  667. az = fabs(normal[2]);
  668. if (ax >= ay && ax >= az)
  669. return PLANE_ANYX;
  670. if (ay >= ax && ay >= az)
  671. return PLANE_ANYY;
  672. return PLANE_ANYZ;
  673. }
  674. //-----------------------------------------------------------------------------
  675. // Purpose:
  676. // Input : iPatch -
  677. // iParentPatch -
  678. // iChild -
  679. // *pPoints -
  680. // *pIndices -
  681. // &flArea -
  682. // Output : Returns true on success, false on failure.
  683. //-----------------------------------------------------------------------------
  684. bool CVRADDispColl::InitParentPatch( int iPatch, Vector *pPoints, float &flArea )
  685. {
  686. // Get the current patch.
  687. CPatch *pPatch = &g_Patches[iPatch];
  688. if ( !pPatch )
  689. return false;
  690. // Clear the patch data.
  691. memset( pPatch, 0, sizeof( CPatch ) );
  692. // This is a parent.
  693. pPatch->ndxNext = g_FacePatches.Element( GetParentIndex() );
  694. g_FacePatches[GetParentIndex()] = iPatch;
  695. pPatch->faceNumber = GetParentIndex();
  696. // Initialize parent and children indices.
  697. pPatch->child1 = g_Patches.InvalidIndex();
  698. pPatch->child2 = g_Patches.InvalidIndex();
  699. pPatch->parent = g_Patches.InvalidIndex();
  700. pPatch->ndxNextClusterChild = g_Patches.InvalidIndex();
  701. pPatch->ndxNextParent = g_Patches.InvalidIndex();
  702. pPatch->staticPropIdx = -1;
  703. Vector vecEdges[2];
  704. vecEdges[0] = pPoints[1] - pPoints[0];
  705. vecEdges[1] = pPoints[3] - pPoints[0];
  706. // Calculate the triangle normal and area.
  707. Vector vecNormal = vecEdges[1].Cross( vecEdges[0] );
  708. flArea = VectorNormalize( vecNormal );
  709. // Initialize the patch scale.
  710. pPatch->scale[0] = pPatch->scale[1] = 1.0f;
  711. // Set the patch chop - minchop (that is what the minimum area is based on).
  712. pPatch->chop = dispchop;
  713. // Displacements are not sky!
  714. pPatch->sky = false;
  715. // Copy the winding.
  716. Vector vecCenter( 0.0f, 0.0f, 0.0f );
  717. pPatch->winding = AllocWinding( 4 );
  718. pPatch->winding->numpoints = 4;
  719. for ( int iPoint = 0; iPoint < 4; ++iPoint )
  720. {
  721. VectorCopy( pPoints[iPoint], pPatch->winding->p[iPoint] );
  722. VectorAdd( pPoints[iPoint], vecCenter, vecCenter );
  723. }
  724. // Set the origin and normal.
  725. VectorScale( vecCenter, ( 1.0f / 4.0f ), vecCenter );
  726. VectorCopy( vecCenter, pPatch->origin );
  727. VectorCopy( vecNormal, pPatch->normal );
  728. // Create the plane.
  729. pPatch->plane = new dplane_t;
  730. if ( !pPatch->plane )
  731. return false;
  732. VectorCopy( vecNormal, pPatch->plane->normal );
  733. pPatch->plane->dist = vecNormal.Dot( pPoints[0] );
  734. pPatch->plane->type = PlaneTypeForNormal( pPatch->plane->normal );
  735. pPatch->planeDist = pPatch->plane->dist;
  736. // Set the area.
  737. pPatch->area = flArea;
  738. // Calculate the mins/maxs.
  739. Vector vecMin( FLT_MAX, FLT_MAX, FLT_MAX );
  740. Vector vecMax( FLT_MIN, FLT_MIN, FLT_MIN );
  741. for ( int iPoint = 0; iPoint < 4; ++iPoint )
  742. {
  743. for ( int iAxis = 0; iAxis < 3; ++iAxis )
  744. {
  745. vecMin[iAxis] = min( vecMin[iAxis], pPoints[iPoint][iAxis] );
  746. vecMax[iAxis] = max( vecMax[iAxis], pPoints[iPoint][iAxis] );
  747. }
  748. }
  749. VectorCopy( vecMin, pPatch->mins );
  750. VectorCopy( vecMax, pPatch->maxs );
  751. VectorCopy( vecMin, pPatch->face_mins );
  752. VectorCopy( vecMax, pPatch->face_maxs );
  753. // Check for bumpmap.
  754. dface_t *pFace = dfaces + pPatch->faceNumber;
  755. texinfo_t *pTexInfo = &texinfo[pFace->texinfo];
  756. pPatch->needsBumpmap = pTexInfo->flags & SURF_BUMPLIGHT ? true : false;
  757. // Misc...
  758. pPatch->m_IterationKey = 0;
  759. // Calculate the base light, area, and reflectivity.
  760. BaseLightForFace( &g_pFaces[pPatch->faceNumber], pPatch->baselight, &pPatch->basearea, pPatch->reflectivity );
  761. return true;
  762. }
  763. //-----------------------------------------------------------------------------
  764. // Purpose:
  765. // Input : *pPatch -
  766. // *pPoints -
  767. // &vecNormal -
  768. // flArea -
  769. //-----------------------------------------------------------------------------
  770. bool CVRADDispColl::InitPatch( int iPatch, int iParentPatch, int iChild, Vector *pPoints, int *pIndices, float &flArea )
  771. {
  772. // Get the current patch.
  773. CPatch *pPatch = &g_Patches[iPatch];
  774. if ( !pPatch )
  775. return false;
  776. // Clear the patch data.
  777. memset( pPatch, 0, sizeof( CPatch ) );
  778. pPatch->staticPropIdx = -1;
  779. // Setup the parent if we are not the parent.
  780. CPatch *pParentPatch = NULL;
  781. if ( iParentPatch != g_Patches.InvalidIndex() )
  782. {
  783. // Get the parent patch.
  784. pParentPatch = &g_Patches[iParentPatch];
  785. if ( !pParentPatch )
  786. return false;
  787. }
  788. // Attach the face to the correct lists.
  789. if ( !pParentPatch )
  790. {
  791. // This is a parent.
  792. pPatch->ndxNext = g_FacePatches.Element( GetParentIndex() );
  793. g_FacePatches[GetParentIndex()] = iPatch;
  794. pPatch->faceNumber = GetParentIndex();
  795. }
  796. else
  797. {
  798. pPatch->ndxNext = g_Patches.InvalidIndex();
  799. pPatch->faceNumber = pParentPatch->faceNumber;
  800. // Attach to the parent patch.
  801. if ( iChild == 0 )
  802. {
  803. pParentPatch->child1 = iPatch;
  804. }
  805. else
  806. {
  807. pParentPatch->child2 = iPatch;
  808. }
  809. }
  810. // Initialize parent and children indices.
  811. pPatch->child1 = g_Patches.InvalidIndex();
  812. pPatch->child2 = g_Patches.InvalidIndex();
  813. pPatch->ndxNextClusterChild = g_Patches.InvalidIndex();
  814. pPatch->ndxNextParent = g_Patches.InvalidIndex();
  815. pPatch->parent = iParentPatch;
  816. // Get triangle edges.
  817. Vector vecEdges[3];
  818. vecEdges[0] = pPoints[1] - pPoints[0];
  819. vecEdges[1] = pPoints[2] - pPoints[0];
  820. vecEdges[2] = pPoints[2] - pPoints[1];
  821. // Find the longest edge.
  822. // float flEdgeLength = 0.0f;
  823. // for ( int iEdge = 0; iEdge < 3; ++iEdge )
  824. // {
  825. // if ( flEdgeLength < vecEdges[iEdge].Length() )
  826. // {
  827. // flEdgeLength = vecEdges[iEdge].Length();
  828. // }
  829. // }
  830. // Calculate the triangle normal and area.
  831. Vector vecNormal = vecEdges[1].Cross( vecEdges[0] );
  832. flArea = VectorNormalize( vecNormal );
  833. flArea *= 0.5f;
  834. // Initialize the patch scale.
  835. pPatch->scale[0] = pPatch->scale[1] = 1.0f;
  836. // Set the patch chop - minchop (that is what the minimum area is based on).
  837. pPatch->chop = dispchop;
  838. // Displacements are not sky!
  839. pPatch->sky = false;
  840. // Copy the winding.
  841. Vector vecCenter( 0.0f, 0.0f, 0.0f );
  842. pPatch->winding = AllocWinding( 3 );
  843. pPatch->winding->numpoints = 3;
  844. for ( int iPoint = 0; iPoint < 3; ++iPoint )
  845. {
  846. VectorCopy( pPoints[iPoint], pPatch->winding->p[iPoint] );
  847. VectorAdd( pPoints[iPoint], vecCenter, vecCenter );
  848. pPatch->indices[iPoint] = static_cast<short>( pIndices[iPoint] );
  849. }
  850. // Set the origin and normal.
  851. VectorScale( vecCenter, ( 1.0f / 3.0f ), vecCenter );
  852. VectorCopy( vecCenter, pPatch->origin );
  853. VectorCopy( vecNormal, pPatch->normal );
  854. // Create the plane.
  855. pPatch->plane = new dplane_t;
  856. if ( !pPatch->plane )
  857. return false;
  858. VectorCopy( vecNormal, pPatch->plane->normal );
  859. pPatch->plane->dist = vecNormal.Dot( pPoints[0] );
  860. pPatch->plane->type = PlaneTypeForNormal( pPatch->plane->normal );
  861. pPatch->planeDist = pPatch->plane->dist;
  862. // Set the area.
  863. pPatch->area = flArea;
  864. // Calculate the mins/maxs.
  865. Vector vecMin( FLT_MAX, FLT_MAX, FLT_MAX );
  866. Vector vecMax( FLT_MIN, FLT_MIN, FLT_MIN );
  867. for ( int iPoint = 0; iPoint < 3; ++iPoint )
  868. {
  869. for ( int iAxis = 0; iAxis < 3; ++iAxis )
  870. {
  871. vecMin[iAxis] = min( vecMin[iAxis], pPoints[iPoint][iAxis] );
  872. vecMax[iAxis] = max( vecMax[iAxis], pPoints[iPoint][iAxis] );
  873. }
  874. }
  875. VectorCopy( vecMin, pPatch->mins );
  876. VectorCopy( vecMax, pPatch->maxs );
  877. if ( !pParentPatch )
  878. {
  879. VectorCopy( vecMin, pPatch->face_mins );
  880. VectorCopy( vecMax, pPatch->face_maxs );
  881. }
  882. else
  883. {
  884. VectorCopy( pParentPatch->face_mins, pPatch->face_mins );
  885. VectorCopy( pParentPatch->face_maxs, pPatch->face_maxs );
  886. }
  887. // Check for bumpmap.
  888. dface_t *pFace = dfaces + pPatch->faceNumber;
  889. texinfo_t *pTexInfo = &texinfo[pFace->texinfo];
  890. pPatch->needsBumpmap = pTexInfo->flags & SURF_BUMPLIGHT ? true : false;
  891. // Misc...
  892. pPatch->m_IterationKey = 0;
  893. // Get the base light for the face.
  894. if ( !pParentPatch )
  895. {
  896. BaseLightForFace( &g_pFaces[pPatch->faceNumber], pPatch->baselight, &pPatch->basearea, pPatch->reflectivity );
  897. }
  898. else
  899. {
  900. VectorCopy( pParentPatch->baselight, pPatch->baselight );
  901. pPatch->basearea = pParentPatch->basearea;
  902. pPatch->reflectivity = pParentPatch->reflectivity;
  903. }
  904. return true;
  905. }
  906. void CVRADDispColl::AddPolysForRayTrace( void )
  907. {
  908. if ( !( m_nContents & MASK_OPAQUE ) )
  909. return;
  910. for ( int ndxTri = 0; ndxTri < m_aTris.Count(); ndxTri++ )
  911. {
  912. CDispCollTri *tri = m_aTris.Base() + ndxTri;
  913. int v[3];
  914. for ( int ndxv = 0; ndxv < 3; ndxv++ )
  915. v[ndxv] = tri->GetVert(ndxv);
  916. Vector fullCoverage;
  917. fullCoverage.x = 1.0f;
  918. g_RtEnv.AddTriangle( TRACE_ID_OPAQUE, m_aVerts[v[0]], m_aVerts[v[1]], m_aVerts[v[2]], fullCoverage );
  919. }
  920. }