diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /hammer/dispsew.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'hammer/dispsew.cpp')
| -rw-r--r-- | hammer/dispsew.cpp | 2297 |
1 files changed, 2297 insertions, 0 deletions
diff --git a/hammer/dispsew.cpp b/hammer/dispsew.cpp new file mode 100644 index 0000000..172ac63 --- /dev/null +++ b/hammer/dispsew.cpp @@ -0,0 +1,2297 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#include <stdafx.h> +#include <malloc.h> +#include "FaceEditSheet.h" +#include "MainFrm.h" +#include "GlobalFunctions.h" +#include "MapDisp.h" +#include "MapFace.h" +#include "utlvector.h" +#include "disp_tesselate.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + +//============================================================================ +// +// e1 +// c1------c2 +// | | +// e0 | | e2 +// | | +// c0------c3 +// e3 +// +// Note: edges refer to internal edge points only, corners "contain" all surfaces +// touching the corner (surfaces that only touch the corner, as well as those +// "edges" that end/begin at the corner(s)) +// +#define DISPSEW_POINT_TOLERANCE 1.0f // one unit + +#define DISPSEW_NULL_INDEX -99999 + +#define DISPSEW_EDGE_NORMAL 0 +#define DISPSEW_EDGE_TJSTART 1 +#define DISPSEW_EDGE_TJEND 2 +#define DISPSEW_EDGE_TJ 3 + +#define DISPSEW_FACES_AT_EDGE 3 +#define DISPSEW_FACES_AT_CORNER 16 +#define DISPSEW_FACES_AT_TJUNC 8 + +struct SewEdgeData_t +{ + int faceCount; // number of faces contributing to the edge sew + CMapFace *pFaces[DISPSEW_FACES_AT_EDGE]; // the faces contributing to the edge sew + int ndxEdges[DISPSEW_FACES_AT_EDGE]; // the faces' edge indices contributing to the edge sew + int type[DISPSEW_FACES_AT_EDGE]; // the type of edge t-junction, match t-junction start, etc.... +}; + +struct SewCornerData_t +{ + int faceCount; // number of faces contributing to the corner sew + CMapFace *pFaces[DISPSEW_FACES_AT_CORNER]; // the faces contributing to the corner sew + int ndxCorners[DISPSEW_FACES_AT_CORNER]; // the faces' corner indices contributing to the corner sew +}; + +struct SewTJuncData_t +{ + int faceCount; // number of faces contributing to the t-junction sew + CMapFace *pFaces[DISPSEW_FACES_AT_TJUNC]; // the faces contributing to the t-junction sew + int ndxCorners[DISPSEW_FACES_AT_TJUNC]; // the faces' corner indices contributing to the t-junction sew + int ndxEdges[DISPSEW_FACES_AT_TJUNC]; // the faces' edge (midpoint) indices contributing to the t-junction sew +}; + +static CUtlVector<SewEdgeData_t*> s_EdgeData; +static CUtlVector<SewCornerData_t*> s_CornerData; +static CUtlVector<SewTJuncData_t*> s_TJData; +static CUtlVector<CCoreDispInfo*> m_aCoreDispInfos; + +// local functions +void SewCorner_Build( void ); +void SewCorner_Resolve( void ); +void SewCorner_Destroy( SewCornerData_t *pCornerData ); +void SewTJunc_Build( void ); +void SewTJunc_Resolve( void ); +void SewTJunc_Destroy( SewTJuncData_t *pTJData ); +void SewEdge_Build( void ); +void SewEdge_Resolve( void ); +void SewEdge_Destroy( SewEdgeData_t *pEdgeData ); + +void PlanarizeDependentVerts( void ); + +//----------------------------------------------------------------------------- +// Purpose: compare two point positions to see if they are equivolent given a +// tolerance +//----------------------------------------------------------------------------- +bool PointCompareWithTolerance( Vector const& pt1, Vector const& pt2, float tolerance ) +{ + for( int i = 0 ; i < 3 ; i++ ) + { + if( fabs( pt1[i] - pt2[i] ) > tolerance ) + return false; + } + + return true; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +bool EdgeCompare( Vector *pEdgePts1, Vector *pEdgePts2, int &edgeType1, int &edgeType2 ) +{ + Vector edge1[3]; + Vector edge2[3]; + + // + // create edges and midpoints + // + edge1[0] = pEdgePts1[0]; + edge1[1] = ( pEdgePts1[0] + pEdgePts1[1] ) * 0.5f; + edge1[2] = pEdgePts1[1]; + + edge2[0] = pEdgePts2[0]; + edge2[1] = ( pEdgePts2[0] + pEdgePts2[1] ) * 0.5f; + edge2[2] = pEdgePts2[1]; + + // assume edge type to be normal (will get overridden if otherwise) + edgeType1 = DISPSEW_EDGE_NORMAL; + edgeType2 = DISPSEW_EDGE_NORMAL; + + // + // compare points and determine how many are shared between the two edges + // + int overlapCount = 0; + int ndxEdge1[2]; + int ndxEdge2[2]; + + for( int ndx1 = 0; ndx1 < 3; ndx1++ ) + { + for( int ndx2 = 0; ndx2 < 3; ndx2++ ) + { + if( PointCompareWithTolerance( edge1[ndx1], edge2[ndx2], DISPSEW_POINT_TOLERANCE ) ) + { + // no midpoint to midpoint sharing allowed (midpoints are odd index values) + if( ( ndx1%2 != 0 ) && ( ndx2%2 != 0 ) ) + continue; + + // sanity check + assert( overlapCount >= 0 ); + assert( overlapCount < 2 ); + + ndxEdge1[overlapCount] = ndx1; + ndxEdge2[overlapCount] = ndx2; + + overlapCount++; + break; + } + } + } + + if( overlapCount != 2 ) + return false; + + // handle edge1 as t-junction edge + if( ndxEdge1[0]%2 != 0 ) + { + edgeType1 = DISPSEW_EDGE_TJ; + + if( ndxEdge1[1] == 0 ) + { + edgeType2 = DISPSEW_EDGE_TJSTART; + } + else if( ndxEdge1[1] == 2 ) + { + edgeType2 = DISPSEW_EDGE_TJEND; + } + } + else if( ndxEdge1[1]%2 != 0 ) + { + edgeType1 = DISPSEW_EDGE_TJ; + + if( ndxEdge1[0] == 0 ) + { + edgeType2 = DISPSEW_EDGE_TJSTART; + } + else if( ndxEdge1[0] == 2 ) + { + edgeType2 = DISPSEW_EDGE_TJEND; + } + } + + // handle edge2 as t-junction edge + if( ndxEdge2[0]%2 != 0 ) + { + edgeType2 = DISPSEW_EDGE_TJ; + + if( ndxEdge2[1] == 0 ) + { + edgeType1 = DISPSEW_EDGE_TJSTART; + } + else if( ndxEdge2[1] == 2 ) + { + edgeType1 = DISPSEW_EDGE_TJEND; + } + } + else if( ndxEdge2[1]%2 != 0 ) + { + edgeType2 = DISPSEW_EDGE_TJ; + + if( ndxEdge2[0] == 0 ) + { + edgeType1 = DISPSEW_EDGE_TJSTART; + } + else if( ndxEdge2[0] == 2 ) + { + edgeType1 = DISPSEW_EDGE_TJEND; + } + } + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: get a point from the surface at the given index, will get the point +// from the displacement surface if it exists, it will get it from the +// base face otherwise +//----------------------------------------------------------------------------- +inline void GetPointFromSurface( CMapFace *pFace, int ndxPt, Vector &pt ) +{ + EditDispHandle_t dispHandle = pFace->GetDisp(); + if( dispHandle != EDITDISPHANDLE_INVALID ) + { + CMapDisp *pDisp = EditDispMgr()->GetDisp( dispHandle ); + pDisp->GetSurfPoint( ndxPt, pt ); + } + else + { + pFace->GetPoint( pt, ndxPt ); + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +int GetEdgePointIndex( CMapDisp *pDisp, int edgeIndex, int edgePtIndex, bool bCCW ) +{ + int height = pDisp->GetHeight(); + int width = pDisp->GetWidth(); + + if( bCCW ) + { + switch( edgeIndex ) + { + case 0: { return ( edgePtIndex * height ); } + case 1: { return ( ( ( height - 1 ) * width ) + edgePtIndex ); } + case 2: { return ( ( height * width - 1 ) - ( edgePtIndex * height ) ); } + case 3: { return ( ( width - 1 ) - edgePtIndex ); } + default: { return -1; } + } + } + else + { + switch( edgeIndex ) + { + case 0: { return ( ( ( height - 1 ) * width ) - ( edgePtIndex * height ) ); } + case 1: { return ( ( height * width - 1 ) - edgePtIndex ); } + case 2: { return ( ( width - 1 ) + ( edgePtIndex * height ) ); } + case 3: { return ( edgePtIndex ); } + default: { return -1; } + } + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +int GetCornerPointIndex( CMapDisp *pDisp, int cornerIndex ) +{ + int width = pDisp->GetWidth(); + int height = pDisp->GetHeight(); + + switch( cornerIndex ) + { + case 0: { return 0; } + case 1: { return ( ( height - 1 ) * width ); } + case 2: { return ( height * width - 1 ); } + case 3: { return ( width - 1 ); } + default: { return -1; } + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +int GetTJuncIndex( CMapDisp *pDisp, int ndxEdge ) +{ + int width = pDisp->GetWidth(); + int height = pDisp->GetHeight(); + + switch( ndxEdge ) + { + case 0: { return( height * ( width / 2 ) ); } + case 1: { return( ( ( height - 1 ) * width ) + ( width / 2 ) ); } + case 2: { return( ( height * ( width / 2 ) ) + ( width - 1 ) ); } + case 3: { return( width / 2 ); } + default: { return -1; } + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void AverageVectorFieldData( CMapDisp *pDisp1, int ndx1, CMapDisp *pDisp2, int ndx2 ) +{ + // + // average the positions at each index + // position = dispVector * dispDist + // + float dist1 = pDisp1->GetFieldDistance( ndx1 ); + float dist2 = pDisp2->GetFieldDistance( ndx2 ); + + Vector v1, v2; + pDisp1->GetFieldVector( ndx1, v1 ); + pDisp2->GetFieldVector( ndx2, v2 ); + + v1 *= dist1; + v2 *= dist2; + + Vector vAvg; + vAvg = ( v1 + v2 ) * 0.5f; + + float distAvg = VectorNormalize( vAvg ); + + pDisp1->SetFieldDistance( ndx1, distAvg ); + pDisp2->SetFieldDistance( ndx2, distAvg ); + pDisp1->SetFieldVector( ndx1, vAvg ); + pDisp2->SetFieldVector( ndx2, vAvg ); + + // Check to see if the materials match and blend alphas if they do. + CMapFace *pFace1 = static_cast<CMapFace*>( pDisp1->GetParent() ); + CMapFace *pFace2 = static_cast<CMapFace*>( pDisp2->GetParent() ); + char szMatName1[128]; + char szMatName2[128]; + pFace1->GetTexture()->GetShortName( szMatName1 ); + pFace2->GetTexture()->GetShortName( szMatName2 ); + if ( !strcmpi( szMatName1, szMatName2 ) ) + { + // Grab the alphas at the points and average them. + float flAlpha1, flAlpha2; + flAlpha1 = pDisp1->GetAlpha( ndx1 ); + flAlpha2 = pDisp2->GetAlpha( ndx2 ); + float flAlphaBlend = ( flAlpha1 + flAlpha1 ) * 0.5f; + pDisp1->SetAlpha( ndx1, flAlphaBlend ); + pDisp2->SetAlpha( ndx2, flAlphaBlend ); + } + + // + // average the subdivion positions and normals + // + pDisp1->GetSubdivPosition( ndx1, v1 ); + pDisp2->GetSubdivPosition( ndx2, v2 ); + vAvg = ( v1 + v2 ) * 0.5f; + pDisp1->SetSubdivPosition( ndx1, vAvg ); + pDisp2->SetSubdivPosition( ndx2, vAvg ); + + pDisp1->GetSubdivNormal( ndx1, v1 ); + pDisp2->GetSubdivNormal( ndx2, v2 ); + vAvg = v1 + v2; + VectorNormalize( vAvg ); + pDisp1->SetSubdivNormal( ndx1, vAvg ); + pDisp2->SetSubdivNormal( ndx2, vAvg ); +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void BlendVectorFieldData( CMapDisp *pDisp1, int ndxSrc1, int ndxDst1, + CMapDisp *pDisp2, int ndxSrc2, int ndxDst2, + float blendFactor ) +{ + // + // to blend positions -- calculate the positions at the end points + // find the new point along the parameterized line and calculate the + // new field vector direction and distance (position) + // + float dist1 = pDisp1->GetFieldDistance( ndxSrc1 ); + float dist2 = pDisp2->GetFieldDistance( ndxSrc2 ); + + Vector v1, v2; + pDisp1->GetFieldVector( ndxSrc1, v1 ); + pDisp2->GetFieldVector( ndxSrc2, v2 ); + + v1 *= dist1; + v2 *= dist2; + + Vector vBlend; + vBlend = v1 + ( v2 - v1 ) * blendFactor; + + float distBlend = VectorNormalize( vBlend ); + + pDisp1->SetFieldDistance( ndxDst1, distBlend ); + pDisp2->SetFieldDistance( ndxDst2, distBlend ); + pDisp1->SetFieldVector( ndxDst1, vBlend ); + pDisp2->SetFieldVector( ndxDst2, vBlend ); + + // Check to see if the materials match and blend alphas if they do. + CMapFace *pFace1 = static_cast<CMapFace*>( pDisp1->GetParent() ); + CMapFace *pFace2 = static_cast<CMapFace*>( pDisp2->GetParent() ); + char szMatName1[128]; + char szMatName2[128]; + pFace1->GetTexture()->GetShortName( szMatName1 ); + pFace2->GetTexture()->GetShortName( szMatName2 ); + if ( !strcmpi( szMatName1, szMatName2 ) ) + { + float flAlpha1, flAlpha2; + flAlpha1 = pDisp1->GetAlpha( ndxDst1 ); + flAlpha2 = pDisp2->GetAlpha( ndxDst2 ); + float flAlphaBlend = flAlpha1 + ( flAlpha2 - flAlpha1 ) * blendFactor; + pDisp1->SetAlpha( ndxDst1, flAlphaBlend ); + pDisp2->SetAlpha( ndxDst2, flAlphaBlend ); + } + + // + // blend subdivision positions and normals as before, + // this isn't truly accurate, but I am not sure what these + // values mean in the edge sewing case anyway??? + // + pDisp1->GetSubdivPosition( ndxSrc1, v1 ); + pDisp2->GetSubdivPosition( ndxSrc2, v2 ); + vBlend = v1 + ( v2 - v1 ) * blendFactor; + pDisp1->SetSubdivPosition( ndxDst1, vBlend ); + pDisp2->SetSubdivPosition( ndxDst2, vBlend ); + + pDisp1->GetSubdivNormal( ndxSrc1, v1 ); + pDisp2->GetSubdivNormal( ndxSrc2, v2 ); + vBlend = v1 + ( v2 - v1 ) * blendFactor; + pDisp1->SetSubdivNormal( ndxDst1, vBlend ); + pDisp2->SetSubdivNormal( ndxDst2, vBlend ); +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +inline bool Face_IsSolid( CMapFace *pFace ) +{ + return ( pFace->GetDisp() == EDITDISPHANDLE_INVALID ); +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void Faces_Update( void ) +{ + // + // get the "faces" selection list (contains displaced and non-displaced faces) + // + CFaceEditSheet *pSheet = GetMainWnd()->GetFaceEditSheet(); + if( !pSheet ) + return; + + // + // for each face in list + // + int faceCount = pSheet->GetFaceListCount(); + + for( int ndxFace = 0; ndxFace < faceCount; ndxFace++ ) + { + // get the current face + CMapFace *pFace = pSheet->GetFaceListDataFace( ndxFace ); + if( !pFace ) + continue; + + // only update displacement surfaces + EditDispHandle_t dispHandle = pFace->GetDisp(); + if( dispHandle == EDITDISPHANDLE_INVALID ) + continue; + + CMapDisp *pDisp = EditDispMgr()->GetDisp( dispHandle ); + pDisp->UpdateData(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Build temporary edge/midpoint/corner info for sewing. +//----------------------------------------------------------------------------- +void PreFaceListSew( void ) +{ + // Build edge/midpoint/corner data. + SewCorner_Build(); + SewTJunc_Build(); + SewEdge_Build(); +} + +//----------------------------------------------------------------------------- +// Purpose: Destroy temporary edge/midpoint/corner info for sewing and +// update the effected displacements. +//----------------------------------------------------------------------------- +void PostFaceListSew( void ) +{ + // Destroy all corners, midpoint, edges. + int count = s_CornerData.Size(); + for( int i = 0; i < count; i++ ) + { + SewCorner_Destroy( s_CornerData.Element( i ) ); + } + + count = s_TJData.Size(); + for( int i = 0; i < count; i++ ) + { + SewTJunc_Destroy( s_TJData.Element( i ) ); + } + + count = s_EdgeData.Size(); + for( int i = 0; i < count; i++ ) + { + SewEdge_Destroy( s_EdgeData.Element( i ) ); + } + + // Flush all of the sewing data buffers. + s_CornerData.Purge(); + s_TJData.Purge(); + s_EdgeData.Purge(); + + // Update the faces. + Faces_Update(); +} + +//----------------------------------------------------------------------------- +// Purpose: given a face with a displacement surface, "sew" all edges to all +// neighboring displacement and non-displacement surfaces +// found in the selection set +//----------------------------------------------------------------------------- +void FaceListSewEdges( void ) +{ + // Setup. + PreFaceListSew(); + + // Resolve/Planarize unusable verts. + PlanarizeDependentVerts(); + + // Resolve sewing. + SewCorner_Resolve(); + SewTJunc_Resolve(); + SewEdge_Resolve(); + + // Update and clean-up. + PostFaceListSew(); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +SewCornerData_t *SewCorner_Create( void ) +{ + SewCornerData_t *pCornerData = new SewCornerData_t; + if( pCornerData ) + { + // initialize the data + pCornerData->faceCount = 0; + return pCornerData; + } + + return NULL; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewCorner_Destroy( SewCornerData_t *pCornerData ) +{ + if( pCornerData ) + { + delete pCornerData; + pCornerData = NULL; + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +bool SewCorner_IsSolid( SewCornerData_t *pCornerData ) +{ + for( int i = 0; i < pCornerData->faceCount; i++ ) + { + if( Face_IsSolid( pCornerData->pFaces[i] ) ) + return true; + } + + return false; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewCorner_Add( SewCornerData_t *pCornerData, CMapFace *pFace, int ndx ) +{ + if ( pCornerData->faceCount >= DISPSEW_FACES_AT_CORNER ) + { + AfxMessageBox( "Warning: Too many displacement faces at corner!\n" ); + return; + } + + pCornerData->pFaces[pCornerData->faceCount] = pFace; + pCornerData->ndxCorners[pCornerData->faceCount] = ndx; + pCornerData->faceCount++; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewCorner_AddToList( SewCornerData_t *pCornerData ) +{ + // get the current corner point + Vector pt; + GetPointFromSurface( pCornerData->pFaces[0], pCornerData->ndxCorners[0], pt ); + + // + // check to see if the corner point already exists in the corner data list + // + int cornerCount = s_CornerData.Size(); + + for( int i = 0; i < cornerCount; i++ ) + { + // + // get the compare corner point + // + SewCornerData_t *pCmpData = s_CornerData.Element( i ); + if( !pCmpData ) + continue; + + Vector cmpPt; + GetPointFromSurface( pCmpData->pFaces[0], pCmpData->ndxCorners[0], cmpPt ); + + // compare the points - return if found + if( PointCompareWithTolerance( pt, cmpPt, DISPSEW_POINT_TOLERANCE ) ) + { + SewCorner_Destroy( pCornerData ); + return; + } + } + + // unique corner point -- add it to the list + s_CornerData.AddToTail( pCornerData ); +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewCorner_Build( void ) +{ + // + // get the "faces" selection list (contains displaced and non-displaced faces) + // + CFaceEditSheet *pSheet = GetMainWnd()->GetFaceEditSheet(); + if( !pSheet ) + return; + + // + // for each face in list + // + int faceCount = pSheet->GetFaceListCount(); + + for( int ndxFace = 0; ndxFace < faceCount; ndxFace++ ) + { + // get the current face + CMapFace *pFace = pSheet->GetFaceListDataFace( ndxFace ); + if( !pFace ) + continue; + + // + // for each face point + // + int ptCount = pFace->GetPointCount(); + for( int ndxPt = 0; ndxPt < ptCount; ndxPt++ ) + { + // get the current point + Vector pt; + GetPointFromSurface( pFace, ndxPt, pt ); + + // allocate new corner point + SewCornerData_t *pCornerData = SewCorner_Create(); + if( !pCornerData ) + return; + + // + // compare this point to all of the other points on all the other faces in the list + // + for( int ndxFace2 = 0; ndxFace2 < faceCount; ndxFace2++ ) + { + // don't compare to itself + if( ndxFace == ndxFace2 ) + continue; + + // get the current compare face + CMapFace *pFace2 = pSheet->GetFaceListDataFace( ndxFace2 ); + if( !pFace2 ) + continue; + + // + // for each compare face point + // + int ptCount2 = pFace2->GetPointCount(); + for( int ndxPt2 = 0; ndxPt2 < ptCount2; ndxPt2++ ) + { + // get the current compare point + Vector pt2; + GetPointFromSurface( pFace2, ndxPt2, pt2 ); + + // compare pt1 and pt2 + if( PointCompareWithTolerance( pt, pt2, DISPSEW_POINT_TOLERANCE ) ) + { + SewCorner_Add( pCornerData, pFace2, ndxPt2 ); + } + } + } + + // had neighbors -- add base point and add it to corner list + if( pCornerData->faceCount > 0 ) + { + SewCorner_Add( pCornerData, pFace, ndxPt ); + SewCorner_AddToList( pCornerData ); + } + // no neighbors -- de-allocate + else + { + SewCorner_Destroy( pCornerData ); + } + } + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewCorner_ResolveDisp( SewCornerData_t *pCornerData ) +{ + // the field data accumulators + float avgDist = 0.0f; + Vector vAvgField( 0.0f, 0.0f, 0.0f ); + Vector vAvgSubdivPos( 0.0f, 0.0f, 0.0f ); + Vector vAvgSubdivNormal( 0.0f, 0.0f, 0.0f ); + float flAvgAlpha = 0.0f; + + // Blend the alpha? + bool bBlendAlpha = true; + char szMatName1[128]; + char szMatName2[128]; + bool bInitMat = false; + for( int i = 0; i < pCornerData->faceCount; i++ ) + { + // get the current corner face + CMapFace *pFace = pCornerData->pFaces[i]; + if( !pFace ) + continue; + + // get the current displacement surface to reset, if solid = done! + EditDispHandle_t dispHandle = pFace->GetDisp(); + if( dispHandle == EDITDISPHANDLE_INVALID ) + continue; + + if ( !bInitMat ) + { + pFace->GetTexture()->GetShortName( szMatName1 ); + bInitMat = true; + continue; + } + else + { + pFace->GetTexture()->GetShortName( szMatName2 ); + if ( strcmpi( szMatName1, szMatName2 ) ) + { + bBlendAlpha = false; + break; + } + } + } + + // for all the faces at the corner + for( int i = 0; i < pCornerData->faceCount; i++ ) + { + // get the current corner face + CMapFace *pFace = pCornerData->pFaces[i]; + if( !pFace ) + continue; + + // get the current displacement surface to reset, if solid = done! + EditDispHandle_t dispHandle = pFace->GetDisp(); + if( dispHandle == EDITDISPHANDLE_INVALID ) + continue; + + CMapDisp *pDisp = EditDispMgr()->GetDisp( dispHandle ); + + // get the corner index + int ndxPt = GetCornerPointIndex( pDisp, pCornerData->ndxCorners[i] ); + if( ndxPt == -1 ) + continue; + + Vector vecPos; + pDisp->GetVert( ndxPt, vecPos ); + + float dist = pDisp->GetFieldDistance( ndxPt ); + avgDist += dist; + + Vector vTmp; + pDisp->GetFieldVector( ndxPt, vTmp ); + vAvgField += vTmp; + + pDisp->GetSubdivPosition( ndxPt, vTmp ); + vAvgSubdivPos += vTmp; + + pDisp->GetSubdivNormal( ndxPt, vTmp ); + vAvgSubdivNormal += vTmp; + + if ( bBlendAlpha ) + { + flAvgAlpha += pDisp->GetAlpha( ndxPt ); + } + } + + // calculate the average + avgDist /= pCornerData->faceCount; + vAvgField /= pCornerData->faceCount; + vAvgSubdivPos /= pCornerData->faceCount; + vAvgSubdivNormal /= pCornerData->faceCount; + if ( bBlendAlpha ) + { + flAvgAlpha /= pCornerData->faceCount; + } + + for( int i = 0; i < pCornerData->faceCount; i++ ) + { + // get the current corner face + CMapFace *pFace = pCornerData->pFaces[i]; + if( !pFace ) + continue; + + // get the current displacement surface to reset, if solid = done! + EditDispHandle_t dispHandle = pFace->GetDisp(); + if( dispHandle == EDITDISPHANDLE_INVALID ) + continue; + + CMapDisp *pDisp = EditDispMgr()->GetDisp( dispHandle ); + + // get the corner index + int ndxPt = GetCornerPointIndex( pDisp, pCornerData->ndxCorners[i] ); + if( ndxPt == -1 ) + continue; + + // set the averaged values + pDisp->SetFieldDistance( ndxPt, avgDist ); + pDisp->SetFieldVector( ndxPt, vAvgField ); + pDisp->SetSubdivPosition( ndxPt, vAvgSubdivPos ); + pDisp->SetSubdivNormal( ndxPt, vAvgSubdivNormal ); + if ( bBlendAlpha ) + { + pDisp->SetAlpha( ndxPt, flAvgAlpha ); + } + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewCorner_ResolveSolid( SewCornerData_t *pCornerData ) +{ + // create a clear vector - to reset the offset vector + Vector vClear( 0.0f, 0.0f, 0.0f ); + + // for all the faces at the corner + for( int i = 0; i < pCornerData->faceCount; i++ ) + { + // get the current corner face + CMapFace *pFace = pCornerData->pFaces[i]; + if( !pFace ) + continue; + + // get the current displacement surface to reset, if solid = done! + EditDispHandle_t dispHandle = pFace->GetDisp(); + if( dispHandle == EDITDISPHANDLE_INVALID ) + continue; + + CMapDisp *pDisp = EditDispMgr()->GetDisp( dispHandle ); + + // get the face normal -- to reset the field vector + Vector vNormal; + pDisp->GetSurfNormal( vNormal ); + + // get the corner index + int ndxPt = GetCornerPointIndex( pDisp, pCornerData->ndxCorners[i] ); + if( ndxPt == -1 ) + continue; + + // + // reset all neighbor surface data - field vector, distance, and offset + // + pDisp->SetFieldDistance( ndxPt, 0.0f ); + pDisp->SetFieldVector( ndxPt, vNormal ); + pDisp->SetSubdivPosition( ndxPt, vClear ); + pDisp->SetSubdivNormal( ndxPt, vNormal ); + pDisp->SetAlpha( ndxPt, 0.0f ); + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewCorner_Resolve( void ) +{ + // get the number of corners in the corner list + int cornerCount = s_CornerData.Size(); + + // resolve each corner + for( int i = 0; i < cornerCount; i++ ) + { + // get the current corner data struct + SewCornerData_t *pCornerData = s_CornerData.Element( i ); + if( !pCornerData ) + continue; + + // determine if any of the faces is solid + bool bSolid = SewCorner_IsSolid( pCornerData ); + + // solid at corner -- reset corner data + if( bSolid ) + { + SewCorner_ResolveSolid( pCornerData ); + } + // all disps at corner -- average + else + { + SewCorner_ResolveDisp( pCornerData ); + } + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +SewTJuncData_t *SewTJunc_Create( void ) +{ + SewTJuncData_t *pTJData = new SewTJuncData_t; + if( pTJData ) + { + // initialize the data + pTJData->faceCount = 0; + return pTJData; + } + + return NULL; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewTJunc_Destroy( SewTJuncData_t *pTJData ) +{ + if( pTJData ) + { + delete pTJData; + pTJData = NULL; + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +bool SewTJunc_IsSolid( SewTJuncData_t *pTJData ) +{ + for( int i = 0; i < pTJData->faceCount; i++ ) + { + if( Face_IsSolid( pTJData->pFaces[i] ) ) + return true; + } + + return false; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewTJunc_Add( SewTJuncData_t *pTJData, CMapFace *pFace, int ndxCorner, int ndxEdge ) +{ + if ( pTJData->faceCount >= DISPSEW_FACES_AT_TJUNC ) + { + AfxMessageBox( "Warning: Too many displacement faces at t-junction!\n" ); + return; + } + + pTJData->pFaces[pTJData->faceCount] = pFace; + pTJData->ndxCorners[pTJData->faceCount] = ndxCorner; + pTJData->ndxEdges[pTJData->faceCount] = ndxEdge; + pTJData->faceCount++; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewTJunc_AddToList( SewTJuncData_t *pTJData ) +{ + // get the current t-junction point + Vector pt; + GetPointFromSurface( pTJData->pFaces[0], pTJData->ndxCorners[0], pt ); + + // + // check to see if the t-junction point already exists in the t-junction data list + // + int tjCount = s_TJData.Size(); + for( int i = 0; i < tjCount; i++ ) + { + // get the compare t-junction point + SewTJuncData_t *pCmpData = s_TJData.Element( i ); + if( !pCmpData ) + continue; + + Vector cmpPt; + GetPointFromSurface( pCmpData->pFaces[0], pCmpData->ndxCorners[0], cmpPt ); + + // compare the points - return if found + if( PointCompareWithTolerance( pt, cmpPt, DISPSEW_POINT_TOLERANCE ) ) + { + SewTJunc_Destroy( pTJData ); + return; + } + } + + // unique t-junction point -- add it to the list + s_TJData.AddToTail( pTJData ); +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewTJunc_Build( void ) +{ + // + // get the "faces" selection list (contains displaced and non-displaced faces) + // + CFaceEditSheet *pSheet = GetMainWnd()->GetFaceEditSheet(); + if( !pSheet ) + return; + + // + // for each face in list + // + int faceCount = pSheet->GetFaceListCount(); + + for( int ndxFace = 0; ndxFace < faceCount; ndxFace++ ) + { + // get the current face + CMapFace *pFace = pSheet->GetFaceListDataFace( ndxFace ); + if( !pFace ) + continue; + + // + // for each face point + // + int ptCount = pFace->GetPointCount(); + for( int ndxPt = 0; ndxPt < ptCount; ndxPt++ ) + { + // get the current t-junction point + Vector pt, tmpPt1, tmpPt2; + GetPointFromSurface( pFace, ndxPt, tmpPt1 ); + GetPointFromSurface( pFace, (ndxPt+1)%ptCount, tmpPt2 ); + pt = ( tmpPt1 + tmpPt2 ) * 0.5f; + + // allocate new corner point + SewTJuncData_t *pTJData = SewTJunc_Create(); + if( !pTJData ) + return; + + // + // compare this point to all of the other points on all the other faces in the list + // + for( int ndxFace2 = 0; ndxFace2 < faceCount; ndxFace2++ ) + { + // don't compare to itself + if( ndxFace == ndxFace2 ) + continue; + + // get the current compare face + CMapFace *pFace2 = pSheet->GetFaceListDataFace( ndxFace2 ); + if( !pFace2 ) + continue; + + // + // for each compare face point + // + int ptCount2 = pFace2->GetPointCount(); + for( int ndxPt2 = 0; ndxPt2 < ptCount2; ndxPt2++ ) + { + // get the current compare point + Vector pt2; + GetPointFromSurface( pFace2, ndxPt2, pt2 ); + + // compare pt1 and pt2 + if( PointCompareWithTolerance( pt, pt2, DISPSEW_POINT_TOLERANCE ) ) + { + SewTJunc_Add( pTJData, pFace2, ndxPt2, -1 ); + } + } + } + + // had neighbors -- add base point and add it to corner list + if( pTJData->faceCount > 0 ) + { + SewTJunc_Add( pTJData, pFace, -1, ndxPt ); + SewTJunc_AddToList( pTJData ); + } + // no neighbors -- de-allocate + else + { + SewTJunc_Destroy( pTJData ); + } + } + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewTJunc_ResolveDisp( SewTJuncData_t *pTJData ) +{ + // the field data accumulators + float avgDist = 0.0f; + Vector vAvgField( 0.0f, 0.0f, 0.0f ); + Vector vAvgSubdivPos( 0.0f, 0.0f, 0.0f ); + Vector vAvgSubdivNormal( 0.0f, 0.0f, 0.0f ); + float flAvgAlpha = 0.0f; + + // for all the faces at the t-junction + for( int i = 0; i < pTJData->faceCount; i++ ) + { + // get the current t-junction face + CMapFace *pFace = pTJData->pFaces[i]; + if( !pFace ) + continue; + + // get the current displacement surface to reset, if solid = done! + EditDispHandle_t dispHandle = pFace->GetDisp(); + if( dispHandle == EDITDISPHANDLE_INVALID ) + continue; + + CMapDisp *pDisp = EditDispMgr()->GetDisp( dispHandle ); + + // get the t-junction index + int ndxPt = -1; + if( pTJData->ndxCorners[i] != -1 ) + { + ndxPt = GetCornerPointIndex( pDisp, pTJData->ndxCorners[i] ); + } + else if( pTJData->ndxEdges[i] != -1 ) + { + int ndxEdgePt = pDisp->GetWidth() / 2; + ndxPt = GetEdgePointIndex( pDisp, pTJData->ndxEdges[i], ndxEdgePt, true ); + } + + if( ndxPt == -1 ) + continue; + + float dist = pDisp->GetFieldDistance( ndxPt ); + avgDist += dist; + + Vector vTmp; + pDisp->GetFieldVector( ndxPt, vTmp ); + vAvgField += vTmp; + + pDisp->GetSubdivPosition( ndxPt, vTmp ); + vAvgSubdivPos += vTmp; + + pDisp->GetSubdivNormal( ndxPt, vTmp ); + vAvgSubdivNormal += vTmp; + + flAvgAlpha += pDisp->GetAlpha( ndxPt ); + } + + // calculate the average + avgDist /= pTJData->faceCount; + vAvgField /= pTJData->faceCount; + vAvgSubdivPos /= pTJData->faceCount; + vAvgSubdivNormal /= pTJData->faceCount; + flAvgAlpha /= pTJData->faceCount; + + for( int i = 0; i < pTJData->faceCount; i++ ) + { + // get the current t-junction face + CMapFace *pFace = pTJData->pFaces[i]; + if( !pFace ) + continue; + + // get the current displacement surface to reset, if solid = done! + EditDispHandle_t dispHandle = pFace->GetDisp(); + if( dispHandle == EDITDISPHANDLE_INVALID ) + continue; + + CMapDisp *pDisp = EditDispMgr()->GetDisp( dispHandle ); + + // get the t-junction index + int ndxPt = -1; + if( pTJData->ndxCorners[i] != -1 ) + { + ndxPt = GetCornerPointIndex( pDisp, pTJData->ndxCorners[i] ); + } + else if( pTJData->ndxEdges[i] != -1 ) + { + int ndxEdgePt = pDisp->GetWidth() / 2; + ndxPt = GetEdgePointIndex( pDisp, pTJData->ndxEdges[i], ndxEdgePt, true ); + } + + if( ndxPt == -1 ) + continue; + + // set the averaged values + pDisp->SetFieldDistance( ndxPt, avgDist ); + pDisp->SetFieldVector( ndxPt, vAvgField ); + pDisp->SetSubdivPosition( ndxPt, vAvgSubdivPos ); + pDisp->SetSubdivNormal( ndxPt, vAvgSubdivNormal ); + pDisp->SetAlpha( ndxPt, flAvgAlpha ); + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewTJunc_ResolveSolid( SewTJuncData_t *pTJData ) +{ + // create a clear vector - to reset the offset vector + Vector vClear( 0.0f, 0.0f, 0.0f ); + + // for all the faces at the t-junction + for( int i = 0; i < pTJData->faceCount; i++ ) + { + // get the current t-junction face + CMapFace *pFace = pTJData->pFaces[i]; + if( !pFace ) + continue; + + // get the current displacement surface to reset, if solid = done! + EditDispHandle_t dispHandle = pFace->GetDisp(); + if( dispHandle == EDITDISPHANDLE_INVALID ) + continue; + + CMapDisp *pDisp = EditDispMgr()->GetDisp( dispHandle ); + + // get the face normal -- to reset the field vector + Vector vNormal; + pDisp->GetSurfNormal( vNormal ); + + // get the t-junction index + int ndxPt = -1; + if( pTJData->ndxCorners[i] != -1 ) + { + ndxPt = GetCornerPointIndex( pDisp, pTJData->ndxCorners[i] ); + } + else if( pTJData->ndxEdges[i] != -1 ) + { + int ndxEdgePt = pDisp->GetWidth() / 2; + ndxPt = GetEdgePointIndex( pDisp, pTJData->ndxEdges[i], ndxEdgePt, true ); + } + + if( ndxPt == -1 ) + continue; + + // + // reset all neighbor surface data - field vector, distance, and offset + // + pDisp->SetFieldDistance( ndxPt, 0.0f ); + pDisp->SetFieldVector( ndxPt, vNormal ); + pDisp->SetSubdivPosition( ndxPt, vClear ); + pDisp->SetSubdivNormal( ndxPt, vNormal ); + pDisp->SetAlpha( ndxPt, 0.0f ); + } +} + + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewTJunc_Resolve( void ) +{ + // get the number of t-junctions in the t-junction list + int tjCount = s_TJData.Size(); + + // resolve each t-junction + for( int i = 0; i < tjCount; i++ ) + { + // get the current t-junction data struct + SewTJuncData_t *pTJData = s_TJData.Element( i ); + if( !pTJData ) + continue; + + // determine if any of the faces is solid + bool bSolid = SewTJunc_IsSolid( pTJData ); + + // solid at t-junction -- reset t-junction data + if( bSolid ) + { + SewTJunc_ResolveSolid( pTJData ); + } + // all disps at t-junction -- average + else + { + SewTJunc_ResolveDisp( pTJData ); + } + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +SewEdgeData_t *SewEdge_Create( void ) +{ + SewEdgeData_t *pEdgeData = new SewEdgeData_t; + if( pEdgeData ) + { + // initialize the data + pEdgeData->faceCount = 0; + return pEdgeData; + } + + return NULL; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewEdge_Destroy( SewEdgeData_t *pEdgeData ) +{ + if( pEdgeData ) + { + delete pEdgeData; + pEdgeData = NULL; + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +inline bool SewEdge_IsSolidNormal( SewEdgeData_t *pEdgeData ) +{ + for( int i = 0; i < pEdgeData->faceCount; i++ ) + { + if( Face_IsSolid( pEdgeData->pFaces[i] ) ) + return true; + } + + return false; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +inline int SewEdge_TJIndex( SewEdgeData_t *pEdgeData, int type ) +{ + for( int i = 0; i < pEdgeData->faceCount; i++ ) + { + if( pEdgeData->type[i] == type ) + return i; + } + + return -1; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +inline bool SewEdge_IsSolidTJunc( SewEdgeData_t *pEdgeData, int type ) +{ + for( int i = 0; i < pEdgeData->faceCount; i++ ) + { + if( pEdgeData->type[i] != type ) + continue; + + if( Face_IsSolid( pEdgeData->pFaces[i] ) ) + return true; + } + + return false; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +bool SewEdge_Add( SewEdgeData_t *pEdgeData, CMapFace *pFace, int ndxEdge, int type ) +{ + if ( pEdgeData->faceCount >= DISPSEW_FACES_AT_EDGE ) + { + return false; + } + + // Add face to edge. + pEdgeData->pFaces[pEdgeData->faceCount] = pFace; + pEdgeData->ndxEdges[pEdgeData->faceCount] = ndxEdge; + pEdgeData->type[pEdgeData->faceCount] = type; + pEdgeData->faceCount++; + + return true; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +bool SewEdge_AddToListMerge( SewEdgeData_t *pEdgeData, SewEdgeData_t *pCmpData ) +{ + bool bReturn = true; + + for( int i = 0; i < pEdgeData->faceCount; i++ ) + { + // t-junction edges already exist in both (skip it!) + if( pEdgeData->type[i] == DISPSEW_EDGE_TJ ) + continue; + + int j; + for( j = 0; j < pCmpData->faceCount; j++ ) + { + // t-junction edges already exist in both (skip it!) + if( pCmpData->type[j] == DISPSEW_EDGE_TJ ) + continue; + + if( pEdgeData->type[i] == pCmpData->type[j] ) + break; + } + + // no match found -- add it + if( j == pCmpData->faceCount ) + { + if (!SewEdge_Add( pCmpData, pEdgeData->pFaces[i], pEdgeData->ndxEdges[i], pEdgeData->type[i] )) + { + bReturn = false; + } + } + } + + return bReturn; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +bool SewEdge_AddToListTJunc( SewEdgeData_t *pEdgeData ) +{ + // find the t-junction edge + int ndxTJ = SewEdge_TJIndex( pEdgeData, DISPSEW_EDGE_TJ ); + if( ndxTJ == -1 ) + return true; + + // get the t-junction edge point count + int ptCount = pEdgeData->pFaces[ndxTJ]->GetPointCount(); + + // get the current t-junction edge (edge points) + Vector edgePts[2]; + GetPointFromSurface( pEdgeData->pFaces[ndxTJ], pEdgeData->ndxEdges[ndxTJ], edgePts[0] ); + GetPointFromSurface( pEdgeData->pFaces[ndxTJ], (pEdgeData->ndxEdges[ndxTJ]+1)%ptCount, edgePts[1] ); + + // + // check to see if the edge already exists in the edge data list + // + int edgeCount = s_EdgeData.Size(); + for( int i = 0; i < edgeCount; i++ ) + { + // get the edge points to compare against + SewEdgeData_t *pCmpData = s_EdgeData.Element( i ); + if( !pCmpData ) + continue; + + // get the compare t-junction edge + int ndxCmp = SewEdge_TJIndex( pCmpData, DISPSEW_EDGE_TJ ); + if( ndxCmp == -1 ) + continue; + + // get the compare face point count + int ptCount2 = pCmpData->pFaces[ndxCmp]->GetPointCount(); + + Vector edgePts2[2]; + GetPointFromSurface( pCmpData->pFaces[ndxCmp], pCmpData->ndxEdges[ndxCmp], edgePts2[0] ); + GetPointFromSurface( pCmpData->pFaces[ndxCmp], (pCmpData->ndxEdges[ndxCmp]+1)%ptCount2, edgePts2[1] ); + + // compare the edges -- return if found + int edgeType1, edgeType2; + if( EdgeCompare( edgePts, edgePts2, edgeType1, edgeType2 ) ) + { + bool bReturn = SewEdge_AddToListMerge( pEdgeData, pCmpData ); + SewEdge_Destroy( pEdgeData ); + return bReturn; + } + } + + // unique edge -- add it to the list + s_EdgeData.AddToTail( pEdgeData ); + return true; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewEdge_AddToListNormal( SewEdgeData_t *pEdgeData ) +{ + // get the face point count + int ptCount = pEdgeData->pFaces[0]->GetPointCount(); + + // get the current edge (edge points) + Vector edgePts[2]; + GetPointFromSurface( pEdgeData->pFaces[0], pEdgeData->ndxEdges[0], edgePts[0] ); + GetPointFromSurface( pEdgeData->pFaces[0], (pEdgeData->ndxEdges[0]+1)%ptCount, edgePts[1] ); + + // + // check to see if the edge already exists in the edge data list + // + int edgeCount = s_EdgeData.Size(); + for( int i = 0; i < edgeCount; i++ ) + { + // get the edge points to compare against + SewEdgeData_t *pCmpData = s_EdgeData.Element( i ); + if( !pCmpData ) + continue; + + // compare against each edge (all colinear) in struct + for( int j = 0; j < pCmpData->faceCount; j++ ) + { + // get the compare face point count + int ptCount2 = pCmpData->pFaces[j]->GetPointCount(); + + Vector edgePts2[2]; + GetPointFromSurface( pCmpData->pFaces[j], pCmpData->ndxEdges[j], edgePts2[0] ); + GetPointFromSurface( pCmpData->pFaces[j], (pCmpData->ndxEdges[j]+1)%ptCount2, edgePts2[1] ); + + // compare the edges -- return if found + int edgeType1, edgeType2; + if( EdgeCompare( edgePts, edgePts2, edgeType1, edgeType2 ) ) + { + SewEdge_Destroy( pEdgeData ); + return; + } + } + } + + // unique edge -- add it to the list + s_EdgeData.AddToTail( pEdgeData ); +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +bool SewEdge_AddToList( SewEdgeData_t *pEdgeData ) +{ + // if this is a "normal" edge - handle it + if( pEdgeData->type[0] == DISPSEW_EDGE_NORMAL ) + { + SewEdge_AddToListNormal( pEdgeData ); + return true; + } + + // this is a "t-junction" edge - handle it + return SewEdge_AddToListTJunc( pEdgeData ); +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewEdge_Build( void ) +{ + // + // get the "faces" selection list (contains displaced and non-displaced faces) + // + CFaceEditSheet *pSheet = GetMainWnd()->GetFaceEditSheet(); + if( !pSheet ) + return; + + bool bError = false; + + // + // for each face in list + // + int faceCount = pSheet->GetFaceListCount(); + + for( int ndxFace = 0; ndxFace < faceCount; ndxFace++ ) + { + // get the current face + CMapFace *pFace = pSheet->GetFaceListDataFace( ndxFace ); + if( !pFace ) + continue; + + // + // for each face edge + // + int ptCount = pFace->GetPointCount(); + for( int ndxPt = 0; ndxPt < ptCount; ndxPt++ ) + { + // get the current edge points + int type1_keep = 0; + Vector edgePts[2]; + GetPointFromSurface( pFace, ndxPt, edgePts[0] ); + GetPointFromSurface( pFace, (ndxPt+1)%ptCount, edgePts[1] ); + + // allocate new edge + SewEdgeData_t *pEdgeData = SewEdge_Create(); + if( !pEdgeData ) + return; + + // + // compare this edge to all of the other edges on all the other faces in the list + // + for( int ndxFace2 = 0; ndxFace2 < faceCount; ndxFace2++ ) + { + // don't compare to itself + if( ndxFace == ndxFace2 ) + continue; + + // get the current compare face + CMapFace *pFace2 = pSheet->GetFaceListDataFace( ndxFace2 ); + if( !pFace2 ) + continue; + + // + // for each compare face edge + // + int ptCount2 = pFace2->GetPointCount(); + for( int ndxPt2 = 0; ndxPt2 < ptCount2; ndxPt2++ ) + { + // get the current compare edge point + Vector edgePts2[2]; + GetPointFromSurface( pFace2, ndxPt2, edgePts2[0] ); + GetPointFromSurface( pFace2, (ndxPt2+1)%ptCount2, edgePts2[1] ); + + // compare pt1 and pt2 + int type1, type2; + if( EdgeCompare( edgePts, edgePts2, type1, type2 ) ) + { + if (!SewEdge_Add( pEdgeData, pFace2, ndxPt2, type2 )) + { + bError = true; + } + type1_keep = type1; + } + } + } + + // had neighbors -- add base point and add it to corner list + if( pEdgeData->faceCount > 0 ) + { + if (!SewEdge_Add( pEdgeData, pFace, ndxPt, type1_keep )) + { + bError = true; + } + + if (!SewEdge_AddToList( pEdgeData )) + { + bError = true; + } + } + // no neighbors -- de-allocate + else + { + SewEdge_Destroy( pEdgeData ); + } + } + } + + if (bError) + { + 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."); + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewEdge_ResolveDispTJunc( SewEdgeData_t *pEdgeData, int ndxTJ, int ndxTJNeighbor, bool bStart ) +{ + // + // handle displacement sewing to displacement t-junction edge + // + EditDispHandle_t tjEdgeHandle = pEdgeData->pFaces[ndxTJ]->GetDisp(); + EditDispHandle_t edgeHandle = pEdgeData->pFaces[ndxTJNeighbor]->GetDisp(); + if( ( tjEdgeHandle == EDITDISPHANDLE_INVALID ) || ( edgeHandle == EDITDISPHANDLE_INVALID ) ) + return; + + CMapDisp *pTJEdgeDisp = EditDispMgr()->GetDisp( tjEdgeHandle ); + CMapDisp *pEdgeDisp = EditDispMgr()->GetDisp( edgeHandle ); + + // + // get the t-junction edge interval (or half of it) + // + int tjWidth = pTJEdgeDisp->GetWidth(); + int tjInterval = pTJEdgeDisp->GetWidth() / 2; + + // + // get edge interval + // + int edgeWidth = pEdgeDisp->GetWidth(); + int edgeInterval = pEdgeDisp->GetWidth(); + + int ratio = ( edgeInterval - 1 ) / tjInterval; + + bool bFlip = ( ratio < 1 ); + if( bFlip ) + { + ratio = tjInterval / ( edgeInterval - 1 ); + } + + // + // average the "like" points + // + if( bStart ) + { + if( bFlip ) + { + for( int i = 1, j = ratio; i < edgeInterval; i++, j += ratio ) + { + int ndxTJPt, ndxEdgePt; + ndxTJPt = GetEdgePointIndex( pTJEdgeDisp, pEdgeData->ndxEdges[ndxTJ], j, true ); + ndxEdgePt = GetEdgePointIndex( pEdgeDisp, pEdgeData->ndxEdges[ndxTJNeighbor], i, false ); + + // average + AverageVectorFieldData( pEdgeDisp, ndxEdgePt, pTJEdgeDisp, ndxTJPt ); + } + } + else + { + for( int i = 1, j = ratio; i < tjInterval; i++, j += ratio ) + { + int ndxTJPt, ndxEdgePt; + + ndxTJPt = GetEdgePointIndex( pTJEdgeDisp, pEdgeData->ndxEdges[ndxTJ], i, true ); + ndxEdgePt = GetEdgePointIndex( pEdgeDisp, pEdgeData->ndxEdges[ndxTJNeighbor], j, false ); + + // average + AverageVectorFieldData( pEdgeDisp, ndxEdgePt, pTJEdgeDisp, ndxTJPt ); + } + } + } + else + { + if( bFlip ) + { + for( int i = 1, j = ratio; i < edgeWidth; i++, j += ratio ) + { + int ndxTJPt, ndxEdgePt; + ndxTJPt = GetEdgePointIndex( pTJEdgeDisp, pEdgeData->ndxEdges[ndxTJ], j, false ); + ndxEdgePt = GetEdgePointIndex( pEdgeDisp, pEdgeData->ndxEdges[ndxTJNeighbor], i, true ); + + // average + AverageVectorFieldData( pEdgeDisp, ndxEdgePt, pTJEdgeDisp, ndxTJPt ); + } + } + else + { + for( int i = ( tjInterval + 1 ), j = ratio; i < ( tjWidth - 1 ); i++, j += ratio ) + { + int ndxTJPt, ndxEdgePt; + ndxTJPt = GetEdgePointIndex( pTJEdgeDisp, pEdgeData->ndxEdges[ndxTJ], i, true ); + ndxEdgePt = GetEdgePointIndex( pEdgeDisp, pEdgeData->ndxEdges[ndxTJNeighbor], j, false ); + + // average + AverageVectorFieldData( pEdgeDisp, ndxEdgePt, pTJEdgeDisp, ndxTJPt ); + } + } + } + + // + // linearly interpolate the "unlike" points + // + float blendRatio = 1.0f / ratio; + + if( bFlip ) + { + for( int i = 0; i < ( tjWidth - ratio ); i += ratio ) + { + int ndxStart = i; + int ndxEnd = ( i + ratio ); + + int ndxStartPt = GetEdgePointIndex( pTJEdgeDisp, pEdgeData->ndxEdges[ndxTJ], ndxStart, true ); + int ndxEndPt = GetEdgePointIndex( pTJEdgeDisp, pEdgeData->ndxEdges[ndxTJ], ndxEnd, true ); + + for( int j = ( ndxStart + 1 ); j < ndxEnd; j++ ) + { + float blend = blendRatio * ( j - ndxStart ); + + int ndxDst = GetEdgePointIndex( pTJEdgeDisp, pEdgeData->ndxEdges[ndxTJ], j, true ); + + BlendVectorFieldData( pTJEdgeDisp, ndxStartPt, ndxDst, pTJEdgeDisp, ndxEndPt, ndxDst, blend ); + } + } + } + else + { + for( int i = 0; i < ( edgeWidth - ratio ); i += ratio ) + { + int ndxStart = i; + int ndxEnd = ( i + ratio ); + + int ndxStartPt = GetEdgePointIndex( pEdgeDisp, pEdgeData->ndxEdges[ndxTJNeighbor], ndxStart, true ); + int ndxEndPt = GetEdgePointIndex( pEdgeDisp, pEdgeData->ndxEdges[ndxTJNeighbor], ndxEnd, true ); + + for( int j = ( ndxStart + 1 ); j < ndxEnd; j++ ) + { + float blend = blendRatio * ( j - ndxStart ); + + int ndxDst = GetEdgePointIndex( pEdgeDisp, pEdgeData->ndxEdges[ndxTJNeighbor], j, true ); + + BlendVectorFieldData( pEdgeDisp, ndxStartPt, ndxDst, pEdgeDisp, ndxEndPt, ndxDst, blend ); + } + } + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewEdge_ResolveSolidTJunc( SewEdgeData_t *pEdgeData, int type, bool bStart ) +{ + // create an empty vector to reset the offset with + Vector vClear( 0.0f, 0.0f, 0.0f ); + + for( int i = 0; i < pEdgeData->faceCount; i++ ) + { + if( pEdgeData->type[i] != type ) + continue; + + // get the displacement surface associated with the face + EditDispHandle_t dispHandle = pEdgeData->pFaces[i]->GetDisp(); + if( dispHandle == EDITDISPHANDLE_INVALID ) + continue; + + CMapDisp *pDisp = EditDispMgr()->GetDisp( dispHandle ); + + // get surface normal, to reset vector field to base state + Vector vNormal; + pDisp->GetSurfNormal( vNormal ); + + // reset tjstart and tjend + if( type != DISPSEW_EDGE_TJ ) + { + // + // for all points along the edge -- reset + // + int width = pDisp->GetWidth(); + for( int j = 1; j < ( width - 1 ); j++ ) + { + // get the edge point index + int ndxPt = GetEdgePointIndex( pDisp, pEdgeData->ndxEdges[i], j, true ); + if( ndxPt == -1 ) + continue; + + // + // reset displacement data (dist, field vector, and offset vector) + // + pDisp->SetFieldDistance( ndxPt, 0.0f ); + pDisp->SetFieldVector( ndxPt, vNormal ); + pDisp->SetSubdivPosition( ndxPt, vClear ); + pDisp->SetSubdivNormal( ndxPt, vNormal ); + pDisp->SetAlpha( ndxPt, 0.0f ); + } + } + // reset tj (upper and lower) + else + { + // + // for all points along the edge -- reset + // + int width = pDisp->GetWidth(); + int widthDiv2 = width / 2; + + if( bStart ) + { + for( int j = 1; j < widthDiv2; j++ ) + { + // get the edge point index + int ndxPt = GetEdgePointIndex( pDisp, pEdgeData->ndxEdges[i], j, true ); + if( ndxPt == -1 ) + continue; + + // + // reset displacement data (dist, field vector, and offset vector) + // + pDisp->SetFieldDistance( ndxPt, 0.0f ); + pDisp->SetFieldVector( ndxPt, vNormal ); + pDisp->SetSubdivPosition( ndxPt, vClear ); + pDisp->SetSubdivNormal( ndxPt, vNormal ); + pDisp->SetAlpha( ndxPt, 0.0f ); + } + } + else + { + for( int j = ( widthDiv2 + 1 ); j < ( width - 1 ); j++ ) + { + // get the edge point index + int ndxPt = GetEdgePointIndex( pDisp, pEdgeData->ndxEdges[i], j, true ); + if( ndxPt == -1 ) + continue; + + // + // reset displacement data (dist, field vector, and offset vector) + // + pDisp->SetFieldDistance( ndxPt, 0.0f ); + pDisp->SetFieldVector( ndxPt, vNormal ); + pDisp->SetSubdivPosition( ndxPt, vClear ); + pDisp->SetSubdivNormal( ndxPt, vNormal ); + pDisp->SetAlpha( ndxPt, 0.0f ); + } + } + } + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewEdge_ResolveDispNormal( SewEdgeData_t *pEdgeData ) +{ + // + // get displacement surfaces -- if any + // + EditDispHandle_t handle1 = pEdgeData->pFaces[0]->GetDisp(); + EditDispHandle_t handle2 = pEdgeData->pFaces[1]->GetDisp(); + if( ( handle1 == EDITDISPHANDLE_INVALID ) || ( handle2 == EDITDISPHANDLE_INVALID ) ) + return; + + CMapDisp *pEdgeDisp1 = EditDispMgr()->GetDisp( handle1 ); + CMapDisp *pEdgeDisp2 = EditDispMgr()->GetDisp( handle2 ); + + // + // sew displacement edges + // + + // + // find displacement with smallest/largest interval + // + CMapDisp *pSmDisp, *pLgDisp; + int smInterval, lgInterval; + int ndxSmEdge, ndxLgEdge; + + if( pEdgeDisp1->GetWidth() > pEdgeDisp2->GetWidth() ) + { + pSmDisp = pEdgeDisp2; + ndxSmEdge = pEdgeData->ndxEdges[1]; + smInterval = pEdgeDisp2->GetWidth(); + + pLgDisp = pEdgeDisp1; + ndxLgEdge = pEdgeData->ndxEdges[0]; + lgInterval = pEdgeDisp1->GetWidth(); + } + else + { + pSmDisp = pEdgeDisp1; + ndxSmEdge = pEdgeData->ndxEdges[0]; + smInterval = pEdgeDisp1->GetWidth(); + + pLgDisp = pEdgeDisp2; + ndxLgEdge = pEdgeData->ndxEdges[1]; + lgInterval = pEdgeDisp2->GetWidth(); + } + + // calculate the ratio + int ratio = ( lgInterval - 1 ) / ( smInterval - 1 ); + + // + // average "like" points + // + for( int ndxSm = 1, ndxLg = ratio; ndxSm < ( smInterval - 1 ); ndxSm++, ndxLg += ratio ) + { + int ndxSmPt = GetEdgePointIndex( pSmDisp, ndxSmEdge, ndxSm, true ); + int ndxLgPt = GetEdgePointIndex( pLgDisp, ndxLgEdge, ndxLg, false ); + + // average + AverageVectorFieldData( pSmDisp, ndxSmPt, pLgDisp, ndxLgPt ); + } + + // + // linearly interpolate the "unlike" points + // + float blendRatio = 1.0f / ratio; + + for( int ndxLg = 0; ndxLg < ( lgInterval - 1 ); ndxLg += ratio ) + { + int ndxStart = ndxLg; + int ndxEnd = ( ndxLg + ratio ); + + int ndxStartPt = GetEdgePointIndex( pLgDisp, ndxLgEdge, ndxStart, true ); + int ndxEndPt = GetEdgePointIndex( pLgDisp, ndxLgEdge, ndxEnd, true ); + + for( int ndx = ( ndxStart + 1 ); ndx < ndxEnd; ndx++ ) + { + float blend = blendRatio * ( ndx - ndxStart ); + int ndxDst = GetEdgePointIndex( pLgDisp, ndxLgEdge, ndx, true ); + BlendVectorFieldData( pLgDisp, ndxStartPt, ndxDst, pLgDisp, ndxEndPt, ndxDst, blend ); + } + } +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewEdge_ResolveSolidNormal( SewEdgeData_t *pEdgeData ) +{ + // create an empty vector to reset the offset with + Vector vClear( 0.0f, 0.0f, 0.0f ); + + for( int i = 0; i < pEdgeData->faceCount; i++ ) + { + // get the displacement surface associated with the face + EditDispHandle_t handle = pEdgeData->pFaces[i]->GetDisp(); + if( handle == EDITDISPHANDLE_INVALID ) + continue; + + CMapDisp *pDisp = EditDispMgr()->GetDisp( handle ); + + // get surface normal, to reset vector field to base state + Vector vNormal; + pDisp->GetSurfNormal( vNormal ); + + // + // for all points along the edge -- reset + // + int width = pDisp->GetWidth(); + for( int j = 0; j < width; j++ ) + { + // get the edge point index + int ndxPt = GetEdgePointIndex( pDisp, pEdgeData->ndxEdges[i], j, true ); + if( ndxPt == -1 ) + continue; + + // + // reset displacement data (dist, field vector, and offset vector) + // + pDisp->SetFieldDistance( ndxPt, 0.0f ); + pDisp->SetFieldVector( ndxPt, vClear ); + pDisp->SetSubdivPosition( ndxPt, vClear ); + pDisp->SetSubdivNormal( ndxPt, vNormal ); + pDisp->SetAlpha( ndxPt, 0.0f ); + } + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SewEdge_Resolve( void ) +{ + // get the number of edges in the edge list + int edgeCount = s_EdgeData.Size(); + + // resolve each edge + for( int i = 0; i < edgeCount; i++ ) + { + // get the current edge data struct + SewEdgeData_t *pEdgeData = s_EdgeData.Element( i ); + if( !pEdgeData ) + continue; + + // handle "normal" edge + if( pEdgeData->type[0] == DISPSEW_EDGE_NORMAL ) + { + // solid "normal" edge + if( SewEdge_IsSolidNormal( pEdgeData ) ) + { + SewEdge_ResolveSolidNormal( pEdgeData ); + } + // disps "normal" edge + else + { + SewEdge_ResolveDispNormal( pEdgeData ); + } + } + // handle "t-junction" edge + else + { + int ndxTJ = SewEdge_TJIndex( pEdgeData, DISPSEW_EDGE_TJ ); + int ndxTJStart = SewEdge_TJIndex( pEdgeData, DISPSEW_EDGE_TJSTART ); + int ndxTJEnd = SewEdge_TJIndex( pEdgeData, DISPSEW_EDGE_TJEND ); + + if( SewEdge_IsSolidTJunc( pEdgeData, DISPSEW_EDGE_TJ ) ) + { + // reset both start and end t-junction edges if they exist + if( ndxTJStart != -1 ) + { + SewEdge_ResolveSolidTJunc( pEdgeData, DISPSEW_EDGE_TJSTART, false ); + } + + if( ndxTJEnd != -1 ) + { + SewEdge_ResolveSolidTJunc( pEdgeData, DISPSEW_EDGE_TJEND, false ); + } + + continue; + } + + // handle start edge + if( ndxTJStart != -1 ) + { + if( SewEdge_IsSolidTJunc( pEdgeData, DISPSEW_EDGE_TJSTART ) ) + { + SewEdge_ResolveSolidTJunc( pEdgeData, DISPSEW_EDGE_TJ, true ); + } + else + { + SewEdge_ResolveDispTJunc( pEdgeData, ndxTJ, ndxTJStart, true ); + } + } + + // handle end edge + if( ndxTJEnd != -1 ) + { + if( SewEdge_IsSolidTJunc( pEdgeData, DISPSEW_EDGE_TJEND ) ) + { + SewEdge_ResolveSolidTJunc( pEdgeData, DISPSEW_EDGE_TJ, false ); + } + else + { + SewEdge_ResolveDispTJunc( pEdgeData, ndxTJ, ndxTJEnd, false ); + } + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Convert the edge/midpoint/corner data for shared code, +//----------------------------------------------------------------------------- +bool PrePlanarizeDependentVerts( void ) +{ + // Create a list of all the selected displacement cores. + CFaceEditSheet *pSheet = GetMainWnd()->GetFaceEditSheet(); + if( !pSheet ) + return false; + + int nFaceCount = pSheet->GetFaceListCount(); + for( int iFace = 0; iFace < nFaceCount; ++iFace ) + { + CMapFace *pFace = pSheet->GetFaceListDataFace( iFace ); + if( !pFace || !pFace->HasDisp() ) + continue; + + CMapDisp *pDisp = EditDispMgr()->GetDisp( pFace->GetDisp() ); + Assert( pDisp ); + + int iDisp = m_aCoreDispInfos.AddToTail(); + pDisp->GetCoreDispInfo()->SetListIndex( iDisp ); + m_aCoreDispInfos[iDisp] = pDisp->GetCoreDispInfo(); + } + + // Add the list to the displacements -- this is a bit hacky!! + for ( int iDisp = 0; iDisp < m_aCoreDispInfos.Count(); ++iDisp ) + { + m_aCoreDispInfos[iDisp]->SetDispUtilsHelperInfo( m_aCoreDispInfos.Base(), m_aCoreDispInfos.Count() ); + } + + // Build neighboring info. + FindNeighboringDispSurfs( m_aCoreDispInfos.Base(), m_aCoreDispInfos.Count() ); + + return true; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +class CHammerTesselateHelper : public CBaseTesselateHelper +{ +public: + + void EndTriangle() + { + m_pIndices->AddToTail( m_TempIndices[0] ); + m_pIndices->AddToTail( m_TempIndices[1] ); + m_pIndices->AddToTail( m_TempIndices[2] ); + } + + DispNodeInfo_t& GetNodeInfo( int iNodeBit ) + { + // Hammer doesn't care about these. Give it back something to play with. + static DispNodeInfo_t dummy; + return dummy; + } + +public: + + CUtlVector<unsigned short> *m_pIndices; +}; + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +bool FindEnclosingTri( const Vector2D &vert, CUtlVector<Vector2D> &vertCoords, + CUtlVector<unsigned short> &indices, int *pStartVert, + float bcCoords[3] ) +{ + for ( int i = 0; i < indices.Count(); i += 3 ) + { + GetBarycentricCoords2D( vertCoords[indices[i+0]], + vertCoords[indices[i+1]], + vertCoords[indices[i+2]], + vert, bcCoords ); + + if ( bcCoords[0] >= 0 && bcCoords[0] <= 1 && + bcCoords[1] >= 0 && bcCoords[1] <= 1 && + bcCoords[2] >= 0 && bcCoords[2] <= 1 ) + { + *pStartVert = i; + return true; + } + } + + return false; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void SnapDependentVertsToSurface( CCoreDispInfo *pCoreDisp ) +{ + // Don't really want to do this, but....... + CUtlVector<unsigned short> indices; + CHammerTesselateHelper helper; + helper.m_pIndices = &indices; + helper.m_pActiveVerts = pCoreDisp->GetAllowedVerts().Base(); + helper.m_pPowerInfo = pCoreDisp->GetPowerInfo(); + TesselateDisplacement( &helper ); + + // Find allowed/non-allowed verts. + CUtlVector<bool> vertsTouched; + vertsTouched.SetSize( pCoreDisp->GetSize() ); + memset( vertsTouched.Base(), 0, sizeof( bool ) * vertsTouched.Count() ); + for ( int iVert = 0; iVert < indices.Count(); ++iVert ) + { + vertsTouched[indices[iVert]] = true; + } + + // Generate 2D floating point coordinates for each vertex. We use these to generate + // barycentric coordinates, and the scale doesn't matter. + CUtlVector<Vector2D> vertCoords; + vertCoords.SetSize( pCoreDisp->GetSize() ); + for ( int iHgt = 0; iHgt < pCoreDisp->GetHeight(); ++iHgt ) + { + for ( int iWid = 0; iWid < pCoreDisp->GetWidth(); ++iWid ) + { + vertCoords[iHgt*pCoreDisp->GetWidth()+iWid].Init( iWid, iHgt ); + } + } + + // Now, for each vert not touched, snap its position to the main surface. + for ( int iHgt = 0; iHgt < pCoreDisp->GetHeight(); ++iHgt ) + { + for ( int iWid = 0; iWid < pCoreDisp->GetWidth(); ++iWid ) + { + int nIndex = iHgt * pCoreDisp->GetWidth() + iWid; + if ( !( vertsTouched[nIndex] ) ) + { + float flBCoords[3]; + int iStartVert = -1; + + if ( FindEnclosingTri( vertCoords[nIndex], vertCoords, indices, &iStartVert, flBCoords ) ) + { + const Vector &A = pCoreDisp->GetVert( indices[iStartVert+0] ); + const Vector &B = pCoreDisp->GetVert( indices[iStartVert+1] ); + const Vector &C = pCoreDisp->GetVert( indices[iStartVert+2] ); + Vector vNewPos = A*flBCoords[0] + B*flBCoords[1] + C*flBCoords[2]; + + // Modify the CCoreDispInfo vert (although it probably won't be used later). + pCoreDisp->Position_Update( nIndex, vNewPos ); + } + else + { + // This shouldn't happen because it would mean that the triangulation that + // disp_tesselation.h produced was missing a chunk of the space that the + // displacement covers. + // It also could indicate a floating-point epsilon error.. check to see if + // FindEnclosingTri finds a triangle that -almost- encloses the vert. + Assert( false ); + } + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Get allowed verts bits and planarize cleared verts and purge disp +// infos. +//----------------------------------------------------------------------------- +void PostPlanarizeDependentVerts( void ) +{ + // Snap dependents verts to the displacement surface. + for ( int iDispCore = 0; iDispCore < m_aCoreDispInfos.Count(); ++iDispCore ) + { + SnapDependentVertsToSurface( m_aCoreDispInfos[iDispCore] ); + } + + // Clear out the displacement info list. + m_aCoreDispInfos.Purge(); +} + +//----------------------------------------------------------------------------- +// Purpose: Planarize vertices that are removed because of dependencies with +// neighboring displacements. +//----------------------------------------------------------------------------- +void PlanarizeDependentVerts( void ) +{ + // Setup. + if ( !PrePlanarizeDependentVerts() ) + return; + + SetupAllowedVerts( m_aCoreDispInfos.Base(), m_aCoreDispInfos.Count() ); + + // Update and clean-up. + PostPlanarizeDependentVerts(); +} |