
前田稔(Maeda Minoru)の超初心者のプログラム入門
![]()
![]()
/****************************************************/
/*★ Men4.x の Quaternion を使って回転 前田 稔 ★*/
/****************************************************/
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 の定義
X_Loader x_load; //X-File Load Class の定義
//回転情報の定義
InterRotDat[] Rot;
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("Men4Rot.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\Men4Rot.x");
Rot = x_load.LoadRot();
// 回転 Interpolator の設定
interrot = new InterRot(Rot);
}
//描画環境の設定
void SetupMatrices()
{
//mat= interrot.GetMat(tim);
mat= interrot.GetMat(Environment.TickCount*4);
device.Transform.World = mat;
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++)
{ 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);
}
}
}
|
/**********************************************/
/*★ 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; //回転情報の定義
//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]));
}
return _Rot;
}
//一件の回転データ(Quaternion)を設定
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;
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;
}
}
}
}
|
AnimationSet AnimationSet0 {
Animation Animation0 {
{Anim_MatrixFrame_Men4}
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;;
}
}
}
|
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"));
}
|
![]()