Windows フォームへの 3D 描画 2
~ Cutting Edge DX 9 - 第 22 回目 ~
Hiroyuki Kawanishi (川西 裕幸)
マイクロソフト株式会社
テクニカル エバンジェリスト
2005 年 3 月 23 日
今回は、Windows フォーム上のピクチャ ボックスに 3D メッシュを描画する方法を紹介します。ピクチャ ボックスに描画すれば、ボタンのような他の .NET Framework コンポーネントと一緒に表示させることができるので便利です。また、System.Windows.Forms.ColorDialog 使って3D メッシュの色を指定できるようにします。この文章では、前回の Windows フォームへの描画サンプルとの違いに焦点を当てて説明します。
この記事のソースコードをダウンロードする (meshInPB.zip, 4 KB)
目次
サンプルの使い方
Direct3D デバイスの作成
メッシュオブジェクトの作成
色の設定
メッシュの描画
最後に
サンプルの使い方
- Visual Studio .NET 2003 から [ファイル] → [新規作成] で、ダイアログの [Windows アプリケーション] を選択し、プロジェクト名と場所を設定して、[OK] ボタンをクリックします。
- 作成されたプロジェクト フォルダに、ダウンロードした meshInPB.cs をコピーします。
- [ソリューション エクスプローラ] で、Form1.cs, App.ico, AssemblyInfo.cs を右クリックし [プロジェクトから削除] を選択します。
- [ソリューション エクスプローラ] でプロジェクト名を右クリックし、[追加] → [既存項目の追加] を選び、既存項目の追加ダイアログで meshInPB.cs を選択します。
- [ソリューション エクスプローラ] で [参照設定] を右クリックし、[参照の追加] を選択し、ダイアログから Microsoft.DirectX, Microsoft.DirectX.Direct3D, Microsoft.DirectX.Direct3DX を [選択] し [OK] をクリックします。複数のバージョンがあるときは、すべて最新のものにしたほうがよいでしょう。
- F5 キーでコンパイル・実行できます。
注意 : このサンプルをビルド・実行するには、DirectX 9.0 SDK Update (Summer 2004) 以降が必要です。
Direct3D デバイスの作成
Direct3D デバイスを作成するとき、前回は第 3 引数に (Form に描画するので) Form オブジェクトを渡しました。今回はそこに PictureBox オブジェクトを引数として渡します。実は、描画先をフォームからピクチャ ボックスに変更するのに必要な修正はその部分だけです。フォームではなくピクチャ ボックスに描画することによって、ボタンなどの他のコントロールが使えるようになります。ボタンなどの作成とコールバックはコードの終わりのほうにあります。
private System.Windows.Forms.PictureBox renderTarget;
...
// Direct3D デバイスの作成に使う構造体を設定する。
presentParams = new PresentParameters();
presentParams.Windowed = true;
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.EnableAutoDepthStencil = true;
presentParams.AutoDepthStencilFormat = DepthFormat.D16;
// Direct3D デバイスの作成
device = new Device(0, DeviceType.Hardware, this.renderTarget, // ピクチャ ボックス
CreateFlags.SoftwareVertexProcessing, presentParams);
device.DeviceReset += new System.EventHandler(this.OnResetDevice);
this.OnResetDevice(device, null);
pause = false;
あるいは、フォームを引数として Direct3D デバイスを作成して、描画時にピクチャ ボックスを指定することも可能です。この手法なら、1 つのデバイスで複数のピクチャ ボックスに別々に描画することもできます。その手法については次回紹介します。
メッシュ オブジェクトの作成
Direct3D.Mesh クラスにはティーポット以外に、円柱 (Cylinder)、球 (Sphere) などの作成メソッドがあることは紹介しました。今回はボタンの操作からそれらを生成し直して、描画しています。円柱や球のコンストラクタには Direct3D デバイス以外の引数があり、メッシュの大きさや細かさを指定できます、詳細はドキュメントを参照してください。
// ボタン操作のコールバック ティーポット
private void button1_Click(object sender, System.EventArgs e)
{
meshObject.Dispose();
meshObject = null;
meshObject = Mesh.Teapot(device);
}
// ボタン操作のコールバック 円柱
private void button2_Click(object sender, System.EventArgs e)
{
meshObject.Dispose();
meshObject = null;
meshObject = Mesh.Cylinder(device, 0.5f, 0.5f, 2.0f, 10, 10);
}
// ボタン操作のコールバック 球
private void button3_Click(object sender, System.EventArgs e)
{
meshObject.Dispose();
meshObject = null;
meshObject = Mesh.Sphere(device, 1.0f, 10, 10);
}
色の設定
メッシュ オブジェクトの色はライトの色とマテリアルの色から決まります。前回はどちらも白でしたので、灰色の陰影を持つ白いティーポットが描画されました。今回はカラー ダイアログ System.Windows.Forms.ColorDialog クラスを使って、マテリアルの色を変更できるようにしました。カラー ダイアログの使い方は通常のアプリケーションと同じです。コールバックの中でカラー ダイアログから取得した色をディフューズ マテリアルに代入します。
Material mtrl;
...
// マテリアルの設定
mtrl = new Material();
mtrl.Diffuse = Color.White;
...
// ボタン操作のコールバック カラーダイアログ
private void button4_Click(object sender, System.EventArgs e)
{
// カラー ダイアログの表示
ColorDialog cd = new ColorDialog();
cd.FullOpen = true;
cd.Color = Color.FromArgb(mtrl.Diffuse.ToArgb());
cd.ShowDialog();
// マテリアル デュフューズ色の設定
mtrl.Diffuse = cd.Color;
}
メッシュの描画
前回はマテリアルの変更がなかったので、描画前に 1 回だけ設定していましたが、このサンプル コードでは描画するたびに (DrawSubset を呼び出す前に) マテリアルを設定しています。コールバックの中でデバイスに設定してもかまいませんが、複数のメッシュを別のマテリアルで描画することが多いので、一般に DrawSubset の前にマテリアル (あるいはテクスチャ) を設定する手順がよく使われます。
private void Render()
{
if (device == null || pause) return;
// バックバッファを青色にクリア、Z バッファもクリア
device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, System.Drawing.Color.DarkBlue, 1.0f, 0);
// シーンの開始
device.BeginScene();
// ワールド・ビュー・投影行列を設定
SetupMatrices();
// マテリアルの設定
device.Material = mtrl;
// メッシュ サブセットを描画
meshObject.DrawSubset(0);
// シーンの終了
device.EndScene();
// シーンの更新
try { device.Present(); }
// デバイス消失のチェックとリセット
catch (DeviceLostException) { OnDeviceLostException(); }
}
最後に
今回は、回転するメッシュ オブジェクトを Windows フォーム上のピクチャ ボックスに描画する単純なサンプルを紹介しました。次回はピクチャ ボックスに表示した複数のジオメトリ オブジェクトをマウスでクリックすると、クリックされたオブジェクトを別のピクチャ ボックスに表示するサンプルを紹介します。
この文章へのご意見やフィードバックは GDNJ Managed DirectX 掲示板に投稿してください。