⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mesh.h

📁 游戏编程精粹2第四章源码
💻 H
📖 第 1 页 / 共 4 页
字号:
	}
#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 + -