📄 mesh.h
字号:
}
#endif
*(TriList.AddItem()) = pTri;
}
inline void MeshPt::AddEdge ( MeshEdge *pEdge )
{
ASSERT ( pEdge != NULL );
#ifdef DEBUG
// Make sure this hasn't been added already.
int i;
MeshEdge **ppEdgeList = EdgeList.Ptr();
for ( i = 0; i < EdgeList.Size(); i++ )
{
ASSERT ( ppEdgeList[i] != NULL );
ASSERT ( ppEdgeList[i] != pEdge );
}
#endif
*(EdgeList.AddItem()) = pEdge;
}
inline MeshEdge *MeshPt::FindEdge ( MeshPt *pPt )
{
ASSERT ( pPt != NULL );
ASSERT ( pPt != this );
MeshEdge **ppEdgeList = EdgeList.Ptr();
int i;
for ( i = 0; i < EdgeList.Size(); i++ )
{
MeshEdge *pEdge = ppEdgeList[i];
ASSERT ( pEdge != NULL );
ASSERT ( ( pEdge->pPt1 == this ) || ( pEdge->pPt2 == this ) );
if ( pEdge->pPt2 == pPt )
{
ASSERT ( pEdge->pPt1 == this );
return ( pEdge );
}
if ( pEdge->pPt1 == pPt )
{
ASSERT ( pEdge->pPt2 == this );
return ( pEdge );
}
}
return ( NULL );
}
// Find the first edge that uses this pt and the other given, and
// also has a free triangle entry, assuming that the points are
// used in that clockwise order. This allows two edges that share
// the same points to exist, e.g. where multiple triangles share
// the same edge (think of the diagonal of the tris of a back-to-back
// quad - same edge, four tris.
// The tri will use the points in the order *this,*pPt.
inline MeshEdge *MeshPt::FindTriEdge ( MeshPt *pPt )
{
ASSERT ( pPt != NULL );
ASSERT ( pPt != this );
MeshEdge **ppEdgeList = EdgeList.Ptr();
int i;
for ( i = 0; i < EdgeList.Size(); i++ )
{
MeshEdge *pEdge = ppEdgeList[i];
ASSERT ( pEdge != NULL );
ASSERT ( ( pEdge->pPt1 == this ) || ( pEdge->pPt2 == this ) );
if ( pEdge->pPt2 == pPt )
{
ASSERT ( pEdge->pPt1 == this );
// Check that it would be possible to add a tri to this.
// The tri will use this,pPt in that order, so must be in
// pTri12
if ( pEdge->pTri12 == NULL )
{
return ( pEdge );
}
else
{
int bogus = 0;
}
}
if ( pEdge->pPt1 == pPt )
{
ASSERT ( pEdge->pPt2 == this );
// Check that it would be possible to add a tri to this.
// The tri will use this,pPt in that order, so must be in
// pTri21
if ( pEdge->pTri21 == NULL )
{
return ( pEdge );
}
else
{
int bogus = 0;
}
}
}
return ( NULL );
}
inline MeshTri *MeshPt::FindTri ( MeshPt *pPt1, MeshPt *pPt2 )
{
ASSERT ( pPt1 != NULL );
ASSERT ( pPt2 != NULL );
MeshTri **ppTriList = TriList.Ptr();
int i;
for ( i = 0; i < TriList.Size(); i++ )
{
MeshTri *pTri = ppTriList[i];
ASSERT ( pTri != NULL );
ASSERT ( ( pTri->pPt1 == this ) || ( pTri->pPt2 == this ) || ( pTri->pPt3 == this ) );
if ( ( pTri->pPt1 == this ) && ( pTri->pPt2 == pPt1 ) && ( pTri->pPt3 == pPt2 ) )
{
return ( pTri );
}
if ( ( pTri->pPt2 == this ) && ( pTri->pPt3 == pPt1 ) && ( pTri->pPt1 == pPt2 ) )
{
return ( pTri );
}
if ( ( pTri->pPt3 == this ) && ( pTri->pPt1 == pPt1 ) && ( pTri->pPt2 == pPt2 ) )
{
return ( pTri );
}
}
return ( NULL );
}
// Return the next tri in the list.
// If a non-NULL pPt is supplied, only tris using this,pPt in that order
// are returned, otherwise all tris are returned.
inline MeshTri *MeshPt::NextTri ( MeshPt *pPt )
{
ASSERT ( this != pPt );
ASSERT ( iCurTriNum >= 0 );
while ( TRUE )
{
if ( iCurTriNum < TriList.Size() )
{
MeshTri *pTri = (TriList.Ptr())[iCurTriNum++];
ASSERT ( pTri != NULL );
if ( pPt == NULL )
{
// Return all tris.
return ( pTri );
}
// Return only tris that use this,pPt
if ( ( ( pTri->pPt1 == this ) && ( pTri->pPt2 == pPt ) ) ||
( ( pTri->pPt2 == this ) && ( pTri->pPt3 == pPt ) ) ||
( ( pTri->pPt3 == this ) && ( pTri->pPt1 == pPt ) ) )
{
return ( pTri );
}
}
else
{
// End of the list.
iCurTriNum = -1;
return ( NULL );
}
}
}
// Return the first tri in the list. MUST be called before calling NextTri().
// If a non-NULL pPt is supplied, only tris using this,pPt in that order
// are returned, otherwise all tris are returned.
inline MeshTri *MeshPt::FirstTri ( MeshPt *pPt )
{
ASSERT ( iCurTriNum == -1 );
iCurTriNum = 0;
return ( NextTri ( pPt ) );
}
// Terminate the current First/Next loop.
inline void MeshPt::EndTri ( void )
{
iCurTriNum = -1;
}
// Return the next Edge in the list.
// If a non-NULL pPt is supplied, only edges using this and pPt
// are returned, otherwise all edges are returned.
inline MeshEdge *MeshPt::NextEdge ( MeshPt *pPt )
{
ASSERT ( this != pPt );
ASSERT ( iCurEdgeNum >= 0 );
while ( TRUE )
{
if ( iCurEdgeNum < EdgeList.Size() )
{
MeshEdge *pEdge = (EdgeList.Ptr())[iCurEdgeNum++];
ASSERT ( pEdge != NULL );
if ( pPt == NULL )
{
// Return all edges.
return ( pEdge );
}
// Return only the edges the use this & pPt.
if ( ( pEdge->pPt1 == pPt ) || ( pEdge->pPt2 == pPt ) )
{
ASSERT ( ( pEdge->pPt1 == this ) || ( pEdge->pPt2 == this ) );
return ( pEdge );
}
}
else
{
// End of the list.
iCurEdgeNum = -1;
return ( NULL );
}
}
}
// Return the first Edge in the list. MUST be called before calling NextEdge().
// If a non-NULL pPt is supplied, only edges using this and pPt
// are returned, otherwise all edges are returned.
inline MeshEdge *MeshPt::FirstEdge ( MeshPt *pPt )
{
ASSERT ( iCurEdgeNum == -1 );
iCurEdgeNum = 0;
return ( NextEdge ( pPt ) );
}
// Terminate the current First/Next loop.
inline void MeshPt::EndEdge ( void )
{
iCurEdgeNum = -1;
}
// Returns TRUE if the two pts are marked as being in proximity.
inline bool MeshPt::CheckProx ( MeshPt *pPt )
{
ASSERT ( pPt != NULL );
MeshPt **ppPt = ProxPtList.Ptr();
for ( int i = 0; i < ProxPtList.Size(); i++ )
{
ASSERT ( ppPt[i] != NULL );
if ( ppPt[i] == pPt )
{
// Yes.
return ( TRUE );
}
}
return ( FALSE );
}
// Add the given pt to the prox list (and vice versa).
// If the pt was not already there, returns TRUE;
// If bProxEdges is set to TRUE (default is FALSE ),
// the edges that these two pts use are made prox if possible.
inline bool MeshPt::AddProx ( MeshPt *pPt, bool bProxEdges )
{
bool bRes;
ASSERT ( pPt != NULL );
if ( CheckProx ( pPt ) )
{
// Already prox.
ASSERT ( pPt->CheckProx ( this ) );
bRes = FALSE;
}
else
{
ASSERT ( !pPt->CheckProx ( this ) );
// Add to this pt.
*(ProxPtList.AddItem()) = pPt;
// Add to the other pt.
*(pPt->ProxPtList.AddItem()) = this;
bRes = TRUE;
}
// Now check all their edges for proximity.
// For each edge of this.
// Find other pt and scan proxs of that.
// If those proxes form and edge with pPt, the edges are prox.
MeshEdge *pedge = FirstEdge();
while ( pedge != NULL )
{
MeshPt *pptOther = pedge->OtherPt ( this );
MeshPt **ppPt = pptOther->ProxPtList.Ptr();
for ( int i = 0; i < pptOther->ProxPtList.Size(); i++ )
{
ASSERT ( ppPt[i] != NULL );
MeshEdge *pedgeProx = pPt->FindEdge ( ppPt[i] );
if ( pedgeProx != NULL )
{
bool bRes = pedgeProx->AddProx ( pedge );
ASSERT ( bRes );
break;
}
}
pedge = NextEdge();
}
return ( bRes );
}
// Remove the given pt from the prox list (and vice versa).
// If the pt was there, returns TRUE.
inline bool MeshPt::RemoveProx ( MeshPt *pPt )
{
ASSERT ( pPt != NULL );
if ( CheckProx ( pPt ) )
{
// Yep, they are prox.
ASSERT ( pPt->CheckProx ( this ) );
MeshPt **ppPtList;
int i;
// Remove pPt from this.
ppPtList = ProxPtList.Ptr();
for ( i = 0; i < ProxPtList.Size(); i++ )
{
if ( ppPtList[i] == pPt )
{
break;
}
}
ASSERT ( i < ProxPtList.Size() );
// Replace this entry with the last entry.
ProxPtList.RemoveItem(i);
// Remove this from pPt.
ppPtList = pPt->ProxPtList.Ptr();
for ( i = 0; i < pPt->ProxPtList.Size(); i++ )
{
if ( ppPtList[i] == this )
{
break;
}
}
ASSERT ( i < pPt->ProxPtList.Size() );
// Replace this entry with the last entry.
ProxPtList.RemoveItem(i);
return ( TRUE );
}
else
{
// No, they're not prox.
ASSERT ( !pPt->CheckProx ( this ) );
return ( FALSE );
}
}
// Return the first prox pt. MUST be called before calling NextProx().
inline MeshPt *MeshPt::FirstProx ( void )
{
ASSERT ( iCurProxNum == -1 );
iCurProxNum = 0;
return ( NextProx() );
}
// Return the next prox pt.
inline MeshPt *MeshPt::NextProx ( void )
{
ASSERT ( iCurProxNum >= 0 );
while ( TRUE )
{
if ( iCurProxNum < ProxPtList.Size() )
{
MeshPt *pptProx = (ProxPtList.Ptr())[iCurProxNum++];
ASSERT ( pptProx != NULL );
return ( pptProx );
}
else
{
// End of the list.
iCurProxNum = -1;
return ( NULL );
}
}
}
// Terminate the current First/Next loop.
inline void MeshPt::EndProx ( void )
{
iCurProxNum = -1;
}
inline MeshPt *MeshPt::QueryList ( void )
{
MeshPt *pListRoot = ListFindFirst();
if ( pListRoot == this )
{
ASSERT ( ListFindLast() == this );
pListRoot = NULL;
}
return ( pListRoot );
}
inline void MeshPt::SetList ( MeshPt *pListRoot )
{
ListDel();
if ( pListRoot != NULL )
{
ListAddAfter ( pListRoot );
}
}
inline bool MeshPt::ConsistencyCheck ( MeshPt *pPtRoot, MeshEdge *pEdgeRoot, MeshTri *pTriRoot )
{
bool bRes = TRUE;
if ( ( pPtRoot != NULL ) && ( QueryList() != pPtRoot ) )
{
FAIL_CHECK();
}
// Check prox.
MeshPt **ppPt = ProxPtList.Ptr();
for ( int i = 0; i < ProxPtList.Size(); i++ )
{
ASSERT ( ppPt[i] != NULL );
if ( !ppPt[i]->CheckProx ( this ) )
{
FAIL_CHECK();
}
if ( ( pPtRoot != NULL ) && ( ppPt[i]->QueryList() != pPtRoot ) )
{
FAIL_CHECK();
}
}
// Just check the consistency of all tris and edges that use this.
MeshEdge *pEdge = FirstEdge();
while ( pEdge != NULL )
{
if ( !pEdge->ConsistencyCheck ( pPtRoot, pEdgeRoot, pTriRoot ) )
{
// Will have already ASSERTed.
bRes = FALSE;
}
pEdge = NextEdge();
}
MeshTri *pTri = FirstTri();
while ( pTri != NULL )
{
if ( !pTri->ConsistencyCheck ( pPtRoot, pEdgeRoot, pTriRoot ) )
{
// Will have already ASSERTed.
bRes = FALSE;
}
pTri = NextTri();
}
return ( bRes );
}
#if 0
// Provides consistent typesafe access to the pMore field of the objects.
// Set them up like this:
//
// MESHPT_PMORE_SET(D3DVERTEX,D3DVert);
//
// And use them like this:
//
// D3DVERTEX *pVert = D3DVert(pPt);
//
// or this:
//
// D3DVert(pPt) = pVert;
#define MESHPT_PMORE_SET(mytype,accessname) \
mytype *accessname ( MeshPt *pPt ) \
{ \
return ( (mytype *)( pPt->pMore ) ); \
}
#define MESHEDGE_PMORE_SET(mytype,accessname) \
mytype *accessname ( MeshEdge *pEdge ) \
{ \
return ( (mytype *)( pEdge->pMore ) ); \
}
#define MESHTRI_PMORE_SET(mytype,accessname) \
mytype *accessname ( MeshTri *pTri ) \
{ \
return ( (mytype *)( pTri->pMore ) ); \
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -