前へ 第05章 ポリゴンを回転させる 次へ

ソース 実行ファイル
dx8_05.cpp dx8_05.exe

せっかくポリゴンなんだから3Dのゲームを作りたいですね。
いよいよ今回からは3Dポリゴンの解説です。
しかし覚えるべき点も数多くあるのでしっかりと理解してくださいね。

まず今までと違う点は奥行き(Z値)があるということです。
3Dの座標はX,Y,Zで構成されています。
今までの2DはXとYだけでしたよね,
このZ座標が加わることにより3Dの画面を構成することが出来るのです。
しかしパソコンのモニターは2Dですよね?映る場所に奥行きなんてありません。
だから一回3Dで計算をしてそれを2Dの画面で見たときの状態を表示させているのです。
内部では3D,実際の表示は2Dです。これで画面に表示可能ですね。
そこでこの奥行き情報は「Zバッファ」と呼ばれる場所に保存します。
各座標(x,y)につきz座標が記憶されているのです。
これにより手前なら描画,奥なら描画しないといった処理が可能です。
これを気にせずどんどん描画すれば後から描いたのが全部前に出てきますね
それは避けなければいけません。

これとは別に「Zソート」といった方法もあります。
これは名前のとおりZ座標に基づいてソートをするのです。
あらかじめ順番を決めて描画するので座標ごとに判定をしなくて良い分高速です。
ただし交差するポリゴンの場合は正常に表示できません。
まず3Dを2D画面で表示している仕組みを理解いただけたでしょうか?

また,3Dを扱う上で関数が色々と用意されています。
種類が豊富ですけど必要なものも多いです。
覚える事が多いですけど頑張ってください(^^;

出てくる関数:
関数名 詳細
HRESULT D3DXMatrixRotationX(
D3DXMATRIX* pOut,/*結果をいれるD3DXMATRIX構造体*/
FLOAT Angle/*回転の角度 (ラジアン単位)。*/
);
X軸を回転軸として回転した行列を作成する。
HRESULT D3DXMatrixRotationY(
D3DXMATRIX* pOut,/*結果をいれるD3DXMATRIX構造体*/
FLOAT Angle/*回転の角度 (ラジアン単位)。*/
);
Y軸を回転軸として回転した行列を作成する。
HRESULT D3DXMatrixRotationZ(
D3DXMATRIX* pOut,/*結果をいれるD3DXMATRIX構造体*/
FLOAT Angle/*回転の角度 (ラジアン単位)。*/
);
Z軸を回転軸として回転した行列を作成する。
INT D3DXMatrixTranslation(
D3DXMATRIX* pOut,/*結果をいれるD3DXMATRIX構造体*/
FLOAT x,/*X座標のオフセット。 */
FLOAT y,/*Y座標のオフセット。 */
FLOAT z,/*Z座標のオフセット。 */
);
オフセットを指定して行列を作成する。
INT D3DXMatrixLookAtLH(
D3DXMATRIX* pOut,/*結果をいれるD3DXMATRIX構造体*/
CONST D3DXVECTOR3* pEye,/*視点ベクトル*/
CONST D3DXVECTOR3* pAt,/*注視点ベクトル*/
CONST D3DXVECTOR3* pUp/*カレント ワールドの上方*/
);
左手座標系ビュー行列を作成する。
INT D3DXMatrixPerspectiveFovLH(
D3DXMATRIX* pOut,/*結果をいれるD3DXMATRIX構造体*/
FLOAT fovy,/*視野 (ラジアン単位)。*/
FLOAT Aspect,/*アスペクト比。*/
FLOAT zn,/*近くのビュープレーンのz値。*/
FLOAT zf/*遠くのビュープレーンのz値。*/
);
視野 (FOV) に基づいて、左手座標系パースペクティブ射影行列を作成する。
INT SetTransform(
D3DTRANSFORMSTATETYPE State,/*変更対象のデバイス ステート変数*/
CONST D3DMATRIX* pMatrix/*変更するD3DMATRIX構造体へのポインタ*/
);
単一デバイスのトランスフォーム関連ステートを設定する。
スタイル効果
D3DTS_WORLD ワールド行列
D3DTS_VIEW ビュー行列
D3DTS_PROJECTION プロジェクション行列
D3DTS_TEXTURE0 〜 D3DTS_TEXTURE7 テクスチャ座標変換行列
さて,上記の関数郡に毎回のように書かれている「行列」と言う言葉。 これは3Dの演算を行う上で実に重要な役割があります。 中学生くらいで習うかと思いますけど普段出てこないことだけに忘れた人も多いかと思います。 ここでは行列の詳しい説明は次回にします。具体的にどう使われるかを先に覚えて置いてください。 (関数名にもいっぱい付いている「MATRIX」と言う言葉,日本語に訳すと行列です。) それではソースの説明に入ります。 最初のほうに #define SCR_X 240 #define SCR_Y 160 とあります。 これは画面の大きさをわかりやすく最初に定義するようにしました。 #define PI (float)3.1415926535897932 これは見てわかるとおり円周率です。 学校で習うのは今後3だけで良いようですが,それだと正六角形の円周率と一緒のはず...本当に良いのか??(^^; まぁプログラム中ではかなり長くありますけどもう少し短くてもいいですよ(笑) ここからは肝心の部分なので一気に掲載しますね。 VOID Render() { if( NULL == g_pd3dDevice )//デバイスがNULLならここで戻る return; // ワールド行列を設定用の構造体の宣言 D3DXMATRIX matWorld,matRotateX,matRotateY,matTrans; // 回転行列の生成(一定量で回転させる) D3DXMatrixRotationX(&matRotateX,(float)timeGetTime() / 500.0f); D3DXMatrixRotationY(&matRotateY,(float)timeGetTime() / 500.0f); // 移動行列の生成 D3DXMatrixTranslation(&matTrans,0.0f,0.0f,5.0f); // 行列を作成(ワールド座標を回転行列によって回転させています) matWorld = matRotateX * matRotateY * matTrans; // ビュー行列を設定 D3DXMATRIX matView; // 視点は (0,0,0) にあり、(0,0,5) の方向を向く D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(0,0,0),//視点 &D3DXVECTOR3(0,0,1),//注視点 &D3DXVECTOR3(0,1,0));//上 // プロジェクション行列を設定 D3DXMATRIX matProj; // 視界 60 度、近くの限界 0.01、遠くの限界 10.0 D3DXMatrixPerspectiveFovLH(&matProj,60.0f * PI / 180.0f,1.0f,0.01f,10.0f); // 各行列を設定 g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld); g_pd3dDevice->SetTransform(D3DTS_VIEW,&matView); g_pd3dDevice->SetTransform(D3DTS_PROJECTION,&matProj); g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET| D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(100,100,100), 1.0f, 0 ); g_pd3dDevice->BeginScene(); // Z バッファ有効化 g_pd3dDevice->SetRenderState(D3DRS_ZENABLE,TRUE); // 頂点の色を使用 g_pd3dDevice->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE); // ポリゴンの両面を描画 g_pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE); // ライト無効化 g_pd3dDevice->SetRenderState(D3DRS_LIGHTING,FALSE); // 頂点を準備 LVERTEX v1[4]; LVERTEX v2[4]; LVERTEX v3[4]; LVERTEX v4[4]; LVERTEX v5[4]; LVERTEX v6[4]; // 面1 D3DCOLOR color = D3DCOLOR_RGBA(255,255,255,255); _LVERTEX(&v1[0],-1,1,1,color,0,1); _LVERTEX(&v1[1],1,1,1,color,1,1); _LVERTEX(&v1[2],1,1,-1,color,1,0); _LVERTEX(&v1[3],-1,1,-1,color,0,0); // 面2 color = D3DCOLOR_RGBA(0,255,255,255); _LVERTEX(&v2[0],-1,-1,1,color,0,1); _LVERTEX(&v2[1],1,-1,1,color,1,1); _LVERTEX(&v2[2],1,-1,-1,color,1,0); _LVERTEX(&v2[3],-1,-1,-1,color,0,0); // 面3 color = D3DCOLOR_RGBA(255,0,255,255); _LVERTEX(&v3[0],-1,-1,1,color,0,1); _LVERTEX(&v3[1],-1,-1,-1,color,0,0); _LVERTEX(&v3[2],-1,1,-1,color,1,0); _LVERTEX(&v3[3],-1,1,1,color,1,1); // 面4 color = D3DCOLOR_RGBA(255,255,0,255); _LVERTEX(&v4[0],1,-1,1,color,0,1); _LVERTEX(&v4[1],1,-1,-1,color,0,0); _LVERTEX(&v4[2],1,1,-1,color,1,0); _LVERTEX(&v4[3],1,1,1,color,1,1); // 面5 color = D3DCOLOR_RGBA(0,0,255,255); _LVERTEX(&v5[0],-1,-1,-1,color,0,0); _LVERTEX(&v5[1],1,-1,-1,color,1,0); _LVERTEX(&v5[2],1,1,-1,color,1,1); _LVERTEX(&v5[3],-1,1,-1,color,0,1); // 面6 color = D3DCOLOR_RGBA(255,0,0,255); _LVERTEX(&v6[0],-1,-1,1,color,0,0); _LVERTEX(&v6[1],1,-1,1,color,1,0); _LVERTEX(&v6[2],1,1,1,color,1,1); _LVERTEX(&v6[3],-1,1,1,color,0,1); // 頂点フォーマット設定 g_pd3dDevice->SetVertexShader(FVF_LVERTEX); //ここに描画処理を入れる g_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,v1,sizeof(LVERTEX)); g_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,v2,sizeof(LVERTEX)); g_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,v3,sizeof(LVERTEX)); g_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,v4,sizeof(LVERTEX)); g_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,v5,sizeof(LVERTEX)); g_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,v6,sizeof(LVERTEX)); g_pd3dDevice->EndScene(); g_pd3dDevice->Present( NULL, NULL, NULL, NULL ); }