モデルの回転
前回は「移動」を行いましたが、向きが変わっていませんでした。もちろん移動する方向によって向きが変わらないとおかしいので、今回はモデルを回転させることにします。
Y軸を回転軸としてキーボードの「←→」にそれぞれモデルが回転します。

下のリンクから今回のプロジェクトをダウンロードできます。
今回のメインコードファイルを載せます。重要なコードを赤色で表示させています。
MainSample.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
namespace MDXSample
{
/// <summary>
///
/// </summary>
public partial class MainSample : IDisposable
{
/// <summary>
/// モデルのY軸回転(Degree)
/// </summary>
private float _rotate = 0.0f;
/// <summary>
///
/// </summary>
/// <param name="topLevelForm"></param>
/// <returns></returns>
/// <remarks>
///
/// </remarks>
public bool InitializeApplication(MainForm topLevelForm)
{
this._form = topLevelForm;
this.CreateInputEvent(topLevelForm);
try
{
this.CreateDevice(topLevelForm);
this.CreateFont();
this.LoadXFileMesh("Deruderu.x");
}
catch (DirectXException ex)
{
MessageBox.Show(ex.ToString(), "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
this.CreateXYZLine();
this.SettingLight();
return true;
}
/// <summary>
///
/// </summary>
public void MainLoop()
{
this.SettingCamera();
// キー操作で回転パラメータを変化
if (this._keys[(int)Keys.Left])
{
this._rotate += 5.0f;
}
if (this._keys[(int)Keys.Right])
{
this._rotate -= 5.0f;
}
this._device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.DarkBlue, 1.0f, 0);
this._device.BeginScene();
this._device.RenderState.Lighting = false;
this._device.SetTransform(TransformType.World, Matrix.Identity);
this.RenderXYZLine();
// ライトを有効
this._device.RenderState.Lighting = true;
// 回転のための座標変換
this._device.SetTransform(TransformType.World,
Matrix.RotationY(Geometry.DegreeToRadian(this._rotate)));
// メッシュの描画
this.RenderMesh();
this._font.DrawText(null, "[←→]±Angle", 0, 0, Color.White);
this._font.DrawText(null, "θ:" + this._lensPosTheta, 0, 12, Color.White);
this._font.DrawText(null, "φ:" + this._lensPosPhi, 0, 24, Color.White);
this._font.DrawText(null, "Angle:" + this._rotate, 0, 36, Color.White);
this._device.EndScene();
this._device.Present();
}
/// <summary>
///
/// </summary>
public void Dispose()
{
this.DisposeMesh();
this.DisposeXYZLine();
if (this._font != null)
{
this._font.Dispose();
}
if (this._device != null)
{
this._device.Dispose();
}
}
}
}
|
では、赤文字の部分を説明していきます。MainSamplePartial.cs ファイルのコードはこちらです。
/// <summary>
///
/// </summary>
private float _rotate = 0.0f;
|
今回は、モデルをY軸を回転軸として回転させるので、保持する値はθの値のみです。通常他にもX軸やZ軸を回転軸にしたり、または任意の回転軸を使ったりするのですが、いきなり複数の回転をやるのも難しいので、今回はY軸限定で行きます。
とりあえず値を「0.0f」で初期化します。単位は「Degree」として扱います。
if (this._keys[(int)Keys.Left])
{
this._rotate += 5.0f;
}
if (this._keys[(int)Keys.Right])
{
this._rotate -= 5.0f;
}
|
変化させる値はθのみなので、プラスかマイナスに変化できるように二つのキーを割り当てます。ほとんど今までと処理内容は同じです。
this._device.RenderState.Lighting = true;
this._device.SetTransform(TransformType.World,
Matrix.RotationY(Geometry.DegreeToRadian(this._rotate)));
this.RenderMesh();
|
処理内容が「移動」から「回転」に変わっただけです。モデルの位置情報を決定するのが「Device.SetTransform」というのは前回と同じで、第1引数に「TransformType.World」を渡します。
前回と違うのは第2引数で、回転量をマトリックスに変換しなければいけないのですが、そこで使用するのが「Matrix.RotateY」メソッドです。Y軸を回転軸にするので「Y」を使用します。もちろん他に「X」や「Z」もあるので試してみてください。
このメソッドにどのくらい回転させるかを「Radian」で渡します。今回フィールドとして持っているのは「Degree」なので「Geometry.DegreeToRadian」メソッドで「Degree」を「Radian」に変換しています。
その後メッシュを描画すれば完成です。見事にモデルが回転します。
コード的にはこれで終わりですが、計算方法や理屈などもっと知りたいなら、この下を読んでください。
まず「Matrix.RotateY」メソッドですが、渡された値を下のようなマトリックスに変換しています。

なにやら難しそうに見えますが、どうあがいてもこうなるので覚えておいてください。
では前回と同じポリゴンに来てもらいましょう。

ちょうどよく真上から見ているのでこれを使います。
では今回はポリゴンを90度まわしてみましょう。ちなみに Degree の90度は Radian の 0.5πに置き換えられます。
まず最初に0番の頂点を計算して見ます。頂点の位置ベクトルは4次元ベクトルに変換します。

残りの頂点は下のような結果になります。
- 0番目 : (1, 0, 1)
- 1番目 : (1, 0, -2)
- 2番目 : (-1, 0, 1)
- 3番目 : (-1, 0, -2)
下が図で表した結果です。

期待通りになりました。
|