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.

2412 lines
67 KiB

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