📄 gemvipm.cpp
字号:
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 + -