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

📄 object.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
📖 第 1 页 / 共 5 页
字号:
			wCurIndex++;
		}
	}

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


	WORD wCurTri = 0;
	for ( tri = pObj->CurTriRoot.ListNext(); tri != NULL; tri = tri->ListNext() )
	{
		tri->mytri.dwIndex = wCurTri;

		// Add the three indices.
		ASSERT ( tri->pPt1->mypt.dwIndex != (DWORD)-1 );
		ASSERT ( tri->pPt2->mypt.dwIndex != (DWORD)-1 );
		ASSERT ( tri->pPt3->mypt.dwIndex != (DWORD)-1 );
		*(wIndices.AddItem()) = (WORD)tri->pPt1->mypt.dwIndex;
		*(wIndices.AddItem()) = (WORD)tri->pPt2->mypt.dwIndex;
		*(wIndices.AddItem()) = (WORD)tri->pPt3->mypt.dwIndex;

		wCurTri++;
	}


	// And undo all the collapses in turn, adding vertices,
	// tris, and VanillaCollapseRecords as we go.
	int iPrevNumChanges = -1;
	int iVCRecordSize = 0;
	iNumCollapses = 0;
	while ( pObj->pNextCollapse->ListNext() != NULL )
	{
		iNumCollapses++;

		GeneralCollapseInfo *pCollapse = pObj->pNextCollapse->ListNext();

		// Create a collapse item.
		int iNumChanges = pCollapse->TriCollapsed.Size();
		int iSizeCollapseRecords = pbCollapseRecords.Size();
		pbCollapseRecords.SizeTo ( iSizeCollapseRecords + sizeof ( VanillaCollapseRecord ) + sizeof(WORD) * iNumChanges );
		// No no no, records were made from plain poly-vinyl, not poly-vinyl chloride.
		// You're thinking of kinky boots. Actually, that was a record, wasn't it? Hmmm.. maybe you're right then.
		// Honor Blackman - oh yes. Patrick MacNee - no thanks.
		VanillaCollapseRecord *pvcRecord = (VanillaCollapseRecord *)pbCollapseRecords.Item ( iSizeCollapseRecords );

		pvcRecord->bNumChanges = iNumChanges;
		pvcRecord->bNumOfTris = pCollapse->TriOriginal.Size() - pCollapse->TriCollapsed.Size();
		ASSERT ( pCollapse->pptKeep->mypt.dwIndex != (DWORD)-1 );
		pvcRecord->wKeptVert = pCollapse->pptKeep->mypt.dwIndex;
		pvcRecord->bPrevNumChanges = iPrevNumChanges;
		iPrevNumChanges = iNumChanges;

		DWORD *pdwTriIndices = new DWORD [pCollapse->TriCollapsed.Size()];
		// These tris will be remapped.
		for ( int i = 0; i < pCollapse->TriCollapsed.Size(); i++ )
		{
			GeneralTriInfo *pTriInfo = pCollapse->TriCollapsed.Item(i);
			MeshTri *pTri = pTriInfo->ppt[0]->FindTri ( pTriInfo->ppt[1], pTriInfo->ppt[2] );
			ASSERT ( pTri != NULL );

			// Find which one will change.
			// Unfortunately, the order of pPt1, pPt2, pPt3 has nothing to
			// do with the order it is in the index list. So we need to check with
			// the index list to see which index needs changing.
			WORD *pwTriIndices = wIndices.Item ( pTri->mytri.dwIndex * 3 );
			int iOffset;
			if ( pwTriIndices[0] == pCollapse->pptKeep->mypt.dwIndex )
			{
				iOffset = 0;
			}
			else if ( pwTriIndices[1] == pCollapse->pptKeep->mypt.dwIndex )
			{
				iOffset = 1;
			}
			else
			{
				ASSERT ( pwTriIndices[2] == pCollapse->pptKeep->mypt.dwIndex );
				iOffset = 2;
			}

			pvcRecord->wIndexOffset[i] = ( 3 * pTri->mytri.dwIndex ) + iOffset;

			// And actually undo the collapse.
			ASSERT ( *(wIndices.Item(pvcRecord->wIndexOffset[i])) == (WORD)pCollapse->pptKeep->mypt.dwIndex );
			*(wIndices.Item(pvcRecord->wIndexOffset[i])) = wCurIndex;

			pdwTriIndices[i] = pTri->mytri.dwIndex;
		}

		// Do the uncollapse.
		pObj->UndoCollapse();

		// Add the vertex.
		MeshPt *pPt = pCollapse->pptBin;

		ASSERT ( pPt->mypt.dwIndex == wCurIndex );
		pCurVertex->v = pPt->mypt.vPos;
		pCurVertex->norm = pPt->mypt.vNorm;
		pCurVertex->tu = pPt->mypt.fU;
		pCurVertex->tv = pPt->mypt.fV;

		pCurVertex++;
		wCurIndex++;


		// Now find which tris were remapped and which are new.
		int iNewTriNum = 0;
		for ( i = 0; i < pCollapse->TriOriginal.Size(); i++ )
		{
			GeneralTriInfo *pTriInfo = pCollapse->TriOriginal.Item(i);
			MeshTri *pTri = pTriInfo->ppt[0]->FindTri ( pTriInfo->ppt[1], pTriInfo->ppt[2] );

			// Because we store these in a specific way, this is a lot easier.
			ASSERT ( pTriInfo->ppt[0] == pCollapse->pptBin );
			if ( i < pCollapse->TriCollapsed.Size() )
			{
				// This should be a remapped tri, and correspond to the one in the Collapsed list.
				ASSERT ( ( pTriInfo->ppt[1] != pCollapse->pptKeep ) && ( pTriInfo->ppt[2] != pCollapse->pptKeep ) );
				ASSERT ( pCollapse->pptKeep == pCollapse->TriCollapsed.Item(i)->ppt[0] );
				ASSERT ( pTriInfo->ppt[1] == pCollapse->TriCollapsed.Item(i)->ppt[1] );
				ASSERT ( pTriInfo->ppt[2] == pCollapse->TriCollapsed.Item(i)->ppt[2] );

				// We don't do anything exiting with these,
				// except remember what index the tri was when it was originally created.
				pTri->mytri.dwIndex = pdwTriIndices[i];
			}
			else
			{
				// This will be binned.
				ASSERT ( ( pTriInfo->ppt[1] == pCollapse->pptKeep ) || ( pTriInfo->ppt[2] == pCollapse->pptKeep ) );

				// And add this tri to the end of the index list.
				pTri->mytri.dwIndex = wCurTri;

				// Add the three indices.
				ASSERT ( pTri->pPt1->mypt.dwIndex != (DWORD)-1 );
				ASSERT ( pTri->pPt2->mypt.dwIndex != (DWORD)-1 );
				ASSERT ( pTri->pPt3->mypt.dwIndex != (DWORD)-1 );
				*(wIndices.AddItem()) = (WORD)pTri->pPt1->mypt.dwIndex;
				*(wIndices.AddItem()) = (WORD)pTri->pPt2->mypt.dwIndex;
				*(wIndices.AddItem()) = (WORD)pTri->pPt3->mypt.dwIndex;

				wCurTri++;
				iNewTriNum++;
			}
		}

		ASSERT ( iNewTriNum == pvcRecord->bNumOfTris );

		delete []pdwTriIndices;

	}



	// Dummy last (well, OK - first) collapse.
	int iSizeCollapseRecords = pbCollapseRecords.Size();
	pbCollapseRecords.SizeTo ( iSizeCollapseRecords + sizeof ( VanillaCollapseRecord ) );
	VanillaCollapseRecord *pvcRecord = (VanillaCollapseRecord *)pbCollapseRecords.Item ( iSizeCollapseRecords );

	pvcRecord->bNumChanges = -1;
	pvcRecord->bNumOfTris = 0;
	pvcRecord->wKeptVert = -1;
	pvcRecord->bPrevNumChanges = iPrevNumChanges;

	pVCRLast = pvcRecord;



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

}








