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

📄 object.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	#endif
				pwIndices[pVCRCur->wIndexOffset[i]] = pVCRCur->wKeptVert;
			}
	#if EXTRA_DEBUGGING
			// Make sure the indices are all in range.
			for ( int j = 0; j < iCurNumTris * 3; j++ )
			{
				ASSERT ( pwIndices[j] < (WORD)iCurNumVerts );
			}
	#endif

		}

		hres = pIndexBuffer->Unlock();
		ASSERT ( SUCCEEDED ( hres ) );

		return TRUE;
	}
}

BOOL OMIVanilla::UndoCollapse ( int iNum )
{
	if ( pVCRCur->bNumChanges == (BYTE)-1 )
	{
		// No more to undo.
		ASSERT ( iCurNumCollapses == 0 );
		return FALSE;
	}
	else
	{
		ASSERT ( pIndexBuffer != NULL );
		WORD *pwIndices;
		HRESULT hres = pIndexBuffer->Lock ( 0,
							iCurNumTris * 3 * sizeof ( WORD ),
							(BYTE**)&pwIndices,
							0 );
		ASSERT ( SUCCEEDED ( hres ) );

		while ( --iNum >= 0 )
		{
			if ( pVCRCur->bNumChanges == (BYTE)-1 )
			{
				// No more to undo.
				ASSERT ( iCurNumCollapses == 0 );
				break;
			}

			iCurNumCollapses--;

			for ( int i = 0; i < pVCRCur->bNumChanges; i++ )
			{
				// Change the relevant instances of the kept vertex to the one that's just been unbinned .
				ASSERT ( pVCRCur->wIndexOffset[i] < ( iCurNumTris * 3 ) );
	#if EXTRA_DEBUGGING
				ASSERT ( pwIndices[pVCRCur->wIndexOffset[i]] == pVCRCur->wKeptVert );
	#endif
				pwIndices[pVCRCur->wIndexOffset[i]] = (WORD)iCurNumVerts;
			}

			iCurNumTris += pVCRCur->bNumOfTris;
			ASSERT ( iCurNumTris <= pOptMesh->wIndices.Size() );
			iCurNumVerts++;
			ASSERT ( iCurNumVerts <= pOptMesh->iNumVerts );

	#if EXTRA_DEBUGGING
			// Make sure the indices are all in range.
			for ( int j = 0; j < iCurNumTris * 3; j++ )
			{
				ASSERT ( pwIndices[j] < (WORD)iCurNumVerts );
			}
	#endif

			pVCRCur = pVCRCur->Next();
		}

		hres = pIndexBuffer->Unlock();
		ASSERT ( SUCCEEDED ( hres ) );

		return TRUE;
	}
}



void OMIVanilla::Check ( void )
{
	// Check my global data is the same type as me!
	ASSERT ( pOptMesh != NULL );
	ASSERT ( pOptMesh->GetType() == GetType() );
	pOptMesh->Check();

}





///////// SLIDING WINDOW VIPM ////////////



// A table of these exists, one per collapse.
struct SlidingWindowRecord
{
	DWORD	dwFirstIndexOffset;			// Offset of the first index in the index buffer to start at (note! no retrictions. Can easily be >64k)
	WORD	wNumTris;					// Number of tris to render (most cards can't do more than 65536)
	WORD	wNumVerts;					// Number of vertices to render with (using WORD indices)
};



class OMSlidingWindow : public OptimisedMesh
{
	friend class OMISlidingWindow;

	Object *pObj;

	int										iNumVerts;			// Number of verts at full rez.
	int										iNumCollapses;		// Total number of collapses.
	int										iNumLevels;			// Total number of levels.
	int										iSizeOfIB;			// In indices. Just for info.
	//ArbitraryList<WORD>						wIndices;			// The index list, all levels clumped together. Always using TRILISTs.
	ArbitraryList<SlidingWindowRecord>		swrRecords;			// The records of the collapses.

	BOOL									bOptimised;			// Have the tris been reordered optimally?

	LPDIRECT3DVERTEXBUFFER8		pVB;							// The VB with the vertices in.
	LPDIRECT3DINDEXBUFFER8		pIB;							// The index list, all levels clumped together. Always using TRILISTs.

public:
	OMSlidingWindow ( Object *pObject );
	virtual ~OMSlidingWindow ( void );
	virtual VIPMTypeEnum GetType ( void );
	virtual char *GetTypeName ( void );
	virtual OptimisedMeshInstance *CreateInstance ( ObjectInstance *pObjectInstance );
	virtual void Check ( void );
	virtual void Update ( void );
	virtual void AboutToChangeDevice ( void );
};


class OMISlidingWindow : public OptimisedMeshInstance
{
	friend class OMSlidingWindow;

	ObjectInstance *pObjInst;
	OMSlidingWindow *pOptMesh;

	SlidingWindowRecord *pswrLast;		// For the Info* functions.

	// No per-instance VIPM data. Hooray!


public:

	OMISlidingWindow ( ObjectInstance *pObjectInstance, OMSlidingWindow *pOptimisedMesh );
	virtual ~OMISlidingWindow ( void );
	virtual VIPMTypeEnum GetType ( void );
	virtual char *GetTypeName ( void );
	virtual void RenderCurrentObject ( LPDIRECT3DDEVICE8 pd3ddev, int iMaterialNumber, int iLoD );
	virtual BOOL bNeedsUpdate ( void );
	virtual void Update ( void );
	virtual void Check ( void );
	virtual void AboutToChangeDevice ( void );
	virtual const void InfoGetGlobal ( DWORD *pdwMemoryUsed, DWORD *pdwOfWhichAGP );
	virtual const void InfoGetInstance ( DWORD *pdwMemoryUsed, DWORD *pdwOfWhichAGP, DWORD *pdwVerticesLoaded, DWORD *pdwRealTrisDrawn, DWORD *pdwTotalVertices );
};




OMSlidingWindow::OMSlidingWindow ( Object *pObject )
{
	pObj = pObject;
	pVB = NULL;
	pIB = NULL;
	bOptimised = FALSE;
}

OMSlidingWindow::~OMSlidingWindow ( void )
{
	pObj = NULL;
	ASSERT ( pVB == NULL );
	ASSERT ( pIB == NULL );
}

VIPMTypeEnum OMSlidingWindow::GetType ( void )
{
	return VIPMType_SlidingWindow;
}

char *OMSlidingWindow::GetTypeName ( void )
{
	return "Sliding Window";
}

void OMSlidingWindow::AboutToChangeDevice ( void )
{
	HRESULT hres = g_pd3dDevice->SetStreamSource ( 0, NULL, 0 );
	ASSERT ( SUCCEEDED ( hres ) );
	hres = g_pd3dDevice->SetIndices ( NULL, 0 );
	ASSERT ( SUCCEEDED ( hres ) );
	SAFE_RELEASE ( pVB );
	SAFE_RELEASE ( pIB );

	MarkAsDirty ( g_bShowVIPMInfo );
	bOptimised = FALSE;
}


// Create an instance of this optimised mesh, and returns the pointer to it.
// Pass in the object instance you wish to associate it with.
OptimisedMeshInstance *OMSlidingWindow::CreateInstance ( ObjectInstance *pObjectInstance )
{
	return new OMISlidingWindow ( pObjectInstance, this );
}


void OMSlidingWindow::Check ( void )
{
}


