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

3116 lines
88 KiB

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