現在DirectXで3Dを勉強しているのですがちょっと親子関係のZバッファのところでつまずいております。
[1.1] 自分が今行いたい事は何か
具体的には親自身の回転をもとに子も周りを回転させようとしているのですが本来なら親が手前に来ないといけないところで子の方が手前にきてしまいます。
これを親が手前に来るように修正したいです
[1.2] どのように取り組んだか
コードはこちらです。
#define NAME "DirectX9 Graphics"
#define TITLE "ポリゴン表示"
#include <Windows.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <mmsystem.h>
// ライブラリのリンク
#pragma once
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib,"dxguid.lib")
#pragma comment(lib,"winmm.lib")
#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } }
#define EMSG(x) MessageBox(NULL,x,"DirectX D3D",MB_OK);
// 構造体定義
//頂点フォーマット
#define D3DFVF_VERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE)
typedef struct _D3DLVERTEX_
{ float x,y,z;
DWORD color;
} D3DVERTEX;
//四面体の定義
//親
D3DVERTEX vtx[6]=
{ { -5, 0, 5, 0xff0000ff }, //青の頂点
{ 5, 0, 5, 0xffff0000 }, //赤の頂点
{ 0, 8.16f, 2.11f, 0xffffffff }, //白の頂点
{ 0, 0, -3.66f, 0xff00ff00 }, //緑の頂点
{ -5, 0, 5, 0xff0000ff }, //青の頂点
{ 5, 0, 5, 0xffff0000 } //赤の頂点
};
//子
D3DVERTEX vtx2[6]=
{ { -5, 0, 5, 0xffADFF2F },
{ 5, 0, 5, 0xffB8860B },
{ 0, 8.16f, 2.11f, 0xff9400D3 },
{ 0, 0, -3.66f, 0xffFFC0CB },
{ -5, 0, 5, 0xffADFF2F },
{ 5, 0, 5, 0xffB8860B }
};
// グローバル変数:
LPDIRECT3D9 g_pD3D= NULL;
LPDIRECT3DDEVICE9 g_pDEV= NULL;
bool g_bActive = false;
D3DXVECTOR3 ViewForm(0.0f,0.0f,50.0f);//カメラの位置
// プロトタイプ宣言
HRESULT Init3DDev(HWND hWnd);
void Cleanup(void);
void SetupMatrices(void);
void Draw(void);
LRESULT CALLBACK MsgProc(HWND hWnd,UINT msg,UINT wParam,LONG lParam);
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, INT);
//メイン
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, INT)
{ MSG msg;
WNDCLASSEX wc = { sizeof(WNDCLASSEX),CS_CLASSDC,MsgProc,0L,0L,hInst,
NULL,NULL,NULL,NULL,NAME,NULL };
if (RegisterClassEx(&wc)==0) return FALSE;
HWND hWnd = CreateWindowEx(0,NAME,TITLE,WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL,hInst,NULL);
if (FAILED(Init3DDev(hWnd))) return FALSE;
ShowWindow(hWnd,SW_SHOWDEFAULT);
UpdateWindow(hWnd);
ZeroMemory(&msg,sizeof(msg));
while(msg.message!=WM_QUIT)
{ if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{ TranslateMessage(&msg);
DispatchMessage(&msg);
}
else Draw();
}
Cleanup();
UnregisterClass(NAME,wc.hInstance);
return TRUE;
}
//デバイスの取得
HRESULT Init3DDev(HWND hWnd)
{ D3DDISPLAYMODE d3ddm;
D3DPRESENT_PARAMETERS d3dpp;
if (NULL==(g_pD3D=Direct3DCreate9(D3D_SDK_VERSION))) return E_FAIL;
if (FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&d3ddm))) return E_FAIL;
ZeroMemory(&d3dpp,sizeof(d3dpp));
d3dpp.Windowed = TRUE; // ウィンドウモード
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // 映像信号に同期してフリップする
d3dpp.EnableAutoDepthStencil = TRUE; // デプスバッファ(Zバッファ)とステンシルバッファを作成
d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // デプスバッファとして16bitを使う
d3dpp.BackBufferFormat = d3ddm.Format; // カラーモードの指定
if (FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp,&g_pDEV)))
return E_FAIL;
// レンダリングステートパラメータの設定
g_pDEV->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); // カリングを行わない
g_pDEV->SetRenderState(D3DRS_ZENABLE, TRUE); // Zバッファを使用
return S_OK;
}
void Cleanup(void)
{ SAFE_RELEASE(g_pDEV);
SAFE_RELEASE(g_pD3D);
}
//描画環境設定
void SetupMatrices(void)
{
D3DXMATRIX matView;
D3DXMATRIX matProj;
//View 座標の設定
D3DXMatrixLookAtLH(&matView,&ViewForm,
&D3DXVECTOR3(0.0f,0.0f,0.0f),&D3DXVECTOR3(0.0f,1.0f,0.0f));
g_pDEV->SetTransform(D3DTS_VIEW,&matView);
//透視変換の設定
D3DXMatrixPerspectiveFovLH(&matProj,D3DX_PI/4,1.0f,0.0f,100.0f);
g_pDEV->SetTransform(D3DTS_PROJECTION,&matProj);
g_pDEV->SetRenderState(D3DRS_AMBIENT,0x00808080);
g_pDEV->SetRenderState(D3DRS_ZENABLE, TRUE);
g_pDEV->SetRenderState(D3DRS_LIGHTING,FALSE);
}
//描画処理
void Draw(void)
{ //黒で塗りつぶして消去
g_pDEV->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(0,0,0),1.0f,0);
if (SUCCEEDED(g_pDEV->BeginScene()))
{
D3DXMATRIX matWorld,matX,matY;
SetupMatrices();
//親の行列
D3DXMatrixRotationY(&matWorld,timeGetTime()/500.0f);
g_pDEV->SetTransform(D3DTS_WORLD,&matWorld);
//デバイスに使用する頂点フォーマットをセットする
g_pDEV->SetFVF(D3DFVF_VERTEX);
//頂点データ(v)を渡して描画する
g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,4,vtx,sizeof(D3DVERTEX));
D3DXMATRIX matLocalWorld;
D3DXMatrixIdentity(&matLocalWorld);//単位行列で初期化
//子の行列
D3DXMatrixRotationY(&matY,0);
D3DXMatrixTranslation(&matX,7.0f,0.0f,0.0f);
matLocalWorld = matX*matY;
matLocalWorld *=matWorld;
g_pDEV->SetTransform(D3DTS_WORLD,&matLocalWorld);
//デバイスに使用する頂点フォーマットをセットする
g_pDEV->SetFVF(D3DFVF_VERTEX);
//頂点データ(v)を渡して描画する
g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,4,vtx2,sizeof(D3DVERTEX));
g_pDEV->EndScene();
}
g_pDEV->Present(NULL,NULL,NULL,NULL);
}
LRESULT WINAPI MsgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
switch(msg)
{ case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_KEYDOWN:
switch(wParam)
{ case VK_ESCAPE:
DestroyWindow(hWnd);
break;
}
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
i.1でも書きましたが本来なら親が手前に来ないといけないところで子の方が手前にきてしまいます。
[1.4] 今何がわからないのか、知りたいのか
どの様に修正すればZバッファが適用され、親が手前に来るところで子が親の後ろに隠れ、見えなくなるのでしょうか?
[2] 環境
[2.1] OS : Windows7
[2.2] コンパイラ名 : VC++ 2010EE
[3] その他
DXライブラリとC++でしたら学校で3Dゲームの勉強の始めにと初音ミクProjectDiva風のリズムゲームを制作しました。
C,C++の基本は理解しています。
・ライブラリを使っている場合は何を使っているか
DirectXSDKはJune 2010を使用しております。
シェーダーレベルで3Dを扱えるようになりたいと思い、現在DirectXでもう一度勉強し直しているところです。