OMIVanilla::OMIVanilla ( ObjectInstance *pObjectInstance, OMVanilla *pOptimisedMesh )
{
	pObjInst = pObjectInstance;
	pOptMesh = pOptimisedMesh;
	pIndexBuffer = NULL;
	pVCRCur = NULL;
	iCurNumTris = 0;
	iCurNumVerts = 0;
	iCurNumCollapses = 0;
}

OMIVanilla::~OMIVanilla ( void )
{
	pObjInst = NULL;
	pOptMesh = NULL;

	ASSERT ( pIndexBuffer == NULL );
}

void OMIVanilla::AboutToChangeDevice ( void )
{
	ASSERT ( pOptMesh != NULL );
	pOptMesh->AboutToChangeDevice();

	HRESULT hres = g_pd3dDevice->SetIndices ( NULL, 0 );
	ASSERT ( SUCCEEDED ( hres ) );
	SAFE_RELEASE ( pIndexBuffer );
}

const void OMIVanilla::InfoGetGlobal ( DWORD *pdwMemoryUsed, DWORD *pdwOfWhichAGP )
{
	ASSERT ( pOptMesh != NULL );
	ASSERT ( pOptMesh->bWillGetInfo );

	DWORD dwMemoryUsed = 0;
	DWORD dwOfWhichAGP = 0;

	// The thing itself.
	dwMemoryUsed += sizeof ( OMVanilla );
	// Master index list.
	dwMemoryUsed += pOptMesh->wIndices.Size() * sizeof ( WORD );
	// Collapse list.
	dwMemoryUsed += pOptMesh->pbCollapseRecords.Size() * sizeof ( BYTE );
	// And the size of the VB.
	dwOfWhichAGP += pOptMesh->iNumVerts * sizeof ( STDVERTEX );

	// Add the AGP memory in.
	dwMemoryUsed += dwOfWhichAGP;


	if ( pdwMemoryUsed != NULL )
	{
		*pdwMemoryUsed = dwMemoryUsed;
	}
	if ( pdwOfWhichAGP != NULL )
	{
		*pdwOfWhichAGP = dwOfWhichAGP;
	}
}

const void OMIVanilla::InfoGetInstance ( DWORD *pdwMemoryUsed, DWORD *pdwOfWhichAGP, DWORD *pdwVerticesLoaded, DWORD *pdwRealTrisDrawn, DWORD *pdwTotalVertices )
{
	ASSERT ( pOptMesh != NULL );
	ASSERT ( pOptMesh->bWillGetInfo );

	DWORD dwMemoryUsed = 0;
	DWORD dwOfWhichAGP = 0;


	// The thing itself.
	dwMemoryUsed += sizeof ( OMIVanilla );

	// The copied index list.
	// Note! This could be better - we could only grow the index buffer
	// to the size we actually need for this instance. 
	// Most of the objects will be far smaller than this.
	// For speed, you'd need to use pools of IBs of the right power-of-two size,
	// to avoid constantly creating and destroying IBs. Which sounds like a lot of boring coding
	// for the sake of a few slightly more accurate numbers (but still larger than
	// anything else per-instance).
	// So I haven't.
	dwOfWhichAGP += pOptMesh->wIndices.Size() * sizeof ( WORD );


	// Add the AGP memory in.
	dwMemoryUsed += dwOfWhichAGP;

	if ( pdwMemoryUsed != NULL )
	{
		*pdwMemoryUsed = dwMemoryUsed;
	}
	if ( pdwOfWhichAGP != NULL )
	{
		*pdwOfWhichAGP = dwOfWhichAGP;
	}


	if ( pdwVerticesLoaded != NULL )
	{
		// Find the vertex-cache info for the current render.
		WORD *pwIndices;
		HRESULT hres = pIndexBuffer->Lock ( 0,
							pOptMesh->wIndices.Size() * sizeof ( WORD ),
							(BYTE**)&pwIndices,
							D3DLOCK_READONLY );
		ASSERT ( SUCCEEDED ( hres ) );

		float fVertexScore = GetNumVerticesLoadedTriList ( pwIndices, iCurNumTris );
		*pdwVerticesLoaded = (DWORD)(fVertexScore + 0.4999f);

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

	if ( pdwRealTrisDrawn != NULL )
	{
		// We don't get degenerate tris in Vanilla.
		*pdwRealTrisDrawn = iCurNumTris;
	}

	if ( pdwTotalVertices != NULL )
	{
		*pdwTotalVertices = iCurNumVerts;
	}
}



VIPMTypeEnum OMIVanilla::GetType ( void )
{
	return VIPMType_Vanilla;
}

char *OMIVanilla::GetTypeName ( void )
{
	return "Vanilla";
}

// Renders the given material of the object with the given level of detail.
void OMIVanilla::RenderCurrentObject ( LPDIRECT3DDEVICE8 pd3ddev, int iMaterialNumber, int iLoD )
{
	// Do an update if necessary.
	if ( bNeedsUpdate() )
	{
		Update();
	}


	if ( iLoD > iCurNumCollapses )
	{
		DoCollapse ( iLoD - iCurNumCollapses );
	}
	else if ( iLoD < iCurNumCollapses )
	{
		UndoCollapse ( iCurNumCollapses - iLoD );
	}

	// And draw the object.
	HRESULT hres;
	
	hres = pd3ddev->SetVertexShader ( STDVERTEX_FVF );
	ASSERT ( SUCCEEDED ( hres ) );

	ASSERT ( pIndexBuffer != NULL );
	hres = pd3ddev->SetIndices ( pIndexBuffer, 0 );
	ASSERT ( SUCCEEDED ( hres ) );

	ASSERT ( pOptMesh->pVB != NULL );
	hres = pd3ddev->SetStreamSource ( 0, pOptMesh->pVB, sizeof ( STDVERTEX ) );
	ASSERT ( SUCCEEDED ( hres ) );

	if ( g_iMaxNumTrisDrawn > 0 )
	{
		// Limit the number of tris.
		int iNumTris = g_iMaxNumTrisDrawn;
		if ( iCurNumTris < iNumTris )
		{
			iNumTris = iCurNumTris;
		}
		hres = pd3ddev->DrawIndexedPrimitive ( D3DPT_TRIANGLELIST, 0, iCurNumVerts, 0, iNumTris );
		ASSERT ( SUCCEEDED ( hres ) );
	}
	else
	{
		hres = pd3ddev->DrawIndexedPrimitive ( D3DPT_TRIANGLELIST, 0, iCurNumVerts, 0, iCurNumTris );
		ASSERT ( SUCCEEDED ( hres ) );
	}

	g_iNumOfObjectTrisDrawn += iCurNumTris;
	g_iNumOfObjectVertsDrawn += iCurNumVerts;

}

BOOL OMIVanilla::bNeedsUpdate ( void )
{
	ASSERT ( pOptMesh != NULL );
	return ( iVersion != pOptMesh->iVersion );
}


void OMIVanilla::Update ( void )
{
	ASSERT ( pOptMesh != NULL );
	pOptMesh->Update();

	if ( bNeedsUpdate() )
	{

		DWORD dwFlags = D3DUSAGE_DYNAMIC;
#if !EXTRA_DEBUGGING
// If doing extra debugging, we're always going to do reads from the IB.
		if ( !pOptMesh->bWillGetInfo )
		{
			// We don't need to do reads from the IB to get vertex-cache info.
			dwFlags |= D3DUSAGE_WRITEONLY;
		}
#endif



		// Copy the base index list.
		SAFE_RELEASE ( pIndexBuffer );
		HRESULT hres = g_pd3dDevice->CreateIndexBuffer ( 
							pOptMesh->wIndices.Size() * sizeof ( WORD ),
							dwFlags,
							D3DFMT_INDEX16,
							D3DPOOL_DEFAULT,
							&pIndexBuffer );
		ASSERT ( SUCCEEDED ( hres ) );

		// And fill.
		WORD *pwIndices;
		hres = pIndexBuffer->Lock ( 0,
							pOptMesh->wIndices.Size() * sizeof ( WORD ),
							(BYTE**)&pwIndices,
							D3DLOCK_DISCARD );
		ASSERT ( SUCCEEDED ( hres ) );

		memcpy ( pwIndices, pOptMesh->wIndices.Ptr(), pOptMesh->wIndices.Size() * sizeof ( WORD ) );

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


		// Point to the last collapse record.
		pVCRCur = pOptMesh->pVCRLast;

		iCurNumVerts = pOptMesh->iNumVerts;
		ASSERT ( ( pOptMesh->wIndices.Size() % 3 ) == 0 );
		iCurNumTris = pOptMesh->wIndices.Size() / 3;

		iCurNumCollapses = 0;

		iVersion = pOptMesh->iVersion;
	}

	Check();
}


BOOL OMIVanilla::DoCollapse ( int iNum )
{
	if ( pVCRCur->bPrevNumChanges == (BYTE)-1 )
	{
		// No more to do.
		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->bPrevNumChanges == (BYTE)-1 )
			{
				// No more to do.
				break;
			}

			iCurNumCollapses++;

			pVCRCur = pVCRCur->Prev();

			iCurNumVerts--;
			ASSERT ( iCurNumVerts >= 0 );
			iCurNumTris -= pVCRCur->bNumOfTris;
			ASSERT ( iCurNumTris >= 0 );

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

⌨️ 快捷键说明

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