回転だけなら意外と簡単です。とりあえず、MatrixとQuaternionの両方を切り替えられます。
操作「上」「下」「右」「左」「Shift+右」「Shift+左」で回転。「Q」で切り替えです。
using System; using System.Drawing; using System.Windows.Forms; using Microsoft.DirectX; using Microsoft.DirectX.Direct3D; namespace Project2 { /// <summary> /// md3d2 の概要の説明です。 /// </summary> public class md3d2:Form { //回転系 private Quaternion qua=Quaternion.Identity; private Matrix rotationMatrix = Matrix.Identity; private bool isMatrix=true; public md3d2():base() { this.MinimumSize=new Size(80,60); this.ClientSize = new Size(300,300); this.Text ="Direct3D-My"; this.KeyDown+=new KeyEventHandler(md3d2_KeyDown); this.KeyUp+=new KeyEventHandler(md3d2_KeyUp); } private Device device_; private PresentParameters presentParam_; /// <summary> /// 立方体メッシュ /// </summary> private Mesh teaMesh_; /// <summary> /// Direct3Dの初期化を行います。 /// </summary> /// <returns>初期化が成功したかどうか</returns> public bool DXInitialize() { try { presentParam_ = new PresentParameters(); presentParam_.Windowed =true; presentParam_.SwapEffect = SwapEffect.Discard; presentParam_.AutoDepthStencilFormat =DepthFormat.D16; presentParam_.EnableAutoDepthStencil=true; device_ = new Device(0,DeviceType.Hardware,this ,CreateFlags.HardwareVertexProcessing,presentParam_); device_.RenderState.ZBufferEnable=true; device_.RenderState.ZBufferWriteEnable=true; //メッシュを作成 creatMesh(); return true; } catch { return false; } } /// <summary> /// メッシュを作成する /// </summary> private void creatMesh() { teaMesh_ = Mesh.Teapot(device_); } public void Render() { if(device_==null)return; if(this.WindowState ==FormWindowState.Minimized)return; //回転計算 rotation(); //回転を行う if(isMatrix) { device_.Transform.World = rotationMatrix; this.Text="Matrix"; } else { device_.Transform.World = Matrix.RotationQuaternion(qua); this.Text="Quaternion"; } //カメラの設定を行う device_.Transform.View = Matrix.LookAtLH( new Vector3( 5.0f, 0.0f, 0.0f ), new Vector3( 0.0f, 0.0f, 0.0f ), new Vector3( 0.0f, 1.0f, 0.0f ) ); device_.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, (float)this.ClientSize.Width / (float)this.ClientSize.Height, 3.0f, 15.0f); //device_.RenderState.Lighting =false; //ライトの設定 device_.Lights[0].Direction =Vector3.Normalize(new Vector3(-1,-2,-3)); device_.Lights[0].Type = LightType.Directional; device_.Lights[0].Diffuse = Color.White; device_.Lights[0].Ambient = Color.FromArgb(255,40,40,40); device_.Lights[0].Enabled =true; device_.Lights[0].Update(); //マテリアルの設定 Material mat =new Material(); mat.AmbientColor = new ColorValue(1.0f,1.0f,0.1f); mat.DiffuseColor = new ColorValue(1.0f,1.0f,0.1f); device_.Material = mat; device_.Clear(ClearFlags.Target|ClearFlags.ZBuffer,Color.Blue,1.0f,0); device_.BeginScene(); teaMesh_.DrawSubset(0); device_.EndScene(); try { //更新 device_.Present(); } catch(DeviceLostException) { resetDevice(); } } /// <summary> /// デバイスのリセットを行う /// </summary> private void resetDevice() { int result; if(!device_.CheckCooperativeLevel(out result)) { if(result ==(int)ResultCode.DeviceLost) { //ちょっと待つ System.Threading.Thread.Sleep(10); } else if(result ==(int)ResultCode.DeviceNotReset) { device_.Reset(presentParam_); } } } //キー入力 private bool up,down,left,right,shift; private void md3d2_KeyDown(object sender, KeyEventArgs e) { switch(e.KeyCode) { case Keys.Down: down = true; break; case Keys.Up: up = true; break; case Keys.Right: right = true; break; case Keys.Left: left = true; break; case Keys.Q: isMatrix = !isMatrix; break; } shift = e.Shift; } private void md3d2_KeyUp(object sender, KeyEventArgs e) { switch(e.KeyCode) { case Keys.Down: down = false; break; case Keys.Up: up = false; break; case Keys.Right: right = false; break; case Keys.Left: left = false; break; case Keys.Shift: shift=false; break; } shift = e.Shift; } private void rotation() { float x=0,y=0,z=0; if(down) { z-=(float)Math.PI/90f; } if(up) { z+=(float)Math.PI/90f; } if(right) { if(shift) { x+=(float)Math.PI/90f; } else { y-=(float)Math.PI/90f; } } if(left) { if(shift) { x-=(float)Math.PI/90f; } else { y+=(float)Math.PI/90f; } } qua.Multiply(Quaternion.RotationYawPitchRoll(y,x,z)); rotationMatrix.Multiply(Matrix.RotationYawPitchRoll(y,x,z)); } } /// <summary> /// エントリクラス /// </summary> class Program { public static void Main() { using(md3d2 dxform =new md3d2()) { if(!dxform.DXInitialize()) { MessageBox.Show("Diret3Dの初期化に失敗しました。" ,"初期化の失敗"); return; } dxform.Show(); while(dxform.Created) { dxform.Render(); Application.DoEvents(); } } } } }
「Quaternion」も「Matrix」も掛け算をして直感に反しない回転を実現しています。つまり、回転の角度を記録しておくわけではなく、現在の傾きに新たな傾きを掛け合わせているのです。
qua.Multiply(Quaternion.RotationYawPitchRoll(y,x,z)); rotationMatrix.Multiply(Matrix.RotationYawPitchRoll(y,x,z));
ここの部分です。「*=」も使えるような気がしますが、メソッド呼び出しにしてみました。