前田稔(Maeda Minoru)の超初心者のプログラム入門
/*********************************************/ /*★ 回転と移動のアニメーション 前田 稔 ★*/ /*********************************************/ using System; using System.Drawing; using System.Windows.Forms; using Microsoft.DirectX; using Microsoft.DirectX.Direct3D; using Direct3D=Microsoft.DirectX.Direct3D; using System.Collections; using System.IO; namespace Anime { public class Meshes : Form { Device device = null; // Our rendering device Mesh mesh = null; // Our mesh object in sysmem Direct3D.Material[] meshMaterials; // Materials for our mesh Texture[] meshTextures; // Textures for our mesh PresentParameters presentParams = new PresentParameters(); bool pause = false; InterRot interrot; //Interpolator の定義 InterMov intermov; //Interpolator の定義 X_Loader x_load; //X-File Load Class の定義 InterRotDat[] Rot; //回転情報の定義 InterMovDat[] Mov; //移動情報の定義 int tim= 0; Matrix mat; //Constructor public Meshes() { // Set the initial size of our form this.ClientSize = new System.Drawing.Size(400, 400); this.Text = "Direct3D Teapot"; } //D3DDevice の取得 bool InitializeGraphics() { try { presentParams.Windowed = true; presentParams.SwapEffect = SwapEffect.Discard; presentParams.EnableAutoDepthStencil = true; presentParams.AutoDepthStencilFormat = DepthFormat.D16; // Create the D3DDevice device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams); device.DeviceReset += new System.EventHandler(this.OnResetDevice); this.OnResetDevice(device, null); pause = false; } catch (DirectXException) { return false; } return true; } //Direct3D の初期化 public void OnResetDevice(object sender, EventArgs e) { ExtendedMaterial[] materials = null; Directory.SetCurrentDirectory(@"c:\data\xfile\"); Device dev = (Device)sender; dev.RenderState.ZBufferEnable = true; dev.RenderState.Ambient = System.Drawing.Color.White; mesh = Mesh.FromFile("Cube_Men4.x", MeshFlags.SystemMemory, device, out materials); meshMaterials = new Material[materials.Length]; meshTextures = new Texture[materials.Length]; for(int i = 0; i < meshMaterials.Length; i++) { meshMaterials[i] = materials[i].Material3D; meshMaterials[i].AmbientColor = meshMaterials[i].DiffuseColor; if ((materials[i].TextureFilename != null) && (materials[i].TextureFilename.Length > 0)) { meshTextures[i] = TextureLoader.FromFile(dev, materials[i].TextureFilename); } } // 法線情報がなければ計算して作成 if ((mesh.VertexFormat & VertexFormats.Normal) == 0) { Mesh temporaryMesh = mesh.Clone(mesh.Options.Value, mesh.VertexFormat | VertexFormats.Normal, device); // 法線を計算 temporaryMesh.ComputeNormals(); // 古いメッシュを破棄し、置き換える mesh.Dispose(); mesh = temporaryMesh; } // アニメーションデータの入力 x_load = new X_Loader(@"c:\data\xfile\Cube_Men4.x"); // 回転 Interpolator の設定 Rot = x_load.LoadRot(); interrot = new InterRot(Rot); // 移動 Interpolator の設定 Mov = x_load.LoadMov(); intermov = new InterMov(Mov); } //描画環境の設定 void SetupMatrices() { device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f,1.0f,-5.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), 1.0f,1.0f,500.0f); } //ライトの設定 private void SetupLights() { System.Drawing.Color col = System.Drawing.Color.White; Direct3D.Material mtrl = new Direct3D.Material(); mtrl.Diffuse = col; mtrl.Ambient = col; device.Material = mtrl; device.Lights[0].Type = LightType.Directional; device.Lights[0].Diffuse = System.Drawing.Color.FromArgb(0xF0F020); device.Lights[0].Direction = new Vector3(50.0f, -40.0f, 100.0f); device.Lights[0].Enabled = true; device.RenderState.Ambient = System.Drawing.Color.FromArgb(0x202020); } //モデルの描画 private void Render() { if (device == null) return; if (pause) return; device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, System.Drawing.Color.Gray, 1.0f, 0); device.BeginScene(); SetupLights(); SetupMatrices(); for(int i=0; i<meshMaterials.Length; i++) { if (i<6) mat = interrot.GetMat(Environment.TickCount*4); else mat = intermov.GetMat(Environment.TickCount * 4); device.Transform.World = mat; device.Material = meshMaterials[i]; device.SetTexture(0, meshTextures[i]); mesh.DrawSubset(i); } device.EndScene(); device.Present(); } //マウスのクリックを検出 protected override void OnMouseDown(MouseEventArgs e) { tim+= 20; } //アニメーションの間隔 protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) { this.Render(); } protected override void OnKeyPress(System.Windows.Forms.KeyPressEventArgs e) { if ((int)(byte)e.KeyChar == (int)System.Windows.Forms.Keys.Escape) this.Dispose(); // Esc was pressed } protected override void OnResize(System.EventArgs e) { pause = ((this.WindowState == FormWindowState.Minimized) || !this.Visible); } //☆ Main() メソッド static void Main() { using (Meshes frm = new Meshes()) { if (!frm.InitializeGraphics()) // Initialize Direct3D { MessageBox.Show("Could not initialize Direct3D. This tutorial will exit."); return; } frm.Show(); // While the form is still valid, render and process messages while (frm.Created) { frm.Render(); Application.DoEvents(); } } } } } |
/*******************************************/ /*★ Interpolator Class(回転) 前田 稔 ★*/ /*******************************************/ using System; using System.Drawing; using System.Windows.Forms; using Microsoft.DirectX; using Microsoft.DirectX.Direct3D; using Direct3D=Microsoft.DirectX.Direct3D; using System.Collections; namespace Anime { //Rotation Interpolator Data class InterRotDat { public int Tim; public Quaternion Qt; //InterRotDat Constructor public InterRotDat(int tim, Quaternion qt) { Tim= tim; //Qt= Quaternion.Normalize(qt); Qt= qt; } public void Print() { Console.WriteLine("Time={0} {1},{2},{3},{4}", Tim, Qt.X, Qt.Y, Qt.Z, Qt.W); } } //☆Interpolator Class class InterRot { InterRotDat[] Rot; int Leng; //InterRot Constructor public InterRot(InterRotDat[] rot) { Rot= rot; Leng= Rot.GetLength(0)-1; } //tim の Matrix を計算 public Matrix GetMat(int tim) { int wk,i; float rate; Quaternion wqt; wk= tim % Rot[Leng].Tim; for(i=0; i<Leng && Rot[i].Tim<wk; i++); if (Rot[i].Tim==wk) return Matrix.RotationQuaternion(Rot[i].Qt); rate= (float)(wk-Rot[i-1].Tim)/(float)(Rot[i].Tim-Rot[i-1].Tim); wqt = Quaternion.Slerp(Rot[i-1].Qt, Rot[i].Qt, rate); return Matrix.RotationQuaternion(wqt); } } } |
/*******************************************/ /*★ Interpolator Class(移動) 前田 稔 ★*/ /*******************************************/ using System; using System.Drawing; using System.Windows.Forms; using Microsoft.DirectX; using Microsoft.DirectX.Direct3D; using Direct3D=Microsoft.DirectX.Direct3D; using System.Collections; namespace Anime { //Moving Interpolator Data class InterMovDat { public int Tim; public Vector3 V3; //InterMovDat Constructor public InterMovDat(int tim, Vector3 v3) { Tim= tim; V3= v3; } public void Print() { Console.WriteLine("Time={0} {1},{2},{3}", Tim, V3.X, V3.Y, V3.Z); } } //☆Interpolator Class class InterMov { InterMovDat[] Mov; int Leng; //Interpolator Constructor public InterMov(InterMovDat[] mov) { Mov= mov; Leng= Mov.GetLength(0)-1; } //tim の Matrix を計算 public Matrix GetMat(int tim) { int wk,i; float rate; Vector3 wv3; wk= tim % Mov[Leng].Tim; for(i=0; i<Leng && Mov[i].Tim<wk; i++); if (i==0 || Mov[i].Tim==wk) return Matrix.Translation(Mov[i].V3); rate= (float)(wk-Mov[i-1].Tim)/(float)(Mov[i].Tim-Mov[i-1].Tim); wv3 = Vector3.Lerp(Mov[i-1].V3, Mov[i].V3, rate); return Matrix.Translation(wv3); } } } |
/****************************************************/ /*★ X-FILE の回転(移動)情報を入力する 前田 稔 ★*/ /****************************************************/ using System; using System.IO; // for File, StreamReader using System.Text; // for Encoding using System.Windows.Forms; using System.Drawing; using Microsoft.DirectX; namespace Anime { //X-File Load Class class X_Loader : IDisposable { StreamReader reader; public string BUF; //文字列入力領域 int LT,RT; //Index Left,Right InterRotDat[] _Rot; //回転情報の定義 InterMovDat[] _Mov; //移動情報の定義 //Constructor public X_Loader(string x_file) { if (!File.Exists(x_file)) { MessageBox.Show("X-File が見つかりません",x_file); return; } reader = new StreamReader(x_file,Encoding.GetEncoding("Shift_JIS")); } //Destructor ~X_Loader() { Dispose(); } //Dispose() 関数 public void Dispose() { reader.Close(); GC.SuppressFinalize(this); } //回転アニメーションデータを入力 public InterRotDat[] LoadRot() { int val=0,tim,i; float[] fval; //Skip("AnimationSet "); while(Skip("AnimationKey ")) { NextRead(); val = Val(); if (val==0) break; } if (val!=0) { MessageBox.Show("回転データが見つかりません"); return null; } NextRead(); val = Val(); //テーブルの件数 _Rot= new InterRotDat[val]; for(i=0; i<val; i++) { NextRead(); tim = Val(); //Time を入力 fval= OneLine(); _Rot[i] = new InterRotDat(tim, new Quaternion(fval[0], fval[1], fval[2], fval[3])); _Rot[i].Print(); } return _Rot; } //移動アニメーションデータを入力 public InterMovDat[] LoadMov() { int val=0,tim,i; float[] fval; //Skip("AnimationSet "); while(Skip("AnimationKey ")) { NextRead(); val = Val(); if (val==2) break; } if (val!=2) { MessageBox.Show("移動データが見つかりません"); return null; } NextRead(); val = Val(); //テーブルの件数 _Mov= new InterMovDat[val]; for(i=0; i<val; i++) { NextRead(); tim = Val(); //Time を入力 fval= OneLine(); _Mov[i] = new InterMovDat(tim, new Vector3(fval[0], fval[1], fval[2])); _Mov[i].Print(); } return _Mov; } //一件のデータ(回転,移動)を設定 public float[] OneLine() { int val,i; float[] fval; fval= new float[4]; val = Val(); //個数を入力 for(i=0; i<val; i++) { fval[i] = FVal(); } return fval; } //次の有効な行を入力(/ はコメント行) public bool NextRead() { int i; while((BUF=reader.ReadLine()) != null) { for(i=0; i<BUF.Length && (BUF[i]==' ' || BUF[i]=='\t'); i++); if (i<BUF.Length && BUF[i]!='/') { RT = 0; return true; } } return false; } //key の行まで読み飛ばす public bool Skip(string key) { while((BUF=reader.ReadLine()) != null) { LT = BUF.IndexOf(key); if (LT!=-1) { RT= LT+key.Length; //Console.WriteLine(BUF); return true; } } return false; } //BUF[RT] から次の int を取得 public int Val() { string wk; while (true) { for(LT=RT; LT<BUF.Length && BUF[LT]!='-' && (BUF[LT]<'0' || BUF[LT]>'9'); LT++); if (LT<BUF.Length) { for (RT=LT+1; RT<BUF.Length && (BUF[RT]>='0' && BUF[RT]<='9'); RT++); wk = BUF.Substring(LT, RT-LT); return int.Parse(wk); } if (NextRead()==false) return -1; } } //BUF[RT] から次の float を取得 public float FVal() { string wk; while (true) { for(LT=RT; LT<BUF.Length && BUF[LT]!='-' && (BUF[LT]<'0' || BUF[LT]>'9'); LT++); if (LT<BUF.Length) { for(RT=LT+1; (RT<BUF.Length && (BUF[RT]>='0' && BUF[RT]<='9') || BUF[RT]=='.'); RT++); wk = BUF.Substring(LT, RT-LT); return float.Parse(wk); } if (NextRead()==false) return -1.0f; } } //Printout() 関数 public void Print() { while((BUF=reader.ReadLine()) != null) { Console.WriteLine(BUF); } } } } |
xof 0303txt 0064 Header { 1; 0; 1; } //※長方体 Frame Frame_World { Frame Anim_MatrixFrame_Box { } Frame Frame_ModelDef { Mesh { 8; -1.0;-1.0;-1.0;, -1.0;0.0;1.0;, -1.0;0.0;-1.0;, -1.0;-1.0;1.0;, 1.0;-1.0;-1.0;, 1.0;0.0;1.0;, 1.0;0.0;-1.0;, 1.0;-1.0;1.0;; 6; 4;0,3,1,2;, 4;4,0,2,6;, 4;6,2,1,5;, 4;5,1,3,7;, 4;7,3,0,4;, 4;4,6,5,7;; MeshMaterialList { 6; 6; 0, 1, 2, 3, 4, 5; Material { 0.0;1.0;1.0;1.0;; 21.3; 0.0;0.0;0.0;; 0.0;0.0;0.0;; } Material { 1.0;0.0;1.0;1.0;; 21.3; 0.0;0.0;0.0;; 0.0;0.0;0.0;; } Material { 0.0;0.0;1.0;1.0;; 21.3; 0.0;0.0;0.0;; 0.0;0.0;0.0;; } Material { 1.0;1.0;0.0;1.0;; 21.3; 0.0;0.0;0.0;; 0.0;0.0;0.0;; } Material { 1.0;0.0;0.0;1.0;; 21.3; 0.0;0.0;0.0;; 0.0;0.0;0.0;; } Material { 0.0;1.0;0.0;1.0;; 21.3; 0.0;0.0;0.0;; 0.0;0.0;0.0;; } } MeshNormals { 6; -1.000000;0.000000;0.000000;, 0.000000;0.000000;-1.000000;, 0.000000;1.000000;0.000000;, 0.000000;0.000000;1.000000;, 0.000000;-1.000000;0.000000;, 1.000000;0.000000;0.000000;; 6; 4;0,0,0,0;, 4;1,1,1,1;, 4;2,2,2,2;, 4;3,3,3,3;, 4;4,4,4,4;, 4;5,5,5,5;; } XSkinMeshHeader { 4; 3; 1; } SkinWeights { "Anim_MatrixFrame_Box"; 24; 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23;; 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0, 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0, 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0;; -0.99995, 0.00999, 0.0, 0.0, -0.00999, -0.99995, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0;; } } // End of Mesh } // End of "ModelDef" frame } // End of "World" frame //※四面体 Frame Frame_World { Frame Anim_MatrixFrame_Men4 { } Frame Frame_ModelDef { Mesh { 12; -1.0; -0.40825; 0.57735;, 1.0; -0.40825; 0.57735;, 0.0; 1.22474; 0.0;, 0.0; -0.40825; -1.1547;, 0.0; 1.22474; 0.0;, 1.0; -0.40825; 0.57735;, 0.0; 1.22474; 0.0;, 0.0; -0.40825; -1.1547;, -1.0; -0.40825; 0.57735;, 1.0; -0.40825; 0.57735;, -1.0; -0.40825; 0.57735;, 0.0; -0.40825; -1.1547;; 4; 3;0,1,2;, 3;3,4,5;, 3;6,7,8;, 3;9,10,11;; MeshMaterialList { 4; 4; 0, 1, 2, 3; Material { 1.0;0.0;0.0;1.0;; 21.3; 0.0;0.0;0.0;; 0.0;0.0;0.0;; } Material { 1.0;1.0;0.0;1.0;; 21.3; 0.0;0.0;0.0;; 0.0;0.0;0.0;; } Material { 0.0;0.0;1.0;1.0;; 21.3; 0.0;0.0;0.0;; 0.0;0.0;0.0;; } Material { 0.0;1.0;0.0;1.0;; 21.3; 0.0;0.0;0.0;; 0.0;0.0;0.0;; } } MeshNormals { 12; -0.82;-0.33;0.47;, 0.82;-0.33;0.47;, 0.00;1.00;-0.00;, 0.00;-0.33;-0.94;, 0.00;1.00;-0.00;, 0.82;-0.33;0.47;, 0.00;1.00;-0.00;, 0.00;-0.33;-0.94;, -0.82;-0.33;0.47;, 0.82;-0.33;0.47;, -0.82;-0.33;0.47;, 0.00;-0.33;-0.94;; 4; 3;0,1,2;, 3;3,4,5;, 3;6,7,8;, 3;9,10,11;; } XSkinMeshHeader { 4; // nMaxSkinWeightsPerVertex 3; // nMaxSkinWeightsPerFace 1; // nBones } // End of XSkinMeshHeader SkinWeights { "Anim_MatrixFrame_Men4"; 12; 0,1,2,3,4,5,6,7,8,9,10,11;; 1.000000,1.000000,1.000000,1.000000, 1.000000,1.000000,1.000000,1.000000, 1.000000,1.000000,1.000000,1.000000; 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0;; } // End of SkinWeights } // End of Mesh } // End of "ModelDef" frame } // End of "World" frame AnimationSet AnimationSet0 { Animation Animation0 { {Anim_MatrixFrame_Box} AnimationKey { 0; // Rotation 5; 0;4; 0.00, 0.72, 0.00, 0.70;; 2000;4; 0.00, 0.00, 0.00, 1.00;; 4000;4; 0.00, -0.72, 0.00, 0.70;; 6000;4; 0.00, 0.00, 0.00, 1.00;; 8000;4; 0.00, 0.72, 0.00, 0.70;; } } Animation Animation1 { {Anim_MatrixFrame_Men4} AnimationKey { 2; // Position 9; 0;3; 0.00,1.11,0.0;;, 840;3; 0.22,2.97,0.00;;, 1260;3; 0.32,2.88,0.00;;, 2160;3; 0.18,2.34,0.00;;, 2580;3; 0.09,1.23,0.00;;, 3900;3;-0.23,0.42,0.00;;, 4980;3;-0.21,1.00,0.00;;, 5820;3;-0.08,0.45,0.00;;, 8700;3; 0.00,0.40,0.00;;; } } } |
for(int i=0; i<meshMaterials.Length; i++) { device.Material = meshMaterials[i]; device.SetTexture(0, meshTextures[i]); mesh.DrawSubset(i); } |
InterRot interrot; //Interpolator の定義 InterMov intermov; //Interpolator の定義 X_Loader x_load; //X-File Load Class の定義 InterRotDat[] Rot; //回転情報の定義 InterMovDat[] Mov; //移動情報の定義 x_load = new X_Loader(@"c:\data\xfile\Cube_Men4.x"); // 回転 Interpolator の設定 Rot = x_load.LoadRot(); interrot = new InterRot(Rot); // 移動 Interpolator の設定 Mov = x_load.LoadMov(); intermov = new InterMov(Mov); |
for(int i=0; i<meshMaterials.Length; i++) { if (i<6) mat = interrot.GetMat(Environment.TickCount * 4); else mat = intermov.GetMat(Environment.TickCount * 4); device.Transform.World = mat; device.Material = meshMaterials[i]; device.SetTexture(0, meshTextures[i]); mesh.DrawSubset(i); } |