DirectX Graphics
中有專門的文字顯示接口ID3DXFont, 和GDI中的HFONT的創建類似, 顯示文字的函數也和GDI中相同. 使用以下兩個函數來創建字體,
HRESULT D3DXCreateFont(LPDIRECT3DDEVICE9 pDevice,
?????????????????????? INT Height,
?????????????????????? UINT Width,
?????????????????????? UINT Weight,
?????????????????????? UINT MipLevels,
?????????????????????? BOOL Italic,
?????????????????????? DWORD CharSet,
?????????????????????? DWORD OutputPrecision,
?????????????????????? DWORD Quality,
?????????????????????? DWORD PitchAndFamily,
?????????????????????? LPCTSTR pFacename,
?????????????????????? LPD3DXFONT * ppFont);
?
HRESULT D3DXCreateFontIndirect(LPDIRECT3DDEVICE9 pDevice,
?????????????????????????????? CONST D3DXFONT_DESC * pDesc,
?????????????????????????????? LPD3DXFONT * ppFont);
實際上, ID3DXFont的創建和顯示字體還是依賴于GDI的FONT的創建和顯示字體的函數的, 所以ID3DXFont顯示字體并非是由DirectX Graphics中的Direct3D來完成的, 如果想提高性能, 建議少量的字體顯示用9.3.1的方式, 大量的字體顯示可事先轉換成bitmap.
?
?
9.4 Pick
的例子
?
9.4.1 game9 project
代碼更新
?
??? game9
中只是演示了
Picking, ID3DXLINE
和文字顯示.
---------------------------------------------------------------
//
全局變量, 用來保存4個測試球的半徑, 原始圓心位置, 變動圓心位置
//
最后兩個向量是Picking Ray的端點和方向
FLOAT?????? g_fRad[4];
D3DXVECTOR3 g_vCenter[4];
D3DXVECTOR3 g_vTest[4];
D3DXVECTOR3 g_pos;
D3DXVECTOR3 g_n;
?
// game9.cpp, LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
//
加入對WM_MOUSEHOVER的消息探測, 大概1秒鐘的鼠標停頓產生WM_MOUSEHOVER
//
注意使用WM_MOUSEHOVER 必須定義 #define _WIN32_WINNT ?0x0500(0x400以上)
???
case WM_MOUSEMOVE:
??????? {
???????????? TRACKMOUSEEVENT tme = { 0 };
???????????? tme.cbSize = sizeof(TRACKMOUSEEVENT);
???????????? tme.dwFlags = TME_LEAVE | TME_HOVER;
???????????? tme.hwndTrack = hWnd;
???????????? tme.dwHoverTime = 0x0400;
???????????? TrackMouseEvent(&tme);
????????????
if (g_bHover)
???????????? {
????????????????? g_bHover = FALSE;
????????????????? g_pGame->EndPick();
???????????? }
??????? }
???????
break;
???
case WM_MOUSEHOVER :
??????? {???
????????????
if (g_bHover == FALSE)
???????????? {
????????????????? g_bHover = g_pGame->Picking((DWORD)lParam);
???????????? }
??????? }
???????
break;
?
// direct9.cpp,
保存Picking Ray的端點和方向, 以為當4個模型自動旋轉時有自動Pick的功能
BOOL CD9Game::Picking(DWORD dwPt)
{
??? LONG x = XLPARAM(dwPt);
??? LONG y = YLPARAM(dwPt);
?
??? FLOAT Rx = 0.0;
??? FLOAT Ry = 0.0;
??? FLOAT mx = 0.0;
??? FLOAT my = 0.0;
?
??? D3DVIEWPORT9 mv;
??? D3DXMATRIX?? mProj;
??? D3DXMATRIX?? mView;
??? m_pD3DDev->GetViewport(&mv);
??? m_pD3DDev->GetTransform(D3DTS_PROJECTION, &mProj);
??? m_pD3DDev->GetTransform(D3DTS_VIEW, &mView);
??? D3DXMatrixInverse(&mView, NULL, &mView);
?
??? mx = mProj(0, 0);
??? my = mProj(1, 1);
??? Rx = (FLOAT)((x * 2.0) - mv.Width) / (mv.Width * mx);
??? Ry = (FLOAT)(mv.Height - (y * 2.0)) / (mv.Height * my);
?
??? g_pos.x = 0.0;
??? g_pos.y = 0.0;
??? g_pos.z = 0.0;
??? g_n.x?? = Rx;
??? g_n.y?? = Ry;
??? g_n.z?? = 1.0;
??? D3DXVec3TransformCoord(&g_pos, &g_pos, &mView);
??? D3DXVec3TransformNormal(&g_n, &g_n, &mView);
??? D3DXVec3Normalize(&g_n, &g_n);
?
???
return WhoAmI();
}
// direct9.cpp,
確定當前選中的物體
BOOL CD9Game::WhoAmI()
{
??? BOOL bPick = FALSE;
??? D3DXVECTOR3 v;
??? FLOAT b, c;
??? INT i = 0;
???
for (; i < 4; i++)
??? {
??????? v = g_pos - g_vTest[i];
??????? b = FLOAT(2.0 * D3DXVec3Dot(&g_n, &v));
??????? c = D3DXVec3Dot(&v, &v) - g_fRad[i] * g_fRad[i];
?
??????? FLOAT del = b * b - 4 * c;
???????
if (del > 0.0)
??????? {
???????????? del = sqrtf(del);
???????????? FLOAT x1 = (FLOAT)(( del - b) / 2.0);
???????????? FLOAT x2 = (FLOAT)((-del - b) / 2.0);
????????????
if ((x1 >= 0.0) || (x2 >= 0.0))
???????????? {
????????????????? bPick = TRUE;
?????????????????
break;
???????????? }
??????? }
??? }
??? lstrcpyn(g_szPick, g_szObj[i], 512);
???
return bPick;
}
?
// direct9.cpp,
渲染物體, 如果自動旋轉時有自動Pick
VOID CD9Game::Render()
{
???
if (m_dwRot >= MAXROT)
??? {
??????? m_dwRot = 1L;
??? }
???
else
if (m_bRot)
??? {
??????? m_dwRot++;
??? }
??? D3DXMATRIX mWorld, mWorldX, mWorldY, mWorldZ;
??? FLOAT rat = m_dwRot * ROT;
??? D3DXMatrixRotationX(&mWorldX, rat);
??? D3DXMatrixRotationY(&mWorldY, rat);
??? D3DXMatrixRotationZ(&mWorldZ, rat);
?
??? D3DXMatrixMultiply(&mWorld, &mWorldX, &mWorldY);
??? D3DXMatrixMultiply(&mWorld, &mWorld, &mWorldZ);
?
??? D3DXMATRIX m1, m2, m3, m4;
??? D3DXMatrixMultiply(&m1, &g_m1, &mWorld);
??? D3DXMatrixMultiply(&m2, &g_m2, &mWorld);
??? D3DXMatrixMultiply(&m3, &g_m3, &mWorld);
??? D3DXMatrixMultiply(&m4, &g_m4, &mWorld);
???
if (m_bRot)
??? {??? //
如果自動旋轉時有自動Pick
??????? D3DXVec3TransformCoord(&g_vTest[0], &g_vCenter[0], &m1);
??????? D3DXVec3TransformCoord(&g_vTest[1], &g_vCenter[1], &m2);
??????? D3DXVec3TransformCoord(&g_vTest[2], &g_vCenter[2], &m3);
??????? D3DXVec3TransformCoord(&g_vTest[3], &g_vCenter[3], &m4);
??????? WhoAmI();
??? }
?
??? m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
???????????????????? D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
??? m_pD3DDev->BeginScene();
?
??? m_pD3DDev->SetTransform(D3DTS_WORLD, &m1);
??? m_pMeshShip->Render();
??? m_pD3DDev->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
??? m_pMeshSphere->DrawSubset(0);
??? m_pD3DDev->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
?
??? m_pD3DDev->SetTransform(D3DTS_WORLD, &m2);
??? m_pMesh1->DrawSubset(0);
??
??? m_pD3DDev->SetTransform(D3DTS_WORLD, &m3);
??? m_pMesh2->DrawSubset(0);
???
??? m_pD3DDev->SetTransform(D3DTS_WORLD, &m4);
??? m_pMesh3->DrawSubset(0);
??
//
畫Y軸向上或向下的偏移, X軸向左或向右的偏移
??? D3DXVECTOR2* pLine = g_vy;
??? m_pLine->Begin();
??? m_pLine->Draw(pLine, 8, D3DCOLOR_XRGB(0, 128, 0));
??? pLine += 8;
??? m_pLine->Draw(pLine, 2, D3DCOLOR_XRGB(0, 255, 0));
??? pLine += 2;
??? m_pLine->Draw(pLine, 8, D3DCOLOR_XRGB(0, 128, 0));
??? pLine += 8;
??? m_pLine->Draw(pLine, 2, D3DCOLOR_XRGB(0, 255, 0));
??? m_pLine->End();
??
//
顯示每秒幀數和選擇物體的類型
??? RECT rect = { 16, 16, 512, 48 };
??? wsprintf(g_szFPS, _T("Current FPS : %ld"), g_dwFPS);
??? m_pFont->DrawText(NULL, g_szFPS, -1, &rect,
???????????????????? DT_NOCLIP | DT_VCENTER, D3DCOLOR_XRGB(0, 128, 0));
??? rect.top = 48;
??? rect.bottom += 32;
??? m_pFont->DrawText(NULL, g_szPick, -1, &rect, DT_NOCLIP, D3DCOLOR_XRGB(0, 128, 0));
???
??? m_pD3DDev->EndScene();
??? m_pD3DDev->Present(NULL, NULL, NULL, NULL);
}
---------------------------------------------------------------
?
9.4.2 game9 project
說明
?
???
為代碼簡單, 在鼠標停留在某地一定時間產生
WM_MOUSEHOVER
消息時, 才會有Pick功能的調用, 物體類型在左上角顯示
.
自動旋轉/停止用Space切換, 自動旋轉時有自動Picking功能, 也就是鼠標不動, 當物體旋轉到鼠標位子將自動識別物體.
?
???
識別物體有延遲現象, 作為例子就不改的太復雜了. 還有這種Picking技術是最普通的, 物體少的時候用還不錯, 實際的游戲可以使用BSP, 反饋法, 直接映射法等.
?
?
第九集 小結?
?
這一集我們學習了要進行DirectX Graphics 3D編程中的物體Pick和文字顯示.