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.

1253 lines
32 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include <stdafx.h>
  8. #include "MainFrm.h"
  9. #include "MapDoc.h"
  10. #include "GlobalFunctions.h"
  11. #include "Subdiv.h"
  12. #include "History.h"
  13. //=============================================================================
  14. //
  15. // Subdivision Point Functions
  16. //
  17. //-----------------------------------------------------------------------------
  18. //-----------------------------------------------------------------------------
  19. void CSubdivPoint::Clear( void )
  20. {
  21. VectorClear( m_Point );
  22. VectorClear( m_NewPoint );
  23. VectorClear( m_Normal );
  24. VectorClear( m_NewNormal );
  25. m_Type = -1;
  26. m_Valence = 0;
  27. for( int i = 0; i < NUM_SUBDIV_EDGES; i++ )
  28. {
  29. m_pEdges[i] = NULL;
  30. }
  31. }
  32. //-----------------------------------------------------------------------------
  33. //-----------------------------------------------------------------------------
  34. void CSubdivPoint::Copy( const CSubdivPoint *pFrom )
  35. {
  36. m_Point = pFrom->m_Point;
  37. m_NewPoint = pFrom->m_NewPoint;
  38. m_Normal = pFrom->m_Normal;
  39. m_NewNormal = pFrom->m_NewNormal;
  40. m_Type = pFrom->m_Type;
  41. m_Valence = pFrom->m_Valence;
  42. for( int i = 0; i < NUM_SUBDIV_EDGES; i++ )
  43. {
  44. m_pEdges[i] = pFrom->m_pEdges[i];
  45. }
  46. }
  47. //-----------------------------------------------------------------------------
  48. //-----------------------------------------------------------------------------
  49. void CSubdivPoint::CalcNewVertexNormal( void )
  50. {
  51. switch( m_Type )
  52. {
  53. case POINT_CORNER:
  54. {
  55. m_NewNormal = m_Normal;
  56. break;
  57. }
  58. case POINT_CREASE:
  59. {
  60. Vector edgeAccum;
  61. VectorClear( edgeAccum );
  62. for( int i = 0; i < m_Valence; i++ )
  63. {
  64. if( m_pEdges[i]->m_Sharpness > 0.0f )
  65. {
  66. VectorAdd( edgeAccum, m_pEdges[i]->m_NewEdgeNormal, edgeAccum );
  67. }
  68. }
  69. //
  70. // normal
  71. //
  72. VectorScale( m_Normal, 6.0f, m_NewNormal );
  73. VectorAdd( m_NewNormal, edgeAccum, m_NewNormal );
  74. VectorScale( m_NewNormal, 0.125f, m_NewNormal );
  75. break;
  76. }
  77. case POINT_ORDINARY:
  78. {
  79. //
  80. // accumulate edge data and multiply by valence ratio
  81. //
  82. Vector edgeAccum;
  83. VectorClear( edgeAccum );
  84. for( int i = 0; i < m_Valence; i++ )
  85. {
  86. VectorAdd( edgeAccum, m_pEdges[i]->m_NewEdgeNormal, edgeAccum );
  87. }
  88. float ratio = ( 1.0f / ( float )( m_Valence * m_Valence ) );
  89. VectorScale( edgeAccum, ratio, edgeAccum );
  90. //
  91. // accumulate centroid data and multiply by valence ratio
  92. //
  93. int quadCount = 0;
  94. CSubdivQuad *quadList[16];
  95. for( i = 0; i < m_Valence; i++ )
  96. {
  97. for( int j = 0; j < 2; j++ )
  98. {
  99. if( m_pEdges[i]->m_pQuads[j] )
  100. {
  101. for( int k = 0; k < quadCount; k++ )
  102. {
  103. if( m_pEdges[i]->m_pQuads[j] == quadList[k] )
  104. break;
  105. }
  106. if( k != quadCount )
  107. continue;
  108. quadList[quadCount] = m_pEdges[i]->m_pQuads[j];
  109. quadCount++;
  110. }
  111. }
  112. }
  113. Vector centroidAccum;
  114. VectorClear( centroidAccum );
  115. for( i = 0; i < quadCount; i++ )
  116. {
  117. Vector centroid;
  118. quadList[i]->GetNormal( centroid );
  119. VectorAdd( centroidAccum, centroid, centroidAccum );
  120. }
  121. VectorScale( centroidAccum, ratio, centroidAccum );
  122. //
  123. // normal
  124. //
  125. VectorScale( m_Normal, ratio, m_NewNormal );
  126. VectorAdd( m_NewNormal, edgeAccum, m_NewNormal );
  127. VectorAdd( m_NewNormal, centroidAccum, m_NewNormal );
  128. break;
  129. }
  130. default:
  131. break;
  132. }
  133. }
  134. //-----------------------------------------------------------------------------
  135. //-----------------------------------------------------------------------------
  136. void CSubdivPoint::CalcNewVertexPoint( void )
  137. {
  138. switch( m_Type )
  139. {
  140. case POINT_CORNER:
  141. {
  142. m_NewPoint = m_Point;
  143. break;
  144. }
  145. case POINT_CREASE:
  146. {
  147. Vector edgeAccum;
  148. VectorClear( edgeAccum );
  149. for( int i = 0; i < m_Valence; i++ )
  150. {
  151. if( m_pEdges[i]->m_Sharpness > 0.0f )
  152. {
  153. VectorAdd( edgeAccum, m_pEdges[i]->m_NewEdgePoint, edgeAccum );
  154. }
  155. }
  156. //
  157. // point
  158. //
  159. VectorScale( m_Point, 6.0f, m_NewPoint );
  160. VectorAdd( m_NewPoint, edgeAccum, m_NewPoint );
  161. VectorScale( m_NewPoint, 0.125f, m_NewPoint );
  162. break;
  163. }
  164. case POINT_ORDINARY:
  165. {
  166. //
  167. // accumulate edge data and multiply by valence ratio
  168. //
  169. Vector edgeAccum;
  170. VectorClear( edgeAccum );
  171. for( int i = 0; i < m_Valence; i++ )
  172. {
  173. VectorAdd( edgeAccum, m_pEdges[i]->m_NewEdgePoint, edgeAccum );
  174. }
  175. float ratio = ( 1.0f / ( float )( m_Valence * m_Valence ) );
  176. VectorScale( edgeAccum, ratio, edgeAccum );
  177. //
  178. // accumulate centroid data and multiply by valence ratio
  179. //
  180. int quadCount = 0;
  181. CSubdivQuad *quadList[16];
  182. for( i = 0; i < m_Valence; i++ )
  183. {
  184. for( int j = 0; j < 2; j++ )
  185. {
  186. if( m_pEdges[i]->m_pQuads[j] )
  187. {
  188. for( int k = 0; k < quadCount; k++ )
  189. {
  190. if( m_pEdges[i]->m_pQuads[j] == quadList[k] )
  191. break;
  192. }
  193. if( k != quadCount )
  194. continue;
  195. quadList[quadCount] = m_pEdges[i]->m_pQuads[j];
  196. quadCount++;
  197. }
  198. }
  199. }
  200. Vector centroidAccum;
  201. VectorClear( centroidAccum );
  202. for( i = 0; i < quadCount; i++ )
  203. {
  204. Vector centroid;
  205. quadList[i]->GetCentroid( centroid );
  206. VectorAdd( centroidAccum, centroid, centroidAccum );
  207. }
  208. VectorScale( centroidAccum, ratio, centroidAccum );
  209. //
  210. // point contribution to eqtn.
  211. //
  212. ratio = ( ( float )m_Valence - 2.0f ) / ( float )m_Valence;
  213. VectorScale( m_Point, ratio, m_NewPoint );
  214. VectorAdd( m_NewPoint, edgeAccum, m_NewPoint );
  215. VectorAdd( m_NewPoint, centroidAccum, m_NewPoint );
  216. break;
  217. }
  218. default:
  219. break;
  220. }
  221. }
  222. //-----------------------------------------------------------------------------
  223. //-----------------------------------------------------------------------------
  224. bool CompareSubdivPoints( const CSubdivPoint *pPoint1, const CSubdivPoint *pPoint2, float tolerance )
  225. {
  226. for( int i = 0 ; i < 3 ; i++ )
  227. {
  228. if( fabs( pPoint1->m_Point[i] - pPoint2->m_Point[i] ) > tolerance )
  229. return false;
  230. }
  231. return true;
  232. }
  233. //-----------------------------------------------------------------------------
  234. //-----------------------------------------------------------------------------
  235. bool CompareSubdivPointToPoint( const CSubdivPoint *pSubdivPoint, const Vector& point, float tolerance )
  236. {
  237. for( int i = 0 ; i < 3 ; i++ )
  238. {
  239. if( fabs( pSubdivPoint->m_Point[i] - point[i] ) > tolerance )
  240. return false;
  241. }
  242. return true;
  243. }
  244. //=============================================================================
  245. //
  246. // Subdivision Edge Functions
  247. //
  248. //-----------------------------------------------------------------------------
  249. //-----------------------------------------------------------------------------
  250. void CSubdivEdge::Clear( void )
  251. {
  252. for( int i = 0; i < 2; i++ )
  253. {
  254. m_ndxPoint[i] = -1;
  255. m_pQuads[i] = NULL;
  256. m_ndxQuadEdge[i] = -1;
  257. }
  258. m_Sharpness = 1.0f;
  259. VectorClear( m_NewEdgePoint );
  260. m_Active = false;
  261. }
  262. //-----------------------------------------------------------------------------
  263. //-----------------------------------------------------------------------------
  264. void CSubdivEdge::Copy( const CSubdivEdge *pFrom )
  265. {
  266. for( int i = 0; i < 2; i++ )
  267. {
  268. m_ndxPoint[i] = pFrom->m_ndxPoint[i];
  269. m_pQuads[i] = pFrom->m_pQuads[i];
  270. m_ndxQuadEdge[i] = pFrom->m_ndxQuadEdge[i];
  271. }
  272. m_Sharpness = pFrom->m_Sharpness;
  273. m_NewEdgePoint = pFrom->m_NewEdgePoint;
  274. m_Active = pFrom->m_Active;
  275. }
  276. //-----------------------------------------------------------------------------
  277. //-----------------------------------------------------------------------------
  278. void CSubdivEdge::CalcNewEdgeNormal( void )
  279. {
  280. if( !m_Active )
  281. return;
  282. //
  283. // get the subdivision mesh
  284. //
  285. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  286. if( !pDoc )
  287. return;
  288. CSubdivMesh *pMesh = pDoc->GetSubdivMesh();
  289. //
  290. // get the edge data
  291. //
  292. Vector normal0, normal1;
  293. pMesh->GetNormal( m_ndxPoint[0], normal0 );
  294. pMesh->GetNormal( m_ndxPoint[1], normal1 );
  295. //
  296. // calculate the "sharp" new edge point
  297. //
  298. Vector vSharp;
  299. VectorClear( vSharp );
  300. VectorAdd( normal0, normal1, vSharp );
  301. VectorScale( vSharp, 0.5f, vSharp );
  302. //
  303. // calculate the "smooth" new edge point if necessary
  304. //
  305. Vector vSmooth;
  306. VectorClear( vSmooth );
  307. if( m_pQuads[1] && ( m_Sharpness != 1.0f ) )
  308. {
  309. Vector quadNormals[2];
  310. m_pQuads[0]->GetNormal( quadNormals[0] );
  311. m_pQuads[1]->GetNormal( quadNormals[1] );
  312. VectorAdd( normal0, normal1, vSmooth );
  313. VectorAdd( vSmooth, quadNormals[0], vSmooth );
  314. VectorAdd( vSmooth, quadNormals[1], vSmooth );
  315. VectorScale( vSmooth, 0.25f, vSmooth );
  316. }
  317. else
  318. {
  319. // make sure -- if here because of no neighboring quad
  320. m_Sharpness = 1.0f;
  321. m_pQuads[0]->CalcNormal();
  322. }
  323. //
  324. // calculate the new edge point
  325. //
  326. // ( 1 - edge(sharpness) ) * vSmooth + edge(sharpness) * vSharp
  327. //
  328. VectorScale( vSmooth, ( 1.0f - m_Sharpness ), vSmooth );
  329. VectorScale( vSharp, m_Sharpness, vSharp );
  330. VectorAdd( vSmooth, vSharp, m_NewEdgeNormal );
  331. }
  332. //-----------------------------------------------------------------------------
  333. //-----------------------------------------------------------------------------
  334. void CSubdivEdge::CalcNewEdgePoint( void )
  335. {
  336. if( !m_Active )
  337. return;
  338. //
  339. // get the subdivision mesh
  340. //
  341. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  342. if( !pDoc )
  343. return;
  344. CSubdivMesh *pMesh = pDoc->GetSubdivMesh();
  345. //
  346. // get the edge data
  347. //
  348. Vector edgePt0, edgePt1;
  349. pMesh->GetPoint( m_ndxPoint[0], edgePt0 );
  350. pMesh->GetPoint( m_ndxPoint[1], edgePt1 );
  351. //
  352. // calculate the "sharp" new edge point
  353. //
  354. Vector vSharp;
  355. VectorClear( vSharp );
  356. VectorAdd( edgePt0, edgePt1, vSharp );
  357. VectorScale( vSharp, 0.5f, vSharp );
  358. //
  359. // calculate the "smooth" new edge point if necessary
  360. //
  361. Vector vSmooth;
  362. VectorClear( vSmooth );
  363. if( m_pQuads[1] && ( m_Sharpness != 1.0f ) )
  364. {
  365. Vector centroids[2];
  366. m_pQuads[0]->GetCentroid( centroids[0] );
  367. m_pQuads[1]->GetCentroid( centroids[1] );
  368. VectorAdd( edgePt0, edgePt1, vSmooth );
  369. VectorAdd( vSmooth, centroids[0], vSmooth );
  370. VectorAdd( vSmooth, centroids[1], vSmooth );
  371. VectorScale( vSmooth, 0.25f, vSmooth );
  372. }
  373. else
  374. {
  375. // make sure -- if here because of no neighboring quad
  376. m_Sharpness = 1.0f;
  377. m_pQuads[0]->CalcCentroid();
  378. }
  379. //
  380. // calculate the new edge point
  381. //
  382. // ( 1 - edge(sharpness) ) * vSmooth + edge(sharpness) * vSharp
  383. //
  384. VectorScale( vSmooth, ( 1.0f - m_Sharpness ), vSmooth );
  385. VectorScale( vSharp, m_Sharpness, vSharp );
  386. VectorAdd( vSmooth, vSharp, m_NewEdgePoint );
  387. }
  388. //-----------------------------------------------------------------------------
  389. //-----------------------------------------------------------------------------
  390. bool CompareSubdivEdges( const CSubdivEdge *pEdge1, const CSubdivEdge *pEdge2 )
  391. {
  392. if( ( ( pEdge1->m_ndxPoint[0] == pEdge2->m_ndxPoint[0] ) && ( pEdge1->m_ndxPoint[1] == pEdge2->m_ndxPoint[1] ) ) ||
  393. ( ( pEdge1->m_ndxPoint[0] == pEdge2->m_ndxPoint[1] ) && ( pEdge1->m_ndxPoint[1] == pEdge2->m_ndxPoint[0] ) ) )
  394. return true;
  395. return false;
  396. }
  397. //=============================================================================
  398. //
  399. // Subdivision Quad Functions
  400. //
  401. //-----------------------------------------------------------------------------
  402. //-----------------------------------------------------------------------------
  403. void CSubdivQuad::GetCentroid( Vector& centroid )
  404. {
  405. // get the subdivision mesh
  406. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  407. if( !pDoc )
  408. return;
  409. CSubdivMesh *pMesh = pDoc->GetSubdivMesh();
  410. VectorClear( centroid );
  411. for( int i = 0; i < 4; i++ )
  412. {
  413. Vector point;
  414. pMesh->GetPoint( m_ndxVert[i], point );
  415. VectorAdd( centroid, point, centroid );
  416. }
  417. VectorScale( centroid, 0.25f, centroid );
  418. // keep to surface creation
  419. m_Centroid = centroid;
  420. }
  421. //-----------------------------------------------------------------------------
  422. //-----------------------------------------------------------------------------
  423. void CSubdivQuad::CalcCentroid( void )
  424. {
  425. // get the subdivision mesh
  426. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  427. if( !pDoc )
  428. return;
  429. CSubdivMesh *pMesh = pDoc->GetSubdivMesh();
  430. VectorClear( m_Centroid );
  431. for( int i = 0; i < 4; i++ )
  432. {
  433. Vector point;
  434. pMesh->GetPoint( m_ndxVert[i], point );
  435. VectorAdd( m_Centroid, point, m_Centroid );
  436. }
  437. VectorScale( m_Centroid, 0.25f, m_Centroid );
  438. }
  439. //-----------------------------------------------------------------------------
  440. //-----------------------------------------------------------------------------
  441. void CSubdivQuad::GetNormal( Vector& normal )
  442. {
  443. // get the subdivision mesh
  444. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  445. if( !pDoc )
  446. return;
  447. CSubdivMesh *pMesh = pDoc->GetSubdivMesh();
  448. Vector points[3];
  449. Vector segs[2];
  450. pMesh->GetPoint( m_ndxVert[0], points[0] );
  451. pMesh->GetPoint( m_ndxVert[1], points[1] );
  452. pMesh->GetPoint( m_ndxVert[2], points[2] );
  453. VectorSubtract( points[1], points[0], segs[0] );
  454. VectorSubtract( points[2], points[0], segs[1] );
  455. CrossProduct( segs[1], segs[0], normal );
  456. VectorNormalize( normal );
  457. m_Normal = normal;
  458. }
  459. //-----------------------------------------------------------------------------
  460. //-----------------------------------------------------------------------------
  461. void CSubdivQuad::CalcNormal( void )
  462. {
  463. // get the subdivision mesh
  464. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  465. if( !pDoc )
  466. return;
  467. CSubdivMesh *pMesh = pDoc->GetSubdivMesh();
  468. Vector points[3];
  469. Vector segs[2];
  470. pMesh->GetPoint( m_ndxVert[0], points[0] );
  471. pMesh->GetPoint( m_ndxVert[1], points[1] );
  472. pMesh->GetPoint( m_ndxVert[2], points[2] );
  473. VectorSubtract( points[1], points[0], segs[0] );
  474. VectorSubtract( points[2], points[0], segs[1] );
  475. CrossProduct( segs[1], segs[0], m_Normal );
  476. VectorNormalize( m_Normal );
  477. }
  478. //=============================================================================
  479. //
  480. // Subdivision Mesh Functions
  481. //
  482. //-----------------------------------------------------------------------------
  483. //-----------------------------------------------------------------------------
  484. CSubdivMesh::CSubdivMesh()
  485. {
  486. Clear();
  487. }
  488. //-----------------------------------------------------------------------------
  489. //-----------------------------------------------------------------------------
  490. CSubdivMesh::~CSubdivMesh()
  491. {
  492. }
  493. //-----------------------------------------------------------------------------
  494. //-----------------------------------------------------------------------------
  495. int CSubdivMesh::AddPoint( const Vector& point, const Vector& normal )
  496. {
  497. //
  498. // check for existing point within CSubdivPoints
  499. //
  500. for( int i = 0; i < m_PointCount; i++ )
  501. {
  502. if( CompareSubdivPointToPoint( &m_pPoints[i], point, 0.01f ) )
  503. return i;
  504. }
  505. if( m_PointCount >= m_MaxPointCount )
  506. {
  507. // error message!
  508. return -1;
  509. }
  510. m_pPoints[m_PointCount].m_Point = point;
  511. m_pPoints[m_PointCount].m_Normal = normal;
  512. m_PointCount++;
  513. return ( m_PointCount - 1 );
  514. }
  515. //-----------------------------------------------------------------------------
  516. //-----------------------------------------------------------------------------
  517. void CSubdivMesh::RemovePoint( Vector& point )
  518. {
  519. //
  520. // find point in list (and remove it)
  521. //
  522. for( int i = 0; i < m_PointCount; i++ )
  523. {
  524. if( !CompareSubdivPointToPoint( &m_pPoints[i], point, 0.01f ) )
  525. continue;
  526. if( i == ( m_PointCount - 1 ) )
  527. {
  528. m_pPoints[i].Clear();
  529. }
  530. else
  531. {
  532. m_pPoints[i].Copy( &m_pPoints[m_PointCount-1] );
  533. m_pPoints[m_PointCount-1].Clear();
  534. }
  535. m_PointCount--;
  536. }
  537. }
  538. //-----------------------------------------------------------------------------
  539. //-----------------------------------------------------------------------------
  540. int CSubdivMesh::AddEdge( CSubdivEdge *edge )
  541. {
  542. //
  543. // check for existing edge
  544. //
  545. for( int i = 0; i < m_EdgeCount; i++ )
  546. {
  547. if( CompareSubdivEdges( edge, &m_pEdges[i] ) )
  548. {
  549. //
  550. // check for "quads" on both sides of edge (add if necessary)
  551. //
  552. if( ( !m_pEdges[i].m_pQuads[1] ) && ( edge->m_pQuads[0] != m_pEdges[i].m_pQuads[0] ) )
  553. {
  554. m_pEdges[i].m_pQuads[1] = edge->m_pQuads[0];
  555. m_pEdges[i].m_ndxQuadEdge[1] = edge->m_ndxQuadEdge[0];
  556. m_pEdges[i].m_Sharpness = 0.0f;
  557. }
  558. return i;
  559. }
  560. }
  561. if( m_EdgeCount >= m_MaxEdgeCount )
  562. {
  563. // error message!
  564. return -1;
  565. }
  566. m_pEdges[m_EdgeCount].Copy( edge );
  567. m_pEdges[m_EdgeCount].m_Active = true;
  568. m_EdgeCount++;
  569. return ( m_EdgeCount - 1 );
  570. }
  571. //-----------------------------------------------------------------------------
  572. //-----------------------------------------------------------------------------
  573. void CSubdivMesh::RemoveEdge( CSubdivEdge *edge )
  574. {
  575. return;
  576. }
  577. //-----------------------------------------------------------------------------
  578. //-----------------------------------------------------------------------------
  579. void CSubdivMesh::CatmullClarkSubdivide( void )
  580. {
  581. //
  582. // calculate the "new edge points"
  583. //
  584. for( int i = 0; i < m_EdgeCount; i++ )
  585. {
  586. m_pEdges[i].CalcNewEdgePoint();
  587. m_pEdges[i].CalcNewEdgeNormal();
  588. }
  589. //
  590. // if point index if part of edge, add to point edge list and increment valence
  591. //
  592. for( i = 0; i < m_PointCount; i++ )
  593. {
  594. for( int j = 0; j < m_EdgeCount; j++ )
  595. {
  596. if( !m_pEdges[j].m_Active )
  597. continue;
  598. if( ( i == m_pEdges[j].m_ndxPoint[0] ) || ( i == m_pEdges[j].m_ndxPoint[1] ) )
  599. {
  600. m_pPoints[i].m_pEdges[m_pPoints[i].m_Valence] = &m_pEdges[j];
  601. m_pPoints[i].m_Valence++;
  602. }
  603. }
  604. }
  605. //
  606. // determine the point's "type"
  607. //
  608. for( i = 0; i < m_PointCount; i++ )
  609. {
  610. //
  611. // get the number of sharp incident edges and neighbor data
  612. //
  613. int sharpnessCount = 0;
  614. int sharpnessThreshold = m_pPoints[i].m_Valence - 1;
  615. bool bHasNeighbors = false;
  616. for( int j = 0; j < m_pPoints[i].m_Valence; j++ )
  617. {
  618. if( m_pPoints[i].m_pEdges[j]->m_Sharpness > 0.0f )
  619. {
  620. sharpnessCount++;
  621. }
  622. if( m_pPoints[i].m_pEdges[j]->m_pQuads[1] )
  623. {
  624. bHasNeighbors = true;
  625. }
  626. }
  627. //
  628. // determine point type
  629. //
  630. if( ( sharpnessCount >= sharpnessThreshold ) || !bHasNeighbors )
  631. // if( ( sharpnessCount > 2 ) || !bHasNeighbors )
  632. {
  633. m_pPoints[i].m_Type = CSubdivPoint::POINT_CORNER;
  634. continue;
  635. }
  636. if( sharpnessCount > 1 )
  637. // if( sharpnessCount == 2 )
  638. {
  639. m_pPoints[i].m_Type = CSubdivPoint::POINT_CREASE;
  640. continue;
  641. }
  642. m_pPoints[i].m_Type = CSubdivPoint::POINT_ORDINARY;
  643. }
  644. //
  645. // calculate the new vertex point
  646. //
  647. for( i = 0; i < m_PointCount; i++ )
  648. {
  649. m_pPoints[i].CalcNewVertexPoint();
  650. m_pPoints[i].CalcNewVertexNormal();
  651. }
  652. //
  653. // move all new points to points
  654. //
  655. for( i = 0; i < m_PointCount; i++ )
  656. {
  657. m_pPoints[i].m_Point = m_pPoints[i].m_NewPoint;
  658. m_pPoints[i].m_Normal = m_pPoints[i].m_NewNormal;
  659. VectorClear( m_pPoints[i].m_NewPoint );
  660. VectorClear( m_pPoints[i].m_NewNormal );
  661. m_pPoints[i].m_Valence = 0;
  662. }
  663. }
  664. //-----------------------------------------------------------------------------
  665. //-----------------------------------------------------------------------------
  666. int CSubdivMesh::AddTree( CSubdivQuad *pTree )
  667. {
  668. //
  669. // check to see if tree already exists in list
  670. //
  671. for( int i = 0; i < m_TreeCount; i++ )
  672. {
  673. if( pTree == m_ppTrees[i] )
  674. return i;
  675. }
  676. //
  677. // check tree count
  678. //
  679. if( m_TreeCount >= m_MaxTreeCount )
  680. {
  681. // error message
  682. _asm int 3;
  683. return -1;
  684. }
  685. //
  686. // add tree to list
  687. //
  688. m_ppTrees[m_TreeCount] = pTree;
  689. m_TreeCount++;
  690. return ( m_TreeCount - 1 );
  691. }
  692. static HCURSOR preSubdivCursor;
  693. //-----------------------------------------------------------------------------
  694. //-----------------------------------------------------------------------------
  695. bool CSubdivMesh::PreSubdivide( void )
  696. {
  697. // change the mouse to hourglass -- so level designers know something is
  698. // happening
  699. preSubdivCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
  700. // clear the mesh
  701. Clear();
  702. //
  703. // get the selection set
  704. //
  705. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  706. if( !pDoc )
  707. return false;
  708. CDispManager *pDispManager = pDoc->GetDispManager();
  709. if( !pDispManager )
  710. return false;
  711. // get number of displacements in selection
  712. int selectionCount = pDispManager->GetSelectionListCount();
  713. // allocate memory
  714. if( !AllocCache( selectionCount ) )
  715. return false;
  716. // mark the subdivision undo
  717. GetHistory()->MarkUndoPosition( NULL, "Subdivision" );
  718. //
  719. // add all surfaces to mesh to subdivide
  720. //
  721. for( int i = 0; i < selectionCount; i++ )
  722. {
  723. // get the current displacement surface
  724. CMapDisp *pDisp = pDispManager->GetFromSelectionList( i );
  725. if( !pDisp )
  726. continue;
  727. //
  728. // setup for undo
  729. //
  730. CMapFace *pFace = ( CMapFace* )pDisp->GetParent();
  731. CMapSolid *pSolid = ( CMapSolid* )pFace->GetParent();
  732. GetHistory()->Keep( ( CMapClass* )pSolid );
  733. //
  734. // add displacement's subdivision tree to mesh list
  735. //
  736. if( AddTree( pDisp->PreSubdivide( this ) ) == -1 )
  737. return false;
  738. }
  739. return true;
  740. }
  741. //-----------------------------------------------------------------------------
  742. //-----------------------------------------------------------------------------
  743. void CSubdivMesh::SetEdgeData( CSubdivQuad *pRoot, int index, int parentIndex, int subdivIndex )
  744. {
  745. for( int i = 0; i < 4; i++ )
  746. {
  747. CSubdivEdge edge;
  748. //
  749. // add vert indices
  750. //
  751. edge.m_ndxPoint[0] = pRoot[index].m_ndxVert[i];
  752. edge.m_ndxPoint[1] = pRoot[index].m_ndxVert[(i+1)%4];
  753. //
  754. // set initial quads and edges data
  755. //
  756. edge.m_pQuads[0] = &pRoot[index];
  757. edge.m_pQuads[1] = NULL;
  758. edge.m_ndxQuadEdge[0] = i;
  759. edge.m_ndxQuadEdge[1] = -1;
  760. //
  761. // set edge sharpness
  762. //
  763. if( ( i == subdivIndex ) || ( i == ( (subdivIndex+3)%4 ) ) )
  764. {
  765. edge.m_Sharpness = m_pEdges[pRoot[parentIndex].m_ndxEdge[i]].m_Sharpness;
  766. }
  767. else
  768. {
  769. edge.m_Sharpness = 0.0f;
  770. }
  771. // add edge to global list
  772. pRoot[index].m_ndxEdge[i] = AddEdge( &edge );
  773. }
  774. }
  775. //-----------------------------------------------------------------------------
  776. //-----------------------------------------------------------------------------
  777. void CSubdivMesh::CreateChildQuad4( CSubdivQuad *pRoot, int index, int parentIndex )
  778. {
  779. //
  780. // set quad indices -- displacement index values
  781. //
  782. pRoot[index].m_ndxQuad[0] = ( ( pRoot[parentIndex].m_ndxQuad[0] + pRoot[parentIndex].m_ndxQuad[3] ) / 2 );
  783. pRoot[index].m_ndxQuad[1] = ( ( pRoot[parentIndex].m_ndxQuad[0] + pRoot[parentIndex].m_ndxQuad[2] ) / 2 );
  784. pRoot[index].m_ndxQuad[2] = ( ( pRoot[parentIndex].m_ndxQuad[2] + pRoot[parentIndex].m_ndxQuad[3] ) / 2 );
  785. pRoot[index].m_ndxQuad[3] = pRoot[parentIndex].m_ndxQuad[3];
  786. //
  787. // set vert indices
  788. //
  789. pRoot[index].m_ndxVert[0] = AddPoint( m_pEdges[pRoot[parentIndex].m_ndxEdge[3]].m_NewEdgePoint,
  790. m_pEdges[pRoot[parentIndex].m_ndxEdge[3]].m_NewEdgeNormal );
  791. pRoot[index].m_ndxVert[1] = AddPoint( pRoot[parentIndex].m_Centroid, pRoot[parentIndex].m_Normal );
  792. pRoot[index].m_ndxVert[2] = AddPoint( m_pEdges[pRoot[parentIndex].m_ndxEdge[2]].m_NewEdgePoint,
  793. m_pEdges[pRoot[parentIndex].m_ndxEdge[2]].m_NewEdgeNormal );
  794. pRoot[index].m_ndxVert[3] = pRoot[parentIndex].m_ndxVert[3];
  795. // set edge data
  796. SetEdgeData( pRoot, index, parentIndex, 3 );
  797. }
  798. //-----------------------------------------------------------------------------
  799. //-----------------------------------------------------------------------------
  800. void CSubdivMesh::CreateChildQuad3( CSubdivQuad *pRoot, int index, int parentIndex )
  801. {
  802. //
  803. // set quad indices -- displacement index values
  804. //
  805. pRoot[index].m_ndxQuad[0] = ( ( pRoot[parentIndex].m_ndxQuad[0] + pRoot[parentIndex].m_ndxQuad[2] ) / 2 );
  806. pRoot[index].m_ndxQuad[1] = ( ( pRoot[parentIndex].m_ndxQuad[1] + pRoot[parentIndex].m_ndxQuad[2] ) / 2 );
  807. pRoot[index].m_ndxQuad[2] = pRoot[parentIndex].m_ndxQuad[2];
  808. pRoot[index].m_ndxQuad[3] = ( ( pRoot[parentIndex].m_ndxQuad[2] + pRoot[parentIndex].m_ndxQuad[3] ) / 2 );
  809. //
  810. // set vert indices
  811. //
  812. pRoot[index].m_ndxVert[0] = AddPoint( pRoot[parentIndex].m_Centroid, pRoot[parentIndex].m_Normal );
  813. pRoot[index].m_ndxVert[1] = AddPoint( m_pEdges[pRoot[parentIndex].m_ndxEdge[1]].m_NewEdgePoint,
  814. m_pEdges[pRoot[parentIndex].m_ndxEdge[1]].m_NewEdgeNormal );
  815. pRoot[index].m_ndxVert[2] = pRoot[parentIndex].m_ndxVert[2];
  816. pRoot[index].m_ndxVert[3] = AddPoint( m_pEdges[pRoot[parentIndex].m_ndxEdge[2]].m_NewEdgePoint,
  817. m_pEdges[pRoot[parentIndex].m_ndxEdge[2]].m_NewEdgeNormal );
  818. // set edge data
  819. SetEdgeData( pRoot, index, parentIndex, 2 );
  820. }
  821. //-----------------------------------------------------------------------------
  822. //-----------------------------------------------------------------------------
  823. void CSubdivMesh::CreateChildQuad2( CSubdivQuad *pRoot, int index, int parentIndex )
  824. {
  825. //
  826. // set quad indices -- displacement index values
  827. //
  828. pRoot[index].m_ndxQuad[0] = ( ( pRoot[parentIndex].m_ndxQuad[0] + pRoot[parentIndex].m_ndxQuad[1] ) / 2 );
  829. pRoot[index].m_ndxQuad[1] = pRoot[parentIndex].m_ndxQuad[1];
  830. pRoot[index].m_ndxQuad[2] = ( ( pRoot[parentIndex].m_ndxQuad[1] + pRoot[parentIndex].m_ndxQuad[2] ) / 2 );
  831. pRoot[index].m_ndxQuad[3] = ( ( pRoot[parentIndex].m_ndxQuad[0] + pRoot[parentIndex].m_ndxQuad[2] ) / 2 );
  832. //
  833. // set vert indices
  834. //
  835. pRoot[index].m_ndxVert[0] = AddPoint( m_pEdges[pRoot[parentIndex].m_ndxEdge[0]].m_NewEdgePoint,
  836. m_pEdges[pRoot[parentIndex].m_ndxEdge[0]].m_NewEdgeNormal );
  837. pRoot[index].m_ndxVert[1] = pRoot[parentIndex].m_ndxVert[1];
  838. pRoot[index].m_ndxVert[2] = AddPoint( m_pEdges[pRoot[parentIndex].m_ndxEdge[1]].m_NewEdgePoint,
  839. m_pEdges[pRoot[parentIndex].m_ndxEdge[1]].m_NewEdgeNormal );
  840. pRoot[index].m_ndxVert[3] = AddPoint( pRoot[parentIndex].m_Centroid, pRoot[parentIndex].m_Normal );
  841. // set edge data
  842. SetEdgeData( pRoot, index, parentIndex, 1 );
  843. }
  844. //-----------------------------------------------------------------------------
  845. //-----------------------------------------------------------------------------
  846. void CSubdivMesh::CreateChildQuad1( CSubdivQuad *pRoot, int index, int parentIndex )
  847. {
  848. //
  849. // set quad indices -- displacement index values
  850. //
  851. pRoot[index].m_ndxQuad[0] = pRoot[parentIndex].m_ndxQuad[0];
  852. pRoot[index].m_ndxQuad[1] = ( ( pRoot[parentIndex].m_ndxQuad[0] + pRoot[parentIndex].m_ndxQuad[1] ) / 2 );
  853. pRoot[index].m_ndxQuad[2] = ( ( pRoot[parentIndex].m_ndxQuad[0] + pRoot[parentIndex].m_ndxQuad[2] ) / 2 );
  854. pRoot[index].m_ndxQuad[3] = ( ( pRoot[parentIndex].m_ndxQuad[0] + pRoot[parentIndex].m_ndxQuad[3] ) / 2 );
  855. //
  856. // set vert indices
  857. //
  858. pRoot[index].m_ndxVert[0] = pRoot[parentIndex].m_ndxVert[0];
  859. pRoot[index].m_ndxVert[1] = AddPoint( m_pEdges[pRoot[parentIndex].m_ndxEdge[0]].m_NewEdgePoint,
  860. m_pEdges[pRoot[parentIndex].m_ndxEdge[0]].m_NewEdgeNormal );
  861. pRoot[index].m_ndxVert[2] = AddPoint( pRoot[parentIndex].m_Centroid, pRoot[parentIndex].m_Normal );
  862. pRoot[index].m_ndxVert[3] = AddPoint( m_pEdges[pRoot[parentIndex].m_ndxEdge[3]].m_NewEdgePoint,
  863. m_pEdges[pRoot[parentIndex].m_ndxEdge[3]].m_NewEdgeNormal );
  864. // set edge data
  865. SetEdgeData( pRoot, index, parentIndex, 0 );
  866. }
  867. //-----------------------------------------------------------------------------
  868. //-----------------------------------------------------------------------------
  869. void CSubdivMesh::CreateChildQuads( CSubdivQuad *pRoot, int quadIndex )
  870. {
  871. //
  872. // create children
  873. //
  874. CreateChildQuad1( pRoot, ( ( quadIndex << 2 ) + 1 ), quadIndex );
  875. CreateChildQuad2( pRoot, ( ( quadIndex << 2 ) + 2 ), quadIndex );
  876. CreateChildQuad3( pRoot, ( ( quadIndex << 2 ) + 3 ), quadIndex );
  877. CreateChildQuad4( pRoot, ( ( quadIndex << 2 ) + 4 ), quadIndex );
  878. for( int i = 0; i < 4; i++ )
  879. {
  880. m_pEdges[pRoot[quadIndex].m_ndxEdge[i]].m_Active = false;
  881. }
  882. }
  883. //-----------------------------------------------------------------------------
  884. //-----------------------------------------------------------------------------
  885. void CSubdivMesh::AddQuadToMesh( CSubdivQuad *pQuad )
  886. {
  887. return;
  888. }
  889. //-----------------------------------------------------------------------------
  890. //-----------------------------------------------------------------------------
  891. int CSubdivMesh::GetEndIndexFromLevel( int levelIndex )
  892. {
  893. switch( levelIndex )
  894. {
  895. case 0: { return 0; }
  896. case 1: { return 4; }
  897. case 2: { return 20; }
  898. case 3: { return 84; }
  899. default: { return 0; }
  900. }
  901. }
  902. //-----------------------------------------------------------------------------
  903. //-----------------------------------------------------------------------------
  904. int CSubdivMesh::GetStartIndexFromLevel( int levelIndex )
  905. {
  906. switch( levelIndex )
  907. {
  908. case 0: { return 0; }
  909. case 1: { return 1; }
  910. case 2: { return 5; }
  911. case 3: { return 21; }
  912. default: { return 0; }
  913. }
  914. }
  915. //-----------------------------------------------------------------------------
  916. //-----------------------------------------------------------------------------
  917. void CSubdivMesh::Subdivide( void )
  918. {
  919. //
  920. // subdivide to four levels always (what the trees hold)
  921. //
  922. for( int subdivLevel = 0; subdivLevel < 4; subdivLevel++ )
  923. {
  924. int startIndex = GetStartIndexFromLevel( subdivLevel );
  925. int endIndex = GetEndIndexFromLevel( subdivLevel );
  926. // subdivide
  927. CatmullClarkSubdivide();
  928. //
  929. // add subdivision data to subdivision tree
  930. //
  931. for( int treeIndex = 0; treeIndex < m_TreeCount; treeIndex++ )
  932. {
  933. //
  934. // get the current tree
  935. //
  936. CSubdivQuad *pTree = m_ppTrees[treeIndex];
  937. if( !pTree )
  938. continue;
  939. //
  940. // for each quad in the tree (at the given level)
  941. //
  942. for( int index = startIndex; index <= endIndex; index++ )
  943. {
  944. CreateChildQuads( pTree, index );
  945. }
  946. }
  947. }
  948. }
  949. //-----------------------------------------------------------------------------
  950. //-----------------------------------------------------------------------------
  951. void CSubdivMesh::PostSubdivide( void )
  952. {
  953. //
  954. // get the selection set
  955. //
  956. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  957. if( !pDoc )
  958. return;
  959. CDispManager *pDispManager = pDoc->GetDispManager();
  960. if( !pDispManager )
  961. return;
  962. //
  963. // add all surfaces to mesh to subdivide
  964. //
  965. int selectionCount = pDispManager->GetSelectionListCount();
  966. for( int i = 0; i < selectionCount; i++ )
  967. {
  968. // get the current displacement surface
  969. CMapDisp *pDisp = pDispManager->GetFromSelectionList( i );
  970. if( !pDisp )
  971. continue;
  972. // post subdivide
  973. pDisp->PostSubdivide( this );
  974. }
  975. // destroy cache!!!
  976. FreeCache();
  977. // set the cursor back to its previous state (before subdivision
  978. SetCursor( preSubdivCursor );
  979. }
  980. //-----------------------------------------------------------------------------
  981. //-----------------------------------------------------------------------------
  982. void CSubdivMesh::DoSubdivide( void )
  983. {
  984. PreSubdivide();
  985. Subdivide();
  986. PostSubdivide();
  987. }
  988. //-----------------------------------------------------------------------------
  989. //-----------------------------------------------------------------------------
  990. bool CSubdivMesh::AllocCache( int dispCount )
  991. {
  992. #define POINTS_PER_DISP 512
  993. #define EDGES_PER_DISP 1024
  994. m_MaxPointCount = POINTS_PER_DISP * dispCount;
  995. m_MaxEdgeCount = EDGES_PER_DISP * dispCount;
  996. m_MaxTreeCount = dispCount;
  997. m_pPoints = new CSubdivPoint[m_MaxPointCount];
  998. m_pEdges = new CSubdivEdge[m_MaxEdgeCount];
  999. m_ppTrees = new CSubdivQuad*[m_MaxTreeCount];
  1000. if( !m_pPoints || !m_pEdges || !m_ppTrees )
  1001. {
  1002. FreeCache();
  1003. return false;
  1004. }
  1005. //
  1006. // clear cache
  1007. //
  1008. for( int i = 0; i < m_MaxPointCount; i++ )
  1009. {
  1010. m_pPoints[i].Clear();
  1011. }
  1012. for( i = 0; i < m_MaxEdgeCount; i++ )
  1013. {
  1014. m_pEdges[i].Clear();
  1015. }
  1016. //
  1017. // tell size of cache
  1018. //
  1019. int size = m_MaxPointCount * sizeof( CSubdivPoint );
  1020. size += m_MaxEdgeCount * sizeof( CSubdivEdge );
  1021. size += m_MaxTreeCount * sizeof( CSubdivQuad );
  1022. TRACE1( "Subdiv Cache: %d\n", size );
  1023. return true;
  1024. #undef POINTS_PER_DISP
  1025. #undef EDGES_PER_DISP
  1026. }
  1027. //-----------------------------------------------------------------------------
  1028. //-----------------------------------------------------------------------------
  1029. void CSubdivMesh::FreeCache( void )
  1030. {
  1031. if( m_pPoints )
  1032. {
  1033. delete [] m_pPoints;
  1034. m_pPoints = NULL;
  1035. m_PointCount = 0;
  1036. }
  1037. if( m_pEdges )
  1038. {
  1039. delete [] m_pEdges;
  1040. m_pEdges = NULL;
  1041. m_EdgeCount = 0;
  1042. }
  1043. if( m_ppTrees )
  1044. {
  1045. delete [] m_ppTrees;
  1046. m_ppTrees = NULL;
  1047. m_TreeCount = 0;
  1048. }
  1049. // tell cache destroyed!!
  1050. TRACE0( "Subdiv Cache Destroyed!\n" );
  1051. }