3Dモデルを描画する
Windows Phoneアプリケーションで3Dモデルを利用する場合、XNA Frameworkを使用する必要があります。XNA Frameworkを使用して、3Dモデルを描画するアプリケーションを作成する方法を以下に記載します。なお、実際にアプリケーションを作成する様子を動画として用意しましたので、以降の説明を補足する資料として参照してください。
1. Silverlight/XNAプロジェクトを作成する
今回は、新規に作成したSilverlight/XNAアプリケーションにおいて3Dモデルを描画します。このため、Visual Studioの[ファイル]メニューから[新しいプロジェクト]を選択し、[Silverlight for Windows Phone]カテゴリの一覧から[Windows Phone Silverlight/XNA アプリケーション]プロジェクトテンプレートを選択します。
2. 3Dモデルを追加して読み込む
以前の記事でも解説した通り、XNA Frameworkを利用して2D画像や3Dモデルを描画するには、Contentプロジェクトにファイルを追加する必要があります。このため、Visual Studioのソリューションエクスプローラから「SlXnaAppLibContent」プロジェクトを選択し、コンテキストメニューから[追加]-[既存の項目]を選択して、前項で出力した「Droid.x」ファイルを追加します。
追加した3Dモデルをコード内で使用するには、Microsoft.Xna.Framework.Graphics.Modelクラスを利用します。「SlXnaAppLib」プロジェクトの「GamePage.xaml.cs」ファイルを開いてフィールドにModelクラスを定義し、PhoneApplicationPage.OnNavigatedTo()メソッド内においてContentManager.Load()メソッドを実行して3Dモデルを読み込みます。
public partial class GamePage : PhoneApplicationPage
{
…
Model model;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
…
// 3Dモデルを読み込みます
model = this.contentManager.Load<Model>("Droid");
…
}
}
3. 行列を設定して描画する
読み込んだ3Dモデルを描画するには、「ワールド行列」「ビュー行列」「プロジェクション行列」という3つの行列を作成する必要があります。ここでいう行列とは、3Dモデルを3D空間に配置して撮影するために必要となる情報のことです。各行列は、それぞれ以下の情報を定義し、Microsoft.Xna.Framework.Matrix構造体のメソッドを用いて作成できます。
-
ワールド行列は、3Dモデルの位置と向きと傾きを定義します。
Matrix.CreateWorld()メソッドを利用して作成できます。 -
ビュー行列は、カメラの位置と向きと傾きを定義します。
Matrix.CreateLookAt()メソッドを利用して作成できます。 -
プロジェクション行列は、カメラのレンズの視野角と縦横比と撮影範囲を定義します。
Matrix.CreatePerspectiveFieldOfView()メソッドを利用して作成できます。
これらの行列をGameTimer.OnDrawイベント内で作成し、Model.Draw()メソッドに指定して実行することにより、3Dモデルを描画できます。例えば下記のコードでは、まず3Dモデルを3D空間の中心に置き、前向きかつ垂直に配置します。次に、カメラを3Dモデルの前方やや上方に置き、3Dモデルの方向を向かせて垂直に配置します。最後に、カメラのレンズの視野角を一般的な45度に設定し、Windows Phoneの画面比率を用いて、直近から適当な距離までを撮影対象とします。
private void OnDraw(object sender, GameTimerEventArgs e)
{
…
// 3Dモデルの位置と向きと傾きを定義します
Matrix world = Matrix.CreateWorld(Vector3.Zero, Vector3.Forward, Vector3.Up);
// カメラの位置と向きと傾きを定義します
Matrix view = Matrix.CreateLookAt(new Vector3(0, 50, 150), new Vector3(0, 50, 0), Vector3.Up);
// カメラのレンズの視野角と縦横比と撮影範囲を定義します
Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45),
SharedGraphicsDeviceManager.Current.GraphicsDevice.Viewport.AspectRatio, 0.1f, 1000f);
// 3Dモデルを描画します
model.Draw(world, view, projection);
}
上記のコード内で使用しているVector3構造体は、3D空間におけるベクトル(X、Y、Z)を定義します。前方や上方などの頻繁に利用される値は、静的プロパティとして提供されています。
上記のコードを実行してGamePageに遷移すると、以下のように3Dモデルが描画されます。
4. エフェクトを設定する
3Dモデルを描画する場合、エフェクトという描画効果を設定できます。例えば、上記で描画した3Dモデルは単一色で描画されており、立体感がありません。これは、3Dモデルにライティングが設定されておらず、陰影が表現されていないためです。XNAで3Dモデルを描画する場合、このようなライティングもエフェクトとして設定する必要があります。
XNAには、基本的なエフェクトを提供するMicrosoft.Xna.Framework.Graphics.BasicEffectクラスが用意されています。例えば、3Dモデルに単純なライティングを設定する場合、描画処理を以下のように実装します。この際、エフェクトはメッシュと呼ばれるグループごとに設定する必要があるため、上記で使用したModel.Draw()メソッドの代わりに、ModelMesh.Draw()メソッドを使用します。
private void OnDraw(object sender, GameTimerEventArgs e)
{
…
//model.Draw(world, view, projection);
// ライティングを有効にして3Dモデルを描画します
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.World = world;
effect.View = view;
effect.Projection = projection;
effect.EnableDefaultLighting();
}
mesh.Draw();
}
}
上記のコードを実行してGamePageに遷移すると、立体的な3Dモデルが描画されます。
以上の手順により、3Dモデルの描画は完了です。次項では、行列に関する応用知識として、3Dモデルを操作する方法を紹介します。





