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

2297 lines
62 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include <stdafx.h>
  9. #include <malloc.h>
  10. #include "FaceEditSheet.h"
  11. #include "MainFrm.h"
  12. #include "GlobalFunctions.h"
  13. #include "MapDisp.h"
  14. #include "MapFace.h"
  15. #include "utlvector.h"
  16. #include "disp_tesselate.h"
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include <tier0/memdbgon.h>
  19. //============================================================================
  20. //
  21. // e1
  22. // c1------c2
  23. // | |
  24. // e0 | | e2
  25. // | |
  26. // c0------c3
  27. // e3
  28. //
  29. // Note: edges refer to internal edge points only, corners "contain" all surfaces
  30. // touching the corner (surfaces that only touch the corner, as well as those
  31. // "edges" that end/begin at the corner(s))
  32. //
  33. #define DISPSEW_POINT_TOLERANCE 1.0f // one unit
  34. #define DISPSEW_NULL_INDEX -99999
  35. #define DISPSEW_EDGE_NORMAL 0
  36. #define DISPSEW_EDGE_TJSTART 1
  37. #define DISPSEW_EDGE_TJEND 2
  38. #define DISPSEW_EDGE_TJ 3
  39. #define DISPSEW_FACES_AT_EDGE 3
  40. #define DISPSEW_FACES_AT_CORNER 16
  41. #define DISPSEW_FACES_AT_TJUNC 8
  42. struct SewEdgeData_t
  43. {
  44. int faceCount; // number of faces contributing to the edge sew
  45. CMapFace *pFaces[DISPSEW_FACES_AT_EDGE]; // the faces contributing to the edge sew
  46. int ndxEdges[DISPSEW_FACES_AT_EDGE]; // the faces' edge indices contributing to the edge sew
  47. int type[DISPSEW_FACES_AT_EDGE]; // the type of edge t-junction, match t-junction start, etc....
  48. };
  49. struct SewCornerData_t
  50. {
  51. int faceCount; // number of faces contributing to the corner sew
  52. CMapFace *pFaces[DISPSEW_FACES_AT_CORNER]; // the faces contributing to the corner sew
  53. int ndxCorners[DISPSEW_FACES_AT_CORNER]; // the faces' corner indices contributing to the corner sew
  54. };
  55. struct SewTJuncData_t
  56. {
  57. int faceCount; // number of faces contributing to the t-junction sew
  58. CMapFace *pFaces[DISPSEW_FACES_AT_TJUNC]; // the faces contributing to the t-junction sew
  59. int ndxCorners[DISPSEW_FACES_AT_TJUNC]; // the faces' corner indices contributing to the t-junction sew
  60. int ndxEdges[DISPSEW_FACES_AT_TJUNC]; // the faces' edge (midpoint) indices contributing to the t-junction sew
  61. };
  62. static CUtlVector<SewEdgeData_t*> s_EdgeData;
  63. static CUtlVector<SewCornerData_t*> s_CornerData;
  64. static CUtlVector<SewTJuncData_t*> s_TJData;
  65. static CUtlVector<CCoreDispInfo*> m_aCoreDispInfos;
  66. // local functions
  67. void SewCorner_Build( void );
  68. void SewCorner_Resolve( void );
  69. void SewCorner_Destroy( SewCornerData_t *pCornerData );
  70. void SewTJunc_Build( void );
  71. void SewTJunc_Resolve( void );
  72. void SewTJunc_Destroy( SewTJuncData_t *pTJData );
  73. void SewEdge_Build( void );
  74. void SewEdge_Resolve( void );
  75. void SewEdge_Destroy( SewEdgeData_t *pEdgeData );
  76. void PlanarizeDependentVerts( void );
  77. //-----------------------------------------------------------------------------
  78. // Purpose: compare two point positions to see if they are equivolent given a
  79. // tolerance
  80. //-----------------------------------------------------------------------------
  81. bool PointCompareWithTolerance( Vector const& pt1, Vector const& pt2, float tolerance )
  82. {
  83. for( int i = 0 ; i < 3 ; i++ )
  84. {
  85. if( fabs( pt1[i] - pt2[i] ) > tolerance )
  86. return false;
  87. }
  88. return true;
  89. }
  90. //-----------------------------------------------------------------------------
  91. //-----------------------------------------------------------------------------
  92. bool EdgeCompare( Vector *pEdgePts1, Vector *pEdgePts2, int &edgeType1, int &edgeType2 )
  93. {
  94. Vector edge1[3];
  95. Vector edge2[3];
  96. //
  97. // create edges and midpoints
  98. //
  99. edge1[0] = pEdgePts1[0];
  100. edge1[1] = ( pEdgePts1[0] + pEdgePts1[1] ) * 0.5f;
  101. edge1[2] = pEdgePts1[1];
  102. edge2[0] = pEdgePts2[0];
  103. edge2[1] = ( pEdgePts2[0] + pEdgePts2[1] ) * 0.5f;
  104. edge2[2] = pEdgePts2[1];
  105. // assume edge type to be normal (will get overridden if otherwise)
  106. edgeType1 = DISPSEW_EDGE_NORMAL;
  107. edgeType2 = DISPSEW_EDGE_NORMAL;
  108. //
  109. // compare points and determine how many are shared between the two edges
  110. //
  111. int overlapCount = 0;
  112. int ndxEdge1[2];
  113. int ndxEdge2[2];
  114. for( int ndx1 = 0; ndx1 < 3; ndx1++ )
  115. {
  116. for( int ndx2 = 0; ndx2 < 3; ndx2++ )
  117. {
  118. if( PointCompareWithTolerance( edge1[ndx1], edge2[ndx2], DISPSEW_POINT_TOLERANCE ) )
  119. {
  120. // no midpoint to midpoint sharing allowed (midpoints are odd index values)
  121. if( ( ndx1%2 != 0 ) && ( ndx2%2 != 0 ) )
  122. continue;
  123. // sanity check
  124. assert( overlapCount >= 0 );
  125. assert( overlapCount < 2 );
  126. ndxEdge1[overlapCount] = ndx1;
  127. ndxEdge2[overlapCount] = ndx2;
  128. overlapCount++;
  129. break;
  130. }
  131. }
  132. }
  133. if( overlapCount != 2 )
  134. return false;
  135. // handle edge1 as t-junction edge
  136. if( ndxEdge1[0]%2 != 0 )
  137. {
  138. edgeType1 = DISPSEW_EDGE_TJ;
  139. if( ndxEdge1[1] == 0 )
  140. {
  141. edgeType2 = DISPSEW_EDGE_TJSTART;
  142. }
  143. else if( ndxEdge1[1] == 2 )
  144. {
  145. edgeType2 = DISPSEW_EDGE_TJEND;
  146. }
  147. }
  148. else if( ndxEdge1[1]%2 != 0 )
  149. {
  150. edgeType1 = DISPSEW_EDGE_TJ;
  151. if( ndxEdge1[0] == 0 )
  152. {
  153. edgeType2 = DISPSEW_EDGE_TJSTART;
  154. }
  155. else if( ndxEdge1[0] == 2 )
  156. {
  157. edgeType2 = DISPSEW_EDGE_TJEND;
  158. }
  159. }
  160. // handle edge2 as t-junction edge
  161. if( ndxEdge2[0]%2 != 0 )
  162. {
  163. edgeType2 = DISPSEW_EDGE_TJ;
  164. if( ndxEdge2[1] == 0 )
  165. {
  166. edgeType1 = DISPSEW_EDGE_TJSTART;
  167. }
  168. else if( ndxEdge2[1] == 2 )
  169. {
  170. edgeType1 = DISPSEW_EDGE_TJEND;
  171. }
  172. }
  173. else if( ndxEdge2[1]%2 != 0 )
  174. {
  175. edgeType2 = DISPSEW_EDGE_TJ;
  176. if( ndxEdge2[0] == 0 )
  177. {
  178. edgeType1 = DISPSEW_EDGE_TJSTART;
  179. }
  180. else if( ndxEdge2[0] == 2 )
  181. {
  182. edgeType1 = DISPSEW_EDGE_TJEND;
  183. }
  184. }
  185. return true;
  186. }
  187. //-----------------------------------------------------------------------------
  188. // Purpose: get a point from the surface at the given index, will get the point
  189. // from the displacement surface if it exists, it will get it from the
  190. // base face otherwise
  191. //-----------------------------------------------------------------------------
  192. inline void GetPointFromSurface( CMapFace *pFace, int ndxPt, Vector &pt )
  193. {
  194. EditDispHandle_t dispHandle = pFace->GetDisp();
  195. if( dispHandle != EDITDISPHANDLE_INVALID )
  196. {
  197. CMapDisp *pDisp = EditDispMgr()->GetDisp( dispHandle );
  198. pDisp->GetSurfPoint( ndxPt, pt );
  199. }
  200. else
  201. {
  202. pFace->GetPoint( pt, ndxPt );
  203. }
  204. }
  205. //-----------------------------------------------------------------------------
  206. //-----------------------------------------------------------------------------
  207. int GetEdgePointIndex( CMapDisp *pDisp, int edgeIndex, int edgePtIndex, bool bCCW )
  208. {
  209. int height = pDisp->GetHeight();
  210. int width = pDisp->GetWidth();
  211. if( bCCW )
  212. {
  213. switch( edgeIndex )
  214. {
  215. case 0: { return ( edgePtIndex * height ); }
  216. case 1: { return ( ( ( height - 1 ) * width ) + edgePtIndex ); }
  217. case 2: { return ( ( height * width - 1 ) - ( edgePtIndex * height ) ); }
  218. case 3: { return ( ( width - 1 ) - edgePtIndex ); }
  219. default: { return -1; }
  220. }
  221. }
  222. else
  223. {
  224. switch( edgeIndex )
  225. {
  226. case 0: { return ( ( ( height - 1 ) * width ) - ( edgePtIndex * height ) ); }
  227. case 1: { return ( ( height * width - 1 ) - edgePtIndex ); }
  228. case 2: { return ( ( width - 1 ) + ( edgePtIndex * height ) ); }
  229. case 3: { return ( edgePtIndex ); }
  230. default: { return -1; }
  231. }
  232. }
  233. }
  234. //-----------------------------------------------------------------------------
  235. //-----------------------------------------------------------------------------
  236. int GetCornerPointIndex( CMapDisp *pDisp, int cornerIndex )
  237. {
  238. int width = pDisp->GetWidth();
  239. int height = pDisp->GetHeight();
  240. switch( cornerIndex )
  241. {
  242. case 0: { return 0; }
  243. case 1: { return ( ( height - 1 ) * width ); }
  244. case 2: { return ( height * width - 1 ); }
  245. case 3: { return ( width - 1 ); }
  246. default: { return -1; }
  247. }
  248. }
  249. //-----------------------------------------------------------------------------
  250. //-----------------------------------------------------------------------------
  251. int GetTJuncIndex( CMapDisp *pDisp, int ndxEdge )
  252. {
  253. int width = pDisp->GetWidth();
  254. int height = pDisp->GetHeight();
  255. switch( ndxEdge )
  256. {
  257. case 0: { return( height * ( width / 2 ) ); }
  258. case 1: { return( ( ( height - 1 ) * width ) + ( width / 2 ) ); }
  259. case 2: { return( ( height * ( width / 2 ) ) + ( width - 1 ) ); }
  260. case 3: { return( width / 2 ); }
  261. default: { return -1; }
  262. }
  263. }
  264. //-----------------------------------------------------------------------------
  265. //-----------------------------------------------------------------------------
  266. void AverageVectorFieldData( CMapDisp *pDisp1, int ndx1, CMapDisp *pDisp2, int ndx2 )
  267. {
  268. //
  269. // average the positions at each index
  270. // position = dispVector * dispDist
  271. //
  272. float dist1 = pDisp1->GetFieldDistance( ndx1 );
  273. float dist2 = pDisp2->GetFieldDistance( ndx2 );
  274. Vector v1, v2;
  275. pDisp1->GetFieldVector( ndx1, v1 );
  276. pDisp2->GetFieldVector( ndx2, v2 );
  277. v1 *= dist1;
  278. v2 *= dist2;
  279. Vector vAvg;
  280. vAvg = ( v1 + v2 ) * 0.5f;
  281. float distAvg = VectorNormalize( vAvg );
  282. pDisp1->SetFieldDistance( ndx1, distAvg );
  283. pDisp2->SetFieldDistance( ndx2, distAvg );
  284. pDisp1->SetFieldVector( ndx1, vAvg );
  285. pDisp2->SetFieldVector( ndx2, vAvg );
  286. // Check to see if the materials match and blend alphas if they do.
  287. CMapFace *pFace1 = static_cast<CMapFace*>( pDisp1->GetParent() );
  288. CMapFace *pFace2 = static_cast<CMapFace*>( pDisp2->GetParent() );
  289. char szMatName1[128];
  290. char szMatName2[128];
  291. pFace1->GetTexture()->GetShortName( szMatName1 );
  292. pFace2->GetTexture()->GetShortName( szMatName2 );
  293. if ( !strcmpi( szMatName1, szMatName2 ) )
  294. {
  295. // Grab the alphas at the points and average them.
  296. float flAlpha1, flAlpha2;
  297. flAlpha1 = pDisp1->GetAlpha( ndx1 );
  298. flAlpha2 = pDisp2->GetAlpha( ndx2 );
  299. float flAlphaBlend = ( flAlpha1 + flAlpha1 ) * 0.5f;
  300. pDisp1->SetAlpha( ndx1, flAlphaBlend );
  301. pDisp2->SetAlpha( ndx2, flAlphaBlend );
  302. }
  303. //
  304. // average the subdivion positions and normals
  305. //
  306. pDisp1->GetSubdivPosition( ndx1, v1 );
  307. pDisp2->GetSubdivPosition( ndx2, v2 );
  308. vAvg = ( v1 + v2 ) * 0.5f;
  309. pDisp1->SetSubdivPosition( ndx1, vAvg );
  310. pDisp2->SetSubdivPosition( ndx2, vAvg );
  311. pDisp1->GetSubdivNormal( ndx1, v1 );
  312. pDisp2->GetSubdivNormal( ndx2, v2 );
  313. vAvg = v1 + v2;
  314. VectorNormalize( vAvg );
  315. pDisp1->SetSubdivNormal( ndx1, vAvg );
  316. pDisp2->SetSubdivNormal( ndx2, vAvg );
  317. }
  318. //-----------------------------------------------------------------------------
  319. //-----------------------------------------------------------------------------
  320. void BlendVectorFieldData( CMapDisp *pDisp1, int ndxSrc1, int ndxDst1,
  321. CMapDisp *pDisp2, int ndxSrc2, int ndxDst2,
  322. float blendFactor )
  323. {
  324. //
  325. // to blend positions -- calculate the positions at the end points
  326. // find the new point along the parameterized line and calculate the
  327. // new field vector direction and distance (position)
  328. //
  329. float dist1 = pDisp1->GetFieldDistance( ndxSrc1 );
  330. float dist2 = pDisp2->GetFieldDistance( ndxSrc2 );
  331. Vector v1, v2;
  332. pDisp1->GetFieldVector( ndxSrc1, v1 );
  333. pDisp2->GetFieldVector( ndxSrc2, v2 );
  334. v1 *= dist1;
  335. v2 *= dist2;
  336. Vector vBlend;
  337. vBlend = v1 + ( v2 - v1 ) * blendFactor;
  338. float distBlend = VectorNormalize( vBlend );
  339. pDisp1->SetFieldDistance( ndxDst1, distBlend );
  340. pDisp2->SetFieldDistance( ndxDst2, distBlend );
  341. pDisp1->SetFieldVector( ndxDst1, vBlend );
  342. pDisp2->SetFieldVector( ndxDst2, vBlend );
  343. // Check to see if the materials match and blend alphas if they do.
  344. CMapFace *pFace1 = static_cast<CMapFace*>( pDisp1->GetParent() );
  345. CMapFace *pFace2 = static_cast<CMapFace*>( pDisp2->GetParent() );
  346. char szMatName1[128];
  347. char szMatName2[128];
  348. pFace1->GetTexture()->GetShortName( szMatName1 );
  349. pFace2->GetTexture()->GetShortName( szMatName2 );
  350. if ( !strcmpi( szMatName1, szMatName2 ) )
  351. {
  352. float flAlpha1, flAlpha2;
  353. flAlpha1 = pDisp1->GetAlpha( ndxDst1 );
  354. flAlpha2 = pDisp2->GetAlpha( ndxDst2 );
  355. float flAlphaBlend = flAlpha1 + ( flAlpha2 - flAlpha1 ) * blendFactor;
  356. pDisp1->SetAlpha( ndxDst1, flAlphaBlend );
  357. pDisp2->SetAlpha( ndxDst2, flAlphaBlend );
  358. }
  359. //
  360. // blend subdivision positions and normals as before,
  361. // this isn't truly accurate, but I am not sure what these
  362. // values mean in the edge sewing case anyway???
  363. //
  364. pDisp1->GetSubdivPosition( ndxSrc1, v1 );
  365. pDisp2->GetSubdivPosition( ndxSrc2, v2 );
  366. vBlend = v1 + ( v2 - v1 ) * blendFactor;
  367. pDisp1->SetSubdivPosition( ndxDst1, vBlend );
  368. pDisp2->SetSubdivPosition( ndxDst2, vBlend );
  369. pDisp1->GetSubdivNormal( ndxSrc1, v1 );
  370. pDisp2->GetSubdivNormal( ndxSrc2, v2 );
  371. vBlend = v1 + ( v2 - v1 ) * blendFactor;
  372. pDisp1->SetSubdivNormal( ndxDst1, vBlend );
  373. pDisp2->SetSubdivNormal( ndxDst2, vBlend );
  374. }
  375. //-----------------------------------------------------------------------------
  376. //-----------------------------------------------------------------------------
  377. inline bool Face_IsSolid( CMapFace *pFace )
  378. {
  379. return ( pFace->GetDisp() == EDITDISPHANDLE_INVALID );
  380. }
  381. //-----------------------------------------------------------------------------
  382. //-----------------------------------------------------------------------------
  383. void Faces_Update( void )
  384. {
  385. //
  386. // get the "faces" selection list (contains displaced and non-displaced faces)
  387. //
  388. CFaceEditSheet *pSheet = GetMainWnd()->GetFaceEditSheet();
  389. if( !pSheet )
  390. return;
  391. //
  392. // for each face in list
  393. //
  394. int faceCount = pSheet->GetFaceListCount();
  395. for( int ndxFace = 0; ndxFace < faceCount; ndxFace++ )
  396. {
  397. // get the current face
  398. CMapFace *pFace = pSheet->GetFaceListDataFace( ndxFace );
  399. if( !pFace )
  400. continue;
  401. // only update displacement surfaces
  402. EditDispHandle_t dispHandle = pFace->GetDisp();
  403. if( dispHandle == EDITDISPHANDLE_INVALID )
  404. continue;
  405. CMapDisp *pDisp = EditDispMgr()->GetDisp( dispHandle );
  406. pDisp->UpdateData();
  407. }
  408. }
  409. //-----------------------------------------------------------------------------
  410. // Purpose: Build temporary edge/midpoint/corner info for sewing.
  411. //-----------------------------------------------------------------------------
  412. void PreFaceListSew( void )
  413. {
  414. // Build edge/midpoint/corner data.
  415. SewCorner_Build();
  416. SewTJunc_Build();
  417. SewEdge_Build();
  418. }
  419. //-----------------------------------------------------------------------------
  420. // Purpose: Destroy temporary edge/midpoint/corner info for sewing and
  421. // update the effected displacements.
  422. //-----------------------------------------------------------------------------
  423. void PostFaceListSew( void )
  424. {
  425. // Destroy all corners, midpoint, edges.
  426. int count = s_CornerData.Size();
  427. for( int i = 0; i < count; i++ )
  428. {
  429. SewCorner_Destroy( s_CornerData.Element( i ) );
  430. }
  431. count = s_TJData.Size();
  432. for( int i = 0; i < count; i++ )
  433. {
  434. SewTJunc_Destroy( s_TJData.Element( i ) );
  435. }
  436. count = s_EdgeData.Size();
  437. for( int i = 0; i < count; i++ )
  438. {
  439. SewEdge_Destroy( s_EdgeData.Element( i ) );
  440. }
  441. // Flush all of the sewing data buffers.
  442. s_CornerData.Purge();
  443. s_TJData.Purge();
  444. s_EdgeData.Purge();
  445. // Update the faces.
  446. Faces_Update();
  447. }
  448. //-----------------------------------------------------------------------------
  449. // Purpose: given a face with a displacement surface, "sew" all edges to all
  450. // neighboring displacement and non-displacement surfaces
  451. // found in the selection set
  452. //-----------------------------------------------------------------------------
  453. void FaceListSewEdges( void )
  454. {
  455. // Setup.
  456. PreFaceListSew();
  457. // Resolve/Planarize unusable verts.
  458. PlanarizeDependentVerts();
  459. // Resolve sewing.
  460. SewCorner_Resolve();
  461. SewTJunc_Resolve();
  462. SewEdge_Resolve();
  463. // Update and clean-up.
  464. PostFaceListSew();
  465. }
  466. //-----------------------------------------------------------------------------
  467. //-----------------------------------------------------------------------------
  468. SewCornerData_t *SewCorner_Create( void )
  469. {
  470. SewCornerData_t *pCornerData = new SewCornerData_t;
  471. if( pCornerData )
  472. {
  473. // initialize the data
  474. pCornerData->faceCount = 0;
  475. return pCornerData;
  476. }
  477. return NULL;
  478. }
  479. //-----------------------------------------------------------------------------
  480. //-----------------------------------------------------------------------------
  481. void SewCorner_Destroy( SewCornerData_t *pCornerData )
  482. {
  483. if( pCornerData )
  484. {
  485. delete pCornerData;
  486. pCornerData = NULL;
  487. }
  488. }
  489. //-----------------------------------------------------------------------------
  490. //-----------------------------------------------------------------------------
  491. bool SewCorner_IsSolid( SewCornerData_t *pCornerData )
  492. {
  493. for( int i = 0; i < pCornerData->faceCount; i++ )
  494. {
  495. if( Face_IsSolid( pCornerData->pFaces[i] ) )
  496. return true;
  497. }
  498. return false;
  499. }
  500. //-----------------------------------------------------------------------------
  501. //-----------------------------------------------------------------------------
  502. void SewCorner_Add( SewCornerData_t *pCornerData, CMapFace *pFace, int ndx )
  503. {
  504. if ( pCornerData->faceCount >= DISPSEW_FACES_AT_CORNER )
  505. {
  506. AfxMessageBox( "Warning: Too many displacement faces at corner!\n" );
  507. return;
  508. }
  509. pCornerData->pFaces[pCornerData->faceCount] = pFace;
  510. pCornerData->ndxCorners[pCornerData->faceCount] = ndx;
  511. pCornerData->faceCount++;
  512. }
  513. //-----------------------------------------------------------------------------
  514. //-----------------------------------------------------------------------------
  515. void SewCorner_AddToList( SewCornerData_t *pCornerData )
  516. {
  517. // get the current corner point
  518. Vector pt;
  519. GetPointFromSurface( pCornerData->pFaces[0], pCornerData->ndxCorners[0], pt );
  520. //
  521. // check to see if the corner point already exists in the corner data list
  522. //
  523. int cornerCount = s_CornerData.Size();
  524. for( int i = 0; i < cornerCount; i++ )
  525. {
  526. //
  527. // get the compare corner point
  528. //
  529. SewCornerData_t *pCmpData = s_CornerData.Element( i );
  530. if( !pCmpData )
  531. continue;
  532. Vector cmpPt;
  533. GetPointFromSurface( pCmpData->pFaces[0], pCmpData->ndxCorners[0], cmpPt );
  534. // compare the points - return if found
  535. if( PointCompareWithTolerance( pt, cmpPt, DISPSEW_POINT_TOLERANCE ) )
  536. {
  537. SewCorner_Destroy( pCornerData );
  538. return;
  539. }
  540. }
  541. // unique corner point -- add it to the list
  542. s_CornerData.AddToTail( pCornerData );
  543. }
  544. //-----------------------------------------------------------------------------
  545. //-----------------------------------------------------------------------------
  546. void SewCorner_Build( void )
  547. {
  548. //
  549. // get the "faces" selection list (contains displaced and non-displaced faces)
  550. //
  551. CFaceEditSheet *pSheet = GetMainWnd()->GetFaceEditSheet();
  552. if( !pSheet )
  553. return;
  554. //
  555. // for each face in list
  556. //
  557. int faceCount = pSheet->GetFaceListCount();
  558. for( int ndxFace = 0; ndxFace < faceCount; ndxFace++ )
  559. {
  560. // get the current face
  561. CMapFace *pFace = pSheet->GetFaceListDataFace( ndxFace );
  562. if( !pFace )
  563. continue;
  564. //
  565. // for each face point
  566. //
  567. int ptCount = pFace->GetPointCount();
  568. for( int ndxPt = 0; ndxPt < ptCount; ndxPt++ )
  569. {
  570. // get the current point
  571. Vector pt;
  572. GetPointFromSurface( pFace, ndxPt, pt );
  573. // allocate new corner point
  574. SewCornerData_t *pCornerData = SewCorner_Create();
  575. if( !pCornerData )
  576. return;
  577. //
  578. // compare this point to all of the other points on all the other faces in the list
  579. //
  580. for( int ndxFace2 = 0; ndxFace2 < faceCount; ndxFace2++ )
  581. {
  582. // don't compare to itself
  583. if( ndxFace == ndxFace2 )
  584. continue;
  585. // get the current compare face
  586. CMapFace *pFace2 = pSheet->GetFaceListDataFace( ndxFace2 );
  587. if( !pFace2 )
  588. continue;
  589. //
  590. // for each compare face point
  591. //
  592. int ptCount2 = pFace2->GetPointCount();
  593. for( int ndxPt2 = 0; ndxPt2 < ptCount2; ndxPt2++ )
  594. {
  595. // get the current compare point
  596. Vector pt2;
  597. GetPointFromSurface( pFace2, ndxPt2, pt2 );
  598. // compare pt1 and pt2
  599. if( PointCompareWithTolerance( pt, pt2, DISPSEW_POINT_TOLERANCE ) )
  600. {
  601. SewCorner_Add( pCornerData, pFace2, ndxPt2 );
  602. }
  603. }
  604. }
  605. // had neighbors -- add base point and add it to corner list
  606. if( pCornerData->faceCount > 0 )
  607. {
  608. SewCorner_Add( pCornerData, pFace, ndxPt );
  609. SewCorner_AddToList( pCornerData );
  610. }
  611. // no neighbors -- de-allocate
  612. else
  613. {
  614. SewCorner_Destroy( pCornerData );
  615. }
  616. }
  617. }
  618. }
  619. //-----------------------------------------------------------------------------
  620. //-----------------------------------------------------------------------------
  621. void SewCorner_ResolveDisp( SewCornerData_t *pCornerData )
  622. {
  623. // the field data accumulators
  624. float avgDist = 0.0f;
  625. Vector vAvgField( 0.0f, 0.0f, 0.0f );
  626. Vector vAvgSubdivPos( 0.0f, 0.0f, 0.0f );
  627. Vector vAvgSubdivNormal( 0.0f, 0.0f, 0.0f );
  628. float flAvgAlpha = 0.0f;
  629. // Blend the alpha?
  630. bool bBlendAlpha = true;
  631. char szMatName1[128];
  632. char szMatName2[128];
  633. bool bInitMat = false;
  634. for( int i = 0; i < pCornerData->faceCount; i++ )
  635. {
  636. // get the current corner face
  637. CMapFace *pFace = pCornerData->pFaces[i];
  638. if( !pFace )
  639. continue;
  640. // get the current displacement surface to reset, if solid = done!
  641. EditDispHandle_t dispHandle = pFace->GetDisp();
  642. if( dispHandle == EDITDISPHANDLE_INVALID )
  643. continue;
  644. if ( !bInitMat )
  645. {
  646. pFace->GetTexture()->GetShortName( szMatName1 );
  647. bInitMat = true;
  648. continue;
  649. }
  650. else
  651. {
  652. pFace->GetTexture()->GetShortName( szMatName2 );
  653. if ( strcmpi( szMatName1, szMatName2 ) )
  654. {
  655. bBlendAlpha = false;
  656. break;
  657. }
  658. }
  659. }
  660. // for all the faces at the corner
  661. for( int i = 0; i < pCornerData->faceCount; i++ )
  662. {
  663. // get the current corner face
  664. CMapFace *pFace = pCornerData->pFaces[i];
  665. if( !pFace )
  666. continue;
  667. // get the current displacement surface to reset, if solid = done!
  668. EditDispHandle_t dispHandle = pFace->GetDisp();
  669. if( dispHandle == EDITDISPHANDLE_INVALID )
  670. continue;
  671. CMapDisp *pDisp = EditDispMgr()->GetDisp( dispHandle );
  672. // get the corner index
  673. int ndxPt = GetCornerPointIndex( pDisp, pCornerData->ndxCorners[i] );
  674. if( ndxPt == -1 )
  675. continue;
  676. Vector vecPos;
  677. pDisp->GetVert( ndxPt, vecPos );
  678. float dist = pDisp->GetFieldDistance( ndxPt );
  679. avgDist += dist;
  680. Vector vTmp;
  681. pDisp->GetFieldVector( ndxPt, vTmp );
  682. vAvgField += vTmp;
  683. pDisp->GetSubdivPosition( ndxPt, vTmp );
  684. vAvgSubdivPos += vTmp;
  685. pDisp->GetSubdivNormal( ndxPt, vTmp );
  686. vAvgSubdivNormal += vTmp;
  687. if ( bBlendAlpha )
  688. {
  689. flAvgAlpha += pDisp->GetAlpha( ndxPt );
  690. }
  691. }
  692. // calculate the average
  693. avgDist /= pCornerData->faceCount;
  694. vAvgField /= pCornerData->faceCount;
  695. vAvgSubdivPos /= pCornerData->faceCount;
  696. vAvgSubdivNormal /= pCornerData->faceCount;
  697. if ( bBlendAlpha )
  698. {
  699. flAvgAlpha /= pCornerData->faceCount;
  700. }
  701. for( int i = 0; i < pCornerData->faceCount; i++ )
  702. {
  703. // get the current corner face
  704. CMapFace *pFace = pCornerData->pFaces[i];
  705. if( !pFace )
  706. continue;
  707. // get the current displacement surface to reset, if solid = done!
  708. EditDispHandle_t dispHandle = pFace->GetDisp();
  709. if( dispHandle == EDITDISPHANDLE_INVALID )
  710. continue;
  711. CMapDisp *pDisp = EditDispMgr()->GetDisp( dispHandle );
  712. // get the corner index
  713. int ndxPt = GetCornerPointIndex( pDisp, pCornerData->ndxCorners[i] );
  714. if( ndxPt == -1 )
  715. continue;
  716. // set the averaged values
  717. pDisp->SetFieldDistance( ndxPt, avgDist );
  718. pDisp->SetFieldVector( ndxPt, vAvgField );
  719. pDisp->SetSubdivPosition( ndxPt, vAvgSubdivPos );
  720. pDisp->SetSubdivNormal( ndxPt, vAvgSubdivNormal );
  721. if ( bBlendAlpha )
  722. {
  723. pDisp->SetAlpha( ndxPt, flAvgAlpha );
  724. }
  725. }
  726. }
  727. //-----------------------------------------------------------------------------
  728. //-----------------------------------------------------------------------------
  729. void SewCorner_ResolveSolid( SewCornerData_t *pCornerData )
  730. {
  731. // create a clear vector - to reset the offset vector
  732. Vector vClear( 0.0f, 0.0f, 0.0f );
  733. // for all the faces at the corner
  734. for( int i = 0; i < pCornerData->faceCount; i++ )
  735. {
  736. // get the current corner face
  737. CMapFace *pFace = pCornerData->pFaces[i];
  738. if( !pFace )
  739. continue;
  740. // get the current displacement surface to reset, if solid = done!
  741. EditDispHandle_t dispHandle = pFace->GetDisp();
  742. if( dispHandle == EDITDISPHANDLE_INVALID )
  743. continue;
  744. CMapDisp *pDisp = EditDispMgr()->GetDisp( dispHandle );
  745. // get the face normal -- to reset the field vector
  746. Vector vNormal;
  747. pDisp->GetSurfNormal( vNormal );
  748. // get the corner index
  749. int ndxPt = GetCornerPointIndex( pDisp, pCornerData->ndxCorners[i] );
  750. if( ndxPt == -1 )
  751. continue;
  752. //
  753. // reset all neighbor surface data - field vector, distance, and offset
  754. //
  755. pDisp->SetFieldDistance( ndxPt, 0.0f );
  756. pDisp->SetFieldVector( ndxPt, vNormal );
  757. pDisp->SetSubdivPosition( ndxPt, vClear );
  758. pDisp->SetSubdivNormal( ndxPt, vNormal );
  759. pDisp->SetAlpha( ndxPt, 0.0f );
  760. }
  761. }
  762. //-----------------------------------------------------------------------------
  763. //-----------------------------------------------------------------------------
  764. void SewCorner_Resolve( void )
  765. {
  766. // get the number of corners in the corner list
  767. int cornerCount = s_CornerData.Size();
  768. // resolve each corner
  769. for( int i = 0; i < cornerCount; i++ )
  770. {
  771. // get the current corner data struct
  772. SewCornerData_t *pCornerData = s_CornerData.Element( i );
  773. if( !pCornerData )
  774. continue;
  775. // determine if any of the faces is solid
  776. bool bSolid = SewCorner_IsSolid( pCornerData );
  777. // solid at corner -- reset corner data
  778. if( bSolid )
  779. {
  780. SewCorner_ResolveSolid( pCornerData );
  781. }
  782. // all disps at corner -- average
  783. else
  784. {
  785. SewCorner_ResolveDisp( pCornerData );
  786. }
  787. }
  788. }
  789. //-----------------------------------------------------------------------------
  790. //-----------------------------------------------------------------------------
  791. SewTJuncData_t *SewTJunc_Create( void )
  792. {
  793. SewTJuncData_t *pTJData = new SewTJuncData_t;
  794. if( pTJData )
  795. {
  796. // initialize the data
  797. pTJData->faceCount = 0;
  798. return pTJData;
  799. }
  800. return NULL;
  801. }
  802. //-----------------------------------------------------------------------------
  803. //-----------------------------------------------------------------------------
  804. void SewTJunc_Destroy( SewTJuncData_t *pTJData )
  805. {
  806. if( pTJData )
  807. {
  808. delete pTJData;
  809. pTJData = NULL;
  810. }
  811. }
  812. //-----------------------------------------------------------------------------
  813. //-----------------------------------------------------------------------------
  814. bool SewTJunc_IsSolid( SewTJuncData_t *pTJData )
  815. {
  816. for( int i = 0; i < pTJData->faceCount; i++ )
  817. {
  818. if( Face_IsSolid( pTJData->pFaces[i] ) )
  819. return true;
  820. }
  821. return false;
  822. }
  823. //-----------------------------------------------------------------------------
  824. //-----------------------------------------------------------------------------
  825. void SewTJunc_Add( SewTJuncData_t *pTJData, CMapFace *pFace, int ndxCorner, int ndxEdge )
  826. {
  827. if ( pTJData->faceCount >= DISPSEW_FACES_AT_TJUNC )
  828. {
  829. AfxMessageBox( "Warning: Too many displacement faces at t-junction!\n" );
  830. return;
  831. }
  832. pTJData->pFaces[pTJData->faceCount] = pFace;
  833. pTJData->ndxCorners[pTJData->faceCount] = ndxCorner;
  834. pTJData->ndxEdges[pTJData->faceCount] = ndxEdge;
  835. pTJData->faceCount++;
  836. }
  837. //-----------------------------------------------------------------------------
  838. //-----------------------------------------------------------------------------
  839. void SewTJunc_AddToList( SewTJuncData_t *pTJData )
  840. {
  841. // get the current t-junction point
  842. Vector pt;
  843. GetPointFromSurface( pTJData->pFaces[0], pTJData->ndxCorners[0], pt );
  844. //
  845. // check to see if the t-junction point already exists in the t-junction data list
  846. //
  847. int tjCount = s_TJData.Size();
  848. for( int i = 0; i < tjCount; i++ )
  849. {
  850. // get the compare t-junction point
  851. SewTJuncData_t *pCmpData = s_TJData.Element( i );
  852. if( !pCmpData )
  853. continue;
  854. Vector cmpPt;
  855. GetPointFromSurface( pCmpData->pFaces[0], pCmpData->ndxCorners[0], cmpPt );
  856. // compare the points - return if found
  857. if( PointCompareWithTolerance( pt, cmpPt, DISPSEW_POINT_TOLERANCE ) )
  858. {
  859. SewTJunc_Destroy( pTJData );
  860. return;
  861. }
  862. }
  863. // unique t-junction point -- add it to the list
  864. s_TJData.AddToTail( pTJData );
  865. }
  866. //-----------------------------------------------------------------------------
  867. //-----------------------------------------------------------------------------
  868. void SewTJunc_Build( void )
  869. {
  870. //
  871. // get the "faces" selection list (contains displaced and non-displaced faces)
  872. //
  873. CFaceEditSheet *pSheet = GetMainWnd()->GetFaceEditSheet();
  874. if( !pSheet )
  875. return;
  876. //
  877. // for each face in list
  878. //
  879. int faceCount = pSheet->GetFaceListCount();
  880. for( int ndxFace = 0; ndxFace < faceCount; ndxFace++ )
  881. {
  882. // get the current face
  883. CMapFace *pFace = pSheet->GetFaceListDataFace( ndxFace );
  884. if( !pFace )
  885. continue;
  886. //
  887. // for each face point
  888. //
  889. int ptCount = pFace->GetPointCount();
  890. for( int ndxPt = 0; ndxPt < ptCount; ndxPt++ )
  891. {
  892. // get the current t-junction point
  893. Vector pt, tmpPt1, tmpPt2;
  894. GetPointFromSurface( pFace, ndxPt, tmpPt1 );
  895. GetPointFromSurface( pFace, (ndxPt+1)%ptCount, tmpPt2 );
  896. pt = ( tmpPt1 + tmpPt2 ) * 0.5f;
  897. // allocate new corner point
  898. SewTJuncData_t *pTJData = SewTJunc_Create();
  899. if( !pTJData )
  900. return;
  901. //
  902. // compare this point to all of the other points on all the other faces in the list
  903. //
  904. for( int ndxFace2 = 0; ndxFace2 < faceCount; ndxFace2++ )
  905. {
  906. // don't compare to itself
  907. if( ndxFace == ndxFace2 )
  908. continue;
  909. // get the current compare face
  910. CMapFace *pFace2 = pSheet->GetFaceListDataFace( ndxFace2 );
  911. if( !pFace2 )
  912. continue;
  913. //
  914. // for each compare face point
  915. //
  916. int ptCount2 = pFace2->GetPointCount();
  917. for( int ndxPt2 = 0; ndxPt2 < ptCount2; ndxPt2++ )
  918. {
  919. // get the current compare point
  920. Vector pt2;
  921. GetPointFromSurface( pFace2, ndxPt2, pt2 );
  922. // compare pt1 and pt2
  923. if( PointCompareWithTolerance( pt, pt2, DISPSEW_POINT_TOLERANCE ) )
  924. {
  925. SewTJunc_Add( pTJData, pFace2, ndxPt2, -1 );
  926. }
  927. }
  928. }
  929. // had neighbors -- add base point and add it to corner list
  930. if( pTJData->faceCount > 0 )
  931. {
  932. SewTJunc_Add( pTJData, pFace, -1, ndxPt );
  933. SewTJunc_AddToList( pTJData );
  934. }
  935. // no neighbors -- de-allocate
  936. else
  937. {
  938. SewTJunc_Destroy( pTJData );
  939. }
  940. }
  941. }
  942. }
  943. //-----------------------------------------------------------------------------
  944. //-----------------------------------------------------------------------------
  945. void SewTJunc_ResolveDisp( SewTJuncData_t *pTJData )
  946. {
  947. // the field data accumulators
  948. float avgDist = 0.0f;
  949. Vector vAvgField( 0.0f, 0.0f, 0.0f );
  950. Vector vAvgSubdivPos( 0.0f, 0.0f, 0.0f );
  951. Vector vAvgSubdivNormal( 0.0f, 0.0f, 0.0f );
  952. float flAvgAlpha = 0.0f;
  953. // for all the faces at the t-junction
  954. for( int i = 0; i < pTJData->faceCount; i++ )
  955. {
  956. // get the current t-junction face
  957. CMapFace *pFace = pTJData->pFaces[i];
  958. if( !pFace )
  959. continue;
  960. // get the current displacement surface to reset, if solid = done!
  961. EditDispHandle_t dispHandle = pFace->GetDisp();
  962. if( dispHandle == EDITDISPHANDLE_INVALID )
  963. continue;
  964. CMapDisp *pDisp = EditDispMgr()->GetDisp( dispHandle );
  965. // get the t-junction index
  966. int ndxPt = -1;
  967. if( pTJData->ndxCorners[i] != -1 )
  968. {
  969. ndxPt = GetCornerPointIndex( pDisp, pTJData->ndxCorners[i] );
  970. }
  971. else if( pTJData->ndxEdges[i] != -1 )
  972. {
  973. int ndxEdgePt = pDisp->GetWidth() / 2;
  974. ndxPt = GetEdgePointIndex( pDisp, pTJData->ndxEdges[i], ndxEdgePt, true );
  975. }
  976. if( ndxPt == -1 )
  977. continue;
  978. float dist = pDisp->GetFieldDistance( ndxPt );
  979. avgDist += dist;
  980. Vector vTmp;
  981. pDisp->GetFieldVector( ndxPt, vTmp );
  982. vAvgField += vTmp;
  983. pDisp->GetSubdivPosition( ndxPt, vTmp );
  984. vAvgSubdivPos += vTmp;
  985. pDisp->GetSubdivNormal( ndxPt, vTmp );
  986. vAvgSubdivNormal += vTmp;
  987. flAvgAlpha += pDisp->GetAlpha( ndxPt );
  988. }
  989. // calculate the average
  990. avgDist /= pTJData->faceCount;
  991. vAvgField /= pTJData->faceCount;
  992. vAvgSubdivPos /= pTJData->faceCount;
  993. vAvgSubdivNormal /= pTJData->faceCount;
  994. flAvgAlpha /= pTJData->faceCount;
  995. for( int i = 0; i < pTJData->faceCount; i++ )
  996. {
  997. // get the current t-junction face
  998. CMapFace *pFace = pTJData->pFaces[i];
  999. if( !pFace )
  1000. continue;
  1001. // get the current displacement surface to reset, if solid = done!
  1002. EditDispHandle_t dispHandle = pFace->GetDisp();
  1003. if( dispHandle == EDITDISPHANDLE_INVALID )
  1004. continue;
  1005. CMapDisp *pDisp = EditDispMgr()->GetDisp( dispHandle );
  1006. // get the t-junction index
  1007. int ndxPt = -1;
  1008. if( pTJData->ndxCorners[i] != -1 )
  1009. {
  1010. ndxPt = GetCornerPointIndex( pDisp, pTJData->ndxCorners[i] );
  1011. }
  1012. else if( pTJData->ndxEdges[i] != -1 )
  1013. {
  1014. int ndxEdgePt = pDisp->GetWidth() / 2;
  1015. ndxPt = GetEdgePointIndex( pDisp, pTJData->ndxEdges[i], ndxEdgePt, true );
  1016. }
  1017. if( ndxPt == -1 )
  1018. continue;
  1019. // set the averaged values
  1020. pDisp->SetFieldDistance( ndxPt, avgDist );
  1021. pDisp->SetFieldVector( ndxPt, vAvgField );
  1022. pDisp->SetSubdivPosition( ndxPt, vAvgSubdivPos );
  1023. pDisp->SetSubdivNormal( ndxPt, vAvgSubdivNormal );
  1024. pDisp->SetAlpha( ndxPt, flAvgAlpha );
  1025. }
  1026. }
  1027. //-----------------------------------------------------------------------------
  1028. //-----------------------------------------------------------------------------
  1029. void SewTJunc_ResolveSolid( SewTJuncData_t *pTJData )
  1030. {
  1031. // create a clear vector - to reset the offset vector
  1032. Vector vClear( 0.0f, 0.0f, 0.0f );
  1033. // for all the faces at the t-junction
  1034. for( int i = 0; i < pTJData->faceCount; i++ )
  1035. {
  1036. // get the current t-junction face
  1037. CMapFace *pFace = pTJData->pFaces[i];
  1038. if( !pFace )
  1039. continue;
  1040. // get the current displacement surface to reset, if solid = done!
  1041. EditDispHandle_t dispHandle = pFace->GetDisp();
  1042. if( dispHandle == EDITDISPHANDLE_INVALID )
  1043. continue;
  1044. CMapDisp *pDisp = EditDispMgr()->GetDisp( dispHandle );
  1045. // get the face normal -- to reset the field vector
  1046. Vector vNormal;
  1047. pDisp->GetSurfNormal( vNormal );
  1048. // get the t-junction index
  1049. int ndxPt = -1;
  1050. if( pTJData->ndxCorners[i] != -1 )
  1051. {
  1052. ndxPt = GetCornerPointIndex( pDisp, pTJData->ndxCorners[i] );
  1053. }
  1054. else if( pTJData->ndxEdges[i] != -1 )
  1055. {
  1056. int ndxEdgePt = pDisp->GetWidth() / 2;
  1057. ndxPt = GetEdgePointIndex( pDisp, pTJData->ndxEdges[i], ndxEdgePt, true );
  1058. }
  1059. if( ndxPt == -1 )
  1060. continue;
  1061. //
  1062. // reset all neighbor surface data - field vector, distance, and offset
  1063. //
  1064. pDisp->SetFieldDistance( ndxPt, 0.0f );
  1065. pDisp->SetFieldVector( ndxPt, vNormal );
  1066. pDisp->SetSubdivPosition( ndxPt, vClear );
  1067. pDisp->SetSubdivNormal( ndxPt, vNormal );
  1068. pDisp->SetAlpha( ndxPt, 0.0f );
  1069. }
  1070. }
  1071. //-----------------------------------------------------------------------------
  1072. //-----------------------------------------------------------------------------
  1073. void SewTJunc_Resolve( void )
  1074. {
  1075. // get the number of t-junctions in the t-junction list
  1076. int tjCount = s_TJData.Size();
  1077. // resolve each t-junction
  1078. for( int i = 0; i < tjCount; i++ )
  1079. {
  1080. // get the current t-junction data struct
  1081. SewTJuncData_t *pTJData = s_TJData.Element( i );
  1082. if( !pTJData )
  1083. continue;
  1084. // determine if any of the faces is solid
  1085. bool bSolid = SewTJunc_IsSolid( pTJData );
  1086. // solid at t-junction -- reset t-junction data
  1087. if( bSolid )
  1088. {
  1089. SewTJunc_ResolveSolid( pTJData );
  1090. }
  1091. // all disps at t-junction -- average
  1092. else
  1093. {
  1094. SewTJunc_ResolveDisp( pTJData );
  1095. }
  1096. }
  1097. }
  1098. //-----------------------------------------------------------------------------
  1099. //-----------------------------------------------------------------------------
  1100. SewEdgeData_t *SewEdge_Create( void )
  1101. {
  1102. SewEdgeData_t *pEdgeData = new SewEdgeData_t;
  1103. if( pEdgeData )
  1104. {
  1105. // initialize the data
  1106. pEdgeData->faceCount = 0;
  1107. return pEdgeData;
  1108. }
  1109. return NULL;
  1110. }
  1111. //-----------------------------------------------------------------------------
  1112. //-----------------------------------------------------------------------------
  1113. void SewEdge_Destroy( SewEdgeData_t *pEdgeData )
  1114. {
  1115. if( pEdgeData )
  1116. {
  1117. delete pEdgeData;
  1118. pEdgeData = NULL;
  1119. }
  1120. }
  1121. //-----------------------------------------------------------------------------
  1122. //-----------------------------------------------------------------------------
  1123. inline bool SewEdge_IsSolidNormal( SewEdgeData_t *pEdgeData )
  1124. {
  1125. for( int i = 0; i < pEdgeData->faceCount; i++ )
  1126. {
  1127. if( Face_IsSolid( pEdgeData->pFaces[i] ) )
  1128. return true;
  1129. }
  1130. return false;
  1131. }
  1132. //-----------------------------------------------------------------------------
  1133. //-----------------------------------------------------------------------------
  1134. inline int SewEdge_TJIndex( SewEdgeData_t *pEdgeData, int type )
  1135. {
  1136. for( int i = 0; i < pEdgeData->faceCount; i++ )
  1137. {
  1138. if( pEdgeData->type[i] == type )
  1139. return i;
  1140. }
  1141. return -1;
  1142. }
  1143. //-----------------------------------------------------------------------------
  1144. //-----------------------------------------------------------------------------
  1145. inline bool SewEdge_IsSolidTJunc( SewEdgeData_t *pEdgeData, int type )
  1146. {
  1147. for( int i = 0; i < pEdgeData->faceCount; i++ )
  1148. {
  1149. if( pEdgeData->type[i] != type )
  1150. continue;
  1151. if( Face_IsSolid( pEdgeData->pFaces[i] ) )
  1152. return true;
  1153. }
  1154. return false;
  1155. }
  1156. //-----------------------------------------------------------------------------
  1157. //-----------------------------------------------------------------------------
  1158. bool SewEdge_Add( SewEdgeData_t *pEdgeData, CMapFace *pFace, int ndxEdge, int type )
  1159. {
  1160. if ( pEdgeData->faceCount >= DISPSEW_FACES_AT_EDGE )
  1161. {
  1162. return false;
  1163. }
  1164. // Add face to edge.
  1165. pEdgeData->pFaces[pEdgeData->faceCount] = pFace;
  1166. pEdgeData->ndxEdges[pEdgeData->faceCount] = ndxEdge;
  1167. pEdgeData->type[pEdgeData->faceCount] = type;
  1168. pEdgeData->faceCount++;
  1169. return true;
  1170. }
  1171. //-----------------------------------------------------------------------------
  1172. //-----------------------------------------------------------------------------
  1173. bool SewEdge_AddToListMerge( SewEdgeData_t *pEdgeData, SewEdgeData_t *pCmpData )
  1174. {
  1175. bool bReturn = true;
  1176. for( int i = 0; i < pEdgeData->faceCount; i++ )
  1177. {
  1178. // t-junction edges already exist in both (skip it!)
  1179. if( pEdgeData->type[i] == DISPSEW_EDGE_TJ )
  1180. continue;
  1181. int j;
  1182. for( j = 0; j < pCmpData->faceCount; j++ )
  1183. {
  1184. // t-junction edges already exist in both (skip it!)
  1185. if( pCmpData->type[j] == DISPSEW_EDGE_TJ )
  1186. continue;
  1187. if( pEdgeData->type[i] == pCmpData->type[j] )
  1188. break;
  1189. }
  1190. // no match found -- add it
  1191. if( j == pCmpData->faceCount )
  1192. {
  1193. if (!SewEdge_Add( pCmpData, pEdgeData->pFaces[i], pEdgeData->ndxEdges[i], pEdgeData->type[i] ))
  1194. {
  1195. bReturn = false;
  1196. }
  1197. }
  1198. }
  1199. return bReturn;
  1200. }
  1201. //-----------------------------------------------------------------------------
  1202. //-----------------------------------------------------------------------------
  1203. bool SewEdge_AddToListTJunc( SewEdgeData_t *pEdgeData )
  1204. {
  1205. // find the t-junction edge
  1206. int ndxTJ = SewEdge_TJIndex( pEdgeData, DISPSEW_EDGE_TJ );
  1207. if( ndxTJ == -1 )
  1208. return true;
  1209. // get the t-junction edge point count
  1210. int ptCount = pEdgeData->pFaces[ndxTJ]->GetPointCount();
  1211. // get the current t-junction edge (edge points)
  1212. Vector edgePts[2];
  1213. GetPointFromSurface( pEdgeData->pFaces[ndxTJ], pEdgeData->ndxEdges[ndxTJ], edgePts[0] );
  1214. GetPointFromSurface( pEdgeData->pFaces[ndxTJ], (pEdgeData->ndxEdges[ndxTJ]+1)%ptCount, edgePts[1] );
  1215. //
  1216. // check to see if the edge already exists in the edge data list
  1217. //
  1218. int edgeCount = s_EdgeData.Size();
  1219. for( int i = 0; i < edgeCount; i++ )
  1220. {
  1221. // get the edge points to compare against
  1222. SewEdgeData_t *pCmpData = s_EdgeData.Element( i );
  1223. if( !pCmpData )
  1224. continue;
  1225. // get the compare t-junction edge
  1226. int ndxCmp = SewEdge_TJIndex( pCmpData, DISPSEW_EDGE_TJ );
  1227. if( ndxCmp == -1 )
  1228. continue;
  1229. // get the compare face point count
  1230. int ptCount2 = pCmpData->pFaces[ndxCmp]->GetPointCount();
  1231. Vector edgePts2[2];
  1232. GetPointFromSurface( pCmpData->pFaces[ndxCmp], pCmpData->ndxEdges[ndxCmp], edgePts2[0] );
  1233. GetPointFromSurface( pCmpData->pFaces[ndxCmp], (pCmpData->ndxEdges[ndxCmp]+1)%ptCount2, edgePts2[1] );
  1234. // compare the edges -- return if found
  1235. int edgeType1, edgeType2;
  1236. if( EdgeCompare( edgePts, edgePts2, edgeType1, edgeType2 ) )
  1237. {
  1238. bool bReturn = SewEdge_AddToListMerge( pEdgeData, pCmpData );
  1239. SewEdge_Destroy( pEdgeData );
  1240. return bReturn;
  1241. }
  1242. }
  1243. // unique edge -- add it to the list
  1244. s_EdgeData.AddToTail( pEdgeData );
  1245. return true;
  1246. }
  1247. //-----------------------------------------------------------------------------
  1248. //-----------------------------------------------------------------------------
  1249. void SewEdge_AddToListNormal( SewEdgeData_t *pEdgeData )
  1250. {
  1251. // get the face point count
  1252. int ptCount = pEdgeData->pFaces[0]->GetPointCount();
  1253. // get the current edge (edge points)
  1254. Vector edgePts[2];
  1255. GetPointFromSurface( pEdgeData->pFaces[0], pEdgeData->ndxEdges[0], edgePts[0] );
  1256. GetPointFromSurface( pEdgeData->pFaces[0], (pEdgeData->ndxEdges[0]+1)%ptCount, edgePts[1] );
  1257. //
  1258. // check to see if the edge already exists in the edge data list
  1259. //
  1260. int edgeCount = s_EdgeData.Size();
  1261. for( int i = 0; i < edgeCount; i++ )
  1262. {
  1263. // get the edge points to compare against
  1264. SewEdgeData_t *pCmpData = s_EdgeData.Element( i );
  1265. if( !pCmpData )
  1266. continue;
  1267. // compare against each edge (all colinear) in struct
  1268. for( int j = 0; j < pCmpData->faceCount; j++ )
  1269. {
  1270. // get the compare face point count
  1271. int ptCount2 = pCmpData->pFaces[j]->GetPointCount();
  1272. Vector edgePts2[2];
  1273. GetPointFromSurface( pCmpData->pFaces[j], pCmpData->ndxEdges[j], edgePts2[0] );
  1274. GetPointFromSurface( pCmpData->pFaces[j], (pCmpData->ndxEdges[j]+1)%ptCount2, edgePts2[1] );
  1275. // compare the edges -- return if found
  1276. int edgeType1, edgeType2;
  1277. if( EdgeCompare( edgePts, edgePts2, edgeType1, edgeType2 ) )
  1278. {
  1279. SewEdge_Destroy( pEdgeData );
  1280. return;
  1281. }
  1282. }
  1283. }
  1284. // unique edge -- add it to the list
  1285. s_EdgeData.AddToTail( pEdgeData );
  1286. }
  1287. //-----------------------------------------------------------------------------
  1288. //-----------------------------------------------------------------------------
  1289. bool SewEdge_AddToList( SewEdgeData_t *pEdgeData )
  1290. {
  1291. // if this is a "normal" edge - handle it
  1292. if( pEdgeData->type[0] == DISPSEW_EDGE_NORMAL )
  1293. {
  1294. SewEdge_AddToListNormal( pEdgeData );
  1295. return true;
  1296. }
  1297. // this is a "t-junction" edge - handle it
  1298. return SewEdge_AddToListTJunc( pEdgeData );
  1299. }
  1300. //-----------------------------------------------------------------------------
  1301. //-----------------------------------------------------------------------------
  1302. void SewEdge_Build( void )
  1303. {
  1304. //
  1305. // get the "faces" selection list (contains displaced and non-displaced faces)
  1306. //
  1307. CFaceEditSheet *pSheet = GetMainWnd()->GetFaceEditSheet();
  1308. if( !pSheet )
  1309. return;
  1310. bool bError = false;
  1311. //
  1312. // for each face in list
  1313. //
  1314. int faceCount = pSheet->GetFaceListCount();
  1315. for( int ndxFace = 0; ndxFace < faceCount; ndxFace++ )
  1316. {
  1317. // get the current face
  1318. CMapFace *pFace = pSheet->GetFaceListDataFace( ndxFace );
  1319. if( !pFace )
  1320. continue;
  1321. //
  1322. // for each face edge
  1323. //
  1324. int ptCount = pFace->GetPointCount();
  1325. for( int ndxPt = 0; ndxPt < ptCount; ndxPt++ )
  1326. {
  1327. // get the current edge points
  1328. int type1_keep = 0;
  1329. Vector edgePts[2];
  1330. GetPointFromSurface( pFace, ndxPt, edgePts[0] );
  1331. GetPointFromSurface( pFace, (ndxPt+1)%ptCount, edgePts[1] );
  1332. // allocate new edge
  1333. SewEdgeData_t *pEdgeData = SewEdge_Create();
  1334. if( !pEdgeData )
  1335. return;
  1336. //
  1337. // compare this edge to all of the other edges on all the other faces in the list
  1338. //
  1339. for( int ndxFace2 = 0; ndxFace2 < faceCount; ndxFace2++ )
  1340. {
  1341. // don't compare to itself
  1342. if( ndxFace == ndxFace2 )
  1343. continue;
  1344. // get the current compare face
  1345. CMapFace *pFace2 = pSheet->GetFaceListDataFace( ndxFace2 );
  1346. if( !pFace2 )
  1347. continue;
  1348. //
  1349. // for each compare face edge
  1350. //
  1351. int ptCount2 = pFace2->GetPointCount();
  1352. for( int ndxPt2 = 0; ndxPt2 < ptCount2; ndxPt2++ )
  1353. {
  1354. // get the current compare edge point
  1355. Vector edgePts2[2];
  1356. GetPointFromSurface( pFace2, ndxPt2, edgePts2[0] );
  1357. GetPointFromSurface( pFace2, (ndxPt2+1)%ptCount2, edgePts2[1] );
  1358. // compare pt1 and pt2
  1359. int type1, type2;
  1360. if( EdgeCompare( edgePts, edgePts2, type1, type2 ) )
  1361. {
  1362. if (!SewEdge_Add( pEdgeData, pFace2, ndxPt2, type2 ))
  1363. {
  1364. bError = true;
  1365. }
  1366. type1_keep = type1;
  1367. }
  1368. }
  1369. }
  1370. // had neighbors -- add base point and add it to corner list
  1371. if( pEdgeData->faceCount > 0 )
  1372. {
  1373. if (!SewEdge_Add( pEdgeData, pFace, ndxPt, type1_keep ))
  1374. {
  1375. bError = true;
  1376. }
  1377. if (!SewEdge_AddToList( pEdgeData ))
  1378. {
  1379. bError = true;
  1380. }
  1381. }
  1382. // no neighbors -- de-allocate
  1383. else
  1384. {
  1385. SewEdge_Destroy( pEdgeData );
  1386. }
  1387. }
  1388. }
  1389. if (bError)
  1390. {
  1391. AfxMessageBox("Not all selected faces could be sewn because too many selected faces share a single edge.\n\nLook for places where 3 or more selected faces (displacement or non-displacement) all share an edge.");
  1392. }
  1393. }
  1394. //-----------------------------------------------------------------------------
  1395. //-----------------------------------------------------------------------------
  1396. void SewEdge_ResolveDispTJunc( SewEdgeData_t *pEdgeData, int ndxTJ, int ndxTJNeighbor, bool bStart )
  1397. {
  1398. //
  1399. // handle displacement sewing to displacement t-junction edge
  1400. //
  1401. EditDispHandle_t tjEdgeHandle = pEdgeData->pFaces[ndxTJ]->GetDisp();
  1402. EditDispHandle_t edgeHandle = pEdgeData->pFaces[ndxTJNeighbor]->GetDisp();
  1403. if( ( tjEdgeHandle == EDITDISPHANDLE_INVALID ) || ( edgeHandle == EDITDISPHANDLE_INVALID ) )
  1404. return;
  1405. CMapDisp *pTJEdgeDisp = EditDispMgr()->GetDisp( tjEdgeHandle );
  1406. CMapDisp *pEdgeDisp = EditDispMgr()->GetDisp( edgeHandle );
  1407. //
  1408. // get the t-junction edge interval (or half of it)
  1409. //
  1410. int tjWidth = pTJEdgeDisp->GetWidth();
  1411. int tjInterval = pTJEdgeDisp->GetWidth() / 2;
  1412. //
  1413. // get edge interval
  1414. //
  1415. int edgeWidth = pEdgeDisp->GetWidth();
  1416. int edgeInterval = pEdgeDisp->GetWidth();
  1417. int ratio = ( edgeInterval - 1 ) / tjInterval;
  1418. bool bFlip = ( ratio < 1 );
  1419. if( bFlip )
  1420. {
  1421. ratio = tjInterval / ( edgeInterval - 1 );
  1422. }
  1423. //
  1424. // average the "like" points
  1425. //
  1426. if( bStart )
  1427. {
  1428. if( bFlip )
  1429. {
  1430. for( int i = 1, j = ratio; i < edgeInterval; i++, j += ratio )
  1431. {
  1432. int ndxTJPt, ndxEdgePt;
  1433. ndxTJPt = GetEdgePointIndex( pTJEdgeDisp, pEdgeData->ndxEdges[ndxTJ], j, true );
  1434. ndxEdgePt = GetEdgePointIndex( pEdgeDisp, pEdgeData->ndxEdges[ndxTJNeighbor], i, false );
  1435. // average
  1436. AverageVectorFieldData( pEdgeDisp, ndxEdgePt, pTJEdgeDisp, ndxTJPt );
  1437. }
  1438. }
  1439. else
  1440. {
  1441. for( int i = 1, j = ratio; i < tjInterval; i++, j += ratio )
  1442. {
  1443. int ndxTJPt, ndxEdgePt;
  1444. ndxTJPt = GetEdgePointIndex( pTJEdgeDisp, pEdgeData->ndxEdges[ndxTJ], i, true );
  1445. ndxEdgePt = GetEdgePointIndex( pEdgeDisp, pEdgeData->ndxEdges[ndxTJNeighbor], j, false );
  1446. // average
  1447. AverageVectorFieldData( pEdgeDisp, ndxEdgePt, pTJEdgeDisp, ndxTJPt );
  1448. }
  1449. }
  1450. }
  1451. else
  1452. {
  1453. if( bFlip )
  1454. {
  1455. for( int i = 1, j = ratio; i < edgeWidth; i++, j += ratio )
  1456. {
  1457. int ndxTJPt, ndxEdgePt;
  1458. ndxTJPt = GetEdgePointIndex( pTJEdgeDisp, pEdgeData->ndxEdges[ndxTJ], j, false );
  1459. ndxEdgePt = GetEdgePointIndex( pEdgeDisp, pEdgeData->ndxEdges[ndxTJNeighbor], i, true );
  1460. // average
  1461. AverageVectorFieldData( pEdgeDisp, ndxEdgePt, pTJEdgeDisp, ndxTJPt );
  1462. }
  1463. }
  1464. else
  1465. {
  1466. for( int i = ( tjInterval + 1 ), j = ratio; i < ( tjWidth - 1 ); i++, j += ratio )
  1467. {
  1468. int ndxTJPt, ndxEdgePt;
  1469. ndxTJPt = GetEdgePointIndex( pTJEdgeDisp, pEdgeData->ndxEdges[ndxTJ], i, true );
  1470. ndxEdgePt = GetEdgePointIndex( pEdgeDisp, pEdgeData->ndxEdges[ndxTJNeighbor], j, false );
  1471. // average
  1472. AverageVectorFieldData( pEdgeDisp, ndxEdgePt, pTJEdgeDisp, ndxTJPt );
  1473. }
  1474. }
  1475. }
  1476. //
  1477. // linearly interpolate the "unlike" points
  1478. //
  1479. float blendRatio = 1.0f / ratio;
  1480. if( bFlip )
  1481. {
  1482. for( int i = 0; i < ( tjWidth - ratio ); i += ratio )
  1483. {
  1484. int ndxStart = i;
  1485. int ndxEnd = ( i + ratio );
  1486. int ndxStartPt = GetEdgePointIndex( pTJEdgeDisp, pEdgeData->ndxEdges[ndxTJ], ndxStart, true );
  1487. int ndxEndPt = GetEdgePointIndex( pTJEdgeDisp, pEdgeData->ndxEdges[ndxTJ], ndxEnd, true );
  1488. for( int j = ( ndxStart + 1 ); j < ndxEnd; j++ )
  1489. {
  1490. float blend = blendRatio * ( j - ndxStart );
  1491. int ndxDst = GetEdgePointIndex( pTJEdgeDisp, pEdgeData->ndxEdges[ndxTJ], j, true );
  1492. BlendVectorFieldData( pTJEdgeDisp, ndxStartPt, ndxDst, pTJEdgeDisp, ndxEndPt, ndxDst, blend );
  1493. }
  1494. }
  1495. }
  1496. else
  1497. {
  1498. for( int i = 0; i < ( edgeWidth - ratio ); i += ratio )
  1499. {
  1500. int ndxStart = i;
  1501. int ndxEnd = ( i + ratio );
  1502. int ndxStartPt = GetEdgePointIndex( pEdgeDisp, pEdgeData->ndxEdges[ndxTJNeighbor], ndxStart, true );
  1503. int ndxEndPt = GetEdgePointIndex( pEdgeDisp, pEdgeData->ndxEdges[ndxTJNeighbor], ndxEnd, true );
  1504. for( int j = ( ndxStart + 1 ); j < ndxEnd; j++ )
  1505. {
  1506. float blend = blendRatio * ( j - ndxStart );
  1507. int ndxDst = GetEdgePointIndex( pEdgeDisp, pEdgeData->ndxEdges[ndxTJNeighbor], j, true );
  1508. BlendVectorFieldData( pEdgeDisp, ndxStartPt, ndxDst, pEdgeDisp, ndxEndPt, ndxDst, blend );
  1509. }
  1510. }
  1511. }
  1512. }
  1513. //-----------------------------------------------------------------------------
  1514. //-----------------------------------------------------------------------------
  1515. void SewEdge_ResolveSolidTJunc( SewEdgeData_t *pEdgeData, int type, bool bStart )
  1516. {
  1517. // create an empty vector to reset the offset with
  1518. Vector vClear( 0.0f, 0.0f, 0.0f );
  1519. for( int i = 0; i < pEdgeData->faceCount; i++ )
  1520. {
  1521. if( pEdgeData->type[i] != type )
  1522. continue;
  1523. // get the displacement surface associated with the face
  1524. EditDispHandle_t dispHandle = pEdgeData->pFaces[i]->GetDisp();
  1525. if( dispHandle == EDITDISPHANDLE_INVALID )
  1526. continue;
  1527. CMapDisp *pDisp = EditDispMgr()->GetDisp( dispHandle );
  1528. // get surface normal, to reset vector field to base state
  1529. Vector vNormal;
  1530. pDisp->GetSurfNormal( vNormal );
  1531. // reset tjstart and tjend
  1532. if( type != DISPSEW_EDGE_TJ )
  1533. {
  1534. //
  1535. // for all points along the edge -- reset
  1536. //
  1537. int width = pDisp->GetWidth();
  1538. for( int j = 1; j < ( width - 1 ); j++ )
  1539. {
  1540. // get the edge point index
  1541. int ndxPt = GetEdgePointIndex( pDisp, pEdgeData->ndxEdges[i], j, true );
  1542. if( ndxPt == -1 )
  1543. continue;
  1544. //
  1545. // reset displacement data (dist, field vector, and offset vector)
  1546. //
  1547. pDisp->SetFieldDistance( ndxPt, 0.0f );
  1548. pDisp->SetFieldVector( ndxPt, vNormal );
  1549. pDisp->SetSubdivPosition( ndxPt, vClear );
  1550. pDisp->SetSubdivNormal( ndxPt, vNormal );
  1551. pDisp->SetAlpha( ndxPt, 0.0f );
  1552. }
  1553. }
  1554. // reset tj (upper and lower)
  1555. else
  1556. {
  1557. //
  1558. // for all points along the edge -- reset
  1559. //
  1560. int width = pDisp->GetWidth();
  1561. int widthDiv2 = width / 2;
  1562. if( bStart )
  1563. {
  1564. for( int j = 1; j < widthDiv2; j++ )
  1565. {
  1566. // get the edge point index
  1567. int ndxPt = GetEdgePointIndex( pDisp, pEdgeData->ndxEdges[i], j, true );
  1568. if( ndxPt == -1 )
  1569. continue;
  1570. //
  1571. // reset displacement data (dist, field vector, and offset vector)
  1572. //
  1573. pDisp->SetFieldDistance( ndxPt, 0.0f );
  1574. pDisp->SetFieldVector( ndxPt, vNormal );
  1575. pDisp->SetSubdivPosition( ndxPt, vClear );
  1576. pDisp->SetSubdivNormal( ndxPt, vNormal );
  1577. pDisp->SetAlpha( ndxPt, 0.0f );
  1578. }
  1579. }
  1580. else
  1581. {
  1582. for( int j = ( widthDiv2 + 1 ); j < ( width - 1 ); j++ )
  1583. {
  1584. // get the edge point index
  1585. int ndxPt = GetEdgePointIndex( pDisp, pEdgeData->ndxEdges[i], j, true );
  1586. if( ndxPt == -1 )
  1587. continue;
  1588. //
  1589. // reset displacement data (dist, field vector, and offset vector)
  1590. //
  1591. pDisp->SetFieldDistance( ndxPt, 0.0f );
  1592. pDisp->SetFieldVector( ndxPt, vNormal );
  1593. pDisp->SetSubdivPosition( ndxPt, vClear );
  1594. pDisp->SetSubdivNormal( ndxPt, vNormal );
  1595. pDisp->SetAlpha( ndxPt, 0.0f );
  1596. }
  1597. }
  1598. }
  1599. }
  1600. }
  1601. //-----------------------------------------------------------------------------
  1602. //-----------------------------------------------------------------------------
  1603. void SewEdge_ResolveDispNormal( SewEdgeData_t *pEdgeData )
  1604. {
  1605. //
  1606. // get displacement surfaces -- if any
  1607. //
  1608. EditDispHandle_t handle1 = pEdgeData->pFaces[0]->GetDisp();
  1609. EditDispHandle_t handle2 = pEdgeData->pFaces[1]->GetDisp();
  1610. if( ( handle1 == EDITDISPHANDLE_INVALID ) || ( handle2 == EDITDISPHANDLE_INVALID ) )
  1611. return;
  1612. CMapDisp *pEdgeDisp1 = EditDispMgr()->GetDisp( handle1 );
  1613. CMapDisp *pEdgeDisp2 = EditDispMgr()->GetDisp( handle2 );
  1614. //
  1615. // sew displacement edges
  1616. //
  1617. //
  1618. // find displacement with smallest/largest interval
  1619. //
  1620. CMapDisp *pSmDisp, *pLgDisp;
  1621. int smInterval, lgInterval;
  1622. int ndxSmEdge, ndxLgEdge;
  1623. if( pEdgeDisp1->GetWidth() > pEdgeDisp2->GetWidth() )
  1624. {
  1625. pSmDisp = pEdgeDisp2;
  1626. ndxSmEdge = pEdgeData->ndxEdges[1];
  1627. smInterval = pEdgeDisp2->GetWidth();
  1628. pLgDisp = pEdgeDisp1;
  1629. ndxLgEdge = pEdgeData->ndxEdges[0];
  1630. lgInterval = pEdgeDisp1->GetWidth();
  1631. }
  1632. else
  1633. {
  1634. pSmDisp = pEdgeDisp1;
  1635. ndxSmEdge = pEdgeData->ndxEdges[0];
  1636. smInterval = pEdgeDisp1->GetWidth();
  1637. pLgDisp = pEdgeDisp2;
  1638. ndxLgEdge = pEdgeData->ndxEdges[1];
  1639. lgInterval = pEdgeDisp2->GetWidth();
  1640. }
  1641. // calculate the ratio
  1642. int ratio = ( lgInterval - 1 ) / ( smInterval - 1 );
  1643. //
  1644. // average "like" points
  1645. //
  1646. for( int ndxSm = 1, ndxLg = ratio; ndxSm < ( smInterval - 1 ); ndxSm++, ndxLg += ratio )
  1647. {
  1648. int ndxSmPt = GetEdgePointIndex( pSmDisp, ndxSmEdge, ndxSm, true );
  1649. int ndxLgPt = GetEdgePointIndex( pLgDisp, ndxLgEdge, ndxLg, false );
  1650. // average
  1651. AverageVectorFieldData( pSmDisp, ndxSmPt, pLgDisp, ndxLgPt );
  1652. }
  1653. //
  1654. // linearly interpolate the "unlike" points
  1655. //
  1656. float blendRatio = 1.0f / ratio;
  1657. for( int ndxLg = 0; ndxLg < ( lgInterval - 1 ); ndxLg += ratio )
  1658. {
  1659. int ndxStart = ndxLg;
  1660. int ndxEnd = ( ndxLg + ratio );
  1661. int ndxStartPt = GetEdgePointIndex( pLgDisp, ndxLgEdge, ndxStart, true );
  1662. int ndxEndPt = GetEdgePointIndex( pLgDisp, ndxLgEdge, ndxEnd, true );
  1663. for( int ndx = ( ndxStart + 1 ); ndx < ndxEnd; ndx++ )
  1664. {
  1665. float blend = blendRatio * ( ndx - ndxStart );
  1666. int ndxDst = GetEdgePointIndex( pLgDisp, ndxLgEdge, ndx, true );
  1667. BlendVectorFieldData( pLgDisp, ndxStartPt, ndxDst, pLgDisp, ndxEndPt, ndxDst, blend );
  1668. }
  1669. }
  1670. }
  1671. //-----------------------------------------------------------------------------
  1672. //-----------------------------------------------------------------------------
  1673. void SewEdge_ResolveSolidNormal( SewEdgeData_t *pEdgeData )
  1674. {
  1675. // create an empty vector to reset the offset with
  1676. Vector vClear( 0.0f, 0.0f, 0.0f );
  1677. for( int i = 0; i < pEdgeData->faceCount; i++ )
  1678. {
  1679. // get the displacement surface associated with the face
  1680. EditDispHandle_t handle = pEdgeData->pFaces[i]->GetDisp();
  1681. if( handle == EDITDISPHANDLE_INVALID )
  1682. continue;
  1683. CMapDisp *pDisp = EditDispMgr()->GetDisp( handle );
  1684. // get surface normal, to reset vector field to base state
  1685. Vector vNormal;
  1686. pDisp->GetSurfNormal( vNormal );
  1687. //
  1688. // for all points along the edge -- reset
  1689. //
  1690. int width = pDisp->GetWidth();
  1691. for( int j = 0; j < width; j++ )
  1692. {
  1693. // get the edge point index
  1694. int ndxPt = GetEdgePointIndex( pDisp, pEdgeData->ndxEdges[i], j, true );
  1695. if( ndxPt == -1 )
  1696. continue;
  1697. //
  1698. // reset displacement data (dist, field vector, and offset vector)
  1699. //
  1700. pDisp->SetFieldDistance( ndxPt, 0.0f );
  1701. pDisp->SetFieldVector( ndxPt, vClear );
  1702. pDisp->SetSubdivPosition( ndxPt, vClear );
  1703. pDisp->SetSubdivNormal( ndxPt, vNormal );
  1704. pDisp->SetAlpha( ndxPt, 0.0f );
  1705. }
  1706. }
  1707. }
  1708. //-----------------------------------------------------------------------------
  1709. //-----------------------------------------------------------------------------
  1710. void SewEdge_Resolve( void )
  1711. {
  1712. // get the number of edges in the edge list
  1713. int edgeCount = s_EdgeData.Size();
  1714. // resolve each edge
  1715. for( int i = 0; i < edgeCount; i++ )
  1716. {
  1717. // get the current edge data struct
  1718. SewEdgeData_t *pEdgeData = s_EdgeData.Element( i );
  1719. if( !pEdgeData )
  1720. continue;
  1721. // handle "normal" edge
  1722. if( pEdgeData->type[0] == DISPSEW_EDGE_NORMAL )
  1723. {
  1724. // solid "normal" edge
  1725. if( SewEdge_IsSolidNormal( pEdgeData ) )
  1726. {
  1727. SewEdge_ResolveSolidNormal( pEdgeData );
  1728. }
  1729. // disps "normal" edge
  1730. else
  1731. {
  1732. SewEdge_ResolveDispNormal( pEdgeData );
  1733. }
  1734. }
  1735. // handle "t-junction" edge
  1736. else
  1737. {
  1738. int ndxTJ = SewEdge_TJIndex( pEdgeData, DISPSEW_EDGE_TJ );
  1739. int ndxTJStart = SewEdge_TJIndex( pEdgeData, DISPSEW_EDGE_TJSTART );
  1740. int ndxTJEnd = SewEdge_TJIndex( pEdgeData, DISPSEW_EDGE_TJEND );
  1741. if( SewEdge_IsSolidTJunc( pEdgeData, DISPSEW_EDGE_TJ ) )
  1742. {
  1743. // reset both start and end t-junction edges if they exist
  1744. if( ndxTJStart != -1 )
  1745. {
  1746. SewEdge_ResolveSolidTJunc( pEdgeData, DISPSEW_EDGE_TJSTART, false );
  1747. }
  1748. if( ndxTJEnd != -1 )
  1749. {
  1750. SewEdge_ResolveSolidTJunc( pEdgeData, DISPSEW_EDGE_TJEND, false );
  1751. }
  1752. continue;
  1753. }
  1754. // handle start edge
  1755. if( ndxTJStart != -1 )
  1756. {
  1757. if( SewEdge_IsSolidTJunc( pEdgeData, DISPSEW_EDGE_TJSTART ) )
  1758. {
  1759. SewEdge_ResolveSolidTJunc( pEdgeData, DISPSEW_EDGE_TJ, true );
  1760. }
  1761. else
  1762. {
  1763. SewEdge_ResolveDispTJunc( pEdgeData, ndxTJ, ndxTJStart, true );
  1764. }
  1765. }
  1766. // handle end edge
  1767. if( ndxTJEnd != -1 )
  1768. {
  1769. if( SewEdge_IsSolidTJunc( pEdgeData, DISPSEW_EDGE_TJEND ) )
  1770. {
  1771. SewEdge_ResolveSolidTJunc( pEdgeData, DISPSEW_EDGE_TJ, false );
  1772. }
  1773. else
  1774. {
  1775. SewEdge_ResolveDispTJunc( pEdgeData, ndxTJ, ndxTJEnd, false );
  1776. }
  1777. }
  1778. }
  1779. }
  1780. }
  1781. //-----------------------------------------------------------------------------
  1782. // Purpose: Convert the edge/midpoint/corner data for shared code,
  1783. //-----------------------------------------------------------------------------
  1784. bool PrePlanarizeDependentVerts( void )
  1785. {
  1786. // Create a list of all the selected displacement cores.
  1787. CFaceEditSheet *pSheet = GetMainWnd()->GetFaceEditSheet();
  1788. if( !pSheet )
  1789. return false;
  1790. int nFaceCount = pSheet->GetFaceListCount();
  1791. for( int iFace = 0; iFace < nFaceCount; ++iFace )
  1792. {
  1793. CMapFace *pFace = pSheet->GetFaceListDataFace( iFace );
  1794. if( !pFace || !pFace->HasDisp() )
  1795. continue;
  1796. CMapDisp *pDisp = EditDispMgr()->GetDisp( pFace->GetDisp() );
  1797. Assert( pDisp );
  1798. int iDisp = m_aCoreDispInfos.AddToTail();
  1799. pDisp->GetCoreDispInfo()->SetListIndex( iDisp );
  1800. m_aCoreDispInfos[iDisp] = pDisp->GetCoreDispInfo();
  1801. }
  1802. // Add the list to the displacements -- this is a bit hacky!!
  1803. for ( int iDisp = 0; iDisp < m_aCoreDispInfos.Count(); ++iDisp )
  1804. {
  1805. m_aCoreDispInfos[iDisp]->SetDispUtilsHelperInfo( m_aCoreDispInfos.Base(), m_aCoreDispInfos.Count() );
  1806. }
  1807. // Build neighboring info.
  1808. FindNeighboringDispSurfs( m_aCoreDispInfos.Base(), m_aCoreDispInfos.Count() );
  1809. return true;
  1810. }
  1811. //-----------------------------------------------------------------------------
  1812. //-----------------------------------------------------------------------------
  1813. class CHammerTesselateHelper : public CBaseTesselateHelper
  1814. {
  1815. public:
  1816. void EndTriangle()
  1817. {
  1818. m_pIndices->AddToTail( m_TempIndices[0] );
  1819. m_pIndices->AddToTail( m_TempIndices[1] );
  1820. m_pIndices->AddToTail( m_TempIndices[2] );
  1821. }
  1822. DispNodeInfo_t& GetNodeInfo( int iNodeBit )
  1823. {
  1824. // Hammer doesn't care about these. Give it back something to play with.
  1825. static DispNodeInfo_t dummy;
  1826. return dummy;
  1827. }
  1828. public:
  1829. CUtlVector<unsigned short> *m_pIndices;
  1830. };
  1831. //-----------------------------------------------------------------------------
  1832. //-----------------------------------------------------------------------------
  1833. bool FindEnclosingTri( const Vector2D &vert, CUtlVector<Vector2D> &vertCoords,
  1834. CUtlVector<unsigned short> &indices, int *pStartVert,
  1835. float bcCoords[3] )
  1836. {
  1837. for ( int i = 0; i < indices.Count(); i += 3 )
  1838. {
  1839. GetBarycentricCoords2D( vertCoords[indices[i+0]],
  1840. vertCoords[indices[i+1]],
  1841. vertCoords[indices[i+2]],
  1842. vert, bcCoords );
  1843. if ( bcCoords[0] >= 0 && bcCoords[0] <= 1 &&
  1844. bcCoords[1] >= 0 && bcCoords[1] <= 1 &&
  1845. bcCoords[2] >= 0 && bcCoords[2] <= 1 )
  1846. {
  1847. *pStartVert = i;
  1848. return true;
  1849. }
  1850. }
  1851. return false;
  1852. }
  1853. //-----------------------------------------------------------------------------
  1854. //-----------------------------------------------------------------------------
  1855. void SnapDependentVertsToSurface( CCoreDispInfo *pCoreDisp )
  1856. {
  1857. // Don't really want to do this, but.......
  1858. CUtlVector<unsigned short> indices;
  1859. CHammerTesselateHelper helper;
  1860. helper.m_pIndices = &indices;
  1861. helper.m_pActiveVerts = pCoreDisp->GetAllowedVerts().Base();
  1862. helper.m_pPowerInfo = pCoreDisp->GetPowerInfo();
  1863. TesselateDisplacement( &helper );
  1864. // Find allowed/non-allowed verts.
  1865. CUtlVector<bool> vertsTouched;
  1866. vertsTouched.SetSize( pCoreDisp->GetSize() );
  1867. memset( vertsTouched.Base(), 0, sizeof( bool ) * vertsTouched.Count() );
  1868. for ( int iVert = 0; iVert < indices.Count(); ++iVert )
  1869. {
  1870. vertsTouched[indices[iVert]] = true;
  1871. }
  1872. // Generate 2D floating point coordinates for each vertex. We use these to generate
  1873. // barycentric coordinates, and the scale doesn't matter.
  1874. CUtlVector<Vector2D> vertCoords;
  1875. vertCoords.SetSize( pCoreDisp->GetSize() );
  1876. for ( int iHgt = 0; iHgt < pCoreDisp->GetHeight(); ++iHgt )
  1877. {
  1878. for ( int iWid = 0; iWid < pCoreDisp->GetWidth(); ++iWid )
  1879. {
  1880. vertCoords[iHgt*pCoreDisp->GetWidth()+iWid].Init( iWid, iHgt );
  1881. }
  1882. }
  1883. // Now, for each vert not touched, snap its position to the main surface.
  1884. for ( int iHgt = 0; iHgt < pCoreDisp->GetHeight(); ++iHgt )
  1885. {
  1886. for ( int iWid = 0; iWid < pCoreDisp->GetWidth(); ++iWid )
  1887. {
  1888. int nIndex = iHgt * pCoreDisp->GetWidth() + iWid;
  1889. if ( !( vertsTouched[nIndex] ) )
  1890. {
  1891. float flBCoords[3];
  1892. int iStartVert = -1;
  1893. if ( FindEnclosingTri( vertCoords[nIndex], vertCoords, indices, &iStartVert, flBCoords ) )
  1894. {
  1895. const Vector &A = pCoreDisp->GetVert( indices[iStartVert+0] );
  1896. const Vector &B = pCoreDisp->GetVert( indices[iStartVert+1] );
  1897. const Vector &C = pCoreDisp->GetVert( indices[iStartVert+2] );
  1898. Vector vNewPos = A*flBCoords[0] + B*flBCoords[1] + C*flBCoords[2];
  1899. // Modify the CCoreDispInfo vert (although it probably won't be used later).
  1900. pCoreDisp->Position_Update( nIndex, vNewPos );
  1901. }
  1902. else
  1903. {
  1904. // This shouldn't happen because it would mean that the triangulation that
  1905. // disp_tesselation.h produced was missing a chunk of the space that the
  1906. // displacement covers.
  1907. // It also could indicate a floating-point epsilon error.. check to see if
  1908. // FindEnclosingTri finds a triangle that -almost- encloses the vert.
  1909. Assert( false );
  1910. }
  1911. }
  1912. }
  1913. }
  1914. }
  1915. //-----------------------------------------------------------------------------
  1916. // Purpose: Get allowed verts bits and planarize cleared verts and purge disp
  1917. // infos.
  1918. //-----------------------------------------------------------------------------
  1919. void PostPlanarizeDependentVerts( void )
  1920. {
  1921. // Snap dependents verts to the displacement surface.
  1922. for ( int iDispCore = 0; iDispCore < m_aCoreDispInfos.Count(); ++iDispCore )
  1923. {
  1924. SnapDependentVertsToSurface( m_aCoreDispInfos[iDispCore] );
  1925. }
  1926. // Clear out the displacement info list.
  1927. m_aCoreDispInfos.Purge();
  1928. }
  1929. //-----------------------------------------------------------------------------
  1930. // Purpose: Planarize vertices that are removed because of dependencies with
  1931. // neighboring displacements.
  1932. //-----------------------------------------------------------------------------
  1933. void PlanarizeDependentVerts( void )
  1934. {
  1935. // Setup.
  1936. if ( !PrePlanarizeDependentVerts() )
  1937. return;
  1938. SetupAllowedVerts( m_aCoreDispInfos.Base(), m_aCoreDispInfos.Count() );
  1939. // Update and clean-up.
  1940. PostPlanarizeDependentVerts();
  1941. }