開発環境 Microsoft Visual C# 2010 Express (SP1)
実行環境 Microsoft Windows XP Home Edition (SP3)
プロジェクトの種類 空のプロジェクト
プロジェクト名 MdxCreateMesh

Program.cs
using System;
using System.Threading;
using System.Windows.Forms;
 
namespace MdxCreateMesh
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            using (Form1 form = new Form1())
            using (MdxCreateMesh main = new MdxCreateMesh())
            {
                if (!main.DXInitialize(form))
                {
                    return;
                }
                form.Show();
                while (form.Created)
                {
                    main.Render();
                    Thread.Sleep(1);
                    Application.DoEvents();
                }
            }
        }
    }
}
 

Form1.cs
using System.Drawing;
using System.Windows.Forms;
 
namespace MdxCreateMesh
{
    class Form1 : Form
    {
        public Form1()
        {
            Text = "MdxCreateMesh";
            ClientSize = new Size(1280, 720);
            MaximizeBox = false;
            FormBorderStyle = FormBorderStyle.FixedSingle;
        }
    }
}
 

MdxCreateMesh.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.DirectInput;
 
namespace MdxCreateMesh
{
    class MdxCreateMesh : IDisposable
    {
        Form1 form;
        PresentParameters pp;
        Microsoft.DirectX.Direct3D.Device dev;
        Microsoft.DirectX.Direct3D.Font font;
        Microsoft.DirectX.DirectInput.Device keyboard;
        List<CustomVertex.PositionNormal> vertexList =
            new List<CustomVertex.PositionNormal>();
        List<short> indexList = new List<short>();
        Mesh mesh;
        Mesh meshBox;
        Mesh meshSphere;
        GraphicsStream adjacencyBox; // 隣接性情報
        int[] adjacency;
 
        // fps
        int fpsSec;
        int fpsDraw = 0;
        int fpsCount = 0;
 
        // カメラ
        float camDist = 10;
        int camLat = 30;
        int camLon = 210;
 
