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

📄 mesh.h

📁 游戏编程精粹2第四章源码
💻 H
📖 第 1 页 / 共 4 页
字号:
				ASSERT ( pEdgeProx->pEdgeProx == pedge );
				pEdgeProx->pEdgeProx = this;
				pedge->pEdgeProx = NULL;
			}
			return TRUE;
		}
		else if ( ( pTri21 == NULL ) && ( pedge->pTri12 == NULL ) &&
				  ( ( pEdgeProx == NULL ) || ( pedge->pEdgeProx == NULL ) ) )
		{
			// Merge them.
			pTri21 = pedge->pTri21;
			if ( pTri21 != NULL )
			{
				if ( pTri21->pEdge12 == pedge )
				{
					pTri21->pEdge12 = this;
				}
				else if ( pTri21->pEdge23 == pedge )
				{
					pTri21->pEdge23 = this;
				}
				else
				{
					ASSERT ( pTri21->pEdge31 == pedge );
					pTri21->pEdge31 = this;
				}
			}
			pedge->pTri21 = NULL;
			if ( pedge->pEdgeProx != NULL )
			{
				ASSERT ( pEdgeProx == NULL );
				pEdgeProx = pedge->pEdgeProx;
				ASSERT ( pEdgeProx->pEdgeProx == pedge );
				pEdgeProx->pEdgeProx = this;
				pedge->pEdgeProx = NULL;
			}
			return TRUE;
		}
		else
		{
			// Nope - they don't match.
			return ( FALSE );
		}
	}
	else
	{
		ASSERT ( pPt1 == pedge->pPt2 );
		ASSERT ( pPt2 == pedge->pPt1 );
		if ( ( pTri12 == NULL ) && ( pedge->pTri12 == NULL ) &&
			 ( ( pEdgeProx == NULL ) || ( pedge->pEdgeProx == NULL ) ) )
		{
			// Merge them.
			pTri12 = pedge->pTri21;
			if ( pTri12 != NULL )
			{
				if ( pTri12->pEdge12 == pedge )
				{
					pTri12->pEdge12 = this;
				}
				else if ( pTri12->pEdge23 == pedge )
				{
					pTri12->pEdge23 = this;
				}
				else
				{
					ASSERT ( pTri12->pEdge31 == pedge );
					pTri12->pEdge31 = this;
				}
			}
			pedge->pTri21 = NULL;
			if ( pedge->pEdgeProx != NULL )
			{
				ASSERT ( pEdgeProx == NULL );
				pEdgeProx = pedge->pEdgeProx;
				ASSERT ( pEdgeProx->pEdgeProx == pedge );
				pEdgeProx->pEdgeProx = this;
				pedge->pEdgeProx = NULL;
			}
			return TRUE;
		}
		else if ( ( pTri21 == NULL ) && ( pedge->pTri21 == NULL ) &&
				  ( ( pEdgeProx == NULL ) || ( pedge->pEdgeProx == NULL ) ) )
		{
			// Merge them.
			pTri21 = pedge->pTri12;
			if ( pTri21 != NULL )
			{
				if ( pTri21->pEdge12 == pedge )
				{
					pTri21->pEdge12 = this;
				}
				else if ( pTri21->pEdge23 == pedge )
				{
					pTri21->pEdge23 = this;
				}
				else
				{
					ASSERT ( pTri21->pEdge31 == pedge );
					pTri21->pEdge31 = this;
				}
			}
			pedge->pTri12 = NULL;
			if ( pedge->pEdgeProx != NULL )
			{
				ASSERT ( pEdgeProx == NULL );
				pEdgeProx = pedge->pEdgeProx;
				ASSERT ( pEdgeProx->pEdgeProx == pedge );
				pEdgeProx->pEdgeProx = this;
				pedge->pEdgeProx = NULL;
			}
			return TRUE;
		}
		else
		{
			// Nope - they don't match.
			return ( FALSE );
		}
	}
}


inline MeshEdge *MeshEdge::QueryList ( void )
{
	MeshEdge *pListRoot = ListFindFirst();
	if ( pListRoot == this )
	{
		ASSERT ( ListFindLast() == this );
		pListRoot = NULL;
	}
	return ( pListRoot );
}

inline void MeshEdge::SetList ( MeshEdge *pListRoot )
{
	ListDel();
	if ( pListRoot != NULL )
	{
		ListAddAfter ( pListRoot );
	}
}




