Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1630 lines
46 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "disp_common.h"
  8. #include "disp_powerinfo.h"
  9. #include "builddisp.h"
  10. // memdbgon must be the last include file in a .cpp file!!!
  11. #include "tier0/memdbgon.h"
  12. class CNodeVert
  13. {
  14. public:
  15. CNodeVert() {}
  16. CNodeVert( int ix, int iy ) {x=ix; y=iy;}
  17. inline int& operator[]( int i ) {return ((int*)this)[i];}
  18. inline int const& operator[]( int i ) const {return ((int*)this)[i];}
  19. int x, y;
  20. };
  21. static CNodeVert const g_NodeChildLookup[4][2] =
  22. {
  23. {CNodeVert(0,0), CNodeVert(1,1)},
  24. {CNodeVert(1,0), CNodeVert(2,1)},
  25. {CNodeVert(0,1), CNodeVert(1,2)},
  26. {CNodeVert(1,1), CNodeVert(2,2)}
  27. };
  28. static CNodeVert const g_NodeTriWinding[9] =
  29. {
  30. CNodeVert(0, 1),
  31. CNodeVert(0, 0),
  32. CNodeVert(1, 0),
  33. CNodeVert(2, 0),
  34. CNodeVert(2, 1),
  35. CNodeVert(2, 2),
  36. CNodeVert(1, 2),
  37. CNodeVert(0, 2),
  38. CNodeVert(0, 1)
  39. };
  40. // Indexed by CORNER_. These store NEIGHBOREDGE_ defines and tell which edges butt up against the corner.
  41. static int g_CornerEdges[4][2] =
  42. {
  43. { NEIGHBOREDGE_BOTTOM, NEIGHBOREDGE_LEFT }, // CORNER_LOWER_LEFT
  44. { NEIGHBOREDGE_TOP, NEIGHBOREDGE_LEFT }, // CORNER_UPPER_LEFT
  45. { NEIGHBOREDGE_TOP, NEIGHBOREDGE_RIGHT }, // CORNER_UPPER_RIGHT
  46. { NEIGHBOREDGE_BOTTOM, NEIGHBOREDGE_RIGHT } // CORNER_LOWER_RIGHT
  47. };
  48. int g_EdgeDims[4] =
  49. {
  50. 0, // NEIGHBOREDGE_LEFT = X
  51. 1, // NEIGHBOREDGE_TOP = Y
  52. 0, // NEIGHBOREDGE_RIGHT = X
  53. 1 // NEIGHBOREDGE_BOTTOM = Y
  54. };
  55. CShiftInfo g_ShiftInfos[3][3] =
  56. {
  57. {
  58. {0, 0, true}, // CORNER_TO_CORNER -> CORNER_TO_CORNER
  59. {0, -1, true}, // CORNER_TO_CORNER -> CORNER_TO_MIDPOINT
  60. {2, -1, true} // CORNER_TO_CORNER -> MIDPOINT_TO_CORNER
  61. },
  62. {
  63. {0, 1, true}, // CORNER_TO_MIDPOINT -> CORNER_TO_CORNER
  64. {0, 0, false}, // CORNER_TO_MIDPOINT -> CORNER_TO_MIDPOINT (invalid)
  65. {0, 0, false} // CORNER_TO_MIDPOINT -> MIDPOINT_TO_CORNER (invalid)
  66. },
  67. {
  68. {-1, 1, true}, // MIDPOINT_TO_CORNER -> CORNER_TO_CORNER
  69. {0, 0, false}, // MIDPOINT_TO_CORNER -> CORNER_TO_MIDPOINT (invalid)
  70. {0, 0, false} // MIDPOINT_TO_CORNER -> MIDPOINT_TO_CORNER (invalid)
  71. }
  72. };
  73. int g_EdgeSideLenMul[4] =
  74. {
  75. 0,
  76. 1,
  77. 1,
  78. 0
  79. };
  80. // --------------------------------------------------------------------------------- //
  81. // Helper functions.
  82. // --------------------------------------------------------------------------------- //
  83. inline int SignedBitShift( int val, int shift )
  84. {
  85. if( shift > 0 )
  86. return val << shift;
  87. else
  88. return val >> -shift;
  89. }
  90. static inline void RotateVertIndex(
  91. NeighborOrientation neighor,
  92. int sideLengthMinus1,
  93. CVertIndex const &in,
  94. CVertIndex &out )
  95. {
  96. if( neighor == ORIENTATION_CCW_0 )
  97. {
  98. out = in;
  99. }
  100. else if( neighor == ORIENTATION_CCW_90 )
  101. {
  102. out.x = in.y;
  103. out.y = sideLengthMinus1 - in.x;
  104. }
  105. else if( neighor == ORIENTATION_CCW_180 )
  106. {
  107. out.x = sideLengthMinus1 - in.x;
  108. out.y = sideLengthMinus1 - in.y;
  109. }
  110. else
  111. {
  112. out.x = sideLengthMinus1 - in.y;
  113. out.y = in.x;
  114. }
  115. }
  116. static inline void RotateVertIncrement(
  117. NeighborOrientation neighor,
  118. CVertIndex const &in,
  119. CVertIndex &out )
  120. {
  121. if( neighor == ORIENTATION_CCW_0 )
  122. {
  123. out = in;
  124. }
  125. else if( neighor == ORIENTATION_CCW_90 )
  126. {
  127. out.x = in.y;
  128. out.y = -in.x;
  129. }
  130. else if( neighor == ORIENTATION_CCW_180 )
  131. {
  132. out.x = -in.x;
  133. out.y = -in.y;
  134. }
  135. else
  136. {
  137. out.x = -in.y;
  138. out.y = in.x;
  139. }
  140. }
  141. // --------------------------------------------------------------------------------- //
  142. // CDispHelper functions.
  143. // --------------------------------------------------------------------------------- //
  144. int GetEdgeIndexFromPoint( CVertIndex const &index, int iMaxPower )
  145. {
  146. int sideLengthMinus1 = 1 << iMaxPower;
  147. if( index.x == 0 )
  148. return NEIGHBOREDGE_LEFT;
  149. else if( index.y == sideLengthMinus1 )
  150. return NEIGHBOREDGE_TOP;
  151. else if( index.x == sideLengthMinus1 )
  152. return NEIGHBOREDGE_RIGHT;
  153. else if( index.y == 0 )
  154. return NEIGHBOREDGE_BOTTOM;
  155. else
  156. return -1;
  157. }
  158. int GetCornerIndexFromPoint( CVertIndex const &index, int iPower )
  159. {
  160. int sideLengthMinus1 = 1 << iPower;
  161. if( index.x == 0 && index.y == 0 )
  162. return CORNER_LOWER_LEFT;
  163. else if( index.x == 0 && index.y == sideLengthMinus1 )
  164. return CORNER_UPPER_LEFT;
  165. else if( index.x == sideLengthMinus1 && index.y == sideLengthMinus1 )
  166. return CORNER_UPPER_RIGHT;
  167. else if( index.x == sideLengthMinus1 && index.y == 0 )
  168. return CORNER_LOWER_RIGHT;
  169. else
  170. return -1;
  171. }
  172. int GetNeighborEdgePower( CDispUtilsHelper *pDisp, int iEdge, int iSub )
  173. {
  174. CDispNeighbor *pEdge = pDisp->GetEdgeNeighbor( iEdge );
  175. CDispSubNeighbor *pSub = &pEdge->m_SubNeighbors[iSub];
  176. if ( !pSub->IsValid() )
  177. return -1;
  178. CDispUtilsHelper *pNeighbor = pDisp->GetDispUtilsByIndex( pSub->GetNeighborIndex() );
  179. CShiftInfo *pInfo = &g_ShiftInfos[pSub->m_Span][pSub->m_NeighborSpan];
  180. Assert( pInfo->m_bValid );
  181. return pNeighbor->GetPower() + pInfo->m_PowerShiftAdd;
  182. }
  183. CDispUtilsHelper* SetupEdgeIncrements(
  184. CDispUtilsHelper *pDisp,
  185. int iEdge,
  186. int iSub,
  187. CVertIndex &myIndex,
  188. CVertIndex &myInc,
  189. CVertIndex &nbIndex,
  190. CVertIndex &nbInc,
  191. int &myEnd,
  192. int &iFreeDim )
  193. {
  194. int iEdgeDim = g_EdgeDims[iEdge];
  195. iFreeDim = !iEdgeDim;
  196. CDispNeighbor *pSide = pDisp->GetEdgeNeighbor( iEdge );
  197. CDispSubNeighbor *pSub = &pSide->m_SubNeighbors[iSub];
  198. if ( !pSub->IsValid() )
  199. return NULL;
  200. CDispUtilsHelper *pNeighbor = pDisp->GetDispUtilsByIndex( pSub->m_iNeighbor );
  201. CShiftInfo *pShiftInfo = &g_ShiftInfos[pSub->m_Span][pSub->m_NeighborSpan];
  202. Assert( pShiftInfo->m_bValid );
  203. // Setup a start point and edge increment (NOTE: just precalculate these
  204. // and store them in the CDispSubNeighbors).
  205. CVertIndex tempInc;
  206. const CPowerInfo *pPowerInfo = pDisp->GetPowerInfo();
  207. myIndex[iEdgeDim] = g_EdgeSideLenMul[iEdge] * pPowerInfo->m_SideLengthM1;
  208. myIndex[iFreeDim] = pPowerInfo->m_MidPoint * iSub;
  209. TransformIntoSubNeighbor( pDisp, iEdge, iSub, myIndex, nbIndex );
  210. int myPower = pDisp->GetPowerInfo()->m_Power;
  211. int nbPower = pNeighbor->GetPowerInfo()->m_Power + pShiftInfo->m_PowerShiftAdd;
  212. myInc[iEdgeDim] = tempInc[iEdgeDim] = 0;
  213. if( nbPower > myPower )
  214. {
  215. myInc[iFreeDim] = 1;
  216. tempInc[iFreeDim] = 1 << (nbPower - myPower);
  217. }
  218. else
  219. {
  220. myInc[iFreeDim] = 1 << (myPower - nbPower);
  221. tempInc[iFreeDim] = 1;
  222. }
  223. RotateVertIncrement( pSub->GetNeighborOrientation(), tempInc, nbInc );
  224. // Walk along the edge.
  225. if( pSub->m_Span == CORNER_TO_MIDPOINT )
  226. myEnd = pDisp->GetPowerInfo()->m_SideLength >> 1;
  227. else
  228. myEnd = pDisp->GetPowerInfo()->m_SideLength - 1;
  229. return pNeighbor;
  230. }
  231. int GetSubNeighborIndex(
  232. CDispUtilsHelper *pDisp,
  233. int iEdge,
  234. CVertIndex const &nodeIndex )
  235. {
  236. const CPowerInfo *pPowerInfo = pDisp->GetPowerInfo();
  237. const CDispNeighbor *pSide = pDisp->GetEdgeNeighbor( iEdge );
  238. // Figure out if this is a vertical or horizontal edge.
  239. int iEdgeDim = g_EdgeDims[iEdge];
  240. int iFreeDim = !iEdgeDim;
  241. int iFreeIndex = nodeIndex[iFreeDim];
  242. // Figure out which of the (up to two) neighbors it lies in.
  243. int iSub = 0;
  244. if( iFreeIndex == pPowerInfo->m_MidPoint )
  245. {
  246. // If it's in the middle, we only are interested if there's one neighbor
  247. // next to us (so we can enable its middle vert). If there are any neighbors
  248. // that touch the midpoint, then we have no need to return them because it would
  249. // touch their corner verts which are always active.
  250. if( pSide->m_SubNeighbors[0].m_Span != CORNER_TO_CORNER )
  251. return -1;
  252. }
  253. else if ( iFreeIndex > pPowerInfo->m_MidPoint )
  254. {
  255. iSub = 1;
  256. }
  257. // Make sure we get a valid neighbor.
  258. if( !pSide->m_SubNeighbors[iSub].IsValid() )
  259. {
  260. if( iSub == 1 &&
  261. pSide->m_SubNeighbors[0].IsValid() &&
  262. pSide->m_SubNeighbors[0].m_Span == CORNER_TO_CORNER )
  263. {
  264. iSub = 0;
  265. }
  266. else
  267. {
  268. return -1;
  269. }
  270. }
  271. return iSub;
  272. }
  273. void SetupSpan( int iPower, int iEdge, NeighborSpan span, CVertIndex &viStart, CVertIndex &viEnd )
  274. {
  275. int iFreeDim = !g_EdgeDims[iEdge];
  276. const CPowerInfo *pPowerInfo = GetPowerInfo( iPower );
  277. viStart = pPowerInfo->GetCornerPointIndex( iEdge );
  278. viEnd = pPowerInfo->GetCornerPointIndex( (iEdge+1) & 3 );;
  279. if ( iEdge == NEIGHBOREDGE_RIGHT || iEdge == NEIGHBOREDGE_BOTTOM )
  280. {
  281. // CORNER_TO_MIDPOINT and MIDPOINT_CORNER are defined where the edge moves up or right,
  282. // but pPowerInfo->GetCornerPointIndex walks around the edges clockwise, so on the
  283. // bottom and right edges (where GetCornerPointIndex has us moving down and left) we need to
  284. // reverse the sense here to make sure we return the right span.
  285. if ( span == CORNER_TO_MIDPOINT )
  286. viStart[iFreeDim] = pPowerInfo->GetMidPoint();
  287. else if ( span == MIDPOINT_TO_CORNER )
  288. viEnd[iFreeDim] = pPowerInfo->GetMidPoint();
  289. }
  290. else
  291. {
  292. if ( span == CORNER_TO_MIDPOINT )
  293. viEnd[iFreeDim] = pPowerInfo->GetMidPoint();
  294. else if ( span == MIDPOINT_TO_CORNER )
  295. viStart[iFreeDim] = pPowerInfo->GetMidPoint();
  296. }
  297. }
  298. CDispUtilsHelper* TransformIntoSubNeighbor(
  299. CDispUtilsHelper *pDisp,
  300. int iEdge,
  301. int iSub,
  302. CVertIndex const &nodeIndex,
  303. CVertIndex &out
  304. )
  305. {
  306. const CDispSubNeighbor *pSub = &pDisp->GetEdgeNeighbor( iEdge )->m_SubNeighbors[iSub];
  307. // Find the part of pDisp's edge that this neighbor covers.
  308. CVertIndex viSrcStart, viSrcEnd;
  309. SetupSpan( pDisp->GetPower(), iEdge, pSub->GetSpan(), viSrcStart, viSrcEnd );
  310. // Find the corresponding parts on the neighbor.
  311. CDispUtilsHelper *pNeighbor = pDisp->GetDispUtilsByIndex( pSub->GetNeighborIndex() );
  312. int iNBEdge = (iEdge + 2 + pSub->GetNeighborOrientation()) & 3;
  313. CVertIndex viDestStart, viDestEnd;
  314. SetupSpan( pNeighbor->GetPower(), iNBEdge, pSub->GetNeighborSpan(), viDestEnd, viDestStart );
  315. // Now map the one into the other.
  316. int iFreeDim = !g_EdgeDims[iEdge];
  317. int fixedPercent = ((nodeIndex[iFreeDim] - viSrcStart[iFreeDim]) * (1<<16)) / (viSrcEnd[iFreeDim] - viSrcStart[iFreeDim]);
  318. Assert( fixedPercent >= 0 && fixedPercent <= (1<<16) );
  319. int nbDim = g_EdgeDims[iNBEdge];
  320. out[nbDim] = viDestStart[nbDim];
  321. out[!nbDim] = viDestStart[!nbDim] + ((viDestEnd[!nbDim] - viDestStart[!nbDim]) * fixedPercent) / (1<<16);
  322. Assert( out.x >= 0 && out.x < pNeighbor->GetSideLength() );
  323. Assert( out.y >= 0 && out.y < pNeighbor->GetSideLength() );
  324. return pNeighbor;
  325. }
  326. CDispUtilsHelper* TransformIntoNeighbor(
  327. CDispUtilsHelper *pDisp,
  328. int iEdge,
  329. CVertIndex const &nodeIndex,
  330. CVertIndex &out
  331. )
  332. {
  333. if ( iEdge == -1 )
  334. iEdge = GetEdgeIndexFromPoint( nodeIndex, pDisp->GetPower() );
  335. int iSub = GetSubNeighborIndex( pDisp, iEdge, nodeIndex );
  336. if ( iSub == -1 )
  337. return NULL;
  338. CDispUtilsHelper *pRet = TransformIntoSubNeighbor( pDisp, iEdge, iSub, nodeIndex, out );
  339. #if 0
  340. // Debug check.. make sure it comes back to the same point from the other side.
  341. #if defined( _DEBUG )
  342. static bool bTesting = false;
  343. if ( pRet && !bTesting )
  344. {
  345. bTesting = true;
  346. // We could let TransformIntoNeighbor figure out the index but if this is a corner vert, then
  347. // it may pick the wrong edge and we'd get a benign assert.
  348. int nbOrientation = pDisp->GetEdgeNeighbor( iEdge )->m_SubNeighbors[iSub].GetNeighborOrientation();
  349. int iNeighborEdge = (iEdge + 2 + nbOrientation) & 3;
  350. CVertIndex testIndex;
  351. CDispUtilsHelper *pTest = TransformIntoNeighbor( pRet, iNeighborEdge, out, testIndex );
  352. Assert( pTest == pDisp );
  353. Assert( testIndex == nodeIndex );
  354. bTesting = false;
  355. }
  356. #endif
  357. #endif
  358. return pRet;
  359. }
  360. bool DoesPointHaveAnyNeighbors(
  361. CDispUtilsHelper *pDisp,
  362. const CVertIndex &index )
  363. {
  364. // See if it connects to a neighbor on the edge.
  365. CVertIndex dummy;
  366. if ( TransformIntoNeighbor( pDisp, -1, index, dummy ) )
  367. return true;
  368. // See if it connects to a neighbor on a corner.
  369. int iCorner = GetCornerIndexFromPoint( index, pDisp->GetPower() );
  370. if ( iCorner == -1 )
  371. return false;
  372. // If there are any neighbors on the specified corner, then the point has neighbors.
  373. if ( pDisp->GetCornerNeighbors( iCorner )->m_nNeighbors > 0 )
  374. return true;
  375. // Since points on corners touch two edges, we actually want to test two edges to see
  376. // if the point has a neighbor on either edge.
  377. for ( int i=0; i < 2; i++ )
  378. {
  379. if ( TransformIntoNeighbor( pDisp, g_CornerEdges[iCorner][i], index, dummy ) )
  380. return true;
  381. }
  382. return false;
  383. }
  384. // ------------------------------------------------------------------------------------ //
  385. // CDispSubEdgeIterator.
  386. // ------------------------------------------------------------------------------------ //
  387. CDispSubEdgeIterator::CDispSubEdgeIterator()
  388. {
  389. m_pNeighbor = 0;
  390. m_FreeDim = m_Index.x = m_Inc.x = m_End = 0; // Setup so Next returns false.
  391. }
  392. void CDispSubEdgeIterator::Start( CDispUtilsHelper *pDisp, int iEdge, int iSub, bool bTouchCorners )
  393. {
  394. m_pNeighbor = SetupEdgeIncrements( pDisp, iEdge, iSub, m_Index, m_Inc, m_NBIndex, m_NBInc, m_End, m_FreeDim );
  395. if ( m_pNeighbor )
  396. {
  397. if ( bTouchCorners )
  398. {
  399. // Back up our current position by 1 so we hit the corner first, and extend the endpoint
  400. // so we hit the other corner too.
  401. m_Index -= m_Inc;
  402. m_NBIndex -= m_NBInc;
  403. m_End += m_Inc[m_FreeDim];
  404. }
  405. }
  406. else
  407. {
  408. m_FreeDim = m_Index.x = m_Inc.x = m_End = 0; // Setup so Next returns false.
  409. }
  410. }
  411. bool CDispSubEdgeIterator::Next()
  412. {
  413. m_Index += m_Inc;
  414. m_NBIndex += m_NBInc;
  415. // Were we just at the last point on the edge?
  416. return m_Index[m_FreeDim] < m_End;
  417. }
  418. bool CDispSubEdgeIterator::IsLastVert() const
  419. {
  420. return (m_Index[m_FreeDim] + m_Inc[m_FreeDim]) >= m_End;
  421. }
  422. // ------------------------------------------------------------------------------------ //
  423. // CDispEdgeIterator.
  424. // ------------------------------------------------------------------------------------ //
  425. CDispEdgeIterator::CDispEdgeIterator( CDispUtilsHelper *pDisp, int iEdge )
  426. {
  427. m_pDisp = pDisp;
  428. m_iEdge = iEdge;
  429. m_iCurSub = -1;
  430. }
  431. bool CDispEdgeIterator::Next()
  432. {
  433. while ( !m_It.Next() )
  434. {
  435. // Ok, move up to the next sub.
  436. if ( m_iCurSub == 1 )
  437. return false;
  438. ++m_iCurSub;
  439. m_It.Start( m_pDisp, m_iEdge, m_iCurSub );
  440. }
  441. return true;
  442. }
  443. // ------------------------------------------------------------------------------------ //
  444. // CDispCircumferenceIterator.
  445. // ------------------------------------------------------------------------------------ //
  446. CDispCircumferenceIterator::CDispCircumferenceIterator( int sideLength )
  447. {
  448. m_iCurEdge = -1;
  449. m_SideLengthM1 = sideLength - 1;
  450. }
  451. bool CDispCircumferenceIterator::Next()
  452. {
  453. switch ( m_iCurEdge )
  454. {
  455. case -1:
  456. {
  457. m_iCurEdge = NEIGHBOREDGE_LEFT;
  458. m_VertIndex.Init( 0, 0 );
  459. }
  460. break;
  461. case NEIGHBOREDGE_LEFT:
  462. {
  463. ++m_VertIndex.y;
  464. if ( m_VertIndex.y == m_SideLengthM1 )
  465. m_iCurEdge = NEIGHBOREDGE_TOP;
  466. }
  467. break;
  468. case NEIGHBOREDGE_TOP:
  469. {
  470. ++m_VertIndex.x;
  471. if ( m_VertIndex.x == m_SideLengthM1 )
  472. m_iCurEdge = NEIGHBOREDGE_RIGHT;
  473. }
  474. break;
  475. case NEIGHBOREDGE_RIGHT:
  476. {
  477. --m_VertIndex.y;
  478. if ( m_VertIndex.y == 0 )
  479. m_iCurEdge = NEIGHBOREDGE_BOTTOM;
  480. }
  481. break;
  482. case NEIGHBOREDGE_BOTTOM:
  483. {
  484. --m_VertIndex.x;
  485. if ( m_VertIndex.x == 0 )
  486. return false; // Done!
  487. }
  488. break;
  489. }
  490. return true;
  491. }
  492. // Helper function to setup an index either on the edges or the center
  493. // of the box defined by [bottomleft,topRight].
  494. static inline void SetupCoordXY( CNodeVert &out, CNodeVert const &bottomLeft, CNodeVert const &topRight, CNodeVert const &info )
  495. {
  496. for( int i=0; i < 2; i++ )
  497. {
  498. if( info[i] == 0 )
  499. out[i] = bottomLeft[i];
  500. else if( info[i] == 1 )
  501. out[i] = (bottomLeft[i] + topRight[i]) >> 1;
  502. else
  503. out[i] = topRight[i];
  504. }
  505. }
  506. static unsigned short* DispCommon_GenerateTriIndices_R(
  507. CNodeVert const &bottomLeft,
  508. CNodeVert const &topRight,
  509. unsigned short *indices,
  510. int power,
  511. int sideLength )
  512. {
  513. if( power == 1 )
  514. {
  515. // Ok, add triangles. All we do here is follow a list of verts (g_NodeTriWinding)
  516. // around the center vert of this node and make triangles.
  517. int iCurTri = 0;
  518. CNodeVert verts[3];
  519. // verts[0] is always the center vert.
  520. SetupCoordXY( verts[0], bottomLeft, topRight, CNodeVert(1,1) );
  521. int iCurVert = 1;
  522. for( int i=0; i < 9; i++ )
  523. {
  524. SetupCoordXY( verts[iCurVert], bottomLeft, topRight, g_NodeTriWinding[i] );
  525. ++iCurVert;
  526. if( iCurVert == 3 )
  527. {
  528. for( int iTriVert=2; iTriVert >= 0; iTriVert-- )
  529. {
  530. int index = verts[iTriVert].y * sideLength + verts[iTriVert].x;
  531. *indices = index;
  532. ++indices;
  533. }
  534. // Setup for the next triangle.
  535. verts[1] = verts[2];
  536. iCurVert = 2;
  537. iCurTri++;
  538. }
  539. }
  540. }
  541. else
  542. {
  543. // Recurse into the children.
  544. for( int i=0; i < 4; i++ )
  545. {
  546. CNodeVert childBottomLeft, childTopRight;
  547. SetupCoordXY( childBottomLeft, bottomLeft, topRight, g_NodeChildLookup[i][0] );
  548. SetupCoordXY( childTopRight, bottomLeft, topRight, g_NodeChildLookup[i][1] );
  549. indices = DispCommon_GenerateTriIndices_R( childBottomLeft, childTopRight, indices, power-1, sideLength );
  550. }
  551. }
  552. return indices;
  553. }
  554. // ------------------------------------------------------------------------------------------- //
  555. // CDispUtilsHelper functions.
  556. // ------------------------------------------------------------------------------------------- //
  557. int CDispUtilsHelper::GetPower() const
  558. {
  559. return GetPowerInfo()->GetPower();
  560. }
  561. int CDispUtilsHelper::GetSideLength() const
  562. {
  563. return GetPowerInfo()->GetSideLength();
  564. }
  565. const CVertIndex& CDispUtilsHelper::GetCornerPointIndex( int iCorner ) const
  566. {
  567. return GetPowerInfo()->GetCornerPointIndex( iCorner );
  568. }
  569. int CDispUtilsHelper::VertIndexToInt( const CVertIndex &i ) const
  570. {
  571. Assert( i.x >= 0 && i.x < GetSideLength() && i.y >= 0 && i.y < GetSideLength() );
  572. return i.y * GetSideLength() + i.x;
  573. }
  574. CVertIndex CDispUtilsHelper::GetEdgeMidPoint( int iEdge ) const
  575. {
  576. int end = GetSideLength() - 1;
  577. int mid = GetPowerInfo()->GetMidPoint();
  578. if ( iEdge == NEIGHBOREDGE_LEFT )
  579. return CVertIndex( 0, mid );
  580. else if ( iEdge == NEIGHBOREDGE_TOP )
  581. return CVertIndex( mid, end );
  582. else if ( iEdge == NEIGHBOREDGE_RIGHT )
  583. return CVertIndex( end, mid );
  584. else if ( iEdge == NEIGHBOREDGE_BOTTOM )
  585. return CVertIndex( mid, 0 );
  586. Assert( false );
  587. return CVertIndex( 0, 0 );
  588. }
  589. int DispCommon_GetNumTriIndices( int power )
  590. {
  591. return (1<<power) * (1<<power) * 2 * 3;
  592. }
  593. void DispCommon_GenerateTriIndices( int power, unsigned short *indices )
  594. {
  595. int sideLength = 1 << power;
  596. DispCommon_GenerateTriIndices_R(
  597. CNodeVert( 0, 0 ),
  598. CNodeVert( sideLength, sideLength ),
  599. indices,
  600. power,
  601. sideLength+1 );
  602. }
  603. //=============================================================================
  604. //
  605. // Finding neighbors.
  606. //
  607. // This table swaps MIDPOINT_TO_CORNER and CORNER_TO_MIDPOINT.
  608. static NeighborSpan g_SpanFlip[3] = {CORNER_TO_CORNER, MIDPOINT_TO_CORNER, CORNER_TO_MIDPOINT};
  609. static bool g_bEdgeNeighborFlip[4] = {false, false, true, true};
  610. // These map CCoreDispSurface neighbor orientations (which are actually edge indices)
  611. // into our 'degrees of rotation' representation.
  612. static int g_CoreDispNeighborOrientationMap[4][4] =
  613. {
  614. {ORIENTATION_CCW_180, ORIENTATION_CCW_270, ORIENTATION_CCW_0, ORIENTATION_CCW_90},
  615. {ORIENTATION_CCW_90, ORIENTATION_CCW_180, ORIENTATION_CCW_270, ORIENTATION_CCW_0},
  616. {ORIENTATION_CCW_0, ORIENTATION_CCW_90, ORIENTATION_CCW_180, ORIENTATION_CCW_270},
  617. {ORIENTATION_CCW_270, ORIENTATION_CCW_0, ORIENTATION_CCW_90, ORIENTATION_CCW_180}
  618. };
  619. //-----------------------------------------------------------------------------
  620. //-----------------------------------------------------------------------------
  621. void ClearNeighborData( CCoreDispInfo *pDisp )
  622. {
  623. for ( int i=0; i < 4; i++ )
  624. {
  625. pDisp->GetEdgeNeighbor( i )->SetInvalid();
  626. pDisp->GetCornerNeighbors( i )->SetInvalid();
  627. }
  628. }
  629. //-----------------------------------------------------------------------------
  630. //-----------------------------------------------------------------------------
  631. void GetDispBox( CCoreDispInfo *pDisp, CDispBox &box )
  632. {
  633. // Calculate the bbox for this displacement.
  634. Vector vMin( 1e24, 1e24, 1e24 );
  635. Vector vMax( -1e24, -1e24, -1e24 );
  636. for ( int iVert = 0; iVert < 4; ++iVert )
  637. {
  638. const Vector &vTest = pDisp->GetSurface()->GetPoint( iVert );
  639. VectorMin( vTest, vMin, vMin );
  640. VectorMax( vTest, vMax, vMax );
  641. }
  642. // Puff the box out a little.
  643. static float flPuff = 0.1f;
  644. vMin -= Vector( flPuff, flPuff, flPuff );
  645. vMax += Vector( flPuff, flPuff, flPuff );
  646. box.m_Min = vMin;
  647. box.m_Max = vMax;
  648. }
  649. //-----------------------------------------------------------------------------
  650. //-----------------------------------------------------------------------------
  651. void SetupDispBoxes( CCoreDispInfo **ppListBase, int nListSize, CUtlVector<CDispBox> &out )
  652. {
  653. out.SetSize( nListSize );
  654. for ( int iDisp = 0; iDisp < nListSize; ++iDisp )
  655. {
  656. CCoreDispInfo *pDisp = ppListBase[iDisp];
  657. GetDispBox( pDisp, out[iDisp] );
  658. }
  659. }
  660. //-----------------------------------------------------------------------------
  661. //-----------------------------------------------------------------------------
  662. inline bool DoBBoxesTouch( const CDispBox &a, const CDispBox &b )
  663. {
  664. for ( int i=0; i < 3; i++ )
  665. {
  666. if ( a.m_Max[i] < b.m_Min[i] )
  667. return false;
  668. if ( a.m_Min[i] > b.m_Max[i] )
  669. return false;
  670. }
  671. return true;
  672. }
  673. //-----------------------------------------------------------------------------
  674. //-----------------------------------------------------------------------------
  675. bool FindEdge( CCoreDispInfo *pInfo, Vector const &vPoint1, Vector const &vPoint2, int &iEdge )
  676. {
  677. CCoreDispSurface *pSurface = pInfo->GetSurface();
  678. for( iEdge=0; iEdge < 4; iEdge++ )
  679. {
  680. if( VectorsAreEqual( vPoint1, pSurface->GetPoint( iEdge ), 0.01f ) &&
  681. VectorsAreEqual( vPoint2, pSurface->GetPoint( (iEdge+1) & 3), 0.01f ) )
  682. {
  683. return true;
  684. }
  685. }
  686. return false;
  687. }
  688. //-----------------------------------------------------------------------------
  689. //-----------------------------------------------------------------------------
  690. NeighborSpan NeighborSpanFlip( int iEdge, NeighborSpan span )
  691. {
  692. if ( g_bEdgeNeighborFlip[iEdge] )
  693. return g_SpanFlip[span];
  694. else
  695. return span;
  696. }
  697. //-----------------------------------------------------------------------------
  698. //-----------------------------------------------------------------------------
  699. void AddNeighbor( CCoreDispInfo *pMain,
  700. int iEdge, // Which of pMain's sides this is on.
  701. int iSub, // Which sub neighbor this takes up in pSide.
  702. NeighborSpan span, // What span this fills in pMain.
  703. CCoreDispInfo *pOther, int iNeighborEdge, NeighborSpan nbSpan )
  704. {
  705. // The edge iteration before coming in here goes 0-1, 1-2, 2-3, 3-4.
  706. // This flips the sense of CORNER_TO_MIDPOINT/MIDPOINT_TO_CORNER on the right and
  707. // bottom edges and is undone here.
  708. span = NeighborSpanFlip( iEdge, span );
  709. nbSpan = NeighborSpanFlip( iNeighborEdge, nbSpan );
  710. // Get the subspan this fills on our displacement.
  711. CDispSubNeighbor *pSub = &pMain->GetEdgeNeighbor(iEdge)->m_SubNeighbors[iSub];
  712. // Which subspan does this use in the neighbor?
  713. CDispSubNeighbor *pNeighborSub;
  714. if ( nbSpan == MIDPOINT_TO_CORNER )
  715. {
  716. pNeighborSub = &pOther->GetEdgeNeighbor(iNeighborEdge)->m_SubNeighbors[1];
  717. }
  718. else
  719. {
  720. pNeighborSub = &pOther->GetEdgeNeighbor(iNeighborEdge)->m_SubNeighbors[0];
  721. }
  722. // Make sure this slot isn't used on either displacement.
  723. if ( pSub->IsValid() || pNeighborSub->IsValid() )
  724. {
  725. ExecuteOnce( Warning( "Found a displacement edge abutting multiple other edges.\n" ) );
  726. return;
  727. }
  728. // Now just copy the data into each displacement.
  729. pSub->m_iNeighbor = pOther->GetListIndex();
  730. pSub->m_NeighborOrientation = g_CoreDispNeighborOrientationMap[iEdge][iNeighborEdge];
  731. pSub->m_Span = span;
  732. pSub->m_NeighborSpan = nbSpan;
  733. pNeighborSub->m_iNeighbor = pMain->GetListIndex();
  734. pNeighborSub->m_NeighborOrientation = g_CoreDispNeighborOrientationMap[iNeighborEdge][iEdge];
  735. pNeighborSub->m_Span = nbSpan;
  736. pNeighborSub->m_NeighborSpan = span;
  737. #if defined( _DEBUG )
  738. // Walk an iterator over the new connection to make sure it works.
  739. CDispSubEdgeIterator it;
  740. it.Start( pMain, iEdge, iSub );
  741. while ( it.Next() )
  742. {
  743. CVertIndex nbIndex;
  744. TransformIntoNeighbor( pMain, iEdge, it.GetVertIndex(), nbIndex );
  745. }
  746. #endif
  747. }
  748. //-----------------------------------------------------------------------------
  749. // This function is symmetric wrt pMain and pOther. It sets up valid neighboring data for
  750. // the relationship between both of them.
  751. //-----------------------------------------------------------------------------
  752. void SetupEdgeNeighbors( CCoreDispInfo *pMain, CCoreDispInfo *pOther )
  753. {
  754. // Initialize..
  755. for( int iEdge=0; iEdge < 4; iEdge++ )
  756. {
  757. // Setup the edge points and the midpoint.
  758. Vector pt[2], mid;
  759. pMain->GetSurface()->GetPoint( iEdge, pt[0] );
  760. pMain->GetSurface()->GetPoint( (iEdge + 1) & 3, pt[1] );
  761. mid = (pt[0] + pt[1]) * 0.5f;
  762. // Find neighbors.
  763. int iNBEdge;
  764. if( FindEdge( pOther, pt[1], pt[0], iNBEdge ) )
  765. {
  766. AddNeighbor( pMain, iEdge, 0, CORNER_TO_CORNER, pOther, iNBEdge, CORNER_TO_CORNER );
  767. }
  768. else
  769. {
  770. // Look for one that takes up our whole side.
  771. if( FindEdge( pOther, pt[1], pt[0]*2 - pt[1], iNBEdge ) )
  772. {
  773. AddNeighbor( pMain, iEdge, 0, CORNER_TO_CORNER, pOther, iNBEdge, CORNER_TO_MIDPOINT );
  774. }
  775. else if( FindEdge( pOther, pt[1]*2 - pt[0], pt[0], iNBEdge ) )
  776. {
  777. AddNeighbor( pMain, iEdge, 0, CORNER_TO_CORNER, pOther, iNBEdge, MIDPOINT_TO_CORNER );
  778. }
  779. else
  780. {
  781. // Ok, look for 1 or two that abut this side.
  782. if( FindEdge( pOther, mid, pt[0], iNBEdge ) )
  783. {
  784. AddNeighbor( pMain, iEdge, g_bEdgeNeighborFlip[iEdge], CORNER_TO_MIDPOINT, pOther, iNBEdge, CORNER_TO_CORNER );
  785. }
  786. if( FindEdge( pOther, pt[1], mid, iNBEdge ) )
  787. {
  788. AddNeighbor( pMain, iEdge, !g_bEdgeNeighborFlip[iEdge], MIDPOINT_TO_CORNER, pOther, iNBEdge, CORNER_TO_CORNER );
  789. }
  790. }
  791. }
  792. }
  793. }
  794. //-----------------------------------------------------------------------------
  795. // Returns true if the displacement has an edge neighbor with the given index.
  796. //-----------------------------------------------------------------------------
  797. bool HasEdgeNeighbor( const CCoreDispInfo *pMain, int iNeighbor )
  798. {
  799. for ( int i=0; i < 4; i++ )
  800. {
  801. const CDispCornerNeighbors *pCorner = pMain->GetCornerNeighbors( i );
  802. for ( int iNB=0; iNB < pCorner->m_nNeighbors; iNB++ )
  803. if ( pCorner->m_Neighbors[iNB] == iNeighbor )
  804. return true;
  805. const CDispNeighbor *pEdge = pMain->GetEdgeNeighbor( i );
  806. if ( pEdge->m_SubNeighbors[0].GetNeighborIndex() == iNeighbor ||
  807. pEdge->m_SubNeighbors[1].GetNeighborIndex() == iNeighbor )
  808. {
  809. return true;
  810. }
  811. }
  812. return false;
  813. }
  814. //-----------------------------------------------------------------------------
  815. //-----------------------------------------------------------------------------
  816. void SetupCornerNeighbors( CCoreDispInfo *pMain, CCoreDispInfo *pOther, int *nOverflows )
  817. {
  818. if ( HasEdgeNeighbor( pMain, pOther->GetListIndex() ) )
  819. return;
  820. // Do these two share a vertex?
  821. int nShared = 0;
  822. int iMainSharedCorner = -1;
  823. int iOtherSharedCorner = -1;
  824. for ( int iMainCorner=0; iMainCorner < 4; iMainCorner++ )
  825. {
  826. Vector const &vMainCorner = pMain->GetCornerPoint( iMainCorner );
  827. for ( int iOtherCorner=0; iOtherCorner < 4; iOtherCorner++ )
  828. {
  829. Vector const &vOtherCorner = pOther->GetCornerPoint( iOtherCorner );
  830. if ( VectorsAreEqual( vMainCorner, vOtherCorner, 0.001f ) )
  831. {
  832. iMainSharedCorner = iMainCorner;
  833. iOtherSharedCorner = iOtherCorner;
  834. ++nShared;
  835. }
  836. }
  837. }
  838. if ( nShared == 1 )
  839. {
  840. CDispCornerNeighbors *pMainCorner = pMain->GetCornerNeighbors( iMainSharedCorner );
  841. CDispCornerNeighbors *pOtherCorner = pOther->GetCornerNeighbors( iOtherSharedCorner );
  842. if ( pMainCorner->m_nNeighbors < MAX_DISP_CORNER_NEIGHBORS &&
  843. pOtherCorner->m_nNeighbors < MAX_DISP_CORNER_NEIGHBORS )
  844. {
  845. pMainCorner->m_Neighbors[pMainCorner->m_nNeighbors++] = pOther->GetListIndex();
  846. pOtherCorner->m_Neighbors[pOtherCorner->m_nNeighbors++] = pMain->GetListIndex();
  847. }
  848. else
  849. {
  850. ++(*nOverflows);
  851. }
  852. }
  853. }
  854. //-----------------------------------------------------------------------------
  855. //-----------------------------------------------------------------------------
  856. bool VerifyNeighborVertConnection( CDispUtilsHelper *pDisp, const CVertIndex &nodeIndex,
  857. const CDispUtilsHelper *pTestNeighbor, const CVertIndex &testNeighborIndex,
  858. int mySide )
  859. {
  860. CVertIndex nbIndex( -1, -1 );
  861. CDispUtilsHelper *pNeighbor = NULL;
  862. if( (pNeighbor = TransformIntoNeighbor( pDisp, mySide, nodeIndex, nbIndex ) ) != NULL )
  863. {
  864. if ( pTestNeighbor != pNeighbor || nbIndex != testNeighborIndex )
  865. return false;
  866. CVertIndex testIndex( -1, -1 );
  867. int iSide = GetEdgeIndexFromPoint( nbIndex, pNeighbor->GetPowerInfo()->m_Power );
  868. if ( iSide == -1 )
  869. {
  870. return false;
  871. }
  872. CDispUtilsHelper *pTest = TransformIntoNeighbor( pNeighbor, iSide, nbIndex, testIndex );
  873. if( pTest != pDisp || nodeIndex != testIndex )
  874. {
  875. return false;
  876. }
  877. }
  878. return true;
  879. }
  880. //-----------------------------------------------------------------------------
  881. //-----------------------------------------------------------------------------
  882. void VerifyNeighborConnections( CCoreDispInfo **ppListBase, int nDisps )
  883. {
  884. while ( 1 )
  885. {
  886. bool bHappy = true;
  887. int iDisp;
  888. for ( iDisp = 0; iDisp < nDisps; ++iDisp )
  889. {
  890. CCoreDispInfo *pDisp = ppListBase[iDisp];
  891. CDispUtilsHelper *pHelper = pDisp;
  892. for ( int iEdge=0; iEdge < 4; iEdge++ )
  893. {
  894. CDispEdgeIterator it( pHelper, iEdge );
  895. while ( it.Next() )
  896. {
  897. if ( !VerifyNeighborVertConnection( pHelper, it.GetVertIndex(), it.GetCurrentNeighbor(), it.GetNBVertIndex(), iEdge ) )
  898. {
  899. pDisp->GetEdgeNeighbor( iEdge )->SetInvalid();
  900. Warning( "Warning: invalid neighbor connection on displacement near (%.2f %.2f %.2f)\n", VectorExpand( pDisp->GetCornerPoint(0) ) );
  901. bHappy = false;
  902. }
  903. }
  904. }
  905. }
  906. if ( bHappy )
  907. break;
  908. }
  909. }
  910. //-----------------------------------------------------------------------------
  911. //-----------------------------------------------------------------------------
  912. void FindNeighboringDispSurfs( CCoreDispInfo **ppListBase, int nListSize )
  913. {
  914. // First, clear all neighboring data.
  915. int iDisp;
  916. for ( iDisp = 0; iDisp < nListSize; ++iDisp )
  917. {
  918. ClearNeighborData( ppListBase[iDisp] );
  919. }
  920. CUtlVector<CDispBox> boxes;
  921. SetupDispBoxes( ppListBase, nListSize, boxes );
  922. int nCornerOverflows = 0;
  923. // Now test all pairs of displacements and setup neighboring relations between them.
  924. for( iDisp = 0; iDisp < nListSize; ++iDisp )
  925. {
  926. CCoreDispInfo *pMain = ppListBase[iDisp];
  927. for ( int iDisp2 = iDisp+1; iDisp2 < nListSize; ++iDisp2 )
  928. {
  929. CCoreDispInfo *pOther = ppListBase[iDisp2];
  930. // Trivial reject.
  931. if ( !DoBBoxesTouch( boxes[iDisp], boxes[iDisp2] ) )
  932. continue;
  933. SetupEdgeNeighbors( pMain, pOther );
  934. // NOTE: this must come after SetupEdgeNeighbors because it makes sure not to add
  935. // corner neighbors for disps that are already edge neighbors.
  936. SetupCornerNeighbors( pMain, pOther, &nCornerOverflows );
  937. }
  938. }
  939. if ( nCornerOverflows )
  940. {
  941. Warning( "Warning: overflowed %d displacement corner-neighbor lists.", nCornerOverflows );
  942. }
  943. // Debug check.. make sure the neighbor connections are intact (make sure that any
  944. // edge vert that gets mapped into a neighbor gets mapped back the same way).
  945. VerifyNeighborConnections( ppListBase, nListSize );
  946. }
  947. //=============================================================================
  948. //
  949. // Allowable verts.
  950. //
  951. //-----------------------------------------------------------------------------
  952. //-----------------------------------------------------------------------------
  953. int IsCorner( CVertIndex const &index, int sideLength )
  954. {
  955. if ( index.x == 0 )
  956. {
  957. if ( index.y == 0 )
  958. return true;
  959. else if ( index.y == sideLength-1 )
  960. return true;
  961. }
  962. else if ( index.x == sideLength-1 )
  963. {
  964. if ( index.y == 0 )
  965. return true;
  966. else if ( index.y == sideLength-1 )
  967. return true;
  968. }
  969. return false;
  970. }
  971. //-----------------------------------------------------------------------------
  972. //-----------------------------------------------------------------------------
  973. bool IsVertAllowed( CDispUtilsHelper *pDisp, CVertIndex const &sideVert, int iLevel )
  974. {
  975. if ( IsCorner( sideVert, pDisp->GetPowerInfo()->GetSideLength() ) )
  976. return true;
  977. int iSide = GetEdgeIndexFromPoint( sideVert, pDisp->GetPowerInfo()->GetPower() );
  978. if ( iSide == -1 )
  979. return true;
  980. int iSub = GetSubNeighborIndex( pDisp, iSide, sideVert );
  981. if ( iSub == -1 )
  982. return true;
  983. CDispSubNeighbor *pSub = &pDisp->GetEdgeNeighbor( iSide )->m_SubNeighbors[iSub];
  984. CDispUtilsHelper *pNeighbor = pDisp->GetDispUtilsByIndex( pSub->m_iNeighbor );
  985. Assert( pNeighbor );
  986. // Ok, there is a neighbor.. see if this vertex exists in the neighbor.
  987. CShiftInfo *pShiftInfo = &g_ShiftInfos[pSub->m_Span][pSub->m_NeighborSpan];
  988. Assert( pShiftInfo->m_bValid );
  989. if ( ( pNeighbor->GetPowerInfo()->GetPower() + pShiftInfo->m_PowerShiftAdd ) < ( iLevel+1 ) )
  990. {
  991. return false;
  992. }
  993. // Ok, it exists. Make sure the neighbor hasn't disallowed it.
  994. CVertIndex nbIndex;
  995. TransformIntoSubNeighbor( pDisp, iSide, iSub, sideVert, nbIndex );
  996. CBitVec<MAX_DISPVERTS> &allowedVerts = CCoreDispInfo::FromDispUtils( pNeighbor )->GetAllowedVerts();
  997. return !!allowedVerts.Get( pNeighbor->VertIndexToInt( nbIndex ) );
  998. }
  999. //-----------------------------------------------------------------------------
  1000. //-----------------------------------------------------------------------------
  1001. void UnallowVerts_R( CDispUtilsHelper *pDisp, CVertIndex const &nodeIndex, int &nUnallowed )
  1002. {
  1003. int iNodeIndex = pDisp->VertIndexToInt( nodeIndex );
  1004. CCoreDispInfo *pCoreDisp = CCoreDispInfo::FromDispUtils( pDisp );
  1005. if ( !pCoreDisp->GetAllowedVerts().Get( iNodeIndex ) )
  1006. return;
  1007. nUnallowed++;
  1008. pCoreDisp->GetAllowedVerts().Clear( iNodeIndex );
  1009. for ( int iDep=0; iDep < CVertInfo::NUM_REVERSE_DEPENDENCIES; iDep++ )
  1010. {
  1011. CVertDependency &dep = pDisp->GetPowerInfo()->m_pVertInfo[iNodeIndex].m_ReverseDependencies[iDep];
  1012. if( dep.m_iVert.x != -1 && dep.m_iNeighbor == -1 )
  1013. {
  1014. UnallowVerts_R( pDisp, dep.m_iVert, nUnallowed );
  1015. }
  1016. }
  1017. }
  1018. //-----------------------------------------------------------------------------
  1019. //-----------------------------------------------------------------------------
  1020. void DisableUnallowedVerts_R( CDispUtilsHelper *pDisp, CVertIndex const &nodeIndex, int iLevel, int &nUnallowed )
  1021. {
  1022. int iNodeIndex = pDisp->VertIndexToInt( nodeIndex );
  1023. // This vertex is not allowed if it is on an edge with a neighbor
  1024. // that does not have this vertex.
  1025. // Test side verts.
  1026. for( int iSide=0; iSide < 4; iSide++ )
  1027. {
  1028. CVertIndex const &sideVert = pDisp->GetPowerInfo()->m_pSideVerts[iNodeIndex].m_Verts[iSide];
  1029. if( !IsVertAllowed( pDisp, sideVert, iLevel ) )
  1030. {
  1031. // This vert (and its dependencies) can't exist.
  1032. UnallowVerts_R( pDisp, sideVert, nUnallowed );
  1033. }
  1034. }
  1035. #if 0
  1036. // Test dependencies.
  1037. for( int iDep=0; iDep < 2; iDep++ )
  1038. {
  1039. CVertDependency const &dep = pDisp->GetPowerInfo()->m_pVertInfo[iNodeIndex].m_Dependencies[iDep];
  1040. if( dep.m_iNeighbor == -1 && !IsVertAllowed( pDisp, dep.m_iVert, iLevel ) )
  1041. {
  1042. UnallowVerts_R( pDisp, nodeIndex, nUnallowed );
  1043. }
  1044. }
  1045. #endif
  1046. // Recurse.
  1047. if( iLevel+1 < pDisp->GetPower() )
  1048. {
  1049. for( int iChild=0; iChild < 4; iChild++ )
  1050. {
  1051. DisableUnallowedVerts_R( pDisp, pDisp->GetPowerInfo()->m_pChildVerts[iNodeIndex].m_Verts[iChild], iLevel+1, nUnallowed );
  1052. }
  1053. }
  1054. }
  1055. //-----------------------------------------------------------------------------
  1056. //-----------------------------------------------------------------------------
  1057. void SetupAllowedVerts( CCoreDispInfo **ppListBase, int nListSize )
  1058. {
  1059. // Set all verts to allowed to start with.
  1060. int iDisp;
  1061. for ( iDisp = 0; iDisp < nListSize; ++iDisp )
  1062. {
  1063. ppListBase[iDisp]->GetAllowedVerts().SetAll();
  1064. }
  1065. // Disable verts that need to be disabled so higher-powered displacements remove
  1066. // the necessary triangles when bordering lower-powered displacements.
  1067. // It is necessary to loop around here because disabling verts can accumulate into
  1068. // neighbors.
  1069. bool bContinue;
  1070. do
  1071. {
  1072. bContinue = false;
  1073. for( iDisp = 0; iDisp < nListSize; ++iDisp )
  1074. {
  1075. CDispUtilsHelper *pDisp = ppListBase[iDisp];
  1076. int nUnallowed = 0;
  1077. DisableUnallowedVerts_R( pDisp, pDisp->GetPowerInfo()->m_RootNode, 0, nUnallowed );
  1078. if ( nUnallowed )
  1079. bContinue = true;
  1080. }
  1081. } while( bContinue );
  1082. }
  1083. //-----------------------------------------------------------------------------
  1084. // Purpose:
  1085. // Input : *pDisp -
  1086. // &vecPoint -
  1087. // Output : int
  1088. //-----------------------------------------------------------------------------
  1089. static int FindNeighborCornerVert( CCoreDispInfo *pDisp, const Vector &vecPoint )
  1090. {
  1091. CDispUtilsHelper *pDispHelper = pDisp;
  1092. int iClosest = 0;
  1093. float flClosest = 1e24;
  1094. for ( int iCorner = 0; iCorner < 4; ++iCorner )
  1095. {
  1096. // Has it been touched?
  1097. CVertIndex viCornerVert = pDispHelper->GetPowerInfo()->GetCornerPointIndex( iCorner );
  1098. int iCornerVert = pDispHelper->VertIndexToInt( viCornerVert );
  1099. const Vector &vecCornerVert = pDisp->GetVert( iCornerVert );
  1100. float flDist = vecCornerVert.DistTo( vecPoint );
  1101. if ( flDist < flClosest )
  1102. {
  1103. iClosest = iCorner;
  1104. flClosest = flDist;
  1105. }
  1106. }
  1107. if ( flClosest <= 0.1f )
  1108. return iClosest;
  1109. else
  1110. return -1;
  1111. }
  1112. // sets a new normal/tangentS, recomputes tangent T
  1113. static void UpdateTangentSpace(CCoreDispInfo *pDisp, int iVert, const Vector &vNormal, const Vector &vTanS)
  1114. {
  1115. Vector tanT;
  1116. pDisp->SetNormal( iVert, vNormal );
  1117. CrossProduct( vTanS, vNormal, tanT );
  1118. pDisp->SetTangentS(iVert, vTanS);
  1119. pDisp->SetTangentT(iVert, tanT);
  1120. }
  1121. static void UpdateTangentSpace(CCoreDispInfo *pDisp, const CVertIndex &index, const Vector &vNormal, const Vector &vTanS)
  1122. {
  1123. UpdateTangentSpace(pDisp, pDisp->VertIndexToInt(index), vNormal, vTanS);
  1124. }
  1125. //-----------------------------------------------------------------------------
  1126. // Purpose:
  1127. // Input : **ppListBase -
  1128. // nListSize -
  1129. //-----------------------------------------------------------------------------
  1130. static void BlendSubNeighbors( CCoreDispInfo **ppListBase, int nListSize )
  1131. {
  1132. // Loop through all of the displacements in the list.
  1133. for ( int iDisp = 0; iDisp < nListSize; ++iDisp )
  1134. {
  1135. // Get the current displacement.
  1136. CCoreDispInfo *pDisp = ppListBase[iDisp];
  1137. if ( !pDisp )
  1138. continue;
  1139. // Loop through all the edges of the displacement.
  1140. for ( int iEdge = 0; iEdge < 4; ++iEdge )
  1141. {
  1142. // Find valid neighbors along the edge.
  1143. CDispNeighbor *pEdge = pDisp->GetEdgeNeighbor( iEdge );
  1144. if ( !pEdge )
  1145. continue;
  1146. // Check to see if we have sub-neighbors - defines a t-junction in this world. If not,
  1147. // then the normal blend edges function will catch it all.
  1148. if ( !pEdge->m_SubNeighbors[0].IsValid() || !pEdge->m_SubNeighbors[1].IsValid() )
  1149. continue;
  1150. // Get the mid-point of the current displacement.
  1151. CVertIndex viMidPoint = pDisp->GetEdgeMidPoint( iEdge );
  1152. int iMidPoint = pDisp->VertIndexToInt( viMidPoint );
  1153. const Vector &vecMidPoint = pDisp->GetVert( iMidPoint );
  1154. // Get the current sub-neighbors along the edge.
  1155. CCoreDispInfo *pNeighbor1 = ppListBase[pEdge->m_SubNeighbors[0].GetNeighborIndex()];
  1156. CCoreDispInfo *pNeighbor2 = ppListBase[pEdge->m_SubNeighbors[1].GetNeighborIndex()];
  1157. // Get the current sub-neighbor corners.
  1158. int iCorners[2];
  1159. iCorners[0] = FindNeighborCornerVert( pNeighbor1, vecMidPoint );
  1160. iCorners[1] = FindNeighborCornerVert( pNeighbor2, vecMidPoint );
  1161. if ( iCorners[0] != -1 && iCorners[1] != -1 )
  1162. {
  1163. CVertIndex viCorners[2] = { pNeighbor1->GetCornerPointIndex( iCorners[0] ),pNeighbor2->GetCornerPointIndex( iCorners[1] ) };
  1164. // Accumulate the normals at the mid-point of the primary edge and corners of the sub-neighbors.
  1165. Vector vecAverage = pDisp->GetNormal( iMidPoint );
  1166. vecAverage += pNeighbor1->GetNormal( viCorners[0] );
  1167. vecAverage += pNeighbor2->GetNormal( viCorners[1] );
  1168. // Re-normalize.
  1169. VectorNormalize( vecAverage );
  1170. Vector vAvgTanS = pDisp->GetTangentS(iMidPoint);
  1171. vAvgTanS += pNeighbor1->GetTangentS(viCorners[0]);
  1172. vAvgTanS += pNeighbor2->GetTangentS(viCorners[1]);
  1173. VectorNormalize(vAvgTanS);
  1174. //vecAverage.Init( 0.0f, 0.0f, 1.0f );
  1175. // Set the new normal value back.
  1176. UpdateTangentSpace( pDisp, iMidPoint, vecAverage, vAvgTanS );
  1177. UpdateTangentSpace( pNeighbor1, viCorners[0], vecAverage, vAvgTanS );
  1178. UpdateTangentSpace( pNeighbor2, viCorners[1], vecAverage, vAvgTanS );
  1179. }
  1180. }
  1181. }
  1182. }
  1183. //-----------------------------------------------------------------------------
  1184. // Purpose:
  1185. // Input : *pDisp -
  1186. // iNeighbors[512] -
  1187. // Output : int
  1188. //-----------------------------------------------------------------------------
  1189. static int GetAllNeighbors( const CCoreDispInfo *pDisp, int (&iNeighbors)[512] )
  1190. {
  1191. int nNeighbors = 0;
  1192. // Check corner neighbors.
  1193. for ( int iCorner=0; iCorner < 4; iCorner++ )
  1194. {
  1195. const CDispCornerNeighbors *pCorner = pDisp->GetCornerNeighbors( iCorner );
  1196. for ( int i=0; i < pCorner->m_nNeighbors; i++ )
  1197. {
  1198. if ( nNeighbors < Q_ARRAYSIZE( iNeighbors ) )
  1199. iNeighbors[nNeighbors++] = pCorner->m_Neighbors[i];
  1200. }
  1201. }
  1202. for ( int iEdge=0; iEdge < 4; iEdge++ )
  1203. {
  1204. const CDispNeighbor *pEdge = pDisp->GetEdgeNeighbor( iEdge );
  1205. for ( int i=0; i < 2; i++ )
  1206. {
  1207. if ( pEdge->m_SubNeighbors[i].IsValid() )
  1208. if ( nNeighbors < Q_ARRAYSIZE( iNeighbors ) )
  1209. iNeighbors[nNeighbors++] = pEdge->m_SubNeighbors[i].GetNeighborIndex();
  1210. }
  1211. }
  1212. return nNeighbors;
  1213. }
  1214. //-----------------------------------------------------------------------------
  1215. // Purpose:
  1216. // Input : **ppListBase -
  1217. // listSize -
  1218. //-----------------------------------------------------------------------------
  1219. static void BlendCorners( CCoreDispInfo **ppListBase, int nListSize )
  1220. {
  1221. CUtlVector<int> nbCornerVerts;
  1222. for ( int iDisp = 0; iDisp < nListSize; ++iDisp )
  1223. {
  1224. CCoreDispInfo *pDisp = ppListBase[iDisp];
  1225. int iNeighbors[512];
  1226. int nNeighbors = GetAllNeighbors( pDisp, iNeighbors );
  1227. // Make sure we have room for all the neighbors.
  1228. nbCornerVerts.RemoveAll();
  1229. nbCornerVerts.EnsureCapacity( nNeighbors );
  1230. nbCornerVerts.AddMultipleToTail( nNeighbors );
  1231. // For each corner.
  1232. for ( int iCorner=0; iCorner < 4; iCorner++ )
  1233. {
  1234. // Has it been touched?
  1235. CVertIndex cornerVert = pDisp->GetCornerPointIndex( iCorner );
  1236. int iCornerVert = pDisp->VertIndexToInt( cornerVert );
  1237. const Vector &vCornerVert = pDisp->GetVert( iCornerVert );
  1238. // For each displacement sharing this corner..
  1239. Vector vAverage = pDisp->GetNormal( iCornerVert );
  1240. Vector vAvgTanS;
  1241. pDisp->GetTangentS( iCornerVert, vAvgTanS );
  1242. for ( int iNeighbor=0; iNeighbor < nNeighbors; iNeighbor++ )
  1243. {
  1244. int iNBListIndex = iNeighbors[iNeighbor];
  1245. CCoreDispInfo *pNeighbor = ppListBase[iNBListIndex];
  1246. // Find out which vert it is on the neighbor.
  1247. int iNBCorner = FindNeighborCornerVert( pNeighbor, vCornerVert );
  1248. if ( iNBCorner == -1 )
  1249. {
  1250. nbCornerVerts[iNeighbor] = -1; // remove this neighbor from the list.
  1251. }
  1252. else
  1253. {
  1254. CVertIndex viNBCornerVert = pNeighbor->GetCornerPointIndex( iNBCorner );
  1255. int iNBVert = pNeighbor->VertIndexToInt( viNBCornerVert );
  1256. nbCornerVerts[iNeighbor] = iNBVert;
  1257. vAverage += pNeighbor->GetNormal( iNBVert );
  1258. vAvgTanS += pNeighbor->GetTangentS( iNBVert );
  1259. }
  1260. }
  1261. // Blend all the neighbor normals with this one.
  1262. VectorNormalize( vAverage );
  1263. VectorNormalize( vAvgTanS );
  1264. UpdateTangentSpace(pDisp, iCornerVert, vAverage, vAvgTanS );
  1265. for ( int iNeighbor=0; iNeighbor < nNeighbors; iNeighbor++ )
  1266. {
  1267. int iNBListIndex = iNeighbors[iNeighbor];
  1268. if ( nbCornerVerts[iNeighbor] == -1 )
  1269. continue;
  1270. CCoreDispInfo *pNeighbor = ppListBase[iNBListIndex];
  1271. UpdateTangentSpace(pNeighbor, nbCornerVerts[iNeighbor], vAverage, vAvgTanS);
  1272. }
  1273. }
  1274. }
  1275. }
  1276. //-----------------------------------------------------------------------------
  1277. // Purpose:
  1278. // Input : **ppListBase -
  1279. // listSize -
  1280. //-----------------------------------------------------------------------------
  1281. static void BlendEdges( CCoreDispInfo **ppListBase, int nListSize )
  1282. {
  1283. // Loop through all the displacements in the list.
  1284. for ( int iDisp = 0; iDisp < nListSize; ++iDisp )
  1285. {
  1286. // Get the current displacement.
  1287. CCoreDispInfo *pDisp = ppListBase[iDisp];
  1288. if ( !pDisp )
  1289. continue;
  1290. // Loop through all of the edges on a displacement.
  1291. for ( int iEdge = 0; iEdge < 4; ++iEdge )
  1292. {
  1293. // Get the current displacement edge.
  1294. CDispNeighbor *pEdge = pDisp->GetEdgeNeighbor( iEdge );
  1295. if ( !pEdge )
  1296. continue;
  1297. // Check for sub-edges.
  1298. for ( int iSubEdge = 0; iSubEdge < 2; ++iSubEdge )
  1299. {
  1300. // Get the current sub-edge.
  1301. CDispSubNeighbor *pSubEdge = &pEdge->m_SubNeighbors[iSubEdge];
  1302. if ( !pSubEdge->IsValid() )
  1303. continue;
  1304. // Get the current neighbor.
  1305. CCoreDispInfo *pNeighbor = ppListBase[pSubEdge->GetNeighborIndex()];
  1306. if ( !pNeighbor )
  1307. continue;
  1308. // Get the edge dimension.
  1309. int iEdgeDim = g_EdgeDims[iEdge];
  1310. CDispSubEdgeIterator it;
  1311. it.Start( pDisp, iEdge, iSubEdge, true );
  1312. // Get setup on the first corner vert.
  1313. it.Next();
  1314. CVertIndex viPrevPos = it.GetVertIndex();
  1315. while ( it.Next() )
  1316. {
  1317. // Blend the two.
  1318. if ( !it.IsLastVert() )
  1319. {
  1320. Vector vecAverage = pDisp->GetNormal( it.GetVertIndex() ) + pNeighbor->GetNormal( it.GetNBVertIndex() );
  1321. Vector vAvgTanS = pDisp->GetTangentS( it.GetVertIndex() ) + pNeighbor->GetTangentS( it.GetNBVertIndex() );
  1322. VectorNormalize( vecAverage );
  1323. VectorNormalize( vAvgTanS );
  1324. UpdateTangentSpace(pDisp, it.GetVertIndex(), vecAverage, vAvgTanS );
  1325. UpdateTangentSpace(pNeighbor, it.GetNBVertIndex(), vecAverage, vAvgTanS );
  1326. }
  1327. // Now blend the in-between verts (if this edge is high-res).
  1328. int iPrevPos = viPrevPos[!iEdgeDim];
  1329. int iCurPos = it.GetVertIndex()[!iEdgeDim];
  1330. for ( int iTween = iPrevPos+1; iTween < iCurPos; iTween++ )
  1331. {
  1332. float flPercent = RemapVal( iTween, iPrevPos, iCurPos, 0, 1 );
  1333. Vector vecNormal;
  1334. VectorLerp( pDisp->GetNormal( viPrevPos ), pDisp->GetNormal( it.GetVertIndex() ), flPercent, vecNormal );
  1335. VectorNormalize( vecNormal );
  1336. Vector vAvgTanS;
  1337. VectorLerp( pDisp->GetTangentS( viPrevPos ), pDisp->GetTangentS( it.GetVertIndex() ), flPercent, vAvgTanS );
  1338. VectorNormalize( vAvgTanS );
  1339. CVertIndex viTween;
  1340. viTween[iEdgeDim] = it.GetVertIndex()[iEdgeDim];
  1341. viTween[!iEdgeDim] = iTween;
  1342. UpdateTangentSpace(pDisp, viTween, vecNormal, vAvgTanS);
  1343. }
  1344. viPrevPos = it.GetVertIndex();
  1345. }
  1346. }
  1347. }
  1348. }
  1349. }
  1350. //-----------------------------------------------------------------------------
  1351. // Purpose:
  1352. // Input : **pListBase -
  1353. // listSize -
  1354. // NOTE: todo - this is almost the same code as found in vrad, should probably
  1355. // move it up into common code at some point if the feature
  1356. // continues to get used
  1357. //-----------------------------------------------------------------------------
  1358. void SmoothDispSurfNormals( CCoreDispInfo **ppListBase, int nListSize )
  1359. {
  1360. // Setup helper list for iteration.
  1361. for ( int iDisp = 0; iDisp < nListSize; ++iDisp )
  1362. {
  1363. ppListBase[iDisp]->SetDispUtilsHelperInfo( ppListBase, nListSize );
  1364. }
  1365. // Blend normals along t-junctions, corners, and edges.
  1366. BlendSubNeighbors( ppListBase, nListSize );
  1367. BlendCorners( ppListBase, nListSize );
  1368. BlendEdges( ppListBase, nListSize );
  1369. }