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.

3156 lines
89 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $Workfile: $
  6. // $Date: $
  7. // $NoKeywords: $
  8. //=============================================================================//
  9. //#include <stdafx.h>
  10. #include <stdlib.h>
  11. #ifndef _PS3
  12. #include <malloc.h>
  13. #endif
  14. #include "builddisp.h"
  15. #include "collisionutils.h"
  16. #include "tier1/strtools.h"
  17. #include "tier0/dbg.h"
  18. // memdbgon must be the last include file in a .cpp file!!!
  19. #include "tier0/memdbgon.h"
  20. //
  21. // Node Functions (friend functions)
  22. //
  23. //-----------------------------------------------------------------------------
  24. // should make this more programatic and extensible!
  25. //-----------------------------------------------------------------------------
  26. int GetNodeLevel( int index )
  27. {
  28. // root
  29. if( index == 0 )
  30. return 1;
  31. // [1...4]
  32. if( index < 5 )
  33. return 2;
  34. // [5....20]
  35. if( index < 21 )
  36. return 3;
  37. // [21....84]
  38. if( index < 85 )
  39. return 4;
  40. // error!!!
  41. return -1;
  42. }
  43. //-----------------------------------------------------------------------------
  44. //-----------------------------------------------------------------------------
  45. int GetNodeCount( int power )
  46. {
  47. return ( ( 1 << ( power << 1 ) ) / 3 );
  48. }
  49. //-----------------------------------------------------------------------------
  50. //-----------------------------------------------------------------------------
  51. int GetNodeParent( int index )
  52. {
  53. // ( index - 1 ) / 4
  54. return ( ( index - 1 ) >> 2 );
  55. }
  56. //-----------------------------------------------------------------------------
  57. //-----------------------------------------------------------------------------
  58. int GetNodeChild( int power, int index, int direction )
  59. {
  60. // ( index * 4 ) + direction
  61. return ( ( index << 2 ) + ( direction - 3 ) );
  62. }
  63. //-----------------------------------------------------------------------------
  64. //-----------------------------------------------------------------------------
  65. int GetNodeMinNodeAtLevel( int level )
  66. {
  67. switch( level )
  68. {
  69. case 1: return 0;
  70. case 2: return 1;
  71. case 3: return 5;
  72. case 4: return 21;
  73. default: return -99999;
  74. }
  75. }
  76. //-----------------------------------------------------------------------------
  77. //-----------------------------------------------------------------------------
  78. void GetComponentsFromNodeIndex( int index, int *x, int *y )
  79. {
  80. *x = 0;
  81. *y = 0;
  82. for( int shift = 0; index != 0; shift++ )
  83. {
  84. *x |= ( index & 1 ) << shift;
  85. index >>= 1;
  86. *y |= ( index & 1 ) << shift;
  87. index >>= 1;
  88. }
  89. }
  90. //-----------------------------------------------------------------------------
  91. //-----------------------------------------------------------------------------
  92. int GetNodeIndexFromComponents( int x, int y )
  93. {
  94. int index = 0;
  95. // Interleave bits from the x and y values to create the index:
  96. int shift;
  97. for( shift = 0; x != 0; shift += 2, x >>= 1 )
  98. {
  99. index |= ( x & 1 ) << shift;
  100. }
  101. for( shift = 1; y != 0; shift += 2, y >>= 1 )
  102. {
  103. index |= ( y & 1 ) << shift;
  104. }
  105. return index;
  106. }
  107. //-----------------------------------------------------------------------------
  108. //-----------------------------------------------------------------------------
  109. bool CalcBarycentricCooefs( Vector const &v0, Vector const &v1, Vector const &v2,
  110. Vector const &pt, float &c0, float &c1, float &c2 )
  111. {
  112. Vector vSeg0, vSeg1, vCross;
  113. vSeg0 = v1 - v0;
  114. vSeg1 = v2 - v0;
  115. // get the area of the triangle
  116. vCross = vSeg0.Cross( vSeg1 );
  117. float totalArea = vCross.Length() * 0.5f;
  118. float ooTotalArea = totalArea ? 1.0f / totalArea : 0.0f;
  119. // get the area for cooeficient 0 (pt, v1, v2)
  120. vSeg0 = v1 - pt;
  121. vSeg1 = v2 - pt;
  122. vCross = vSeg0.Cross( vSeg1 );
  123. float subArea = vCross.Length() * 0.5f;
  124. c0 = subArea * ooTotalArea;
  125. // get the area for cooeficient 1 (v0, pt, v2)
  126. vSeg0 = v2 - pt;
  127. vSeg1 = v0 - pt;
  128. vCross = vSeg0.Cross( vSeg1 );
  129. subArea = vCross.Length() * 0.5f;
  130. c1 = subArea * ooTotalArea;
  131. // get the area for cooeficient 2 (v0, v1, pt)
  132. vSeg0 = v0 - pt;
  133. vSeg1 = v1 - pt;
  134. vCross = vSeg0.Cross( vSeg1 );
  135. subArea = vCross.Length() * 0.5f;
  136. c2 = subArea * ooTotalArea;
  137. float cTotal = c0 + c1 + c2;
  138. if ( FloatMakePositive( 1.0f - cTotal ) < 1e-3 )
  139. return true;
  140. return false;
  141. }
  142. CCoreDispSurface::CCoreDispSurface()
  143. {
  144. Init();
  145. }
  146. //=============================================================================
  147. //
  148. // CDispSurface Functions
  149. //
  150. //-----------------------------------------------------------------------------
  151. //-----------------------------------------------------------------------------
  152. void CCoreDispSurface::Init( void )
  153. {
  154. m_Index = -1;
  155. m_PointCount = 0;
  156. int i;
  157. for( i = 0; i < QUAD_POINT_COUNT; i++ )
  158. {
  159. VectorClear( m_Points[i] );
  160. VectorClear( m_Normals[i] );
  161. Vector2DClear( m_TexCoords[i] );
  162. for( int j = 0; j < NUM_BUMP_VECTS+1; j++ )
  163. {
  164. Vector2DClear( m_LuxelCoords[i][j] );
  165. }
  166. m_Alphas[i] = 1.0f;
  167. m_MultiBlends[ i ].Init( 0.0f, 0.0f, 0.0f, 0.0f );
  168. m_AlphaBlends[ i ].Init( 0.0f, 0.0f, 0.0f, 0.0f );
  169. for( int j = 0; j < MAX_MULTIBLEND_CHANNELS; j++ )
  170. {
  171. m_vBlendColors[ i ][ j ].Init( 1.0f, 1.0f, 1.0f );
  172. }
  173. }
  174. m_PointStartIndex = -1;
  175. VectorClear( m_PointStart );
  176. VectorClear( sAxis );
  177. VectorClear( tAxis );
  178. for( i = 0; i < 4; i++ )
  179. {
  180. m_EdgeNeighbors[i].SetInvalid();
  181. m_CornerNeighbors[i].SetInvalid();
  182. }
  183. m_Flags = 0;
  184. m_Contents = 0;
  185. }
  186. void CCoreDispSurface::SetNeighborData( const CDispNeighbor edgeNeighbors[4], const CDispCornerNeighbors cornerNeighbors[4] )
  187. {
  188. for ( int i=0; i < 4; i++ )
  189. {
  190. m_EdgeNeighbors[i] = edgeNeighbors[i];
  191. m_CornerNeighbors[i] = cornerNeighbors[i];
  192. }
  193. }
  194. //-----------------------------------------------------------------------------
  195. //-----------------------------------------------------------------------------
  196. void CCoreDispSurface::GeneratePointStartIndexFromMappingAxes( Vector const &sAxis, Vector const &tAxis )
  197. {
  198. if( m_PointStartIndex != -1 )
  199. return;
  200. int numIndices = 0;
  201. int indices[4];
  202. int offsetIndex;
  203. //
  204. // project all points on to the v-axis first and find the minimum
  205. //
  206. float minValue = DotProduct( tAxis, m_Points[0] );
  207. indices[numIndices] = 0;
  208. numIndices++;
  209. int i;
  210. for( i = 1; i < m_PointCount; i++ )
  211. {
  212. float value = DotProduct( tAxis, m_Points[i] );
  213. float delta = ( value - minValue );
  214. delta = FloatMakePositive( delta );
  215. if( delta < 0.1 )
  216. {
  217. indices[numIndices] = i;
  218. numIndices++;
  219. }
  220. else if( value < minValue )
  221. {
  222. minValue = value;
  223. indices[0] = i;
  224. numIndices = 1;
  225. }
  226. }
  227. //
  228. // break ties with the u-axis projection
  229. //
  230. minValue = DotProduct( sAxis, m_Points[indices[0]] );
  231. offsetIndex = indices[0];
  232. for( i = 1; i < numIndices; i++ )
  233. {
  234. float value = DotProduct( sAxis, m_Points[indices[i]] );
  235. if( ( value < minValue ) )
  236. {
  237. minValue = value;
  238. offsetIndex = indices[i];
  239. }
  240. }
  241. m_PointStartIndex = offsetIndex;
  242. }
  243. //-----------------------------------------------------------------------------
  244. //-----------------------------------------------------------------------------
  245. int CCoreDispSurface::GenerateSurfPointStartIndex( void )
  246. {
  247. //
  248. // get the minimum surface component values
  249. //
  250. Vector bMin;
  251. VectorFill( bMin, 99999.0f );
  252. int i;
  253. for( i = 0; i < QUAD_POINT_COUNT; i++ )
  254. {
  255. for( int j = 0; j < 3; j++ )
  256. {
  257. if( m_Points[i][j] < bMin[j] )
  258. {
  259. bMin[j] = m_Points[i][j];
  260. }
  261. }
  262. }
  263. //
  264. // find the point closest to the minimum, that is the start point
  265. //
  266. int minIndex = -1;
  267. float minDistance = 999999999.0f;
  268. for( i = 0; i < QUAD_POINT_COUNT; i++ )
  269. {
  270. Vector segment;
  271. segment = m_Points[i] - bMin;
  272. float distanceSq = segment.LengthSqr();
  273. if( distanceSq < minDistance )
  274. {
  275. minDistance = distanceSq;
  276. minIndex = i;
  277. }
  278. }
  279. m_PointStartIndex = minIndex;
  280. return minIndex;
  281. }
  282. //-----------------------------------------------------------------------------
  283. //-----------------------------------------------------------------------------
  284. int CCoreDispSurface::FindSurfPointStartIndex( void )
  285. {
  286. if( m_PointStartIndex != -1 )
  287. return m_PointStartIndex;
  288. int minIndex = -1;
  289. float minDistance = 999999999.0f;
  290. for( int i = 0; i < QUAD_POINT_COUNT; i++ )
  291. {
  292. Vector segment;
  293. VectorSubtract( m_PointStart, m_Points[i], segment );
  294. float distanceSq = segment.LengthSqr();
  295. if( distanceSq < minDistance )
  296. {
  297. minDistance = distanceSq;
  298. minIndex = i;
  299. }
  300. }
  301. m_PointStartIndex = minIndex;
  302. return minIndex;
  303. }
  304. //-----------------------------------------------------------------------------
  305. //-----------------------------------------------------------------------------
  306. void CCoreDispSurface::AdjustSurfPointData( void )
  307. {
  308. Vector tmpPoints[4];
  309. Vector tmpNormals[4];
  310. Vector2D tmpTexCoords[4];
  311. float tmpAlphas[4];
  312. Vector4D tmpMultiBlend[ 4 ];
  313. Vector4D tmpAlphaBlend[ 4 ];
  314. Vector tmpBlendColor[ 4 ][ MAX_MULTIBLEND_CHANNELS ];
  315. int i;
  316. for( i = 0; i < QUAD_POINT_COUNT; i++ )
  317. {
  318. VectorCopy( m_Points[i], tmpPoints[i] );
  319. VectorCopy( m_Normals[i], tmpNormals[i] );
  320. Vector2DCopy( m_TexCoords[i], tmpTexCoords[i] );
  321. tmpAlphas[i] = m_Alphas[i];
  322. tmpMultiBlend[ i ] = m_MultiBlends[ i ];
  323. tmpAlphaBlend[ i ] = m_AlphaBlends[ i ];
  324. for( int j = 0; j < MAX_MULTIBLEND_CHANNELS; j++ )
  325. {
  326. tmpBlendColor[ i ][ j ] = m_vBlendColors[ i ][ j ];
  327. }
  328. }
  329. for( i = 0; i < QUAD_POINT_COUNT; i++ )
  330. {
  331. VectorCopy( tmpPoints[(i+m_PointStartIndex)%4], m_Points[i] );
  332. VectorCopy( tmpNormals[(i+m_PointStartIndex)%4], m_Normals[i] );
  333. Vector2DCopy( tmpTexCoords[(i+m_PointStartIndex)%4], m_TexCoords[i] );
  334. m_Alphas[i] = tmpAlphas[i]; // is this correct?
  335. m_MultiBlends[ i ] = tmpMultiBlend[ (i+m_PointStartIndex)%4 ];
  336. m_AlphaBlends[ i ] = tmpAlphaBlend[ (i+m_PointStartIndex)%4 ];
  337. for( int j = 0; j < MAX_MULTIBLEND_CHANNELS; j++ )
  338. {
  339. m_vBlendColors[ i ][ j ] = tmpBlendColor[ ( i + m_PointStartIndex ) % 4 ][ j ];
  340. }
  341. }
  342. }
  343. //-----------------------------------------------------------------------------
  344. // Purpose:
  345. //-----------------------------------------------------------------------------
  346. bool CCoreDispSurface::LongestInU( const Vector &vecU, const Vector &vecV )
  347. {
  348. Vector vecNormU = vecU;
  349. Vector vecNormV = vecV;
  350. VectorNormalize( vecNormU );
  351. VectorNormalize( vecNormV );
  352. float flDistU[4];
  353. float flDistV[4];
  354. for ( int iPoint = 0; iPoint < 4; ++iPoint )
  355. {
  356. flDistU[iPoint] = vecNormU.Dot( m_Points[iPoint] );
  357. flDistV[iPoint] = vecNormV.Dot( m_Points[iPoint] );
  358. }
  359. float flULength = 0.0f;
  360. float flVLength = 0.0f;
  361. for ( int iPoint = 0; iPoint < 4; ++iPoint )
  362. {
  363. float flTestDist = fabs( flDistU[(iPoint+1)%4] - flDistU[iPoint] );
  364. if ( flTestDist > flULength )
  365. {
  366. flULength = flTestDist;
  367. }
  368. flTestDist = fabs( flDistV[(iPoint+1)%4] - flDistV[iPoint] );
  369. if ( flTestDist > flVLength )
  370. {
  371. flVLength = flTestDist;
  372. }
  373. }
  374. if ( flULength < flVLength )
  375. {
  376. return false;
  377. }
  378. return true;
  379. }
  380. //-----------------------------------------------------------------------------
  381. // Purpose:
  382. // Input : -
  383. //-----------------------------------------------------------------------------
  384. bool CCoreDispSurface::CalcLuxelCoords( int nLuxels, bool bAdjust, const Vector &vecU, const Vector &vecV )
  385. {
  386. // Valid value?
  387. if ( nLuxels <= 0.0f )
  388. return false;
  389. // Get the start point offset.
  390. int iOffset = 0;
  391. if ( bAdjust )
  392. {
  393. iOffset = GetPointStartIndex();
  394. }
  395. // Does projecting along U or V create the longest edge?
  396. bool bLongU = LongestInU( vecU, vecV );
  397. float flLengthTemp = 0.0f;
  398. float flULength = ( m_Points[(3+iOffset)%4] - m_Points[(0+iOffset)%4] ).Length();
  399. flLengthTemp = ( m_Points[(2+iOffset)%4] - m_Points[(1+iOffset)%4] ).Length();
  400. if ( flLengthTemp > flULength )
  401. {
  402. flULength = flLengthTemp;
  403. }
  404. // Find the largest edge in V.
  405. float flVLength = ( m_Points[(1+iOffset)%4] - m_Points[(0+iOffset)%4] ).Length();
  406. flLengthTemp = ( m_Points[(2+iOffset)%4] - m_Points[(3+iOffset)%4] ).Length();
  407. if ( flLengthTemp > flVLength )
  408. {
  409. flVLength = flLengthTemp;
  410. }
  411. float flOOLuxelScale = 1.0f / static_cast<float>( nLuxels );
  412. float flUValue = static_cast<float>( static_cast<int>( flULength * flOOLuxelScale ) + 1 );
  413. if ( flUValue > MAX_DISP_LIGHTMAP_DIM_WITHOUT_BORDER )
  414. {
  415. flUValue = MAX_DISP_LIGHTMAP_DIM_WITHOUT_BORDER;
  416. }
  417. float flVValue = static_cast<float>( static_cast<int>( flVLength * flOOLuxelScale ) + 1 );
  418. if ( flVValue > MAX_DISP_LIGHTMAP_DIM_WITHOUT_BORDER )
  419. {
  420. flVValue = MAX_DISP_LIGHTMAP_DIM_WITHOUT_BORDER;
  421. }
  422. // Swap if necessary.
  423. bool bSwapped = false;
  424. if ( bLongU )
  425. {
  426. if ( flVValue > flUValue )
  427. {
  428. bSwapped = true;
  429. }
  430. }
  431. else
  432. {
  433. if ( flUValue > flVValue )
  434. {
  435. bSwapped = true;
  436. }
  437. }
  438. m_nLuxelU = static_cast<int>( flUValue );
  439. m_nLuxelV = static_cast<int>( flVValue );
  440. // Generate luxel coordinates.
  441. for( int iBump = 0; iBump < NUM_BUMP_VECTS+1; ++iBump )
  442. {
  443. m_LuxelCoords[iBump][(0+iOffset)%4].Init( 0.5f, 0.5f );
  444. m_LuxelCoords[iBump][(1+iOffset)%4].Init( 0.5f, flVValue + 0.5 );
  445. m_LuxelCoords[iBump][(2+iOffset)%4].Init( flUValue + 0.5, flVValue + 0.5 );
  446. m_LuxelCoords[iBump][(3+iOffset)%4].Init( flUValue + 0.5, 0.5f );
  447. }
  448. return bSwapped;
  449. }
  450. //=============================================================================
  451. //
  452. // CDispNode Functions
  453. //
  454. //-----------------------------------------------------------------------------
  455. //-----------------------------------------------------------------------------
  456. void CCoreDispNode::Init( void )
  457. {
  458. VectorClear( m_BBox[0] );
  459. VectorClear( m_BBox[1] );
  460. m_ErrorTerm = 0.0f;
  461. m_VertIndex = -1;
  462. int j;
  463. for( j = 0; j < MAX_NEIGHBOR_NODE_COUNT; j++ )
  464. {
  465. m_NeighborVertIndices[j] = -1;
  466. }
  467. for( j = 0; j < MAX_SURF_AT_NODE_COUNT; j++ )
  468. {
  469. VectorClear( m_SurfBBoxes[j][0] );
  470. VectorClear( m_SurfBBoxes[j][1] );
  471. VectorClear( m_SurfPlanes[j].normal );
  472. m_SurfPlanes[j].dist = 0.0f;
  473. }
  474. }
  475. //-----------------------------------------------------------------------------
  476. //-----------------------------------------------------------------------------
  477. void GetDispNodeTriVerts( CCoreDispInfo *pDisp, int nodeIndex, int triIndex, Vector& v1, Vector& v2, Vector& v3 )
  478. {
  479. // get the node
  480. CCoreDispNode *pNode = pDisp->GetNode( nodeIndex );
  481. switch( triIndex )
  482. {
  483. case 0:
  484. {
  485. pDisp->GetVert( pNode->GetNeighborVertIndex( 4 ), v1 );
  486. pDisp->GetVert( pNode->GetNeighborVertIndex( 0 ), v2 );
  487. pDisp->GetVert( pNode->GetNeighborVertIndex( 3 ), v3 );
  488. return;
  489. }
  490. case 1:
  491. {
  492. pDisp->GetVert( pNode->GetNeighborVertIndex( 3 ), v1 );
  493. pDisp->GetVert( pNode->GetNeighborVertIndex( 0 ), v2 );
  494. pDisp->GetVert( pNode->GetCenterVertIndex(), v3 );
  495. return;
  496. }
  497. case 2:
  498. {
  499. pDisp->GetVert( pNode->GetNeighborVertIndex( 3 ), v1 );
  500. pDisp->GetVert( pNode->GetCenterVertIndex(), v2 );
  501. pDisp->GetVert( pNode->GetNeighborVertIndex( 5 ), v3 );
  502. return;
  503. }
  504. case 3:
  505. {
  506. pDisp->GetVert( pNode->GetNeighborVertIndex( 5 ), v1 );
  507. pDisp->GetVert( pNode->GetCenterVertIndex(), v2 );
  508. pDisp->GetVert( pNode->GetNeighborVertIndex( 2 ), v3 );
  509. return;
  510. }
  511. case 4:
  512. {
  513. pDisp->GetVert( pNode->GetNeighborVertIndex( 0 ), v1 );
  514. pDisp->GetVert( pNode->GetNeighborVertIndex( 6 ), v2 );
  515. pDisp->GetVert( pNode->GetCenterVertIndex(), v3 );
  516. return;
  517. }
  518. case 5:
  519. {
  520. pDisp->GetVert( pNode->GetCenterVertIndex(), v1 );
  521. pDisp->GetVert( pNode->GetNeighborVertIndex( 6 ), v2 );
  522. pDisp->GetVert( pNode->GetNeighborVertIndex( 1 ), v3 );
  523. return;
  524. }
  525. case 6:
  526. {
  527. pDisp->GetVert( pNode->GetCenterVertIndex(), v1 );
  528. pDisp->GetVert( pNode->GetNeighborVertIndex( 1 ), v2 );
  529. pDisp->GetVert( pNode->GetNeighborVertIndex( 2 ), v3 );
  530. return;
  531. }
  532. case 7:
  533. {
  534. pDisp->GetVert( pNode->GetNeighborVertIndex( 2 ), v1 );
  535. pDisp->GetVert( pNode->GetNeighborVertIndex( 1 ), v2 );
  536. pDisp->GetVert( pNode->GetNeighborVertIndex( 7 ), v3 );
  537. return;
  538. }
  539. default: { return; }
  540. }
  541. }
  542. //=============================================================================
  543. //
  544. // CCoreDispInfo Functions
  545. //
  546. //-----------------------------------------------------------------------------
  547. //-----------------------------------------------------------------------------
  548. CCoreDispInfo::CCoreDispInfo()
  549. {
  550. m_pVerts = NULL;
  551. m_RenderIndices = NULL;
  552. m_Nodes = NULL;
  553. m_pTris = NULL;
  554. // initialize the base surface data
  555. m_Surf.Init();
  556. //
  557. // initialize the disp info
  558. //
  559. m_Power = 0;
  560. m_Elevation = 0.0f;
  561. m_RenderIndexCount = 0;
  562. m_RenderCounter = 0;
  563. m_bTouched = false;
  564. m_pNext = NULL;
  565. m_ppListBase = NULL;
  566. m_ListSize = 0;
  567. m_nListIndex = -1;
  568. }
  569. //-----------------------------------------------------------------------------
  570. //-----------------------------------------------------------------------------
  571. CCoreDispInfo::~CCoreDispInfo()
  572. {
  573. if (m_pVerts)
  574. delete [] m_pVerts;
  575. if (m_RenderIndices)
  576. delete [] m_RenderIndices;
  577. if (m_Nodes)
  578. delete [] m_Nodes;
  579. if (m_pTris)
  580. delete [] m_pTris;
  581. }
  582. #if 0
  583. //-----------------------------------------------------------------------------
  584. //-----------------------------------------------------------------------------
  585. void CCoreDispInfo::InitSurf( int parentIndex, Vector points[4], Vector normals[4],
  586. Vector2D texCoords[4], Vector2D lightCoords[4][4], int contents, int flags,
  587. bool bGenerateSurfPointStart, Vector& startPoint,
  588. bool bHasMappingAxes, Vector& uAxis, Vector& vAxis )
  589. {
  590. // save the "parent" index
  591. m_Surf.m_Index = parentIndex;
  592. //
  593. // save the surface points and point normals, texture coordinates, and
  594. // lightmap coordinates
  595. //
  596. m_Surf.m_PointCount = CSurface::QUAD_POINT_COUNT;
  597. for( int i = 0; i < CSurface::QUAD_POINT_COUNT; i++ )
  598. {
  599. VectorCopy( points[i], m_Surf.m_Points[i] );
  600. if( normals )
  601. {
  602. VectorCopy( normals[i], m_Surf.m_pVerts[i].m_Normal );
  603. }
  604. if( texCoords )
  605. {
  606. Vector2DCopy( texCoords[i], m_Surf.m_TexCoords[i] );
  607. }
  608. if( lightCoords )
  609. {
  610. Assert( NUM_BUMP_VECTS == 3 );
  611. Vector2DCopy( lightCoords[0][i], m_Surf.m_LightCoords[i][0] );
  612. Vector2DCopy( lightCoords[1][i], m_Surf.m_LightCoords[i][1] );
  613. Vector2DCopy( lightCoords[2][i], m_Surf.m_LightCoords[i][2] );
  614. Vector2DCopy( lightCoords[3][i], m_Surf.m_LightCoords[i][3] );
  615. }
  616. }
  617. // save the starting point
  618. if( startPoint )
  619. {
  620. VectorCopy( startPoint, m_Surf.m_PointStart );
  621. }
  622. //
  623. // save the surface contents and flags
  624. //
  625. m_Contents = contents;
  626. m_Flags = flags;
  627. //
  628. // adjust surface points, texture coordinates, etc....
  629. //
  630. if( bHasMappingAxes && ( m_Surf.m_PointStartIndex == -1 ) )
  631. {
  632. GeneratePointStartIndexFromMappingAxes( uAxis, vAxis );
  633. }
  634. else
  635. {
  636. //
  637. // adjust the surf data
  638. //
  639. if( bGenerateSurfPointStart )
  640. {
  641. GenerateSurfPointStartIndex();
  642. }
  643. else
  644. {
  645. FindSurfPointStartIndex();
  646. }
  647. }
  648. AdjustSurfPointData();
  649. }
  650. #endif
  651. //-----------------------------------------------------------------------------
  652. //-----------------------------------------------------------------------------
  653. void CCoreDispInfo::InitDispInfo( int power, int minTess, float smoothingAngle, float *alphas, Vector *dispVectorField, float *dispDistances, int nFlags, const CDispMultiBlend *pvMultiBlends )
  654. {
  655. Assert( power >= MIN_MAP_DISP_POWER && power <= MAX_MAP_DISP_POWER );
  656. //
  657. // general displacement data
  658. //
  659. m_Power = power;
  660. m_nFlags = nFlags;
  661. if ( ( minTess & 0x80000000 ) != 0 )
  662. {
  663. // If the high bit is set, this represents FLAGS (SURF_NOPHYSICS_COLL, etc.) flags.
  664. int nFlags = minTess;
  665. nFlags &= ~0x80000000;
  666. GetSurface()->SetFlags( nFlags );
  667. }
  668. // Allocate + initialize verts
  669. int size = GetSize();
  670. m_pVerts = new CoreDispVert_t[size];
  671. int nIndexCount = size * 2 * 3;
  672. m_RenderIndices = new unsigned short[nIndexCount];
  673. int nNodeCount = GetNodeCount(power);
  674. m_Nodes = new CCoreDispNode[nNodeCount];
  675. int i;
  676. for( i = 0; i < size; i++ )
  677. {
  678. m_pVerts[i].m_FieldVector.Init();
  679. m_pVerts[i].m_SubdivPos.Init();
  680. m_pVerts[i].m_SubdivNormal.Init();
  681. m_pVerts[i].m_FieldDistance = 0.0f;
  682. m_pVerts[i].m_Vert.Init();
  683. m_pVerts[i].m_FlatVert.Init();
  684. m_pVerts[i].m_Normal.Init();
  685. m_pVerts[i].m_TangentS.Init();
  686. m_pVerts[i].m_TangentT.Init();
  687. m_pVerts[i].m_TexCoord.Init();
  688. for( int j = 0; j < ( NUM_BUMP_VECTS + 1 ); j++ )
  689. {
  690. m_pVerts[i].m_LuxelCoords[j].Init();
  691. }
  692. m_pVerts[i].m_Alpha = 0.0f;
  693. m_pVerts[i].m_MultiBlend.Init( 0.0f, 0.0f, 0.0f, 0.0f );
  694. m_pVerts[i].m_AlphaBlend.Init( 0.0f, 0.0f, 0.0f, 0.0f );
  695. for( int j = 0; j < MAX_MULTIBLEND_CHANNELS; j++ )
  696. {
  697. m_pVerts[i].m_vBlendColors[ j ].Init( 1.0f, 1.0f, 1.0f );
  698. }
  699. }
  700. for( i = 0; i < nIndexCount; i++ )
  701. {
  702. m_RenderIndices[i] = 0;
  703. }
  704. for( i = 0; i < nNodeCount; i++ )
  705. {
  706. m_Nodes[i].Init();
  707. }
  708. //
  709. // save the displacement vector field and distances within the field
  710. // offset have been combined with fieldvectors at this point!!!
  711. //
  712. if (alphas && dispVectorField && dispDistances)
  713. {
  714. for( i = 0; i < size; i++ )
  715. {
  716. VectorCopy( dispVectorField[i], m_pVerts[i].m_FieldVector );
  717. m_pVerts[i].m_FieldDistance = dispDistances[i];
  718. m_pVerts[i].m_Alpha = alphas[i];
  719. }
  720. }
  721. if ( ( m_nFlags & DISP_INFO_FLAG_HAS_MULTIBLEND ) != 0 && pvMultiBlends != NULL )
  722. {
  723. for( i = 0; i < size; i++ )
  724. {
  725. m_pVerts[ i ].m_MultiBlend = pvMultiBlends[ i ].m_vMultiBlend;
  726. m_pVerts[ i ].m_AlphaBlend = pvMultiBlends[ i ].m_vAlphaBlend;
  727. for( int j = 0; j < MAX_MULTIBLEND_CHANNELS; j++ )
  728. {
  729. m_pVerts[ i ].m_vBlendColors[ j ] = pvMultiBlends[ i ].m_vMultiBlendColors[ j ];
  730. }
  731. }
  732. }
  733. else
  734. { // clear it just in case
  735. m_nFlags &= ~DISP_INFO_FLAG_HAS_MULTIBLEND;
  736. }
  737. // Init triangle information.
  738. int nTriCount = GetTriCount();
  739. if ( nTriCount != 0 )
  740. {
  741. m_pTris = new CoreDispTri_t[nTriCount];
  742. if ( m_pTris )
  743. {
  744. InitTris();
  745. }
  746. }
  747. }
  748. void CCoreDispInfo::InitDispInfo( int power, int minTess, float smoothingAngle, const CDispVert *pVerts, const CDispTri *pTris, int nFlags, const CDispMultiBlend *pvMultiBlends )
  749. {
  750. Vector vectors[MAX_DISPVERTS];
  751. float dists[MAX_DISPVERTS];
  752. float alphas[MAX_DISPVERTS];
  753. int nVerts = NUM_DISP_POWER_VERTS( power );
  754. for ( int i=0; i < nVerts; i++ )
  755. {
  756. vectors[i] = pVerts[i].m_vVector;
  757. dists[i] = pVerts[i].m_flDist;
  758. alphas[i] = pVerts[i].m_flAlpha;
  759. }
  760. InitDispInfo( power, minTess, smoothingAngle, alphas, vectors, dists, nFlags, pvMultiBlends );
  761. int nTris = NUM_DISP_POWER_TRIS( power );
  762. for ( int iTri = 0; iTri < nTris; ++iTri )
  763. {
  764. m_pTris[iTri].m_uiTags = pTris[iTri].m_uiTags;
  765. }
  766. }
  767. void CCoreDispInfo::SetDispUtilsHelperInfo( CCoreDispInfo **ppListBase, int listSize )
  768. {
  769. m_ppListBase = ppListBase;
  770. m_ListSize = listSize;
  771. }
  772. const CPowerInfo* CCoreDispInfo::GetPowerInfo() const
  773. {
  774. return ::GetPowerInfo( GetPower() );
  775. }
  776. CDispNeighbor* CCoreDispInfo::GetEdgeNeighbor( int index )
  777. {
  778. return GetSurface()->GetEdgeNeighbor( index );
  779. }
  780. CDispCornerNeighbors* CCoreDispInfo::GetCornerNeighbors( int index )
  781. {
  782. return GetSurface()->GetCornerNeighbors( index );
  783. }
  784. CDispUtilsHelper* CCoreDispInfo::GetDispUtilsByIndex( int index )
  785. {
  786. Assert( m_ppListBase );
  787. return index == 0xFFFF ? 0 : m_ppListBase[index];
  788. }
  789. //-----------------------------------------------------------------------------
  790. //-----------------------------------------------------------------------------
  791. void CCoreDispInfo::BuildTriTLtoBR( int ndx )
  792. {
  793. // get width and height of displacement maps
  794. int nWidth = ( ( 1 << m_Power ) + 1 );
  795. m_RenderIndices[m_RenderIndexCount] = ndx;
  796. m_RenderIndices[m_RenderIndexCount+1] = ndx + nWidth;
  797. m_RenderIndices[m_RenderIndexCount+2] = ndx + 1;
  798. m_RenderIndexCount += 3;
  799. m_RenderIndices[m_RenderIndexCount] = ndx + 1;
  800. m_RenderIndices[m_RenderIndexCount+1] = ndx + nWidth;
  801. m_RenderIndices[m_RenderIndexCount+2] = ndx + nWidth + 1;
  802. m_RenderIndexCount += 3;
  803. }
  804. //-----------------------------------------------------------------------------
  805. //-----------------------------------------------------------------------------
  806. void CCoreDispInfo::BuildTriBLtoTR( int ndx )
  807. {
  808. // get width and height of displacement maps
  809. int nWidth = ( ( 1 << m_Power ) + 1 );
  810. m_RenderIndices[m_RenderIndexCount] = ndx;
  811. m_RenderIndices[m_RenderIndexCount+1] = ndx + nWidth;
  812. m_RenderIndices[m_RenderIndexCount+2] = ndx + nWidth + 1;
  813. m_RenderIndexCount += 3;
  814. m_RenderIndices[m_RenderIndexCount] = ndx;
  815. m_RenderIndices[m_RenderIndexCount+1] = ndx + nWidth + 1;
  816. m_RenderIndices[m_RenderIndexCount+2] = ndx + 1;
  817. m_RenderIndexCount += 3;
  818. }
  819. //-----------------------------------------------------------------------------
  820. //-----------------------------------------------------------------------------
  821. void CCoreDispInfo::GenerateCollisionSurface( void )
  822. {
  823. // get width and height of displacement maps
  824. int nWidth = ( ( 1 << m_Power ) + 1 );
  825. int nHeight = ( ( 1 << m_Power ) + 1 );
  826. //
  827. // generate a fan tesselated (at quadtree node) rendering index list
  828. //
  829. m_RenderIndexCount = 0;
  830. for ( int iV = 0; iV < ( nHeight - 1 ); iV++ )
  831. {
  832. for ( int iU = 0; iU < ( nWidth - 1 ); iU++ )
  833. {
  834. int ndx = ( iV * nWidth ) + iU;
  835. // test whether or not the index is odd
  836. bool bOdd = ( ( ndx %2 ) == 1 );
  837. // Top Left to Bottom Right
  838. if( bOdd )
  839. {
  840. BuildTriTLtoBR( ndx );
  841. }
  842. // Bottom Left to Top Right
  843. else
  844. {
  845. BuildTriBLtoTR( ndx );
  846. }
  847. }
  848. }
  849. }
  850. //-----------------------------------------------------------------------------
  851. //-----------------------------------------------------------------------------
  852. void CCoreDispInfo::GenerateCollisionData( void )
  853. {
  854. GenerateCollisionSurface();
  855. }
  856. //-----------------------------------------------------------------------------
  857. //-----------------------------------------------------------------------------
  858. void CCoreDispInfo::CalcTriSurfPlanes( int nodeIndex, int indices[8][3] )
  859. {
  860. //
  861. // calculate plane info for each face
  862. //
  863. for( int i = 0; i < 8; i++ )
  864. {
  865. Vector v[3];
  866. VectorCopy( m_pVerts[indices[i][0]].m_Vert, v[0] );
  867. VectorCopy( m_pVerts[indices[i][1]].m_Vert, v[1] );
  868. VectorCopy( m_pVerts[indices[i][2]].m_Vert, v[2] );
  869. Vector seg[2];
  870. VectorSubtract( v[1], v[0], seg[0] );
  871. VectorSubtract( v[2], v[0], seg[1] );
  872. Vector normal;
  873. CrossProduct( seg[1], seg[0], normal );
  874. VectorNormalize( normal );
  875. float dist = DotProduct( v[0], normal );
  876. m_Nodes[nodeIndex].SetTriPlane( i, normal, dist );
  877. }
  878. }
  879. //-----------------------------------------------------------------------------
  880. //-----------------------------------------------------------------------------
  881. void CCoreDispInfo::CalcRayBoundingBoxes( int nodeIndex, int indices[8][3] )
  882. {
  883. Vector triMin, triMax;
  884. for( int i = 0; i < 4; i++ )
  885. {
  886. triMin[0] = triMax[0] = m_pVerts[indices[(i*2)][0]].m_Vert[0];
  887. triMin[1] = triMax[1] = m_pVerts[indices[(i*2)][0]].m_Vert[1];
  888. triMin[2] = triMax[2] = m_pVerts[indices[(i*2)][0]].m_Vert[2];
  889. for( int j = 0; j < 3; j++ )
  890. {
  891. //
  892. // minimum
  893. //
  894. if( triMin[0] > m_pVerts[indices[(i*2)][j]].m_Vert[0] )
  895. triMin[0] = m_pVerts[indices[(i*2)][j]].m_Vert[0];
  896. if( triMin[0] > m_pVerts[indices[(i*2+1)][j]].m_Vert[0] )
  897. triMin[0] = m_pVerts[indices[(i*2+1)][j]].m_Vert[0];
  898. if( triMin[1] > m_pVerts[indices[(i*2)][j]].m_Vert[1] )
  899. triMin[1] = m_pVerts[indices[(i*2)][j]].m_Vert[1];
  900. if( triMin[1] > m_pVerts[indices[(i*2+1)][j]].m_Vert[1] )
  901. triMin[1] = m_pVerts[indices[(i*2+1)][j]].m_Vert[1];
  902. if( triMin[2] > m_pVerts[indices[(i*2)][j]].m_Vert[2] )
  903. triMin[2] = m_pVerts[indices[(i*2)][j]].m_Vert[2];
  904. if( triMin[2] > m_pVerts[indices[(i*2+1)][j]].m_Vert[2] )
  905. triMin[2] = m_pVerts[indices[(i*2+1)][j]].m_Vert[2];
  906. //
  907. // maximum
  908. //
  909. if( triMax[0] < m_pVerts[indices[(i*2)][j]].m_Vert[0] )
  910. triMax[0] = m_pVerts[indices[(i*2)][j]].m_Vert[0];
  911. if( triMax[0] < m_pVerts[indices[(i*2+1)][j]].m_Vert[0] )
  912. triMax[0] = m_pVerts[indices[(i*2+1)][j]].m_Vert[0];
  913. if( triMax[1] < m_pVerts[indices[(i*2)][j]].m_Vert[1] )
  914. triMax[1] = m_pVerts[indices[(i*2)][j]].m_Vert[1];
  915. if( triMax[1] < m_pVerts[indices[(i*2+1)][j]].m_Vert[1] )
  916. triMax[1] = m_pVerts[indices[(i*2+1)][j]].m_Vert[1];
  917. if( triMax[2] < m_pVerts[indices[(i*2)][j]].m_Vert[2] )
  918. triMax[2] = m_pVerts[indices[(i*2)][j]].m_Vert[2];
  919. if( triMax[2] < m_pVerts[indices[(i*2+1)][j]].m_Vert[2] )
  920. triMax[2] = m_pVerts[indices[(i*2+1)][j]].m_Vert[2];
  921. }
  922. m_Nodes[nodeIndex].SetRayBoundingBox( i, triMin, triMax );
  923. }
  924. }
  925. //-----------------------------------------------------------------------------
  926. //-----------------------------------------------------------------------------
  927. void CCoreDispInfo::CalcTriSurfBoundingBoxes( int nodeIndex, int indices[8][3] )
  928. {
  929. Vector triMin, triMax;
  930. for( int i = 0; i < 8; i++ )
  931. {
  932. m_Nodes[nodeIndex].GetTriBoundingBox( i, triMin, triMax );
  933. for( int j = 0; j < 3; j++ )
  934. {
  935. //
  936. // minimum
  937. //
  938. if( triMin[0] > m_pVerts[indices[i][j]].m_Vert[0] )
  939. triMin[0] = m_pVerts[indices[i][j]].m_Vert[0];
  940. if( triMin[1] > m_pVerts[indices[i][j]].m_Vert[1] )
  941. triMin[1] = m_pVerts[indices[i][j]].m_Vert[1];
  942. if( triMin[2] > m_pVerts[indices[i][j]].m_Vert[2] )
  943. triMin[2] = m_pVerts[indices[i][j]].m_Vert[2];
  944. //
  945. // maximum
  946. //
  947. if( triMax[0] < m_pVerts[indices[i][j]].m_Vert[0] )
  948. triMax[0] = m_pVerts[indices[i][j]].m_Vert[0];
  949. if( triMax[1] < m_pVerts[indices[i][j]].m_Vert[1] )
  950. triMax[1] = m_pVerts[indices[i][j]].m_Vert[1];
  951. if( triMax[2] < m_pVerts[indices[i][j]].m_Vert[2] )
  952. triMax[2] = m_pVerts[indices[i][j]].m_Vert[2];
  953. }
  954. m_Nodes[nodeIndex].SetTriBoundingBox( i, triMin, triMax );
  955. }
  956. }
  957. //-----------------------------------------------------------------------------
  958. //-----------------------------------------------------------------------------
  959. void CCoreDispInfo::CalcTriSurfIndices( int nodeIndex, int indices[8][3] )
  960. {
  961. indices[0][0] = m_Nodes[nodeIndex].GetNeighborVertIndex( 4 );
  962. indices[0][1] = m_Nodes[nodeIndex].GetNeighborVertIndex( 0 );
  963. indices[0][2] = m_Nodes[nodeIndex].GetNeighborVertIndex( 3 );
  964. indices[1][0] = m_Nodes[nodeIndex].GetNeighborVertIndex( 3 );
  965. indices[1][1] = m_Nodes[nodeIndex].GetNeighborVertIndex( 0 );
  966. indices[1][2] = m_Nodes[nodeIndex].GetCenterVertIndex();
  967. indices[2][0] = m_Nodes[nodeIndex].GetNeighborVertIndex( 3 );
  968. indices[2][1] = m_Nodes[nodeIndex].GetCenterVertIndex();
  969. indices[2][2] = m_Nodes[nodeIndex].GetNeighborVertIndex( 5 );
  970. indices[3][0] = m_Nodes[nodeIndex].GetNeighborVertIndex( 5 );
  971. indices[3][1] = m_Nodes[nodeIndex].GetCenterVertIndex();
  972. indices[3][2] = m_Nodes[nodeIndex].GetNeighborVertIndex( 2 );
  973. indices[4][0] = m_Nodes[nodeIndex].GetNeighborVertIndex( 0 );
  974. indices[4][1] = m_Nodes[nodeIndex].GetNeighborVertIndex( 6 );
  975. indices[4][2] = m_Nodes[nodeIndex].GetCenterVertIndex();
  976. indices[5][0] = m_Nodes[nodeIndex].GetCenterVertIndex();
  977. indices[5][1] = m_Nodes[nodeIndex].GetNeighborVertIndex( 6 );
  978. indices[5][2] = m_Nodes[nodeIndex].GetNeighborVertIndex( 1 );
  979. indices[6][0] = m_Nodes[nodeIndex].GetCenterVertIndex();
  980. indices[6][1] = m_Nodes[nodeIndex].GetNeighborVertIndex( 1 );
  981. indices[6][2] = m_Nodes[nodeIndex].GetNeighborVertIndex( 2 );
  982. indices[7][0] = m_Nodes[nodeIndex].GetNeighborVertIndex( 2 );
  983. indices[7][1] = m_Nodes[nodeIndex].GetNeighborVertIndex( 1 );
  984. indices[7][2] = m_Nodes[nodeIndex].GetNeighborVertIndex( 7 );
  985. }
  986. //-----------------------------------------------------------------------------
  987. //-----------------------------------------------------------------------------
  988. void CCoreDispInfo::CalcTriSurfInfoAtNode( int nodeIndex )
  989. {
  990. int indices[8][3];
  991. CalcTriSurfIndices( nodeIndex, indices );
  992. CalcTriSurfBoundingBoxes( nodeIndex, indices );
  993. CalcRayBoundingBoxes( nodeIndex, indices );
  994. CalcTriSurfPlanes( nodeIndex, indices );
  995. }
  996. //-----------------------------------------------------------------------------
  997. //-----------------------------------------------------------------------------
  998. void CCoreDispInfo::CalcMinMaxBoundingBoxAtNode( int nodeIndex, Vector& bMin, Vector& bMax )
  999. {
  1000. // get the child node index
  1001. int childNodeIndex = GetNodeChild( m_Power, nodeIndex, 4 );
  1002. // get initial bounding box values
  1003. m_Nodes[childNodeIndex].GetBoundingBox( bMin, bMax );
  1004. Vector nodeMin, nodeMax;
  1005. for( int i = 1, j = 5; i < 4; i++, j++ )
  1006. {
  1007. //
  1008. // get the child node bounding box
  1009. //
  1010. childNodeIndex = GetNodeChild( m_Power, nodeIndex, j );
  1011. m_Nodes[childNodeIndex].GetBoundingBox( nodeMin, nodeMax );
  1012. // minimum
  1013. if( bMin[0] > nodeMin[0] )
  1014. bMin[0] = nodeMin[0];
  1015. if( bMin[1] > nodeMin[1] )
  1016. bMin[1] = nodeMin[1];
  1017. if( bMin[2] > nodeMin[2] )
  1018. bMin[2] = nodeMin[2];
  1019. // maximum
  1020. if( bMax[0] < nodeMax[0] )
  1021. bMax[0] = nodeMax[0];
  1022. if( bMax[1] < nodeMax[1] )
  1023. bMax[1] = nodeMax[1];
  1024. if( bMax[2] < nodeMax[2] )
  1025. bMax[2] = nodeMax[2];
  1026. }
  1027. }
  1028. //-----------------------------------------------------------------------------
  1029. //-----------------------------------------------------------------------------
  1030. void CCoreDispInfo::CalcBoundingBoxAtNode( int nodeIndex )
  1031. {
  1032. Vector bMin, bMax;
  1033. //
  1034. // initialize the minimum and maximum values for the bounding box
  1035. //
  1036. int level = GetNodeLevel( nodeIndex );
  1037. int vertIndex = m_Nodes[nodeIndex].GetCenterVertIndex();
  1038. if( level == m_Power )
  1039. {
  1040. VectorCopy( m_pVerts[vertIndex].m_Vert, bMin );
  1041. VectorCopy( m_pVerts[vertIndex].m_Vert, bMax );
  1042. }
  1043. else
  1044. {
  1045. CalcMinMaxBoundingBoxAtNode( nodeIndex, bMin, bMax );
  1046. if( bMin[0] > m_pVerts[vertIndex].m_Vert[0] )
  1047. bMin[0] = m_pVerts[vertIndex].m_Vert[0];
  1048. if( bMin[1] > m_pVerts[vertIndex].m_Vert[1] )
  1049. bMin[1] = m_pVerts[vertIndex].m_Vert[1];
  1050. if( bMin[2] > m_pVerts[vertIndex].m_Vert[2] )
  1051. bMin[2] = m_pVerts[vertIndex].m_Vert[2];
  1052. if( bMax[0] < m_pVerts[vertIndex].m_Vert[0] )
  1053. bMax[0] = m_pVerts[vertIndex].m_Vert[0];
  1054. if( bMax[1] < m_pVerts[vertIndex].m_Vert[1] )
  1055. bMax[1] = m_pVerts[vertIndex].m_Vert[1];
  1056. if( bMax[2] < m_pVerts[vertIndex].m_Vert[2] )
  1057. bMax[2] = m_pVerts[vertIndex].m_Vert[2];
  1058. }
  1059. for( int i = 0; i < 8; i++ )
  1060. {
  1061. int neighborVertIndex = m_Nodes[nodeIndex].GetNeighborVertIndex( i );
  1062. //
  1063. // minimum
  1064. //
  1065. if( bMin[0] > m_pVerts[neighborVertIndex].m_Vert[0] )
  1066. bMin[0] = m_pVerts[neighborVertIndex].m_Vert[0];
  1067. if( bMin[1] > m_pVerts[neighborVertIndex].m_Vert[1] )
  1068. bMin[1] = m_pVerts[neighborVertIndex].m_Vert[1];
  1069. if( bMin[2] > m_pVerts[neighborVertIndex].m_Vert[2] )
  1070. bMin[2] = m_pVerts[neighborVertIndex].m_Vert[2];
  1071. //
  1072. // maximum
  1073. //
  1074. if( bMax[0] < m_pVerts[neighborVertIndex].m_Vert[0] )
  1075. bMax[0] = m_pVerts[neighborVertIndex].m_Vert[0];
  1076. if( bMax[1] < m_pVerts[neighborVertIndex].m_Vert[1] )
  1077. bMax[1] = m_pVerts[neighborVertIndex].m_Vert[1];
  1078. if( bMax[2] < m_pVerts[neighborVertIndex].m_Vert[2] )
  1079. bMax[2] = m_pVerts[neighborVertIndex].m_Vert[2];
  1080. }
  1081. m_Nodes[nodeIndex].SetBoundingBox( bMin, bMax );
  1082. }
  1083. //-----------------------------------------------------------------------------
  1084. //-----------------------------------------------------------------------------
  1085. float CCoreDispInfo::GetMaxErrorFromChildren( int nodeIndex, int level )
  1086. {
  1087. //
  1088. // check for children nodes
  1089. //
  1090. if( level == m_Power )
  1091. return 0.0f;
  1092. //
  1093. // get the child's error term and save the greatest error -- SW, SE, NW, NE
  1094. //
  1095. float errorTerm = 0.0f;
  1096. for( int i = 4; i < 8; i++ )
  1097. {
  1098. int childIndex = GetNodeChild( m_Power, nodeIndex, i );
  1099. float nodeErrorTerm = m_Nodes[childIndex].GetErrorTerm();
  1100. if( errorTerm < nodeErrorTerm )
  1101. {
  1102. errorTerm = nodeErrorTerm;
  1103. }
  1104. }
  1105. return errorTerm;
  1106. }
  1107. //-----------------------------------------------------------------------------
  1108. //-----------------------------------------------------------------------------
  1109. void CCoreDispInfo::CalcErrorTermAtNode( int nodeIndex, int level )
  1110. {
  1111. if( level == m_Power )
  1112. return;
  1113. //
  1114. // get the vertex indices
  1115. //
  1116. int neighborVertIndices[9];
  1117. for( int i = 0; i < 8; i++ )
  1118. {
  1119. neighborVertIndices[i] = m_Nodes[nodeIndex].GetNeighborVertIndex( i );
  1120. }
  1121. neighborVertIndices[8] = m_Nodes[nodeIndex].GetCenterVertIndex();
  1122. //
  1123. // calculate the error terms
  1124. //
  1125. Vector segment;
  1126. Vector v;
  1127. VectorAdd( m_pVerts[neighborVertIndices[5]].m_Vert, m_pVerts[neighborVertIndices[4]].m_Vert, v );
  1128. VectorScale( v, 0.5f, v );
  1129. VectorSubtract( m_pVerts[neighborVertIndices[0]].m_Vert, v, segment );
  1130. float errorTerm = ( float )VectorLength( segment );
  1131. VectorAdd( m_pVerts[neighborVertIndices[5]].m_Vert, m_pVerts[neighborVertIndices[6]].m_Vert, v );
  1132. VectorScale( v, 0.5f, v );
  1133. VectorSubtract( m_pVerts[neighborVertIndices[1]].m_Vert, v, segment );
  1134. if( errorTerm < ( float )VectorLength( segment ) )
  1135. errorTerm = ( float )VectorLength( segment );
  1136. VectorAdd( m_pVerts[neighborVertIndices[6]].m_Vert, m_pVerts[neighborVertIndices[7]].m_Vert, v );
  1137. VectorScale( v, 0.5f, v );
  1138. VectorSubtract( m_pVerts[neighborVertIndices[2]].m_Vert, v, segment );
  1139. if( errorTerm < ( float )VectorLength( segment ) )
  1140. errorTerm = ( float )VectorLength( segment );
  1141. VectorAdd( m_pVerts[neighborVertIndices[7]].m_Vert, m_pVerts[neighborVertIndices[4]].m_Vert, v );
  1142. VectorScale( v, 0.5f, v );
  1143. VectorSubtract( m_pVerts[neighborVertIndices[3]].m_Vert, v, segment );
  1144. if( errorTerm < ( float )VectorLength( segment ) )
  1145. errorTerm = ( float )VectorLength( segment );
  1146. VectorAdd( m_pVerts[neighborVertIndices[4]].m_Vert, m_pVerts[neighborVertIndices[6]].m_Vert, v );
  1147. VectorScale( v, 0.5f, v );
  1148. VectorSubtract( m_pVerts[neighborVertIndices[8]].m_Vert, v, segment );
  1149. if( errorTerm < ( float )VectorLength( segment ) )
  1150. errorTerm = ( float )VectorLength( segment );
  1151. VectorAdd( m_pVerts[neighborVertIndices[5]].m_Vert, m_pVerts[neighborVertIndices[7]].m_Vert, v );
  1152. VectorScale( v, 0.5f, v );
  1153. VectorSubtract( m_pVerts[neighborVertIndices[8]].m_Vert, v, segment );
  1154. if( errorTerm < ( float )VectorLength( segment ) )
  1155. errorTerm = ( float )VectorLength( segment );
  1156. //
  1157. // add the max child's error term
  1158. //
  1159. errorTerm += GetMaxErrorFromChildren( nodeIndex, level );
  1160. // set the error term
  1161. m_Nodes[nodeIndex].SetErrorTerm( errorTerm );
  1162. }
  1163. //-----------------------------------------------------------------------------
  1164. //-----------------------------------------------------------------------------
  1165. void CCoreDispInfo::CalcNeighborVertIndicesAtNode( int nodeIndex, int level )
  1166. {
  1167. // calculate the shift in direction in the matrix
  1168. int shift = ( 1 << ( m_Power - level ) );
  1169. // calculate the width, height of the displacement surface (are uniform)
  1170. int extent = ( ( 1 << m_Power ) + 1 );
  1171. //
  1172. // get the neighbor vertex indices (defining the surface at the node level)
  1173. //
  1174. for( int direction = 0; direction < 8; direction++ )
  1175. {
  1176. //
  1177. // get the parent vertex index in component form
  1178. //
  1179. int posX = m_Nodes[nodeIndex].GetCenterVertIndex() % extent;
  1180. int posY = m_Nodes[nodeIndex].GetCenterVertIndex() / extent;
  1181. //
  1182. // calculate the neighboring vertex indices for surface rendering
  1183. //
  1184. bool bError = false;
  1185. switch( direction )
  1186. {
  1187. case WEST: { posX -= shift; break; }
  1188. case NORTH: { posY += shift; break; }
  1189. case EAST: { posX += shift; break; }
  1190. case SOUTH: { posY -= shift; break; }
  1191. case SOUTHWEST: { posX -= shift; posY -= shift; break; }
  1192. case SOUTHEAST: { posX += shift; posY -= shift; break; }
  1193. case NORTHWEST: { posX -= shift; posY += shift; break; }
  1194. case NORTHEAST: { posX += shift; posY += shift; break; }
  1195. default: { bError = true; break; }
  1196. }
  1197. if( bError )
  1198. {
  1199. m_Nodes[nodeIndex].SetNeighborVertIndex( direction, -99999 );
  1200. }
  1201. else
  1202. {
  1203. m_Nodes[nodeIndex].SetNeighborVertIndex( direction, ( ( posY * extent ) + posX ) );
  1204. }
  1205. }
  1206. }
  1207. //-----------------------------------------------------------------------------
  1208. //-----------------------------------------------------------------------------
  1209. void CCoreDispInfo::CalcNodeInfo( int nodeIndex, int terminationLevel )
  1210. {
  1211. // get the level of the current node
  1212. int level = GetNodeLevel( nodeIndex );
  1213. //
  1214. // get the node data at the termination level
  1215. //
  1216. if( level == terminationLevel )
  1217. {
  1218. // get the neighbor vertex indices (used to create surface at node level)
  1219. CalcNeighborVertIndicesAtNode( nodeIndex, level );
  1220. // get the neighbor node indices
  1221. //CalcNeighborNodeIndicesAtNode( nodeIndex, level );
  1222. // calculate the error term at the node
  1223. CalcErrorTermAtNode( nodeIndex, level );
  1224. // calcluate the axial-aligned bounding box at the node
  1225. CalcBoundingBoxAtNode( nodeIndex );
  1226. // calculate the triangular surface info at the node
  1227. CalcTriSurfInfoAtNode( nodeIndex );
  1228. return;
  1229. }
  1230. //
  1231. // continue recursion (down to nodes "children")
  1232. //
  1233. for( int i = 4; i < 8; i++ )
  1234. {
  1235. int childIndex = GetNodeChild( m_Power, nodeIndex, i );
  1236. CalcNodeInfo( childIndex, terminationLevel );
  1237. }
  1238. }
  1239. //-----------------------------------------------------------------------------
  1240. //-----------------------------------------------------------------------------
  1241. int CCoreDispInfo::GetNodeVertIndexFromParentIndex( int level, int parentVertIndex, int direction )
  1242. {
  1243. // calculate the "shift"
  1244. int shift = ( 1 << ( m_Power - ( level + 1 ) ) );
  1245. // calculate the width and height of displacement (is uniform)
  1246. int extent = ( ( 1 << m_Power ) + 1 );
  1247. // get the parent vertex index in component form
  1248. int posX = parentVertIndex % extent;
  1249. int posY = parentVertIndex / extent;
  1250. //
  1251. // calculate the child index based on the parent index and child
  1252. // direction
  1253. //
  1254. switch( direction )
  1255. {
  1256. case SOUTHWEST: { posX -= shift; posY -= shift; break; }
  1257. case SOUTHEAST: { posX += shift; posY -= shift; break; }
  1258. case NORTHWEST: { posX -= shift; posY += shift; break; }
  1259. case NORTHEAST: { posX += shift; posY += shift; break; }
  1260. default: return -99999;
  1261. }
  1262. // return the child vertex index
  1263. return ( ( posY * extent ) + posX );
  1264. }
  1265. //-----------------------------------------------------------------------------
  1266. //-----------------------------------------------------------------------------
  1267. void CCoreDispInfo::CalcVertIndicesAtNodes( int nodeIndex )
  1268. {
  1269. //
  1270. // check for recursion termination ( node level = power )
  1271. //
  1272. int level = GetNodeLevel( nodeIndex );
  1273. if( level == m_Power )
  1274. return;
  1275. //
  1276. // get the children indices - SW, SE, NW, NE
  1277. //
  1278. int childIndices[4];
  1279. int i, j;
  1280. for( i = 0, j = 4; i < 4; i++, j++ )
  1281. {
  1282. childIndices[i] = GetNodeChild( m_Power, nodeIndex, j );
  1283. int centerIndex = GetNodeVertIndexFromParentIndex( level, m_Nodes[nodeIndex].GetCenterVertIndex(), j );
  1284. m_Nodes[childIndices[i]].SetCenterVertIndex( centerIndex );
  1285. }
  1286. //
  1287. // calculate the children's node vertex indices
  1288. //
  1289. for( i = 0; i < 4; i++ )
  1290. {
  1291. CalcVertIndicesAtNodes( childIndices[i] );
  1292. }
  1293. }
  1294. //-----------------------------------------------------------------------------
  1295. //-----------------------------------------------------------------------------
  1296. void CCoreDispInfo::GenerateLODTree( void )
  1297. {
  1298. //
  1299. // calculate the displacement surface's vertex index at each quad-tree node
  1300. // centroid
  1301. //
  1302. int size = GetSize();
  1303. int initialIndex = ( ( size - 1 ) >> 1 );
  1304. m_Nodes[0].SetCenterVertIndex( initialIndex );
  1305. CalcVertIndicesAtNodes( 0 );
  1306. //
  1307. // calculate the error terms, bounding boxes, and neighboring vertex indices
  1308. // at each node
  1309. //
  1310. for( int i = m_Power; i > 0; i-- )
  1311. {
  1312. CalcNodeInfo( 0, i );
  1313. }
  1314. }
  1315. //-----------------------------------------------------------------------------
  1316. //-----------------------------------------------------------------------------
  1317. void CCoreDispInfo::CalcDispSurfCoords( bool bLightMap, int lightmapID )
  1318. {
  1319. //
  1320. // get base surface texture coords
  1321. //
  1322. Vector2D texCoords[4];
  1323. Vector2D luxelCoords[4];
  1324. CCoreDispSurface *pSurf = GetSurface();
  1325. int i;
  1326. for( i = 0; i < 4; i++ )
  1327. {
  1328. pSurf->GetTexCoord( i, texCoords[i] );
  1329. pSurf->GetLuxelCoord( lightmapID, i, luxelCoords[i] );
  1330. }
  1331. //
  1332. // get images width and intervals along the edge
  1333. //
  1334. int postSpacing = GetPostSpacing();
  1335. float ooInt = ( 1.0f / ( float )( postSpacing - 1 ) );
  1336. //
  1337. // calculate the parallel edge intervals
  1338. //
  1339. Vector2D edgeInt[2];
  1340. if( !bLightMap )
  1341. {
  1342. Vector2DSubtract( texCoords[1], texCoords[0], edgeInt[0] );
  1343. Vector2DSubtract( texCoords[2], texCoords[3], edgeInt[1] );
  1344. }
  1345. else
  1346. {
  1347. Vector2DSubtract( luxelCoords[1], luxelCoords[0], edgeInt[0] );
  1348. Vector2DSubtract( luxelCoords[2], luxelCoords[3], edgeInt[1] );
  1349. }
  1350. Vector2DMultiply( edgeInt[0], ooInt, edgeInt[0] );
  1351. Vector2DMultiply( edgeInt[1], ooInt, edgeInt[1] );
  1352. //
  1353. // calculate the displacement points
  1354. //
  1355. for( i = 0; i < postSpacing; i++ )
  1356. {
  1357. //
  1358. // position along parallel edges (start and end for a perpendicular segment)
  1359. //
  1360. Vector2D endPts[2];
  1361. Vector2DMultiply( edgeInt[0], ( float )i, endPts[0] );
  1362. Vector2DMultiply( edgeInt[1], ( float )i, endPts[1] );
  1363. if( !bLightMap )
  1364. {
  1365. Vector2DAdd( endPts[0], texCoords[0], endPts[0] );
  1366. Vector2DAdd( endPts[1], texCoords[3], endPts[1] );
  1367. }
  1368. else
  1369. {
  1370. Vector2DAdd( endPts[0], luxelCoords[0], endPts[0] );
  1371. Vector2DAdd( endPts[1], luxelCoords[3], endPts[1] );
  1372. }
  1373. //
  1374. // interval length for perpendicular edge
  1375. //
  1376. Vector2D seg, segInt;
  1377. Vector2DSubtract( endPts[1], endPts[0], seg );
  1378. Vector2DMultiply( seg, ooInt, segInt );
  1379. //
  1380. // calculate the material (texture or light) coordinate at each point
  1381. //
  1382. for( int j = 0; j < postSpacing; j++ )
  1383. {
  1384. Vector2DMultiply( segInt, ( float )j, seg );
  1385. if( !bLightMap )
  1386. {
  1387. Vector2DAdd( endPts[0], seg, m_pVerts[i*postSpacing+j].m_TexCoord );
  1388. }
  1389. else
  1390. {
  1391. Vector2DAdd( endPts[0], seg, m_pVerts[i*postSpacing+j].m_LuxelCoords[lightmapID] );
  1392. }
  1393. }
  1394. }
  1395. }
  1396. #if 0
  1397. //-----------------------------------------------------------------------------
  1398. //-----------------------------------------------------------------------------
  1399. void CCoreDispInfo::CalcDispSurfAlphas( void )
  1400. {
  1401. //
  1402. // get images width and intervals along the edge
  1403. //
  1404. int postSpacing = GetPostSpacing();
  1405. float ooInt = ( 1.0f / ( float )( postSpacing - 1 ) );
  1406. //
  1407. // calculate the parallel edge intervals
  1408. //
  1409. float edgeInt[2];
  1410. edgeInt[0] = m_Surf.m_Alpha[1] - m_Surf.m_Alpha[0];
  1411. edgeInt[1] = m_Surf.m_Alpha[2] - m_Surf.m_Alpha[3];
  1412. edgeInt[0] *= ooInt;
  1413. edgeInt[1] *= ooInt;
  1414. //
  1415. // calculate the displacement points
  1416. //
  1417. for( int i = 0; i < postSpacing; i++ )
  1418. {
  1419. //
  1420. // position along parallel edges (start and end for a perpendicular segment)
  1421. //
  1422. float endValues[2];
  1423. endValues[0] = edgeInt[0] * ( float )i;
  1424. endValues[1] = edgeInt[1] * ( float )i;
  1425. endValues[0] += m_Surf.m_Alpha[0];
  1426. endValues[1] += m_Surf.m_Alpha[3];
  1427. //
  1428. // interval length for perpendicular edge
  1429. //
  1430. float seg, segInt;
  1431. seg = endValues[1] - endValues[0];
  1432. segInt = seg * ooInt;
  1433. //
  1434. // calculate the alpha value at each point
  1435. //
  1436. for( int j = 0; j < postSpacing; j++ )
  1437. {
  1438. seg = segInt * ( float )j;
  1439. m_Alphas[i*postSpacing+j] = endValues[0] + seg;
  1440. }
  1441. }
  1442. }
  1443. #endif
  1444. //-----------------------------------------------------------------------------
  1445. //-----------------------------------------------------------------------------
  1446. void CCoreDispInfo::GenerateDispSurfTangentSpaces( void )
  1447. {
  1448. //
  1449. // get texture axes from base surface
  1450. //
  1451. CCoreDispSurface *pSurf = GetSurface();
  1452. Vector sAxis, tAxis;
  1453. pSurf->GetSAxis( sAxis );
  1454. pSurf->GetTAxis( tAxis );
  1455. //
  1456. // calculate the tangent spaces
  1457. //
  1458. int size = GetSize();
  1459. for( int i = 0; i < size; i++ )
  1460. {
  1461. //
  1462. // create the axes - normals, tangents, and binormals
  1463. //
  1464. VectorCopy( tAxis, m_pVerts[i].m_TangentT );
  1465. VectorNormalize( m_pVerts[i].m_TangentT );
  1466. CrossProduct( m_pVerts[i].m_Normal, m_pVerts[i].m_TangentT, m_pVerts[i].m_TangentS );
  1467. VectorNormalize( m_pVerts[i].m_TangentS );
  1468. CrossProduct( m_pVerts[i].m_TangentS, m_pVerts[i].m_Normal, m_pVerts[i].m_TangentT );
  1469. VectorNormalize( m_pVerts[i].m_TangentT );
  1470. Vector tmpVect;
  1471. Vector planeNormal;
  1472. pSurf->GetNormal( planeNormal );
  1473. CrossProduct( sAxis, tAxis, tmpVect );
  1474. if( DotProduct( planeNormal, tmpVect ) > 0.0f )
  1475. {
  1476. VectorScale( m_pVerts[i].m_TangentS, -1.0f, m_pVerts[i].m_TangentS );
  1477. }
  1478. }
  1479. }
  1480. //-----------------------------------------------------------------------------
  1481. //-----------------------------------------------------------------------------
  1482. void CCoreDispInfo::CalcNormalFromEdges( int indexRow, int indexCol, bool bIsEdge[4],
  1483. Vector& normal )
  1484. {
  1485. // get the post spacing (size/interval of displacement surface)
  1486. int postSpacing = ( ( 1 << m_Power ) + 1 );
  1487. // initialize the normal accumulator - counter
  1488. Vector accumNormal;
  1489. int normalCount = 0;
  1490. VectorClear( accumNormal );
  1491. Vector tmpVect[2];
  1492. Vector tmpNormal;
  1493. //
  1494. // check quadrant I (posX, posY)
  1495. //
  1496. if( bIsEdge[1] && bIsEdge[2] )
  1497. {
  1498. // tri i
  1499. VectorSubtract( m_pVerts[(indexCol+1)*postSpacing+indexRow].m_Vert, m_pVerts[indexCol*postSpacing+indexRow].m_Vert, tmpVect[0] );
  1500. VectorSubtract( m_pVerts[indexCol*postSpacing+(indexRow+1)].m_Vert, m_pVerts[indexCol*postSpacing+indexRow].m_Vert, tmpVect[1] );
  1501. CrossProduct( tmpVect[1], tmpVect[0], tmpNormal );
  1502. VectorNormalize( tmpNormal );
  1503. VectorAdd( accumNormal, tmpNormal, accumNormal );
  1504. normalCount++;
  1505. // tri 2
  1506. VectorSubtract( m_pVerts[(indexCol+1)*postSpacing+indexRow].m_Vert, m_pVerts[indexCol*postSpacing+(indexRow+1)].m_Vert, tmpVect[0] );
  1507. VectorSubtract( m_pVerts[(indexCol+1)*postSpacing+(indexRow+1)].m_Vert, m_pVerts[indexCol*postSpacing+(indexRow+1)].m_Vert, tmpVect[1] );
  1508. CrossProduct( tmpVect[1], tmpVect[0], tmpNormal );
  1509. VectorNormalize( tmpNormal );
  1510. VectorAdd( accumNormal, tmpNormal, accumNormal );
  1511. normalCount++;
  1512. }
  1513. //
  1514. // check quadrant II (negX, posY)
  1515. //
  1516. if( bIsEdge[0] && bIsEdge[1] )
  1517. {
  1518. // tri i
  1519. VectorSubtract( m_pVerts[(indexCol+1)*postSpacing+(indexRow-1)].m_Vert, m_pVerts[indexCol*postSpacing+(indexRow-1)].m_Vert, tmpVect[0] );
  1520. VectorSubtract( m_pVerts[indexCol*postSpacing+indexRow].m_Vert, m_pVerts[indexCol*postSpacing+(indexRow-1)].m_Vert, tmpVect[1] );
  1521. CrossProduct( tmpVect[1], tmpVect[0], tmpNormal );
  1522. VectorNormalize( tmpNormal );
  1523. VectorAdd( accumNormal, tmpNormal, accumNormal );
  1524. normalCount++;
  1525. // tri 2
  1526. VectorSubtract( m_pVerts[(indexCol+1)*postSpacing+(indexRow-1)].m_Vert, m_pVerts[indexCol*postSpacing+indexRow].m_Vert, tmpVect[0] );
  1527. VectorSubtract( m_pVerts[(indexCol+1)*postSpacing+indexRow].m_Vert, m_pVerts[indexCol*postSpacing+indexRow].m_Vert, tmpVect[1] );
  1528. CrossProduct( tmpVect[1], tmpVect[0], tmpNormal );
  1529. VectorNormalize( tmpNormal );
  1530. VectorAdd( accumNormal, tmpNormal, accumNormal );
  1531. normalCount++;
  1532. }
  1533. //
  1534. // check quadrant III (negX, negY)
  1535. //
  1536. if( bIsEdge[0] && bIsEdge[3] )
  1537. {
  1538. // tri i
  1539. VectorSubtract( m_pVerts[indexCol*postSpacing+(indexRow-1)].m_Vert, m_pVerts[(indexCol-1)*postSpacing+(indexRow-1)].m_Vert, tmpVect[0] );
  1540. VectorSubtract( m_pVerts[(indexCol-1)*postSpacing+indexRow].m_Vert, m_pVerts[(indexCol-1)*postSpacing+(indexRow-1)].m_Vert, tmpVect[1] );
  1541. CrossProduct( tmpVect[1], tmpVect[0], tmpNormal );
  1542. VectorNormalize( tmpNormal );
  1543. VectorAdd( accumNormal, tmpNormal, accumNormal );
  1544. normalCount++;
  1545. // tri 2
  1546. VectorSubtract( m_pVerts[indexCol*postSpacing+(indexRow-1)].m_Vert, m_pVerts[(indexCol-1)*postSpacing+indexRow].m_Vert, tmpVect[0] );
  1547. VectorSubtract( m_pVerts[indexCol*postSpacing+indexRow].m_Vert, m_pVerts[(indexCol-1)*postSpacing+indexRow].m_Vert, tmpVect[1] );
  1548. CrossProduct( tmpVect[1], tmpVect[0], tmpNormal );
  1549. VectorNormalize( tmpNormal );
  1550. VectorAdd( accumNormal, tmpNormal, accumNormal );
  1551. normalCount++;
  1552. }
  1553. //
  1554. // check quadrant IV (posX, negY)
  1555. //
  1556. if( bIsEdge[2] && bIsEdge[3] )
  1557. {
  1558. // tri i
  1559. VectorSubtract( m_pVerts[indexCol*postSpacing+indexRow].m_Vert, m_pVerts[(indexCol-1)*postSpacing+indexRow].m_Vert, tmpVect[0] );
  1560. VectorSubtract( m_pVerts[(indexCol-1)*postSpacing+(indexRow+1)].m_Vert, m_pVerts[(indexCol-1)*postSpacing+indexRow].m_Vert, tmpVect[1] );
  1561. CrossProduct( tmpVect[1], tmpVect[0], tmpNormal );
  1562. VectorNormalize( tmpNormal );
  1563. VectorAdd( accumNormal, tmpNormal, accumNormal );
  1564. normalCount++;
  1565. // tri 2
  1566. VectorSubtract( m_pVerts[indexCol*postSpacing+indexRow].m_Vert, m_pVerts[(indexCol-1)*postSpacing+(indexRow+1)].m_Vert, tmpVect[0] );
  1567. VectorSubtract( m_pVerts[indexCol*postSpacing+(indexRow+1)].m_Vert, m_pVerts[(indexCol-1)*postSpacing+(indexRow+1)].m_Vert, tmpVect[1] );
  1568. CrossProduct( tmpVect[1], tmpVect[0], tmpNormal );
  1569. VectorNormalize( tmpNormal );
  1570. VectorAdd( accumNormal, tmpNormal, accumNormal );
  1571. normalCount++;
  1572. }
  1573. VectorScale( accumNormal, ( 1.0f / ( float )normalCount ), normal );
  1574. }
  1575. //-----------------------------------------------------------------------------
  1576. // Purpose: This function determines if edges exist in each of the directions
  1577. // off of the given point (given in component form). We know ahead of
  1578. // time that there are only 4 possibilities.
  1579. //
  1580. // 1 "directions"
  1581. // 0 + 2
  1582. // 3
  1583. //
  1584. // Input: indexRow - row position
  1585. // indexCol - col position
  1586. // direction - the direction (edge) currently being evaluated
  1587. // postSpacing - the number of intervals in the row and col directions
  1588. // Output: the edge existed? (true/false)
  1589. //-----------------------------------------------------------------------------
  1590. bool CCoreDispInfo::DoesEdgeExist( int indexRow, int indexCol, int direction, int postSpacing )
  1591. {
  1592. switch( direction )
  1593. {
  1594. case 0:
  1595. // left edge
  1596. if( ( indexRow - 1 ) < 0 )
  1597. return false;
  1598. return true;
  1599. case 1:
  1600. // top edge
  1601. if( ( indexCol + 1 ) > ( postSpacing - 1 ) )
  1602. return false;
  1603. return true;
  1604. case 2:
  1605. // right edge
  1606. if( ( indexRow + 1 ) > ( postSpacing - 1 ) )
  1607. return false;
  1608. return true;
  1609. case 3:
  1610. // bottom edge
  1611. if( ( indexCol - 1 ) < 0 )
  1612. return false;
  1613. return true;
  1614. default:
  1615. return false;
  1616. }
  1617. }
  1618. //-----------------------------------------------------------------------------
  1619. //-----------------------------------------------------------------------------
  1620. void CCoreDispInfo::GenerateDispSurfNormals( void )
  1621. {
  1622. // get the post spacing (size/interval of displacement surface)
  1623. int postSpacing = GetPostSpacing();
  1624. //
  1625. // generate the normals at each displacement surface vertex
  1626. //
  1627. for( int i = 0; i < postSpacing; i++ )
  1628. {
  1629. for( int j = 0; j < postSpacing; j++ )
  1630. {
  1631. bool bIsEdge[4];
  1632. // edges
  1633. for( int k = 0; k < 4; k++ )
  1634. {
  1635. bIsEdge[k] = DoesEdgeExist( j, i, k, postSpacing );
  1636. }
  1637. Vector normal;
  1638. CalcNormalFromEdges( j, i, bIsEdge, normal );
  1639. // save generated normal
  1640. VectorCopy( normal, m_pVerts[i*postSpacing+j].m_Normal );
  1641. }
  1642. }
  1643. }
  1644. //-----------------------------------------------------------------------------
  1645. //-----------------------------------------------------------------------------
  1646. void CCoreDispInfo::GenerateDispSurf( void )
  1647. {
  1648. int i;
  1649. CCoreDispSurface *pSurf = GetSurface();
  1650. Vector points[4];
  1651. for( i = 0; i < 4; i++ )
  1652. {
  1653. pSurf->GetPoint( i, points[i] );
  1654. }
  1655. //
  1656. // get the spacing (interval = width/height, are equal because it is uniform) along the edge
  1657. //
  1658. int postSpacing = GetPostSpacing();
  1659. float ooInt = 1.0f / ( float )( postSpacing - 1 );
  1660. //
  1661. // calculate the opposite edge intervals
  1662. //
  1663. Vector edgeInt[2];
  1664. VectorSubtract( points[1], points[0], edgeInt[0] );
  1665. VectorScale( edgeInt[0], ooInt, edgeInt[0] );
  1666. VectorSubtract( points[2], points[3], edgeInt[1] );
  1667. VectorScale( edgeInt[1], ooInt, edgeInt[1] );
  1668. Vector elevNormal;
  1669. elevNormal.Init();
  1670. if( m_Elevation != 0.0f )
  1671. {
  1672. pSurf->GetNormal( elevNormal );
  1673. VectorScale( elevNormal, m_Elevation, elevNormal );
  1674. }
  1675. //
  1676. // calculate the displaced vertices
  1677. //
  1678. for( i = 0; i < postSpacing; i++ )
  1679. {
  1680. //
  1681. // calculate segment interval between opposite edges
  1682. //
  1683. Vector endPts[2];
  1684. VectorScale( edgeInt[0], ( float )i, endPts[0] );
  1685. VectorAdd( endPts[0], points[0], endPts[0] );
  1686. VectorScale( edgeInt[1], ( float )i, endPts[1] );
  1687. VectorAdd( endPts[1], points[3], endPts[1] );
  1688. Vector seg, segInt;
  1689. VectorSubtract( endPts[1], endPts[0], seg );
  1690. VectorScale( seg, ooInt, segInt );
  1691. //
  1692. // calculate the surface vertices
  1693. //
  1694. for( int j = 0; j < postSpacing; j++ )
  1695. {
  1696. int ndx = i * postSpacing + j;
  1697. CoreDispVert_t *pVert = &m_pVerts[ndx];
  1698. // calculate the flat surface position -- saved separately
  1699. pVert->m_FlatVert = endPts[0] + ( segInt * ( float )j );
  1700. // start with the base surface position
  1701. pVert->m_Vert = pVert->m_FlatVert;
  1702. // add the elevation vector -- if it exists
  1703. if( m_Elevation != 0.0f )
  1704. {
  1705. pVert->m_Vert += elevNormal;
  1706. }
  1707. // add the subdivision surface position
  1708. pVert->m_Vert += pVert->m_SubdivPos;
  1709. // add the displacement field direction(normalized) and distance
  1710. pVert->m_Vert += pVert->m_FieldVector * pVert->m_FieldDistance;
  1711. }
  1712. }
  1713. }
  1714. //-----------------------------------------------------------------------------
  1715. //-----------------------------------------------------------------------------
  1716. //bool CCoreDispInfo::Create( int creationFlags )
  1717. bool CCoreDispInfo::Create( void )
  1718. {
  1719. // sanity check
  1720. CCoreDispSurface *pSurf = GetSurface();
  1721. if( pSurf->GetPointCount() != 4 )
  1722. return false;
  1723. // generate the displacement surface
  1724. GenerateDispSurf();
  1725. GenerateDispSurfNormals();
  1726. GenerateDispSurfTangentSpaces();
  1727. CalcDispSurfCoords( false, 0 );
  1728. for( int bumpID = 0; bumpID < ( NUM_BUMP_VECTS + 1 ); bumpID++ )
  1729. {
  1730. CalcDispSurfCoords( true, bumpID );
  1731. }
  1732. GenerateLODTree();
  1733. GenerateCollisionData();
  1734. CreateTris();
  1735. return true;
  1736. }
  1737. //-----------------------------------------------------------------------------
  1738. // Purpose: Create a displacement surface without generating the LOD for it.
  1739. //-----------------------------------------------------------------------------
  1740. bool CCoreDispInfo::CreateWithoutLOD( void )
  1741. {
  1742. // sanity check
  1743. CCoreDispSurface *pSurf = GetSurface();
  1744. if( pSurf->GetPointCount() != 4 )
  1745. return false;
  1746. GenerateDispSurf();
  1747. GenerateDispSurfNormals();
  1748. GenerateDispSurfTangentSpaces();
  1749. CalcDispSurfCoords( false, 0 );
  1750. for( int bumpID = 0; bumpID < ( NUM_BUMP_VECTS + 1 ); bumpID++ )
  1751. {
  1752. CalcDispSurfCoords( true, bumpID );
  1753. }
  1754. GenerateCollisionData();
  1755. CreateTris();
  1756. return true;
  1757. }
  1758. //-----------------------------------------------------------------------------
  1759. // Purpose: This function calculates the neighbor node index given the base
  1760. // node and direction of the neighbor node in the tree.
  1761. // Input: power - the size in one dimension of the displacement map (2^power + 1 )
  1762. // index - the "base" node index
  1763. // direction - the direction of the neighbor { W = 1, N = 2, E = 3, S = 4 }
  1764. // Output: returns the index of the neighbor node
  1765. //-----------------------------------------------------------------------------
  1766. int GetNodeNeighborNode( int power, int index, int direction, int level )
  1767. {
  1768. // adjust the index to range [0...?]
  1769. int minNodeIndex = GetNodeMinNodeAtLevel( level );
  1770. // get node extent (uniform: height = width)
  1771. int nodeExtent = ( 1 << ( level - 1 ) );
  1772. //
  1773. // get node's component positions in quad-tree
  1774. //
  1775. int posX, posY;
  1776. GetComponentsFromNodeIndex( ( index - minNodeIndex ), &posX, &posY );
  1777. //
  1778. // find the neighbor in the "direction"
  1779. //
  1780. switch( direction )
  1781. {
  1782. case CCoreDispInfo::WEST:
  1783. {
  1784. if( ( posX - 1 ) < 0 )
  1785. {
  1786. return -( CCoreDispInfo::WEST + 1 );
  1787. }
  1788. else
  1789. {
  1790. return ( GetNodeIndexFromComponents( ( posX - 1 ), posY ) + minNodeIndex );
  1791. }
  1792. }
  1793. case CCoreDispInfo::NORTH:
  1794. {
  1795. if( ( posY + 1 ) == nodeExtent )
  1796. {
  1797. return -( CCoreDispInfo::NORTH + 1 );
  1798. }
  1799. else
  1800. {
  1801. return ( GetNodeIndexFromComponents( posX, ( posY + 1 ) ) + minNodeIndex );
  1802. }
  1803. }
  1804. case CCoreDispInfo::EAST:
  1805. {
  1806. if( ( posX + 1 ) == nodeExtent )
  1807. {
  1808. return -( CCoreDispInfo::EAST + 1 );
  1809. }
  1810. else
  1811. {
  1812. return ( GetNodeIndexFromComponents( ( posX + 1 ), posY ) + minNodeIndex );
  1813. }
  1814. }
  1815. case CCoreDispInfo::SOUTH:
  1816. {
  1817. if( ( posY - 1 ) < 0 )
  1818. {
  1819. return -( CCoreDispInfo::SOUTH + 1 );
  1820. }
  1821. else
  1822. {
  1823. return ( GetNodeIndexFromComponents( posX, ( posY - 1 ) ) + minNodeIndex );
  1824. }
  1825. }
  1826. default:
  1827. {
  1828. return -99999;
  1829. }
  1830. }
  1831. }
  1832. //-----------------------------------------------------------------------------
  1833. //-----------------------------------------------------------------------------
  1834. int GetNodeNeighborNodeFromNeighborSurf( int power, int index, int direction, int level, int neighborOrient )
  1835. {
  1836. // adjust the index to range [0...?]
  1837. int minNodeIndex = GetNodeMinNodeAtLevel( level );
  1838. // get node extent (uniform: height = width)
  1839. int nodeExtent = ( 1 << ( level - 1 ) );
  1840. //
  1841. // get node's component positions in quad-tree
  1842. //
  1843. int posX, posY;
  1844. GetComponentsFromNodeIndex( ( index - minNodeIndex ), &posX, &posY );
  1845. switch( direction )
  1846. {
  1847. case CCoreDispInfo::WEST:
  1848. {
  1849. switch( neighborOrient )
  1850. {
  1851. case CCoreDispInfo::WEST: return -( ( GetNodeIndexFromComponents( posX, ( ( nodeExtent - 1 ) - posY ) ) ) + minNodeIndex );
  1852. case CCoreDispInfo::NORTH: return -( ( GetNodeIndexFromComponents( ( nodeExtent - 1 ) - posY, ( nodeExtent - 1 ) ) ) + minNodeIndex );
  1853. case CCoreDispInfo::EAST: return -( ( GetNodeIndexFromComponents( ( nodeExtent - 1 ), posY ) ) + minNodeIndex );
  1854. case CCoreDispInfo::SOUTH: return -( ( GetNodeIndexFromComponents( posY, posX ) ) + minNodeIndex );
  1855. default: return -99999;
  1856. }
  1857. }
  1858. case CCoreDispInfo::NORTH:
  1859. {
  1860. switch( neighborOrient )
  1861. {
  1862. case CCoreDispInfo::WEST: return -( ( GetNodeIndexFromComponents( ( ( nodeExtent - 1 ) - posY ), ( ( nodeExtent - 1 ) - posX ) ) ) + minNodeIndex );
  1863. case CCoreDispInfo::NORTH: return -( ( GetNodeIndexFromComponents( ( ( nodeExtent - 1 ) - posX ), posY ) ) + minNodeIndex );
  1864. case CCoreDispInfo::EAST: return -( ( GetNodeIndexFromComponents( posY, posX ) ) + minNodeIndex );
  1865. case CCoreDispInfo::SOUTH: return -( ( GetNodeIndexFromComponents( posX, ( ( nodeExtent - 1 ) - posY ) ) ) + minNodeIndex );
  1866. default: return -99999;
  1867. }
  1868. }
  1869. case CCoreDispInfo::EAST:
  1870. {
  1871. switch( neighborOrient )
  1872. {
  1873. case CCoreDispInfo::WEST: return -( ( GetNodeIndexFromComponents( ( ( nodeExtent - 1 ) - posX ), posY ) ) + minNodeIndex );
  1874. case CCoreDispInfo::NORTH: return -( ( GetNodeIndexFromComponents( posY, posX ) ) + minNodeIndex );
  1875. case CCoreDispInfo::EAST: return -( ( GetNodeIndexFromComponents( posX, ( ( nodeExtent - 1 ) - posY ) ) ) + minNodeIndex );
  1876. case CCoreDispInfo::SOUTH: return -( ( GetNodeIndexFromComponents( ( ( nodeExtent - 1 ) - posY ), ( ( nodeExtent - 1 ) - posX ) ) ) + minNodeIndex );
  1877. default: return -99999;
  1878. }
  1879. }
  1880. case CCoreDispInfo::SOUTH:
  1881. {
  1882. switch( neighborOrient )
  1883. {
  1884. case CCoreDispInfo::WEST: return -( ( GetNodeIndexFromComponents( posY, posX ) ) + minNodeIndex );
  1885. case CCoreDispInfo::NORTH: return -( ( GetNodeIndexFromComponents( posX, ( nodeExtent - 1 ) ) ) + minNodeIndex );
  1886. case CCoreDispInfo::EAST: return -( ( GetNodeIndexFromComponents( ( nodeExtent - 1 ), ( ( nodeExtent - 1 ) - posX ) ) ) + minNodeIndex );
  1887. case CCoreDispInfo::SOUTH: return -( ( GetNodeIndexFromComponents( ( ( nodeExtent - 1 ) - posX ), posY ) ) + minNodeIndex );
  1888. default: return -99999;
  1889. }
  1890. }
  1891. default:
  1892. {
  1893. return -99999;
  1894. }
  1895. }
  1896. }
  1897. //-----------------------------------------------------------------------------
  1898. //-----------------------------------------------------------------------------
  1899. void CCoreDispInfo::GetPositionOnSurface( float u, float v, Vector &vPos,
  1900. Vector *pNormal, float *pAlpha )
  1901. {
  1902. Vector2D dispUV( u, v );
  1903. DispUVToSurf( dispUV, vPos, pNormal, pAlpha );
  1904. }
  1905. //-----------------------------------------------------------------------------
  1906. //-----------------------------------------------------------------------------
  1907. void CCoreDispInfo::BaseFacePlaneToDispUV( Vector const &planePt, Vector2D &dispUV )
  1908. {
  1909. // Get the base surface points.
  1910. CCoreDispSurface *pSurf = GetSurface();
  1911. Vector vecPoints[4];
  1912. for( int iPoint = 0; iPoint < 4; ++iPoint )
  1913. {
  1914. pSurf->GetPoint( iPoint, vecPoints[iPoint] );
  1915. }
  1916. PointInQuadToBarycentric( vecPoints[0], vecPoints[3], vecPoints[2], vecPoints[1], planePt, dispUV );
  1917. }
  1918. //-----------------------------------------------------------------------------
  1919. // Purpose:
  1920. //-----------------------------------------------------------------------------
  1921. void CCoreDispInfo::DispUVToSurf_TriTLToBR_1( const Vector &vecIntersectPoint,
  1922. int nSnapU, int nNextU, int nSnapV, int nNextV,
  1923. Vector &vecPoint, Vector *pNormal, float *pAlpha,
  1924. bool bBackup )
  1925. {
  1926. int nWidth = GetWidth();
  1927. int nIndices[3];
  1928. nIndices[0] = nNextV * nWidth + nSnapU;
  1929. nIndices[1] = nNextV * nWidth + nNextU;
  1930. nIndices[2] = nSnapV * nWidth + nNextU;
  1931. Vector vecFlatVerts[3], vecVerts[3];
  1932. float flAlphas[3];
  1933. for ( int iVert = 0; iVert < 3; ++iVert )
  1934. {
  1935. vecFlatVerts[iVert] = m_pVerts[nIndices[iVert]].m_FlatVert;
  1936. vecVerts[iVert] = m_pVerts[nIndices[iVert]].m_Vert;
  1937. flAlphas[iVert] = m_pVerts[nIndices[iVert]].m_Alpha;
  1938. }
  1939. if ( nSnapU == nNextU )
  1940. {
  1941. if ( nSnapV == nNextV )
  1942. {
  1943. vecPoint = vecVerts[0];
  1944. *pAlpha = flAlphas[0];
  1945. }
  1946. else
  1947. {
  1948. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length();
  1949. vecPoint = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) );
  1950. if ( pAlpha )
  1951. {
  1952. *pAlpha = flAlphas[0] + ( flFrac * ( flAlphas[2] - flAlphas[0] ) );
  1953. }
  1954. }
  1955. if( pNormal )
  1956. {
  1957. Vector edgeU = vecVerts[0] - vecVerts[1];
  1958. Vector edgeV = vecVerts[2] - vecVerts[1];
  1959. *pNormal = CrossProduct( edgeU, edgeV );
  1960. VectorNormalize( *pNormal );
  1961. }
  1962. }
  1963. else if ( nSnapV == nNextV )
  1964. {
  1965. if ( nSnapU == nNextU )
  1966. {
  1967. vecPoint = vecVerts[0];
  1968. *pAlpha = flAlphas[0];
  1969. }
  1970. else
  1971. {
  1972. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length();
  1973. vecPoint = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) );
  1974. if ( pAlpha )
  1975. {
  1976. *pAlpha = flAlphas[0] + ( flFrac * ( flAlphas[2] - flAlphas[0] ) );
  1977. }
  1978. }
  1979. if( pNormal )
  1980. {
  1981. Vector edgeU = vecVerts[0] - vecVerts[1];
  1982. Vector edgeV = vecVerts[2] - vecVerts[1];
  1983. *pNormal = CrossProduct( edgeU, edgeV );
  1984. VectorNormalize( *pNormal );
  1985. }
  1986. }
  1987. else
  1988. {
  1989. float flCfs[3];
  1990. if ( CalcBarycentricCooefs( vecFlatVerts[0], vecFlatVerts[1], vecFlatVerts[2], vecIntersectPoint, flCfs[0], flCfs[1], flCfs[2] ) )
  1991. {
  1992. vecPoint = ( vecVerts[0] * flCfs[0] ) + ( vecVerts[1] * flCfs[1] ) + ( vecVerts[2] * flCfs[2] );
  1993. if( pAlpha )
  1994. {
  1995. *pAlpha = ( flAlphas[0] * flCfs[0] ) + ( flAlphas[1] * flCfs[1] ) + ( flAlphas[2] * flCfs[2] );
  1996. }
  1997. if( pNormal )
  1998. {
  1999. Vector edgeU = vecVerts[0] - vecVerts[1];
  2000. Vector edgeV = vecVerts[2] - vecVerts[1];
  2001. *pNormal = CrossProduct( edgeU, edgeV );
  2002. VectorNormalize( *pNormal );
  2003. }
  2004. }
  2005. else
  2006. {
  2007. if ( !bBackup )
  2008. {
  2009. DispUVToSurf_TriTLToBR_2( vecIntersectPoint, nSnapU, nNextU, nSnapV, nNextV, vecPoint, pNormal, pAlpha, true );
  2010. }
  2011. }
  2012. }
  2013. }
  2014. //-----------------------------------------------------------------------------
  2015. // Purpose:
  2016. //-----------------------------------------------------------------------------
  2017. void CCoreDispInfo::DispUVToSurf_TriTLToBR_2( const Vector &vecIntersectPoint,
  2018. int nSnapU, int nNextU, int nSnapV, int nNextV,
  2019. Vector &vecPoint, Vector *pNormal, float *pAlpha,
  2020. bool bBackup )
  2021. {
  2022. int nWidth = GetWidth();
  2023. int nIndices[3];
  2024. nIndices[0] = nSnapV * nWidth + nSnapU;
  2025. nIndices[1] = nNextV * nWidth + nSnapU;
  2026. nIndices[2] = nSnapV * nWidth + nNextU;
  2027. Vector vecFlatVerts[3], vecVerts[3];
  2028. float flAlphas[3];
  2029. for ( int iVert = 0; iVert < 3; ++iVert )
  2030. {
  2031. vecFlatVerts[iVert] = m_pVerts[nIndices[iVert]].m_FlatVert;
  2032. vecVerts[iVert] = m_pVerts[nIndices[iVert]].m_Vert;
  2033. flAlphas[iVert] = m_pVerts[nIndices[iVert]].m_Alpha;
  2034. }
  2035. if ( nSnapU == nNextU )
  2036. {
  2037. if ( nSnapV == nNextV )
  2038. {
  2039. vecPoint = vecVerts[0];
  2040. *pAlpha = flAlphas[0];
  2041. }
  2042. else
  2043. {
  2044. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[1] - vecFlatVerts[0] ).Length();
  2045. vecPoint = vecVerts[0] + ( flFrac * ( vecVerts[1] - vecVerts[0] ) );
  2046. if ( pAlpha )
  2047. {
  2048. *pAlpha = flAlphas[0] + ( flFrac * ( flAlphas[1] - flAlphas[0] ) );
  2049. }
  2050. }
  2051. if( pNormal )
  2052. {
  2053. Vector edgeU = vecVerts[2] - vecVerts[0];
  2054. Vector edgeV = vecVerts[1] - vecVerts[0];
  2055. *pNormal = CrossProduct( edgeU, edgeV );
  2056. VectorNormalize( *pNormal );
  2057. }
  2058. }
  2059. else if ( nSnapV == nNextV )
  2060. {
  2061. if ( nSnapU == nNextU )
  2062. {
  2063. vecPoint = vecVerts[0];
  2064. *pAlpha = flAlphas[0];
  2065. }
  2066. else
  2067. {
  2068. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length();
  2069. vecPoint = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) );
  2070. if ( pAlpha )
  2071. {
  2072. *pAlpha = flAlphas[0] + ( flFrac * ( flAlphas[2] - flAlphas[0] ) );
  2073. }
  2074. }
  2075. if( pNormal )
  2076. {
  2077. Vector edgeU = vecVerts[2] - vecVerts[0];
  2078. Vector edgeV = vecVerts[1] - vecVerts[0];
  2079. *pNormal = CrossProduct( edgeU, edgeV );
  2080. VectorNormalize( *pNormal );
  2081. }
  2082. }
  2083. else
  2084. {
  2085. float flCfs[3];
  2086. if ( CalcBarycentricCooefs( vecFlatVerts[0], vecFlatVerts[1], vecFlatVerts[2], vecIntersectPoint, flCfs[0], flCfs[1], flCfs[2] ) )
  2087. {
  2088. vecPoint = ( vecVerts[0] * flCfs[0] ) + ( vecVerts[1] * flCfs[1] ) + ( vecVerts[2] * flCfs[2] );
  2089. if( pAlpha )
  2090. {
  2091. *pAlpha = ( flAlphas[0] * flCfs[0] ) + ( flAlphas[1] * flCfs[1] ) + ( flAlphas[2] * flCfs[2] );
  2092. }
  2093. if( pNormal )
  2094. {
  2095. Vector edgeU = vecVerts[2] - vecVerts[0];
  2096. Vector edgeV = vecVerts[1] - vecVerts[0];
  2097. *pNormal = CrossProduct( edgeU, edgeV );
  2098. VectorNormalize( *pNormal );
  2099. }
  2100. }
  2101. else
  2102. {
  2103. if ( !bBackup )
  2104. {
  2105. DispUVToSurf_TriTLToBR_1( vecIntersectPoint, nSnapU, nNextU, nSnapV, nNextV, vecPoint, pNormal, pAlpha, true );
  2106. }
  2107. }
  2108. }
  2109. }
  2110. //-----------------------------------------------------------------------------
  2111. // Purpose:
  2112. //-----------------------------------------------------------------------------
  2113. void CCoreDispInfo::DispUVToSurf_TriTLToBR( Vector &vecPoint, Vector *pNormal, float *pAlpha,
  2114. float flU, float flV, const Vector &vecIntersectPoint )
  2115. {
  2116. const float TRIEDGE_EPSILON = 0.00001f;
  2117. int nWidth = GetWidth();
  2118. int nHeight = GetHeight();
  2119. int nSnapU = static_cast<int>( flU );
  2120. int nSnapV = static_cast<int>( flV );
  2121. int nNextU = nSnapU + 1;
  2122. int nNextV = nSnapV + 1;
  2123. if ( nNextU == nWidth) { --nNextU; }
  2124. if ( nNextV == nHeight ) { --nNextV; }
  2125. float flFracU = flU - static_cast<float>( nSnapU );
  2126. float flFracV = flV - static_cast<float>( nSnapV );
  2127. if ( ( flFracU + flFracV ) >= ( 1.0f + TRIEDGE_EPSILON ) )
  2128. {
  2129. DispUVToSurf_TriTLToBR_1( vecIntersectPoint, nSnapU, nNextU, nSnapV, nNextV, vecPoint, pNormal, pAlpha, false );
  2130. }
  2131. else
  2132. {
  2133. DispUVToSurf_TriTLToBR_2( vecIntersectPoint, nSnapU, nNextU, nSnapV, nNextV, vecPoint, pNormal, pAlpha, false );
  2134. }
  2135. }
  2136. //-----------------------------------------------------------------------------
  2137. // Purpose:
  2138. //-----------------------------------------------------------------------------
  2139. void CCoreDispInfo::DispUVToSurf_TriBLToTR_1( const Vector &vecIntersectPoint,
  2140. int nSnapU, int nNextU, int nSnapV, int nNextV,
  2141. Vector &vecPoint, Vector *pNormal, float *pAlpha,
  2142. bool bBackup )
  2143. {
  2144. int nWidth = GetWidth();
  2145. int nIndices[3];
  2146. nIndices[0] = nSnapV * nWidth + nSnapU;
  2147. nIndices[1] = nNextV * nWidth + nSnapU;
  2148. nIndices[2] = nNextV * nWidth + nNextU;
  2149. Vector vecFlatVerts[3], vecVerts[3];
  2150. float flAlphas[3];
  2151. for ( int iVert = 0; iVert < 3; ++iVert )
  2152. {
  2153. vecFlatVerts[iVert] = m_pVerts[nIndices[iVert]].m_FlatVert;
  2154. vecVerts[iVert] = m_pVerts[nIndices[iVert]].m_Vert;
  2155. flAlphas[iVert] = m_pVerts[nIndices[iVert]].m_Alpha;
  2156. }
  2157. if ( nSnapU == nNextU )
  2158. {
  2159. if ( nSnapV == nNextV )
  2160. {
  2161. vecPoint = vecVerts[0];
  2162. *pAlpha = flAlphas[0];
  2163. }
  2164. else
  2165. {
  2166. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length();
  2167. vecPoint = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) );
  2168. if ( pAlpha )
  2169. {
  2170. *pAlpha = flAlphas[0] + ( flFrac * ( flAlphas[2] - flAlphas[0] ) );
  2171. }
  2172. }
  2173. if( pNormal )
  2174. {
  2175. Vector edgeU = vecVerts[2] - vecVerts[1];
  2176. Vector edgeV = vecVerts[0] - vecVerts[1];
  2177. *pNormal = CrossProduct( edgeU, edgeV );
  2178. VectorNormalize( *pNormal );
  2179. }
  2180. }
  2181. else if ( nSnapV == nNextV )
  2182. {
  2183. if ( nSnapU == nNextU )
  2184. {
  2185. vecPoint = vecVerts[0];
  2186. *pAlpha = flAlphas[0];
  2187. }
  2188. else
  2189. {
  2190. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length();
  2191. vecPoint = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) );
  2192. if ( pAlpha )
  2193. {
  2194. *pAlpha = flAlphas[0] + ( flFrac * ( flAlphas[2] - flAlphas[0] ) );
  2195. }
  2196. }
  2197. if( pNormal )
  2198. {
  2199. Vector edgeU = vecVerts[2] - vecVerts[1];
  2200. Vector edgeV = vecVerts[0] - vecVerts[1];
  2201. *pNormal = CrossProduct( edgeV, edgeU );
  2202. VectorNormalize( *pNormal );
  2203. }
  2204. }
  2205. else
  2206. {
  2207. float flCfs[3];
  2208. if ( CalcBarycentricCooefs( vecFlatVerts[0], vecFlatVerts[1], vecFlatVerts[2], vecIntersectPoint, flCfs[0], flCfs[1], flCfs[2] ) )
  2209. {
  2210. vecPoint = ( vecVerts[0] * flCfs[0] ) + ( vecVerts[1] * flCfs[1] ) + ( vecVerts[2] * flCfs[2] );
  2211. if( pAlpha )
  2212. {
  2213. *pAlpha = ( flAlphas[0] * flCfs[0] ) + ( flAlphas[1] * flCfs[1] ) + ( flAlphas[2] * flCfs[2] );
  2214. }
  2215. if( pNormal )
  2216. {
  2217. Vector edgeU = vecVerts[2] - vecVerts[1];
  2218. Vector edgeV = vecVerts[0] - vecVerts[1];
  2219. *pNormal = CrossProduct( edgeV, edgeU );
  2220. VectorNormalize( *pNormal );
  2221. }
  2222. }
  2223. else
  2224. {
  2225. if ( !bBackup )
  2226. {
  2227. DispUVToSurf_TriBLToTR_2( vecIntersectPoint, nSnapU, nNextU, nSnapV, nNextV, vecPoint, pNormal, pAlpha, true );
  2228. }
  2229. }
  2230. }
  2231. }
  2232. //-----------------------------------------------------------------------------
  2233. // Purpose:
  2234. //-----------------------------------------------------------------------------
  2235. void CCoreDispInfo::DispUVToSurf_TriBLToTR_2( const Vector &vecIntersectPoint,
  2236. int nSnapU, int nNextU, int nSnapV, int nNextV,
  2237. Vector &vecPoint, Vector *pNormal, float *pAlpha,
  2238. bool bBackup )
  2239. {
  2240. int nWidth = GetWidth();
  2241. int nIndices[3];
  2242. nIndices[0] = nSnapV * nWidth + nSnapU;
  2243. nIndices[1] = nNextV * nWidth + nNextU;
  2244. nIndices[2] = nSnapV * nWidth + nNextU;
  2245. Vector vecFlatVerts[3], vecVerts[3];
  2246. float flAlphas[3];
  2247. for ( int iVert = 0; iVert < 3; ++iVert )
  2248. {
  2249. vecFlatVerts[iVert] = m_pVerts[nIndices[iVert]].m_FlatVert;
  2250. vecVerts[iVert] = m_pVerts[nIndices[iVert]].m_Vert;
  2251. flAlphas[iVert] = m_pVerts[nIndices[iVert]].m_Alpha;
  2252. }
  2253. if ( nSnapU == nNextU )
  2254. {
  2255. if ( nSnapV == nNextV )
  2256. {
  2257. vecPoint = vecVerts[0];
  2258. *pAlpha = flAlphas[0];
  2259. }
  2260. else
  2261. {
  2262. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[1] - vecFlatVerts[0] ).Length();
  2263. vecPoint = vecVerts[0] + ( flFrac * ( vecVerts[1] - vecVerts[0] ) );
  2264. if ( pAlpha )
  2265. {
  2266. *pAlpha = flAlphas[0] + ( flFrac * ( flAlphas[1] - flAlphas[0] ) );
  2267. }
  2268. }
  2269. if( pNormal )
  2270. {
  2271. Vector edgeU = vecVerts[0] - vecVerts[2];
  2272. Vector edgeV = vecVerts[1] - vecVerts[2];
  2273. *pNormal = CrossProduct( edgeV, edgeU );
  2274. VectorNormalize( *pNormal );
  2275. }
  2276. }
  2277. else if ( nSnapV == nNextV )
  2278. {
  2279. if ( nSnapU == nNextU )
  2280. {
  2281. vecPoint = vecVerts[0];
  2282. *pAlpha = flAlphas[0];
  2283. }
  2284. else
  2285. {
  2286. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length();
  2287. vecPoint = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) );
  2288. if ( pAlpha )
  2289. {
  2290. *pAlpha = flAlphas[0] + ( flFrac * ( flAlphas[2] - flAlphas[0] ) );
  2291. }
  2292. }
  2293. if( pNormal )
  2294. {
  2295. Vector edgeU = vecVerts[0] - vecVerts[2];
  2296. Vector edgeV = vecVerts[1] - vecVerts[2];
  2297. *pNormal = CrossProduct( edgeV, edgeU );
  2298. VectorNormalize( *pNormal );
  2299. }
  2300. }
  2301. else
  2302. {
  2303. float flCfs[3];
  2304. if ( CalcBarycentricCooefs( vecFlatVerts[0], vecFlatVerts[1], vecFlatVerts[2], vecIntersectPoint, flCfs[0], flCfs[1], flCfs[2] ) )
  2305. {
  2306. vecPoint = ( vecVerts[0] * flCfs[0] ) + ( vecVerts[1] * flCfs[1] ) + ( vecVerts[2] * flCfs[2] );
  2307. if( pAlpha )
  2308. {
  2309. *pAlpha = ( flAlphas[0] * flCfs[0] ) + ( flAlphas[1] * flCfs[1] ) + ( flAlphas[2] * flCfs[2] );
  2310. }
  2311. if( pNormal )
  2312. {
  2313. Vector edgeU = vecVerts[0] - vecVerts[2];
  2314. Vector edgeV = vecVerts[1] - vecVerts[2];
  2315. *pNormal = CrossProduct( edgeV, edgeU );
  2316. VectorNormalize( *pNormal );
  2317. }
  2318. }
  2319. else
  2320. {
  2321. if ( !bBackup )
  2322. {
  2323. DispUVToSurf_TriBLToTR_1( vecIntersectPoint, nSnapU, nNextU, nSnapV, nNextV, vecPoint, pNormal, pAlpha, true );
  2324. }
  2325. }
  2326. }
  2327. }
  2328. //-----------------------------------------------------------------------------
  2329. // Purpose:
  2330. //-----------------------------------------------------------------------------
  2331. void CCoreDispInfo::DispUVToSurf_TriBLToTR( Vector &vecPoint, Vector *pNormal, float *pAlpha,
  2332. float flU, float flV, const Vector &vecIntersectPoint )
  2333. {
  2334. int nWidth = GetWidth();
  2335. int nHeight = GetHeight();
  2336. int nSnapU = static_cast<int>( flU );
  2337. int nSnapV = static_cast<int>( flV );
  2338. int nNextU = nSnapU + 1;
  2339. int nNextV = nSnapV + 1;
  2340. if ( nNextU == nWidth) { --nNextU; }
  2341. if ( nNextV == nHeight ) { --nNextV; }
  2342. float flFracU = flU - static_cast<float>( nSnapU );
  2343. float flFracV = flV - static_cast<float>( nSnapV );
  2344. if( flFracU < flFracV )
  2345. {
  2346. DispUVToSurf_TriBLToTR_1( vecIntersectPoint, nSnapU, nNextU, nSnapV, nNextV, vecPoint, pNormal, pAlpha, false );
  2347. }
  2348. else
  2349. {
  2350. DispUVToSurf_TriBLToTR_2( vecIntersectPoint, nSnapU, nNextU, nSnapV, nNextV, vecPoint, pNormal, pAlpha, false );
  2351. }
  2352. }
  2353. //-----------------------------------------------------------------------------
  2354. //-----------------------------------------------------------------------------
  2355. void CCoreDispInfo::DispUVToSurf( Vector2D const &dispUV, Vector &vecPoint,
  2356. Vector *pNormal, float *pAlpha )
  2357. {
  2358. // Check to see that the point is on the surface.
  2359. if ( dispUV.x < 0.0f || dispUV.x > 1.0f || dispUV.y < 0.0f || dispUV.y > 1.0f )
  2360. return;
  2361. // Get the base surface points.
  2362. Vector vecIntersectPoint;
  2363. CCoreDispSurface *pSurf = GetSurface();
  2364. PointInQuadFromBarycentric( pSurf->GetPoint( 0 ), pSurf->GetPoint( 3 ), pSurf->GetPoint( 2 ), pSurf->GetPoint( 1 ), dispUV, vecIntersectPoint );
  2365. // Get the displacement power.
  2366. int nWidth = GetWidth();
  2367. int nHeight = GetHeight();
  2368. // Scale the U, V coordinates to the displacement grid size.
  2369. float flU = dispUV.x * ( static_cast<float>( nWidth ) - 1.000001f );
  2370. float flV = dispUV.y * ( static_cast<float>( nHeight ) - 1.000001f );
  2371. // Find the base U, V.
  2372. int nSnapU = static_cast<int>( flU );
  2373. int nSnapV = static_cast<int>( flV );
  2374. // Use this to get the triangle orientation.
  2375. bool bOdd = ( ( ( nSnapV * nWidth ) + nSnapU ) % 2 == 1 );
  2376. // Top Left to Bottom Right
  2377. if( bOdd )
  2378. {
  2379. DispUVToSurf_TriTLToBR( vecPoint, pNormal, pAlpha, flU, flV, vecIntersectPoint );
  2380. }
  2381. // Bottom Left to Top Right
  2382. else
  2383. {
  2384. DispUVToSurf_TriBLToTR( vecPoint, pNormal, pAlpha, flU, flV, vecIntersectPoint );
  2385. }
  2386. }
  2387. //-----------------------------------------------------------------------------
  2388. // Purpose: Create bounding boxes around pairs of triangles (in a grid-like)
  2389. // fashion; used for culling
  2390. //-----------------------------------------------------------------------------
  2391. void CCoreDispInfo::CreateBoundingBoxes( CoreDispBBox_t *pBBox, int count )
  2392. {
  2393. //
  2394. // Initialize the bounding boxes.
  2395. //
  2396. int iBox;
  2397. for( iBox = 0; iBox < count; ++iBox )
  2398. {
  2399. pBBox[iBox].vMin.Init( FLT_MAX, FLT_MAX, FLT_MAX );
  2400. pBBox[iBox].vMax.Init( FLT_MIN, FLT_MIN, FLT_MIN );
  2401. }
  2402. // Get the width and height of the displacement surface.
  2403. int nHeight = GetHeight();
  2404. int nWidth = GetWidth();
  2405. // Find bounding box of every two consecutive triangles
  2406. iBox = 0;
  2407. int nIndex = 0;
  2408. for( int iHgt = 0; iHgt < ( nHeight - 1 ); ++iHgt )
  2409. {
  2410. for( int iWid = 0; iWid < ( nWidth - 1 ); ++iWid )
  2411. {
  2412. for( int iPoint = 0; iPoint < 4; ++iPoint )
  2413. {
  2414. switch( iPoint )
  2415. {
  2416. case 0: { nIndex = ( nHeight * iHgt ) + iWid; break; }
  2417. case 1: { nIndex = ( nHeight * ( iHgt + 1 ) ) + iWid; break; }
  2418. case 2: { nIndex = ( nHeight * ( iHgt + 1 ) ) + ( iWid + 1 ); break; }
  2419. case 3: { nIndex = ( nHeight * iHgt ) + ( iWid + 1 ); break; }
  2420. default: { break; }
  2421. }
  2422. Vector vecPoint;
  2423. GetVert( nIndex, vecPoint );
  2424. if( vecPoint[0] < pBBox[iBox].vMin[0] ) { pBBox[iBox].vMin[0] = vecPoint[0]; }
  2425. if( vecPoint[1] < pBBox[iBox].vMin[1] ) { pBBox[iBox].vMin[1] = vecPoint[1]; }
  2426. if( vecPoint[2] < pBBox[iBox].vMin[2] ) { pBBox[iBox].vMin[2] = vecPoint[2]; }
  2427. if( vecPoint[0] > pBBox[iBox].vMax[0] ) { pBBox[iBox].vMax[0] = vecPoint[0]; }
  2428. if( vecPoint[1] > pBBox[iBox].vMax[1] ) { pBBox[iBox].vMax[1] = vecPoint[1]; }
  2429. if( vecPoint[2] > pBBox[iBox].vMax[2] ) { pBBox[iBox].vMax[2] = vecPoint[2]; }
  2430. }
  2431. iBox++;
  2432. }
  2433. }
  2434. // Verify.
  2435. Assert( iBox == count );
  2436. // Bloat.
  2437. for ( iBox = 0; iBox < count; ++iBox )
  2438. {
  2439. for( int iAxis = 0; iAxis < 3; ++iAxis )
  2440. {
  2441. pBBox[iBox].vMin[iAxis] -= 1.0f;
  2442. pBBox[iBox].vMax[iAxis] += 1.0f;
  2443. }
  2444. }
  2445. }
  2446. //-----------------------------------------------------------------------------
  2447. //-----------------------------------------------------------------------------
  2448. inline bool PointInDispBBox( CoreDispBBox_t *pBox, const Vector &vecPoint )
  2449. {
  2450. // Check to see if point lies in box
  2451. if( ( vecPoint.x < pBox->vMin.x ) || ( vecPoint.x > pBox->vMax.x ) )
  2452. return false;
  2453. if( ( vecPoint.y < pBox->vMin.y ) || ( vecPoint.y > pBox->vMax.y ) )
  2454. return false;
  2455. if( ( vecPoint.z < pBox->vMin.z ) || ( vecPoint.z > pBox->vMax.z ) )
  2456. return false;
  2457. return true;
  2458. }
  2459. //-----------------------------------------------------------------------------
  2460. //-----------------------------------------------------------------------------
  2461. void CCoreDispInfo::GetTriangleIndicesForDispBBox( int nIndex, int nTris[2][3] )
  2462. {
  2463. // Test to see whether or not the index is odd.
  2464. bool bOdd = ( ( nIndex % 2 ) == 1 );
  2465. int nWidth = GetWidth();
  2466. // Tris for TLtoBR
  2467. if ( bOdd )
  2468. {
  2469. nTris[0][0] = nIndex;
  2470. nTris[0][1] = nIndex + nWidth;
  2471. nTris[0][2] = nIndex + 1;
  2472. nTris[1][0] = nIndex + 1;
  2473. nTris[1][1] = nIndex + nWidth;
  2474. nTris[1][2] = nIndex + nWidth + 1;
  2475. }
  2476. // Tris for BLtoTR
  2477. else
  2478. {
  2479. nTris[0][0] = nIndex;
  2480. nTris[0][1] = nIndex + nWidth;
  2481. nTris[0][2] = nIndex + nWidth + 1;
  2482. nTris[1][0] = nIndex;
  2483. nTris[1][1] = nIndex + nWidth + 1;
  2484. nTris[1][2] = nIndex + 1;
  2485. }
  2486. }
  2487. //-----------------------------------------------------------------------------
  2488. //-----------------------------------------------------------------------------
  2489. bool CCoreDispInfo::SurfToBaseFacePlane( Vector const &surfPt, Vector &planePt )
  2490. {
  2491. // Create bounding boxes
  2492. int nBoxCount = ( GetHeight() - 1 ) * ( GetWidth() - 1 );
  2493. CoreDispBBox_t *pBBox = new CoreDispBBox_t[nBoxCount];
  2494. CreateBoundingBoxes( pBBox, nBoxCount );
  2495. // Use the boxes as a first-pass culling mechanism.
  2496. for( int iBox = 0; iBox < nBoxCount; ++iBox )
  2497. {
  2498. // Get the current displacement triangle-pair bounding-box.
  2499. CoreDispBBox_t *pBox = &pBBox[iBox];
  2500. if( !pBox )
  2501. continue;
  2502. // Check the point against the current displacement bounding-box.
  2503. if ( !PointInDispBBox( pBox, surfPt ) )
  2504. continue;
  2505. // Point lies within the bounding box.
  2506. int nIndex = iBox + ( iBox / ( GetWidth() - 1 ) );
  2507. // Get the triangle coordinates for this box.
  2508. int aTris[2][3];
  2509. GetTriangleIndicesForDispBBox( nIndex, aTris );
  2510. // Barycentrically test the triangles on the displacement surface.
  2511. Vector vecPoints[3];
  2512. for ( int iTri = 0; iTri < 2; ++iTri )
  2513. {
  2514. for ( int iVert = 0; iVert < 3; ++iVert )
  2515. {
  2516. GetVert( aTris[iTri][iVert], vecPoints[iVert] );
  2517. }
  2518. float c[3];
  2519. if ( CalcBarycentricCooefs( vecPoints[0], vecPoints[1], vecPoints[2], surfPt, c[0], c[1], c[2] ) )
  2520. {
  2521. Vector vecFlatPoints[3];
  2522. for ( int iVert = 0; iVert < 3; ++iVert )
  2523. {
  2524. GetFlatVert( aTris[iTri][iVert], vecFlatPoints[iVert] );
  2525. }
  2526. planePt = ( vecFlatPoints[0] * c[0] ) + ( vecFlatPoints[1] * c[1] ) + ( vecFlatPoints[2] * c[2] );
  2527. // Delete temporary memory.
  2528. delete [] pBBox;
  2529. return true;
  2530. }
  2531. }
  2532. }
  2533. // Delete temporary memory
  2534. delete [] pBBox;
  2535. return false;
  2536. }
  2537. //-----------------------------------------------------------------------------
  2538. // Purpose:
  2539. //-----------------------------------------------------------------------------
  2540. int CCoreDispInfo::GetTriCount( void )
  2541. {
  2542. return ( ( GetHeight() - 1 ) * ( GetWidth() -1 ) * 2 );
  2543. }
  2544. //-----------------------------------------------------------------------------
  2545. // Purpose:
  2546. //-----------------------------------------------------------------------------
  2547. void CCoreDispInfo::GetTriIndices( int iTri, unsigned short &v1, unsigned short &v2, unsigned short &v3 )
  2548. {
  2549. // Verify we have the correct data (only build when collision data is built).
  2550. if ( !m_pTris || ( iTri < 0 ) || ( iTri >= GetTriCount() ) )
  2551. {
  2552. Assert( iTri >= 0 );
  2553. Assert( iTri < GetTriCount() );
  2554. Assert( m_pTris );
  2555. return;
  2556. }
  2557. CoreDispTri_t *pTri = &m_pTris[iTri];
  2558. v1 = pTri->m_iIndex[0];
  2559. v2 = pTri->m_iIndex[1];
  2560. v3 = pTri->m_iIndex[2];
  2561. }
  2562. //-----------------------------------------------------------------------------
  2563. // Purpose:
  2564. //-----------------------------------------------------------------------------
  2565. void CCoreDispInfo::SetTriIndices( int iTri, unsigned short v1, unsigned short v2, unsigned short v3 )
  2566. {
  2567. // Verify we have the correct data (only build when collision data is built).
  2568. if ( !m_pTris || ( iTri < 0 ) || ( iTri >= GetTriCount() ) )
  2569. {
  2570. Assert( iTri >= 0 );
  2571. Assert( iTri < GetTriCount() );
  2572. Assert( m_pTris );
  2573. return;
  2574. }
  2575. CoreDispTri_t *pTri = &m_pTris[iTri];
  2576. pTri->m_iIndex[0] = v1;
  2577. pTri->m_iIndex[1] = v2;
  2578. pTri->m_iIndex[2] = v3;
  2579. }
  2580. //-----------------------------------------------------------------------------
  2581. // Purpose:
  2582. //-----------------------------------------------------------------------------
  2583. void CCoreDispInfo::GetTriPos( int iTri, Vector &v1, Vector &v2, Vector &v3 )
  2584. {
  2585. // Verify we have the correct data (only build when collision data is built).
  2586. if ( !m_pTris || ( iTri < 0 ) || ( iTri >= GetTriCount() ) )
  2587. {
  2588. Assert( iTri >= 0 );
  2589. Assert( iTri < GetTriCount() );
  2590. Assert( m_pTris );
  2591. return;
  2592. }
  2593. CoreDispTri_t *pTri = &m_pTris[iTri];
  2594. v1 = m_pVerts[pTri->m_iIndex[0]].m_Vert;
  2595. v2 = m_pVerts[pTri->m_iIndex[1]].m_Vert;
  2596. v3 = m_pVerts[pTri->m_iIndex[2]].m_Vert;
  2597. }
  2598. //-----------------------------------------------------------------------------
  2599. // Purpose:
  2600. //-----------------------------------------------------------------------------
  2601. void CCoreDispInfo::InitTris( void )
  2602. {
  2603. // Verify we have the correct data (only build when collision data is built).
  2604. if ( !m_pTris )
  2605. {
  2606. Assert( m_pTris );
  2607. return;
  2608. }
  2609. int nTriCount = GetTriCount();
  2610. for ( int iTri = 0; iTri < nTriCount; ++iTri )
  2611. {
  2612. m_pTris[iTri].m_uiTags = 0;
  2613. }
  2614. }
  2615. //-----------------------------------------------------------------------------
  2616. // Purpose:
  2617. //-----------------------------------------------------------------------------
  2618. void CCoreDispInfo::CreateTris( void )
  2619. {
  2620. // Verify we have the correct data (only build when collision data is built).
  2621. if ( !m_pTris )
  2622. {
  2623. Assert( m_pTris );
  2624. return;
  2625. }
  2626. // Extra sanity check if wanted!
  2627. Assert( GetTriCount() == ( m_RenderIndexCount / 3 ) );
  2628. int nTriCount = GetTriCount();
  2629. for ( int iTri = 0, iRender = 0; iTri < nTriCount; ++iTri, iRender += 3 )
  2630. {
  2631. m_pTris[iTri].m_iIndex[0] = m_RenderIndices[iRender];
  2632. m_pTris[iTri].m_iIndex[1] = m_RenderIndices[iRender+1];
  2633. m_pTris[iTri].m_iIndex[2] = m_RenderIndices[iRender+2];
  2634. }
  2635. }
  2636. //-----------------------------------------------------------------------------
  2637. // Purpose:
  2638. //-----------------------------------------------------------------------------
  2639. bool CCoreDispInfo::IsTriWalkable( int iTri )
  2640. {
  2641. if ( IsTriTag( iTri, COREDISPTRI_TAG_FORCE_WALKABLE_BIT ) )
  2642. {
  2643. return IsTriTag( iTri, COREDISPTRI_TAG_FORCE_WALKABLE_VAL );
  2644. }
  2645. return IsTriTag( iTri, COREDISPTRI_TAG_WALKABLE );
  2646. }
  2647. //-----------------------------------------------------------------------------
  2648. // Purpose:
  2649. //-----------------------------------------------------------------------------
  2650. bool CCoreDispInfo::IsTriBuildable( int iTri )
  2651. {
  2652. if ( IsTriTag( iTri, COREDISPTRI_TAG_FORCE_BUILDABLE_BIT ) )
  2653. {
  2654. return IsTriTag( iTri, COREDISPTRI_TAG_FORCE_BUILDABLE_VAL );
  2655. }
  2656. return IsTriTag( iTri, COREDISPTRI_TAG_BUILDABLE );
  2657. }
  2658. //-----------------------------------------------------------------------------
  2659. // Purpose:
  2660. //-----------------------------------------------------------------------------
  2661. bool CCoreDispInfo::IsTriRemove( int iTri )
  2662. {
  2663. return IsTriTag( iTri, COREDISPTRI_TAG_FORCE_REMOVE_BIT );
  2664. }
  2665. //-----------------------------------------------------------------------------
  2666. // Purpose:
  2667. //-----------------------------------------------------------------------------
  2668. void CCoreDispInfo::Position_Update( int iVert, Vector vecPos )
  2669. {
  2670. Vector vSPos, vFlat;
  2671. GetFlatVert( iVert, vFlat );
  2672. GetSubdivPosition( iVert, vSPos );
  2673. Vector vSeg;
  2674. vSeg = vecPos - vFlat;
  2675. vSeg -= vSPos;
  2676. // Subtract out the elevation.
  2677. float elev = GetElevation();
  2678. if( elev != 0.0 )
  2679. {
  2680. Vector vNormal;
  2681. GetSurface()->GetNormal( vNormal );
  2682. vNormal *= elev;
  2683. vSeg -= vNormal;
  2684. }
  2685. float flDistance = VectorNormalize( vSeg );
  2686. SetFieldVector( iVert, vSeg );
  2687. SetFieldDistance( iVert, flDistance );
  2688. }