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

プロジェクト


プロジェクトの保存
[ソリューションのディレクトリを作成]はチェックを付けなくてもいい。

プロジェクトのプロパティ
[アプリケーション]タブ
出力の種類:Windows アプリケーション

プロジェクトにクラスを追加。
テンプレート:クラス
名前:Program.cs
名前:Form1.cs
名前:MdxSample.cs

プロジェクトに新しい項目を追加。
テンプレート:アプリケーション構成ファイル
名前:App.config

プロジェクトの参照設定に追加。(.NETタブ) ※Ctrlキーで複数選択可
System
System.Drawing
System.Windows.Forms

プロジェクトの参照設定に追加。(参照タブ) ※Ctrlキーで複数選択可
C:\WINDOWS\Microsoft.NET\DirectX for Managed Code\1.0.2902.0
Microsoft.DirectX.dll
Microsoft.DirectX.Direct3D.dll
Microsoft.DirectX.Direct3DX.dll
Microsoft.DirectX.DirectInput.dll

注意
MdxSample.exeと同じディレクトリにMdxSample.exe.configがないと動作が不安定になる。

参考



LoaderLockエラーの対処
メニューから[ツール]-[設定]-[上級者設定]を選択する。
メニューから[デバッグ]-[例外]を選択する。
Managed Debugging Assistants/LoaderLockの[スローされるとき]のチェックを外す。

App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup useLegacyV2RuntimeActivationPolicy="true">
    <supportedRuntime version="v4.0"/>
  </startup>
</configuration>
 

Program.cs
using System;
using System.Threading;
using System.Windows.Forms;
 
namespace MdxSample
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            using (Form1 form = new Form1())
            using (MdxSample main = new MdxSample())
            {
                if (!main.DXInitialize(form))
                {
                    MessageBox.Show("Direct3Dの初期化に失敗しました。", "MdxSample");
                    return;
                }
                form.Show();
                while (form.Created)
                {
                    main.Render();
                    Thread.Sleep(1);
                    Application.DoEvents();
                }
            }
        }
    }
}
 

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

MdxSample.cs
using System;
using System.Drawing;
using System.Threading;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.DirectInput;
 
namespace MdxSample
{
    class MdxSample : IDisposable
    {
        Form1 form;
        PresentParameters pp;
        Microsoft.DirectX.Direct3D.Device dev;
        Microsoft.DirectX.Direct3D.Font font;
        Microsoft.DirectX.DirectInput.Device keyboard;
        VertexBuffer vertexBuffer;
 
        // fps
        int fpsSec;
        int fpsDraw = 0;
        int fpsCount = 0;
 
        // カメラ
        float camDist = 3;
        int camLat = 0;
        int camLon = 180;
 
        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.EnableAutoDepthStencil = true;
                pp.AutoDepthStencilFormat = DepthFormat.D16;
                dev = new Microsoft.DirectX.Direct3D.Device(0,
                    Microsoft.DirectX.Direct3D.DeviceType.Hardware, form.Handle,
                    CreateFlags.HardwareVertexProcessing, pp);
 
                // フォントの作成
                FontDescription fd = new FontDescription();
                fd.Height = 24;
                fd.FaceName = "MS ゴシック";
                font = new Microsoft.DirectX.Direct3D.Font(dev, fd);
 
                // 頂点バッファ
                CustomVertex.PositionColored[] vertices = new CustomVertex.PositionColored[3];
                vertices[0] = new CustomVertex.PositionColored(0, 1, 0, Color.Red.ToArgb());
                vertices[1] = new CustomVertex.PositionColored(1, -1, 0, Color.Green.ToArgb());
                vertices[2] = new CustomVertex.PositionColored(-1, -1, 0, Color.Blue.ToArgb());
 
                vertexBuffer = new VertexBuffer(typeof(CustomVertex.PositionColored),
                    3, dev, Usage.WriteOnly, CustomVertex.PositionColored.Format, Pool.Managed);
                using (GraphicsStream data = vertexBuffer.Lock(0, 0, LockFlags.None))
                {
                    data.Write(vertices);
                    vertexBuffer.Unlock();
                }
 
                dev.Transform.Projection = Matrix.PerspectiveFovLH(Geometry.DegreeToRadian(45),
                    (float)dev.Viewport.Width / (float)dev.Viewport.Height, 1, 100);
                dev.RenderState.Lighting = false;
 
                return true;
            }
            catch
            {
                return false;
            }
        }
 
        public void Render()
        {
            KeyboardState state;
            state = keyboard.GetCurrentKeyboardState();
            if (state[Key.Escape])
            {
                form.Close();
                return;
            }
            if (state[Key.Up]) camLat = Math.Min(camLat + 1, 89);
            if (state[Key.Down]) camLat = Math.Max(camLat - 1, -89);
            if (state[Key.Left]) camLon = (camLon + 1) % 360;
            if (state[Key.Right]) camLon = (camLon + 359) % 360;
            if (state[Key.PageUp]) camDist -= 0.1f;
            if (state[Key.PageDown]) camDist += 0.1f;
 
            // 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.X = (float)Math.Sin(rad) * r;
            pos.Z = (float)Math.Cos(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();
 
            dev.SetStreamSource(0, vertexBuffer, 0);
            dev.VertexFormat = CustomVertex.PositionColored.Format;
            dev.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
            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;
                }
            }
        }
 
        public void Dispose()
        {
            if (font != null)
            {
                font.Dispose();
            }
        }
    }
}
 
最終更新:2012年12月24日 21:25