
前田稔(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);
}
|
![]()