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

📄 gemvipm.cpp

📁 游戏编程精粹2第四章源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	vert[0].rhw = 0.5f;		// Random non-wierd value.
	vert[1].rhw = 0.5f;
	vert[2].rhw = 0.5f;
	vert[3].rhw = 0.5f;

	HRESULT hres;
	hres = g_pd3dDevice->SetVertexShader ( TVERTEX_FVF );
	const float fSizeOfDot = 4.0f;

	vert[0].v		= vecBig;
	vert[0].v.y -= fSizeOfDot;

	vert[1].v		= vecBig;
	vert[1].v.x -= fSizeOfDot * 0.866f;
	vert[1].v.y += fSizeOfDot * 0.5f;

	vert[2].v		= vecBig;
	vert[2].v.x += fSizeOfDot * 0.866f;
	vert[2].v.y += fSizeOfDot * 0.5f;

	vert[3].v		= vecSmall;

	WORD wIndex[6];
	wIndex[0] = 0;
	wIndex[1] = 3;
	wIndex[2] = 1;
	wIndex[3] = 3;
	wIndex[4] = 2;
	wIndex[5] = 3;

	hres = g_pd3dDevice->DrawIndexedPrimitiveUP ( D3DPT_LINELIST, 0, 4, 3, wIndex, D3DFMT_INDEX16, vert, sizeof(vert[0]) );
}

void DrawScreenSpaceEdge ( D3DXVECTOR4 &vecBig, D3DXVECTOR4 &vecSmall )
{
	if ( ( vecBig.w > 0.0f ) && ( vecSmall.w > 0.0f ) )
	{
		D3DXVECTOR3 vecBig3 ( vecBig.x, vecBig.y, vecBig.z );
		D3DXVECTOR3 vecSmall3 ( vecSmall.x, vecSmall.y, vecSmall.z );
		DrawScreenSpaceEdge ( vecBig3, vecSmall3 );
	}
}







//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Called once per frame, the call is the entry point for 3d
//       rendering. This function sets up render states, clears the
//       viewport, and renders the scene.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::Render()
{


	ObjectInstance *pFirstObjInst = m_ObjectInstRoot.ListNext();
	ASSERT ( pFirstObjInst != NULL );
	Object *pFirstObj = pFirstObjInst->pObj;


	MeshEdge *pClosestEdge = NULL;
	MeshPt *pClosestPt = NULL;

	float fBestError = 0.0f;
	float fBestOfAnyError = 0.0f;


	if ( m_bCreateCollapseMode )
	{

		// Find out which edge we are closest to.
		// This involves first transforming all the vertices to screenspace.
		// Edges with either end point behind the camera are ignored.

		// Find the complete transform from object space to camera space.
		D3DXMATRIX matViewport;
		D3DVIEWPORT8 vpViewport;

		// The framework annoyingly hides the viewport from me, and indeed it's implicit, not set.
		//HRESULT hres = m_pd3dDevice->GetViewport ( &vpViewport );
		vpViewport.MaxZ = 1.0f;
		vpViewport.MinZ = 1.0f;
		vpViewport.X = 0;
		vpViewport.Y = 0;
		vpViewport.Height = m_d3dsdBackBuffer.Height;
		vpViewport.Width = m_d3dsdBackBuffer.Width;

		MakeMatrixFromViewport ( matViewport, vpViewport );

		D3DXMATRIX matTotal;
		D3DXMatrixMultiply ( &matTotal, &(pFirstObjInst->matOrn), &m_matView );
		D3DXMatrixMultiply ( &matTotal, &(matTotal), &m_matProjClose );
		D3DXMatrixMultiply ( &matTotal, &(matTotal), &matViewport );



		POINT ptMouse;
		if( GetFocus() )
		{
			// Where is the mouse?
			GetCursorPos( &ptMouse );
			ScreenToClient( m_hWnd, &ptMouse );
		}
		else
		{
			ptMouse.x = 0;
			ptMouse.y = 0;
		}


		if ( pFirstObj->bSomethingHappened )
		{
			pFirstObj->bSomethingHappened = FALSE;
		}


		MeshPt *ppt;
		MeshEdge *pedge;
		MeshTri *ptri;

		for ( ppt = pFirstObj->CurPtRoot.ListNext(); ppt != NULL; ppt = ppt->ListNext() )
		{
			ppt->mypt.bFrontFaced = FALSE;

			//D3DXVec3TransformCoord ( &ppt->mypt.v4ScrPos, &(ppt->mypt.vPos), &matTotal );
			D3DXVECTOR4 &pPos = ppt->mypt.v4ScrPos;
			D3DXVec3Transform ( &pPos, &(ppt->mypt.vPos), &matTotal );
			// And do the homogenous thing.
			// I do it this way, instead of using D3DXVec3TransformCoord, because the
			// sign of the W tells me if the vert was behind the camera or not.
			pPos.x /= pPos.w;
			pPos.y /= pPos.w;
			pPos.z /= pPos.w;
		}

		for ( pedge = pFirstObj->CurEdgeRoot.ListNext(); pedge != NULL; pedge = pedge->ListNext() )
		{
			pedge->myedge.bFrontFaced = FALSE;
		}

		for ( ptri = pFirstObj->CurTriRoot.ListNext(); ptri != NULL; ptri = ptri->ListNext() )
		{
			ptri->mytri.bFrontFaced = FALSE;
			D3DXVECTOR2 v2Pos1 ( ptri->pPt1->mypt.v4ScrPos.x, ptri->pPt1->mypt.v4ScrPos.y );
			D3DXVECTOR2 v2Pos2 ( ptri->pPt2->mypt.v4ScrPos.x, ptri->pPt2->mypt.v4ScrPos.y );
			D3DXVECTOR2 v2Pos3 ( ptri->pPt3->mypt.v4ScrPos.x, ptri->pPt3->mypt.v4ScrPos.y );

			// Find front facing tris.
			v2Pos2 -= v2Pos1;
			v2Pos3 -= v2Pos1;
			if ( ( v2Pos2.x * v2Pos3.y - v2Pos3.x * v2Pos2.y ) > 0.0f )
			{
				ptri->mytri.bFrontFaced = TRUE;
				ptri->pPt1->mypt.bFrontFaced = TRUE;
				ptri->pPt2->mypt.bFrontFaced = TRUE;
				ptri->pPt3->mypt.bFrontFaced = TRUE;
				ptri->pEdge12->myedge.bFrontFaced = TRUE;
				ptri->pEdge23->myedge.bFrontFaced = TRUE;
				ptri->pEdge31->myedge.bFrontFaced = TRUE;
			}
		}


		// Find the closest point to the cursor position.
		// Ignore points with no edges on them.
		float fClosestDistSquared = 1.0e10f;
		for ( ppt = pFirstObj->CurPtRoot.ListNext(); ppt != NULL; ppt = ppt->ListNext() )
		{
			if ( ppt->FirstEdge() != NULL )
			{
				// Is this one closer?
				D3DXVECTOR4 &pPos = ppt->mypt.v4ScrPos;
				if ( pPos.w > 0.0f )
				{
					if ( ppt->mypt.bFrontFaced || !m_bIgnoreBackFaced )
					{
						float fTemp;
						fTemp = pPos.x - (float)ptMouse.x;
						float fDistSquared = fTemp * fTemp;
						fTemp = pPos.y - (float)ptMouse.y;
						fDistSquared += fTemp * fTemp;

						if ( fClosestDistSquared > fDistSquared )
						{
							fClosestDistSquared = fDistSquared;
							pClosestPt = ppt;
						}
					}
				}
			}

			// Keep the FirstEdge/NextEdge sequencer happy.
			ppt->EndEdge();
		}


		// Now find the closest edge from the closest point.
		fClosestDistSquared = 1.0e10f;
		if ( pClosestPt != NULL )
		{
			D3DXVECTOR2 v2Pos1 ( pClosestPt->mypt.v4ScrPos.x, pClosestPt->mypt.v4ScrPos.y );
			D3DXVECTOR2 v2Mouse ( (float)ptMouse.x, (float)ptMouse.y );
			D3DXVECTOR2 v2DeltaMouse = v2Mouse - v2Pos1;
			float fDeltaMouseSqu = D3DXVec2Dot ( &v2DeltaMouse, &v2DeltaMouse );
			for ( MeshEdge *pedge = pClosestPt->FirstEdge(); pedge != NULL; pedge = pClosestPt->NextEdge() )
			{
				if ( pedge->myedge.bFrontFaced || !m_bIgnoreBackFaced )
				{
					MeshPt *pOtherPt = pedge->OtherPt ( pClosestPt );

					if ( pOtherPt->mypt.v4ScrPos.w > 0.0f )
					{
						D3DXVECTOR2 v2Pos2 ( pOtherPt->mypt.v4ScrPos.x, pOtherPt->mypt.v4ScrPos.y );
						D3DXVECTOR2 v2DeltaPos2 = v2Pos2 - v2Pos1;

						float fDeltaPos2Squ = D3DXVec2Dot ( &v2DeltaPos2, &v2DeltaPos2 );
						float fPos2DotMouse = D3DXVec2Dot ( &v2DeltaPos2, &v2DeltaMouse );
						if ( fPos2DotMouse > 0.0f )
						{
							float fDistSquared = fDeltaMouseSqu - ( fPos2DotMouse * fPos2DotMouse ) / fDeltaPos2Squ;
							if ( fClosestDistSquared > fDistSquared )
							{
								fClosestDistSquared = fDistSquared;
								pClosestEdge = pedge;
							}
						}
					}
				}
			}
		}


		if ( m_iFindBestErrorCountdown > 0 )
		{
			// Don't find the best one yet.
			// This allows some operations to be done quickly without
			// this (very slow) search slowing stuff down.
			m_pedgeBestError = NULL;
			m_pptBestError = NULL;
			m_iFindBestErrorCountdown--;
		}
		else
		{
			// Find the best collapse you can.
			// (how expensive is this? Ohhhh yes).
			fBestError = 1.0e10f;
			m_pedgeBestError = NULL;
			m_pptBestError = NULL;
			// NL = NewLevel - would force a new level.
			float fBestErrorNL = 1.0e10f;
			MeshEdge *pedgeBestErrorNL = NULL;
			MeshPt *pptBestErrorNL = NULL;

		// Set to 0 (mean) or 1 (geom av)
	#define USE_GEOM_AV 0

	#if USE_GEOM_AV
			float fAverage = 1.0f;
	#else
			float fAverage = 0.0f;
	#endif
			int iAvCount = 0;

			// Flush the cache, just in case.
			pFirstObj->FindCollapseError ( NULL, NULL, FALSE );

			for ( ppt = pFirstObj->CurPtRoot.ListNext(); ppt != NULL; ppt = ppt->ListNext() )
			{
				// Disallow any pts that are on an edge - shouldn't be collapsing them.
				BOOL bAllowed = TRUE;
				for ( pedge = ppt->FirstEdge(); pedge != NULL; pedge = ppt->NextEdge() )
				{
					if ( ( pedge->pTri12 == NULL ) || ( pedge->pTri21 == NULL ) )
					{
						// This edge does not have two tris on it - disallow it.
						bAllowed = FALSE;
					}
				}
				if ( !bAllowed )
				{
					continue;
				}

				BOOL bRequiresNewLevel = FALSE;
				if ( m_bShowSlidingWindowInfo && !pFirstObj->CollapseAllowedForLevel ( ppt, pFirstObj->iCurSlidingWindowLevel ) )
				{
					// This collapse would force a new level.
					bRequiresNewLevel = TRUE;
				}

				for ( pedge = ppt->FirstEdge(); pedge != NULL; pedge = ppt->NextEdge() )
				{
					float fErrorBin = pFirstObj->FindCollapseError ( ppt, pedge, TRUE );

					iAvCount++;

	#if USE_GEOM_AV
					fAverage *= fErrorBin;
	#else
					fAverage += fErrorBin;
	#endif

					if ( bRequiresNewLevel )
					{
						if ( fBestErrorNL > fErrorBin )
						{
							fBestErrorNL = fErrorBin;
							pedgeBestErrorNL = pedge;
							pptBestErrorNL = ppt;
						}
					}
					else
					{
						if ( fBestError > fErrorBin )
						{
							fBestError = fErrorBin;
							m_pedgeBestError = pedge;
							m_pptBestError = ppt;
						}
					}
				}
			}

			if ( m_bShowSlidingWindowInfo )
			{

				// Store the best of either error for later display.
				if ( fBestError > fBestErrorNL )
				{
					fBestOfAnyError = fBestErrorNL;
				}
				else
				{
					fBestOfAnyError = fBestError;
				}



				// Tweak up the NewLevel errors by a factor.
	#if USE_GEOM_AV
				fAverage = powf ( fAverage, (float)iAvCount );
	#else
				fAverage /= (float)iAvCount;
	#endif

				if ( fBestError > ( fBestErrorNL + fAverage * m_fSlidingWindowErrorTolerance ) )
				{
					// Despite the boost, it's still the best,
					// so bite the bullet and do the collapse.
					fBestError = fBestErrorNL;
					m_pedgeBestError = pedgeBestErrorNL;
					m_pptBestError = pptBestErrorNL;
				}
			}
			else
			{
				ASSERT ( pedgeBestErrorNL == NULL );
			}
	#undef USE_GEOM_AV

			// Flush the cache, just in case.
			pFirstObj->FindCollapseError ( NULL, NULL, FALSE );
		}



		

		// Move the viewer here. FrameMove() doesn't get called during pause mode,
		// and we still want to move around then.

		static DWORD dwLastTime = timeGetTime();


		// Get the relative time, in seconds
		DWORD dwThisTime = timeGetTime();
		float fTimeKey = (float)( dwThisTime - dwLastTime ) * 0.001f;
		if ( fTimeKey > 0.1f )
		{
			// A hiccup in framerate - clamp it.
			fTimeKey = 0.1f;
		}
		dwLastTime = dwThisTime;





		// Clear the render target
		m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x00000000f, 1.0f, 0L );

		// Begin the scene
		if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
		{


			m_pd3dDevice->SetTransform( D3DTS_VIEW,       &m_matView );
			m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &m_matProjClose );

			ObjectInstance *pObjInst = pFirstObjInst;
			Object *pObj = pObjInst->pObj;

			m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
			m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_SELECTARG2 );
			m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TFACTOR );
			m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
			m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG2 );
			m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_TFACTOR );


			m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP,   D3DTOP_DISABLE );
			m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,   D3DTOP_DISABLE );

			m_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );
			m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );


			m_pd3dDevice->SetTexture( 0, NULL );



			m_pd3dDevice->SetTransform( D3DTS_WORLD,      &pObjInst->matOrn );


			m_pd3dDevice->SetRenderState ( D3DRS_LIGHTING, FALSE );
			m_pd3dDevice->SetRenderState ( D3DRS_ZENABLE, TRUE );
			m_pd3dDevice->SetRenderState ( D3DRS_TEXTUREFACTOR, 0xffff0000 );
			m_pd3dDevice->SetRenderState ( D3DRS_FILLMODE, D3DFILL_SOLID );


			// Draw the current state of the object.
			if ( m_bShowSlidingWindowInfo )
			{
				// Render twice.
				// Current level.
				pObjInst->RenderCurrentObject ( m_pd3dDevice, 0, pObj->iCurSlidingWindowLevel );
				// Next level.
				m_pd3dDevice->SetRenderState ( D3DRS_TEXTUREFACTOR, 0xff800000 );
				pObjInst->RenderCurrentObject ( m_pd3dDevice, 0, pObj->iCurSlidingWindowLevel + 1 );
			}
			else
			{
				pObjInst->RenderCurrentObject ( m_pd3dDevice, 0 );
			}


			// Tweak the projection matrix so that things are a bit more visible.
			m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &m_matProjCloseZbias );


			// Render all edges
			m_pd3dDevice->SetRenderState ( D3DRS_TEXTUREFACTOR, 0xff000000 );
			m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );

			pObjInst->RenderCurrentEdges ( m_pd3dDevice, 0, m_bIgnoreBackFaced );
			// Render visible edges again in a different colour.
			m_pd3dDevice->SetRenderState ( D3DRS_TEXTUREFACTOR, 0xffffff00 );
			m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
			pObjInst->RenderCurrentEdges ( m_pd3dDevice, 0, m_bIgnoreBackFaced );


			if ( pFirstObj->bSomethingHappened )
			{
				// A collapse or expand happened, so the ps and edges
				// may not be valid any more.
				pFirstObj->bSomethingHappened = FALSE;
				pClosestPt = NULL;
				pClosestEdge = NULL;
				m_pptBestError = NULL;
				m_pedgeBestError = NULL;
			}


	#if 0
	// Shows the vertices on-screen.
	// Basically just shows that my software projection pipe works!

			m_pd3dDevice->SetRenderState ( D3DRS_TEXTUREFACTOR, 0xff0000ff );
			m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
			for ( MeshPt *ppt = pFirstObj->CurPtRoot.ListNext(); ppt != NULL; ppt = ppt->ListNext() )
			{
				DrawScreenSpacePoint ( ppt->mypt.v4ScrPos );
			}
	#endif


			m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
			m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_SELECTARG2 );
			m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TFACTOR );
			m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
			m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG2 );
			m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_TFACTOR );

			m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP,   D3DTOP_DISABLE );
			m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,   D3DTOP_DISABLE );

			m_pd3dDevice->SetRenderState ( D3DRS_LIGHTING, FALSE );



			if ( pClosestPt != NULL )
			{
				m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );

				m_pd3dDevice->SetRenderState ( D3DRS_TEXTUREFACTOR, 0xff00ff00 );
				if ( m_bShowSlidingWindowInfo )
				{
					if ( !pFirstObj->CollapseAllowedForLevel ( pClosestPt, pFirstObj->iCurSlidingWindowLevel ) )
					{
						// This collapse would force a new level to be created.
						m_pd3dDevice->SetRenderState ( D3DRS_TEXTUREFACTOR, 0xff008000 );
					}
				}

				// Draw the current pt.
				DrawScreenSpacePoint ( pClosestPt->mypt.v4ScrPos );

				// And draw the current edge.
				if ( pClosestEdge != NULL )
				{
					MeshPt *pOtherPt = pClosestEdge->OtherPt ( pClosestPt );
					DrawScreenSpaceEdge ( pClosestPt->mypt.v4ScrPos, pOtherPt->mypt.v4ScrPos );
				}
			}

			if ( m_pptBestError != NULL )
			{
				m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );

				m_pd3dDevice->SetRenderState ( D3DRS_TEXTUREFACTOR, 0xff0080ff );
				if ( m_bShowSlidingWindowInfo )
				{
					if ( !pFirstObj->CollapseAllowedForLevel ( m_pptBestError, pFirstObj->iCurSlidingWindowLevel ) )
					{
						// This collapse would force a new level to be created.
						m_pd3dDevice->SetRenderState ( D3DRS_TEXTUREFACTOR, 0xff0000ff );
					}
				}

				// Draw the best-error pt.
				DrawScreenSpacePoint ( m_pptBestError->mypt.v4ScrPos );

				// And draw the best-error edge.
				if ( m_pedgeBestError != NULL )
				{
					MeshPt *pOtherPt = m_pedgeBestError->OtherPt ( m_pptBestError );
					DrawScreenSpaceEdge ( m_pptBestError->mypt.v4ScrPos, pOtherPt->mypt.v4ScrPos );
				}
			}

			// Output statistics
			m_pFont->DrawText( 2,  0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats );
			m_pFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats );

⌨️ 快捷键说明

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