void OMSlidingWindow::Update ( void )
{
	if ( !bDirty && ( bOptimised == g_bOptimiseVertexOrder ) )
	{
		// Nothing to do!
		return;
	}

	bDirty = FALSE;
	iVersion++;			// Just for luck.


	bOptimised = g_bOptimiseVertexOrder;


	SAFE_RELEASE ( pVB );
	SAFE_RELEASE ( pIB );
	swrRecords.SizeTo ( 0 );




	MeshPt *pt;
	MeshTri *tri;


	// Undo all the collapses, so we start from the maximum mesh.
	while ( pObj->UndoCollapse() ) {}


	// How many vertices are we looking at?
	iNumVerts = 0;
	for ( pt = pObj->CurPtRoot.ListNext(); pt != NULL; pt = pt->ListNext() )
	{
		pt->mypt.dwIndex = -1;
		iNumVerts++;
	}
	// Er... word indices, guys... nothing supports 32-bit indices yet.
	ASSERT ( iNumVerts < 65535 );


	// How many tris are we looking at?
	int iNumTris = 0;
	for ( tri = pObj->CurTriRoot.ListNext(); tri != NULL; tri = tri->ListNext() )
	{
		tri->mytri.dwIndex = -1;
		iNumTris++;
	}
	// A lot of cards have this annoying limit - see D3DCAPS8.MaxPrimitiveCount, which is
	// exactly 65535 for DX7 and previous devices. So might as well stick with that number.
	ASSERT ( iNumTris < 65535 );




	// Create a place to put indices while we build up the list. Because we don't know
	// how many we need yet, we can't create the IB until the end. Then we'll copy this into it.
	ArbitraryList<WORD> wIndices;
	wIndices.SizeTo ( 0 );




	// Create the vertex buffer.
	HRESULT hres = g_pd3dDevice->CreateVertexBuffer ( iNumVerts * sizeof ( STDVERTEX ),
										D3DUSAGE_WRITEONLY,
										STDVERTEX_FVF,
										D3DPOOL_DEFAULT,
										&pVB );
	ASSERT ( SUCCEEDED ( hres ) );

	STDVERTEX *pVertices, *pCurVertex;
	hres = pVB->Lock ( 0, 0, (BYTE **)(&pVertices), 0 );
	ASSERT ( SUCCEEDED ( hres ) );

	pCurVertex = pVertices;






	// Now do all the collapses, so we start from the minimum mesh.
	// Along the way, mark the vertices in reverse order.
	int iCurVerts = iNumVerts;
	int iCurCollapse = 0;
	int iCurSlidingWindowLevel = 0;
	while ( TRUE )
	{
		GeneralCollapseInfo *pCollapse = pObj->pNextCollapse;
		if ( pObj->pNextCollapse == &(pObj->CollapseRoot) )
		{
			break;
		}

		iCurSlidingWindowLevel = pCollapse->iSlidingWindowLevel;

		iCurCollapse++;

		iCurVerts--;
		pCollapse->pptBin->mypt.dwIndex = iCurVerts;

		pObj->DoCollapse();
	}

	iNumCollapses = iCurCollapse;


	// Add the remaining existing pts in any old order.
	WORD wCurIndex = 0;
	for ( pt = pObj->CurPtRoot.ListNext(); pt != NULL; pt = pt->ListNext() )
	{
		if ( pt->mypt.dwIndex == (DWORD)-1 )
		{
			// Not binned in a collapse.
			pt->mypt.dwIndex = wCurIndex;
			pCurVertex->v = pt->mypt.vPos;
			pCurVertex->norm = pt->mypt.vNorm;
			pCurVertex->tu = pt->mypt.fU;
			pCurVertex->tv = pt->mypt.fV;

			pCurVertex++;
			wCurIndex++;
		}
	}

	// Should meet in the middle!
	ASSERT ( wCurIndex == iCurVerts );


	// And count the tris that are left.
	int iCurNumTris = 0;
	for ( tri = pObj->CurTriRoot.ListNext(); tri != NULL; tri = tri->ListNext() )
	{
		iCurNumTris++;
	}



	// Reserve space for the collapse table - this is stored so that
	// "number of collapses" is the index. So we'll be adding from the
	// back.
	iCurCollapse++;		// Implicit "last collapse" is state after last collapse.
	swrRecords.SizeTo ( iCurCollapse );
	// And add the last one.
	iCurCollapse--;
	SlidingWindowRecord *swr = swrRecords.Item ( iCurCollapse );
	swr->dwFirstIndexOffset = 0;
	swr->wNumTris = (WORD)iCurNumTris;
	swr->wNumVerts = wCurIndex;


	// Now go through each level in turn.

	int iCurTriBinned = 0;


	// Useful thing.
	ArbitraryList<WORD> wTempIndices;


	int iMaxSlidingWindowLevel = iCurSlidingWindowLevel;


#if ALLOW_PROGRESS_BARS
	CreateProgressBars();
	if ( g_hProgress1 != NULL )
	{
		// Set min to 0, max to whatever
		SendMessage ( g_hProgress1, PBM_SETRANGE, 0, MAKELPARAM ( 0, iMaxSlidingWindowLevel + 1 ) ); 
		// Set step increment to 1.
		SendMessage ( g_hProgress1, PBM_SETSTEP, (WPARAM) 1, 0 ); 
		// Start it at 0.
		SendMessage ( g_hProgress1, PBM_SETPOS, 0, 0 ); 
	}
#else
	ASSERT ( g_hProgress1 == NULL );
#endif //#if ALLOW_PROGRESS_BARS


    
	while ( TRUE )
	{
		// Now we go through the collapses for this level, undoing them.
		// As we go, we add the binned tris to the start of the index list,
		// 

		// This coming list will be three sections:
		// 1. the tris that get binned by the splits.
		// 2. the tris that aren't affected.
		// 3. the tris that are added by the splits.
		//
		// We know that at the moment, we are just rendering
		// 1+2, which must equal the number of tris.
		// So 3 starts iCurNumTris on from the start of 1.
		int iCurTriAdded = iCurTriBinned + iCurNumTris;
		wIndices.SizeTo ( iCurTriAdded * 3 );



		int iJustCheckingNumTris = 0;
		for ( tri = pObj->CurTriRoot.ListNext(); tri != NULL; tri = tri->ListNext() )
		{
			tri->mytri.dwIndex = -1;		// Mark them as not being in a collapse.
			iJustCheckingNumTris++;
		}
		ASSERT ( iJustCheckingNumTris == iCurNumTris );


		BOOL bJustStartedANewLevel = TRUE;


		// Now undo all the collapses for this level in turn, adding vertices,
		// binned tris, and SlidingWindowRecords as we go.
		while ( ( pObj->pNextCollapse->ListNext() != NULL ) &&
			    ( pObj->pNextCollapse->ListNext()->iSlidingWindowLevel == iCurSlidingWindowLevel ) )
		{
			GeneralCollapseInfo *pCollapse = pObj->pNextCollapse->ListNext();


			// If we've just started a new level, EXCEPT on the last level,
			// we don't need to store the post-collapse version of the tris,
			// since we'll just switch down to the next level instead.
			if ( !bJustStartedANewLevel || ( iCurSlidingWindowLevel == iMaxSlidingWindowLevel  ) )
			{
				// These tris will be binned by the split.
				if ( pCollapse->TriCollapsed.Size() > 0 )
				{
					wTempIndices.SizeTo(pCollapse->TriCollapsed.Size() * 3);
					for ( int i = 0; i < pCollapse->TriCollapsed.Size(); i++ )
					{
						GeneralTriInfo *pTriInfo = pCollapse->TriCollapsed.Item(i);
						MeshTri *tri = pTriInfo->ppt[0]->FindTri ( pTriInfo->ppt[1], pTriInfo->ppt[2] );
						ASSERT ( tri != NULL );
						ASSERT ( tri->mytri.dwIndex == -1 );	// Should not have been in a collapse this level.

						ASSERT ( pTriInfo->ppt[0]->mypt.dwIndex < wCurIndex );
						ASSERT ( pTriInfo->ppt[1]->mypt.dwIndex < wCurIndex );
						ASSERT ( pTriInfo->ppt[2]->mypt.dwIndex < wCurIndex );
						*wTempIndices.Item(i*3+0) = (WORD)pTriInfo->ppt[0]->mypt.dwIndex;
						*wTempIndices.Item(i*3+1) = (WORD)pTriInfo->ppt[1]->mypt.dwIndex;
						*wTempIndices.Item(i*3+2) = (WORD)pTriInfo->ppt[2]->mypt.dwIndex;
						iCurNumTris--;
					}

					// Now try to order them as best you can.
					if ( g_bOptimiseVertexOrder )
					{
						OptimiseVertexCoherencyTriList ( wTempIndices.Ptr(), pCollapse->TriCollapsed.Size() );
					}

					// And write them to the index list.
					wIndices.CopyFrom ( iCurTriBinned * 3, wTempIndices, 0, 3 * pCollapse->TriCollapsed.Size() );
					//memcpy ( wIndices.Item ( iCurTriBinned * 3 ), wTempIndices.Ptr(), sizeof(WORD)

⌨️ 快捷键说明

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