        public bool DXInitialize(Form1 topLevelForm)
        {
            try
            {
                form = topLevelForm;
 
                // キーボードデバイスの初期化
                keyboard = new Microsoft.DirectX.DirectInput.Device(SystemGuid.Keyboard);
                keyboard.SetCooperativeLevel(form,
                    CooperativeLevelFlags.NonExclusive | CooperativeLevelFlags.Background);
                keyboard.Acquire();
 
                // Direct3Dデバイス作成
                pp = new PresentParameters();
                pp.Windowed = true;
                pp.SwapEffect = SwapEffect.Discard;
                pp.AutoDepthStencilFormat = DepthFormat.D16;
                pp.EnableAutoDepthStencil = true;
                dev = new Microsoft.DirectX.Direct3D.Device(0,
                    Microsoft.DirectX.Direct3D.DeviceType.Hardware, form,
                    CreateFlags.HardwareVertexProcessing, pp);
 
                // フォントの作成
                FontDescription fd = new FontDescription();
                fd.Height = 24;
                fd.FaceName = "MS ゴシック";
                font = new Microsoft.DirectX.Direct3D.Font(dev, fd);
 
                dev.Transform.Projection = Matrix.PerspectiveFovLH(Geometry.DegreeToRadian(45),
                    (float)dev.Viewport.Width / (float)dev.Viewport.Height, 1, 100);
 
                // ライト
                //dev.RenderState.Lighting = false;
                dev.RenderState.Ambient = Color.FromArgb(0x7f, 0x7f, 0x7f);
                dev.Lights[0].Type = LightType.Directional;
                dev.Lights[0].Direction = Vector3.Normalize(new Vector3(1, -2, 3));
                dev.Lights[0].Diffuse = Color.FromArgb(0xff, 0xff, 0xff);
                dev.Lights[0].Ambient = Color.FromArgb(0x7f, 0x7f, 0x7f);
                dev.Lights[0].Enabled = true;
                dev.Lights[0].Update();
 
                CreateMesh();
                return true;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "MdxCreateMesh",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }
 
        void CreateMesh()
        {
            meshBox = Mesh.Box(dev, 1, 1, 1, out adjacencyBox);
            meshSphere = Mesh.Sphere(dev, 0.5f, 16, 8);
 
            CreateBox(-0.5f, 0.5f, -0.5f, 0.5f, -2.5f, 5); // 胴体
            CreateBox(-5, 5, -0.4f, -0.2f, -1, 1); // 主翼
            CreateBox(-2, 2, 0.2f, 0.3f, 3.5f, 4.5f); // 水平尾翼
            CreateBox(-0.05f, 0.05f, 0.5f, 1.5f, 4, 5); // 垂直尾翼
            CreateBox(-0.3f, 0.3f, 0.5f, 1, -0.5f, 1.5f); // 風防
 
            int numVertices = vertexList.Count;
            mesh = new Mesh(numVertices * 3 / 2, numVertices, MeshFlags.Managed,
                CustomVertex.PositionNormal.Format, dev);
            using (VertexBuffer vb = mesh.VertexBuffer)
            {
                GraphicsStream data = vb.Lock(0, 0, LockFlags.None);
                data.Write(vertexList.ToArray());
                vb.Unlock();
            }
            using (IndexBuffer ib = mesh.IndexBuffer)
            {
                ib.SetData(indexList.ToArray(), 0, LockFlags.None);
            }
 
            adjacency = new int[3 * mesh.NumberFaces];
            mesh.GenerateAdjacency(0.01f, adjacency);
        }
 
        void CreateBox(float x1, float x2, float y1, float y2, float z1, float z2)
        {
            int numVertices = vertexList.Count;
 
            // 頂点リスト
            Vector3[] box =
            {
                new Vector3(x2, y2, z1), new Vector3(x2, y2, z2),
                new Vector3(x2, y1, z1), new Vector3(x2, y1, z2),
                new Vector3(x1, y1, z2), new Vector3(x1, y2, z2),
                new Vector3(x1, y1, z1), new Vector3(x1, y2, z1),
            };
            Vector3 center = new Vector3((x1 + x2) / 2, (y1 + y2) / 2, (z1 + z2) / 2);
            for (int i = 0; i < 8; i++)
            {
                vertexList.Add(new CustomVertex.PositionNormal(
                    box[i], Vector3.Normalize(box[i] - center)));
            }
 
            // 索引リスト
            short[] indices =
            {
                0, 1, 2, 3, 2, 1, // +X面
                4, 5, 6, 7, 6, 5, // -X面
                0, 7, 1, 5, 1, 7, // +Y面
                4, 6, 3, 2, 3, 6, // -Y面
                0, 2, 7, 6, 7, 2, // +Z面
                4, 3, 5, 1, 5, 3, // -Z面
            };
            for (int i = 0; i < 36; i++)
            {
                indexList.Add((short)(numVertices + indices[i]));
            }
        }
 
        public void Render()
        {
            if (form.WindowState == FormWindowState.Minimized) return;
            dev.RenderState.ZBufferEnable = true;
            dev.RenderState.ZBufferWriteEnable = true;
 
            // キー入力
            const int delta = 2;
            KeyboardState state;
            state = keyboard.GetCurrentKeyboardState();
            if (state[Key.Escape])
            {
                form.Close();
                return;
            }
            if (state[Key.Up]) camLat = Math.Min(camLat + delta, 89);
            if (state[Key.Down]) camLat = Math.Max(camLat - delta, -89);
            if (state[Key.Left]) camLon = (camLon + delta) % 360;
            if (state[Key.Right]) camLon = (camLon + (360 - delta)) % 360;
            if (state[Key.PageUp]) camDist -= 0.1f;
            if (state[Key.PageDown]) camDist += 0.1f;
            if (state[Key.S] && state[Key.LeftControl])
            {
                if (SaveMesh())
                {
                    MessageBox.Show("保存しました。", "MdxCreateMesh");
                }
            }
 
            // fps
            fpsDraw++;
            int sec = DateTime.Now.Second;
            if (fpsSec != sec)
            {
                fpsCount = fpsDraw;
                fpsDraw = 0;
                fpsSec = sec;
            }
 
            // カメラ位置
            Vector3 pos;
            float rad = Geometry.DegreeToRadian(camLat);
            pos.Y = (float)Math.Sin(rad) * camDist;
            float r = (float)Math.Cos(rad) * camDist;
            rad = Geometry.DegreeToRadian(camLon);
            pos.Z = (float)Math.Cos(rad) * r;
            pos.X = (float)Math.Sin(rad) * r;
            dev.Transform.View = Matrix.LookAtLH(pos, new Vector3(), new Vector3(0, 1, 0));
 
            // バックバッファのクリア
            dev.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.CornflowerBlue, 1.0f, 0);
            dev.BeginScene();
 
            // メッシュ描画
            Material mat = new Material();
 
            dev.Transform.World = Matrix.Translation(0, 0, 0);
            mat.DiffuseColor = new ColorValue(0.0f, 0.8f, 0.0f);
            mat.AmbientColor = new ColorValue(0.0f, 0.3f, 0.0f);
            dev.Material = mat;
            mesh.DrawSubset(0);
 
            dev.Transform.World = Matrix.Translation(0, -2, 0);
            mat.DiffuseColor = new ColorValue(0.0f, 0.0f, 0.8f);
            mat.AmbientColor = new ColorValue(0.0f, 0.0f, 0.3f);
            dev.Material = mat;
            meshBox.DrawSubset(0);
 
            dev.Transform.World = Matrix.Translation(0, 2, 0);
            mat.DiffuseColor = new ColorValue(0.8f, 0.0f, 0.0f);
            mat.AmbientColor = new ColorValue(0.3f, 0.0f, 0.0f);
            dev.Material = mat;
            meshSphere.DrawSubset(0);
 
            string text = string.Format("fps={0} lat={1} lon={2} dist={3:f1}",
                fpsCount, camLat, camLon, camDist);
            font.DrawText(null, text, 0, 0, Color.White);
 
            // バックバッファを表画面に反映
            dev.EndScene();
            try
            {
                dev.Present();
            }
            catch (DeviceLostException)
            {
                ResetDevice();
            }
        }
 
        void ResetDevice()
        {
            int result;
            if (!dev.CheckCooperativeLevel(out result))
            {
                switch ((ResultCode)result)
                {
                    case ResultCode.DeviceLost:
                        Thread.Sleep(10);
                        break;
                    case ResultCode.DeviceNotReset:
                        dev.Reset(pp);
                        break;
                    default:
                        form.Close();
                        break;
                }
            }
        }
 
        bool SaveMesh()
        {
            try
            {
                ExtendedMaterial[] mtrl = new ExtendedMaterial[0];
                mesh.Save(@"C:\tmp\mesh.x", adjacency, mtrl, XFileFormat.Text);
                meshBox.Save(@"C:\tmp\box_2.x", adjacencyBox, mtrl, XFileFormat.Text);
                return true;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "エラー");
                return false;
            }
        }
 
        public void Dispose()
        {
            if (font != null)
            {
                font.Dispose();
            }
        }
    }
}
 
最終更新:2012年12月25日 16:32