// Makes these two edges prox.
// The point prox data must agree.
// Returns TRUE on success, or FALSE if it failed.
inline bool MeshEdge::AddProx ( MeshEdge *pEdge )
{
	ASSERT ( pEdge != NULL );
	if ( pEdgeProx != NULL )
	{
		// Already got prox.
		return ( FALSE );
	}
	else if ( pEdge->pEdgeProx != NULL )
	{
		// Already got prox.
		return ( FALSE );
	}
	else
	{
		// Check that the pts agree.
		// Either pPt1<->pPt1 and pPt2<->pPt2, or the other way round.
		if ( pEdge->pPt1->CheckProx ( pPt1 ) )
		{
			if ( !pEdge->pPt2->CheckProx ( pPt2 ) )
			{
				return ( FALSE );
			}
		}
		else if ( pEdge->pPt1->CheckProx ( pPt2 ) )
		{
			if ( !pEdge->pPt2->CheckProx ( pPt1 ) )
			{
				return ( FALSE );
			}
		}
		else
		{
			return ( FALSE );
		}

		// OK, must have passed.
		pEdgeProx = pEdge;
		pEdge->pEdgeProx = this;
		return ( TRUE );
	}
}

// Find the proximity edge, if any.
// Relies on the point proximity values having been set up.
// If one is found, it is returned.
inline MeshEdge *MeshEdge::DoProxMatch ( void )
{
	// Loop through all the prox pts to pPt1
	//		Loop through all their edges.
	//			If the other pt is prox to pPt2, then we found a prox edge.
	int i;
	MeshPt **ppPt = pPt1->ProxPtList.Ptr();
	for ( i = 0; i < pPt1->ProxPtList.Size(); i++ )
	{
		MeshPt *pPtProx = ppPt[i];
		ASSERT ( pPtProx != NULL );

		MeshEdge *pEdgeOther = pPtProx->FirstEdge();
		while ( pEdgeOther != NULL )
		{
			MeshPt *pPtOther = pEdgeOther->OtherPt ( pPtProx );
			if ( pPtOther->CheckProx ( pPt2 ) )
			{
				// Yes - this is prox.
				bool bRes = AddProx ( pEdgeOther );
				if ( bRes )
				{
					pPtProx->EndEdge();
					return pEdgeOther;
				}
				else
				{
					// Too many edges trying to be prox!
					pPtProx->EndEdge();
					return NULL;
				}
			}

			pEdgeOther = pPtProx->NextEdge();
		}
	}
	return NULL;
}

// Removes any edge prox data.
// Returns TRUE if there was some.
// The pt prox data can still agree - it is not touched.
inline bool MeshEdge::RemoveProx ( void )
{
	if ( pEdgeProx == NULL )
	{
		return ( FALSE );
	}
	else
	{
		ASSERT ( pEdgeProx->pEdgeProx == this );
		pEdgeProx->pEdgeProx = NULL;
		pEdgeProx = NULL;
		return ( TRUE );
	}
}





inline bool MeshEdge::ConsistencyCheck ( MeshPt *pPtRoot, MeshEdge *pEdgeRoot, MeshTri *pTriRoot )
{
	bool bRes = TRUE;
	if ( ( pEdgeRoot != NULL ) && ( QueryList() != pEdgeRoot ) )
	{
		FAIL_CHECK();
	}

	if ( pEdgeProx != NULL )
	{
		if ( pEdgeProx->pEdgeProx != this )
		{
			FAIL_CHECK();
		}
		if ( ( pEdgeRoot != NULL ) && ( pEdgeProx->QueryList() != pEdgeRoot ) )
		{
			FAIL_CHECK();
		}
		// Either pPt1<->pPt1 and pPt2<->pPt2, or the other way round.
		if ( pEdgeProx->pPt1->CheckProx ( pPt1 ) )
		{
			if ( !pEdgeProx->pPt2->CheckProx ( pPt2 ) )
			{
				FAIL_CHECK();
			}
		}
		else if ( pEdgeProx->pPt1->CheckProx ( pPt2 ) )
		{
			if ( !pEdgeProx->pPt2->CheckProx ( pPt1 ) )
			{
				FAIL_CHECK();
			}
		}
		else
		{
			FAIL_CHECK();
		}
	}

	if ( pTri12 != NULL )
	{
		if ( ( pTriRoot != NULL ) && ( pTri12->QueryList() != pTriRoot ) )
		{
			FAIL_CHECK();
		}
		
		if ( pTri12->pEdge12 == this )
		{
			if ( ( pTri12->pPt1 != pPt1 ) || ( pTri12->pPt2 != pPt2 ) )
			{
				FAIL_CHECK();
			}
		}
		else if ( pTri12->pEdge23 == this )
		{
			if ( ( pTri12->pPt2 != pPt1 ) || ( pTri12->pPt3 != pPt2 ) )
			{
				FAIL_CHECK();
			}
		}
		else if ( pTri12->pEdge31 == this )
		{
			if ( ( pTri12->pPt3 != pPt1 ) || ( pTri12->pPt1 != pPt2 ) )
			{
				FAIL_CHECK();
			}
		}
		else
		{
			FAIL_CHECK();
		}
	}

	if ( pTri21 != NULL )
	{
		if ( ( pTriRoot != NULL ) && ( pTri21->QueryList() != pTriRoot ) )
		{
			FAIL_CHECK();
		}
		
		if ( pTri21->pEdge12 == this )
		{
			if ( ( pTri21->pPt1 != pPt2 ) || ( pTri21->pPt2 != pPt1 ) )
			{
				FAIL_CHECK();
			}
		}
		else if ( pTri21->pEdge23 == this )
		{
			if ( ( pTri21->pPt2 != pPt2 ) || ( pTri21->pPt3 != pPt1 ) )
			{
				FAIL_CHECK();
			}
		}
		else if ( pTri21->pEdge31 == this )
		{
			if ( ( pTri21->pPt3 != pPt2 ) || ( pTri21->pPt1 != pPt1 ) )
			{
				FAIL_CHECK();
			}
		}
		else
		{
			FAIL_CHECK();
		}
	}


	if ( ( pPt1 == NULL ) || ( pPt2 == NULL ) )
	{
		FAIL_CHECK();
	}
	else
	{
		if ( pPtRoot != NULL )
		{
			if ( pPt1->QueryList() != pPtRoot )
			{
				FAIL_CHECK();
			}
			if ( pPt2->QueryList() != pPtRoot )
			{
				FAIL_CHECK();
			}
		}

#if 0
		if ( pPt1->FindEdge ( pPt2 ) != this )
		{
			FAIL_CHECK();
		}
		if ( pPt2->FindEdge ( pPt1 ) != this )
		{
			FAIL_CHECK();
		}
#endif

// Should update to use FirstTri/NextTri until a verdict is reached.
#if 0
		// Note that pTri12 can be NULL, but if and only if
		// the FindTri is NULL, so this is a valid test.
		// Either both are NULL, or both are the same.
		if ( pPt1->FindTri ( pPt2 ) != pTri12 )
		{
			FAIL_CHECK();
		}
		if ( pPt2->FindTri ( pPt1 ) != pTri21 )
		{
			FAIL_CHECK();
		}
#endif
	}

	return ( bRes );
}







inline MeshPt::MeshPt ( MeshPt *pListRoot )
{
	iCurEdgeNum = -1;
	iCurTriNum = -1;
	iCurProxNum = -1;

	ListInit();
	if ( pListRoot != NULL )
	{
		ListAddAfter ( pListRoot );
	}
}

inline MeshPt::~MeshPt ( void )
{
#if !MESHCTRL_PTS_ALWAYS_ADDED_BEFORE_TRIS || !MESHCTRL_PTS_ALWAYS_ADDED_BEFORE_EDGES
	int i;
#endif

	// Can't just do a simple loop - RemoveProx modifies the list.
	while ( ProxPtList.Size() > 0 )
	{
		bool bRes = RemoveProx ( ProxPtList.Ptr()[0] );
		ASSERT ( bRes );
	}
 
#if MESHCTRL_PTS_ALWAYS_ADDED_BEFORE_TRIS
	// Should not be any tris.
	ASSERT ( TriList.Size() == 0 );
#else
	MeshTri **ppTri = TriList.Ptr();
	for ( i = 0; i < TriList.Size(); i++ )
	{
		ASSERT ( ppTri[i] != NULL );
		ppTri[i]->RemovePt ( this );
	}
#endif

#if MESHCTRL_PTS_ALWAYS_ADDED_BEFORE_EDGES
	// Should not be any edges.
	ASSERT ( EdgeList.Size() == 0 );
#else
	MeshEdge **ppEdge = EdgeList.Ptr();
	for ( i = 0; i < EdgeList.Size(); i++ )
	{
		ASSERT ( ppEdge[i] != NULL );
		ppEdge[i]->RemovePt ( this );
	}
#endif

	ListDel();
}

inline void MeshPt::RemoveEdge ( MeshEdge *pEdge )
{
	ASSERT ( pEdge != NULL );
	MeshEdge **ppEdgeList = EdgeList.Ptr();
	int i;
	for ( i = 0; i < EdgeList.Size(); i++ )
	{
		if ( ppEdgeList[i] == pEdge )
		{
			break;
		}
	}
	ASSERT ( i < EdgeList.Size() );
	// Bin this entry.
	EdgeList.RemoveItem ( i );
}

inline void MeshPt::RemoveTri ( MeshTri *pTri )
{
	ASSERT ( pTri != NULL );
	MeshTri **ppTriList = TriList.Ptr();
	int i;
	for ( i = 0; i < TriList.Size(); i++ )
	{
		if ( ppTriList[i] == pTri )
		{
			break;
		}
	}
	ASSERT ( i < TriList.Size() );
	// Bin this entry with the last entry.
	TriList.RemoveItem ( i );
}

inline void MeshPt::AddTri ( MeshTri *pTri )
{
	ASSERT ( pTri != NULL );
#ifdef DEBUG
	// Make sure this hasn't been added already.
	MeshTri **ppTriList = TriList.Ptr();
	int i;
	for ( i = 0; i < TriList.Size(); i++ )
	{
		ASSERT ( ppTriList[i] != NULL );
		ASSERT ( ppTriList[i] != pTri );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -