Sample Brower でティーポットを描画

Sample Brower で生成したプロジェクトでティーポットを描画します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの作成

  1. DirectX のプロジェクトは Sample Brower を使って生成する方法がお勧めです。
    Sample Brower から提供されるサンプルは、何も手を加えなくてもそのまま実行できます。
    Tiny のアニメーション などはその例です。
    ここでは Sample Brower を使ってティーポットのメッシュを描画する方法を説明します。
  2. [スタート] から [プログラム][Microsoft DirectX] を選択して [DirectX Sample Browser] を実行して下さい。
    Managed から「EmptyProject」の「Install Project」をクリックすると、自動的に空のプロジェクトが構築されます。
    DirectX のバージョンによっては Sample Browser に Managed Mode が含まれていない場合があります。
    作成されたプロジェクトをそのままコンパイルして、空のウインドウが表示される事を確かめて下さい。
    エラーが発生するときや、正常に実行出来ないときは、残念ながら現在の構成は相性が悪いようです。
    詳細は「Tiny のアニメーション」を参照して下さい。
  3. 生成された EmptyProject から、次のファイルを残して削除して下さい。
    ・Common のフォルダー
    ・EmptyProject_2005.csproj
    次に下記のファイルを格納して下さい。
    ファイル名 説明
    EmptyProject.cs ティーポットを描画
  4. EmptyProject_2005.csproj から起動して下さい。
    x86 に設定してコンパイル&実行をするとティーポットのメッシュが描画されます。
    メッシュの描画は トーラスをライトで照らして描画する を参照して下さい。

プログラムの説明

  1. プロジェクトの共通領域です。
    sampleFramework は Direct3D を制御する Framework Class です。
    mesh はティーポットのメッシュです。
    aspectRatio は縦横比です。
            private Framework sampleFramework = null;
            private Mesh    mesh = null;
            private float   aspectRatio = 1.0f;
    
  2. OnCreateDevice() でティーポットのメッシュを生成します。
            private void OnCreateDevice(object sender, DeviceEventArgs e)
            {
                mesh = Mesh.Teapot(e.Device);
            }
    
  3. OnResetDevice() でマテリアルとライトを設定します。
            private void OnResetDevice(object sender, DeviceEventArgs e)
            {   SurfaceDescription desc = e.BackBufferDescription;
                aspectRatio = (float)desc.Width / (float)desc.Height;
    
                //☆ マテリアルとライトを設定する
                System.Drawing.Color col = System.Drawing.Color.White;
                Microsoft.DirectX.Direct3D.Material mtrl = new Microsoft.DirectX.Direct3D.Material();
                mtrl.Diffuse = col;
                mtrl.Ambient = col;
                e.Device.Material = mtrl;
    
                e.Device.Lights[0].Type = LightType.Directional;
                e.Device.Lights[0].Diffuse = System.Drawing.Color.DarkTurquoise;
    
                e.Device.Lights[0].Direction = new Vector3(50.0f, -40.0f, 100.0f);
                e.Device.Lights[0].Enabled = true;
                e.Device.RenderState.Ambient = System.Drawing.Color.FromArgb(0x202020);
            }
    
  4. OnFrameMove() で View と Projection を設定します。
            public void OnFrameMove(Device device, double appTime, float elapsedTime)
            {   device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 2.0f, -7.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), aspectRatio, 1.0f, 500.0f);
            }
    
  5. OnFrameRender() でティーポットのメッシュを描画します。
            public void OnFrameRender(Device device, double appTime, float elapsedTime)
            {   bool beginSceneCalled = false;
    
                // Clear the render target and the zbuffer 
                device.Clear(ClearFlags.ZBuffer | ClearFlags.Target, 0x002D32AA, 1.0f, 0);
                try
                {   device.BeginScene();
                    beginSceneCalled = true;
                    mesh.DrawSubset(0);
                }
                finally
                {   if (beginSceneCalled)   device.EndScene();  }
            }
    
  6. ティーポットをタイマで自動的に回転してみましょう。
    自動的に回転するのは簡単で、次の行のコメントを外すだけです。
            public void OnFrameMove(Device device, double appTime, float elapsedTime)
            {
                //device.Transform.World = Matrix.RotationY(Environment.TickCount / 1000.0f);
                device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 2.0f, -7.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), aspectRatio, 1.0f, 500.0f);
            }
    

メニューを設定する

  1. 先のプロジェクトにプログラムの終了とバージョン表示のメニューを設定します。
    using に Forms を追加して下さい。
    using System.Windows.Forms;
  2. プロジェクトの共通領域に menu を追加します。
            static  MainMenu menu = null;
    
  3. EmptyProject の Constructor で MainMenu() を生成します。
            public EmptyProject(Framework f) 
            {   sampleFramework = f;
    
                // メインメニューを生成
                menu = new MainMenu();
                MenuItem item = menu.MenuItems.Add("ファイル(&F)");
                item.MenuItems.Add(new MenuItem("終了(&X)", new EventHandler(this.FileExit), Shortcut.CtrlQ));
                item = menu.MenuItems.Add("ヘルプ(&H)");
                item.MenuItems.Add(new MenuItem("バージョン情報(&A)...", new EventHandler(this.HelpAbout)));
            }
    
  4. メニューを使用する CreateWindow() を呼び出します。
        //sampleFramework.CreateWindow("EmptyProject");
        sampleFramework.CreateWindow("EmptyProject",null,menu,-1,-1);
    
  5. メニューを処理する関数です。
            // ファイル/終了メニューのイベントハンドラ
            private void FileExit(object sender, EventArgs e)
            {
                sampleFramework.Dispose();
            }
    
            // ヘルプ/バージョン情報メニューのイベントハンドラ
            private void HelpAbout(object sender, EventArgs e)
            {
                MessageBox.Show("Project Menu Ver 1.0  Maeda Minoru");
            }
    
  6. 本来ならこれでメニューが設定されるはずなのですが CreateWindow() にミス(手抜き?)があるようです。 (^_^;)
    それとも、これぐらいのことが解らないようなら DirectX を使う資格が無いと言う事なのでしょうか?
    Common のフォルダーの dxmut.cs を開いて下さい。
    CreateWindow() に次のコードを追加します。
        public void CreateWindow(string windowTitle, System.Drawing.Icon icon, 
            System.Windows.Forms.MainMenu menu, int x, int y)
        {
                ・
                ・
                ・
            // Store the window title
            State.WindowTitle = windowTitle;
            renderWindow.Text = windowTitle;
    
            //+++ 追加するコードです
            if (menu != null)
            {
                State.Menu = menu;
                renderWindow.Menu = menu;
            }
    

マウスの操作で回転する

  1. ティーポットをマウスの操作で回転します。
    マウスをキャプチャーしてモデルを回転するプログラムは結構面倒なのですが、ModelViewerCamera を使うと全て面倒を見てくれます。
    プロジェクトの共通領域に camera を追加します。
    camera には View, Projection, World などの領域が定義されていて、これを利用するのが便利です。
    縦横比は camera の領域を使うので aspectRatio は不要です。
            private ModelViewerCamera camera = new ModelViewerCamera();
    
  2. OnResetDevice() で camera に View, Projection を設定します。
            private void OnResetDevice(object sender, DeviceEventArgs e)
            {
                SurfaceDescription desc = e.BackBufferDescription;
                float aspectRatio = (float)desc.Width / (float)desc.Height;
                camera.SetViewParameters(new Vector3(0.0f, 2.0f, -7.0f), Vector3.Empty);
                camera.SetProjectionParameters((float)Math.PI / 4, aspectRatio, 1.0f, 500.0f);
                camera.SetWindow(desc.Width, desc.Height);
    
                //☆ マテリアルとライトの設定が続きます
                    ・
                    ・
    
  3. マウスでモデルを回転するには OnMsgProc() 関数を定義して呼び出すだけです。
            public IntPtr OnMsgProc(IntPtr hWnd, NativeMethods.WindowMessage msg, IntPtr wParam, IntPtr lParam, ref bool noFurtherProcessing)
            {
                // Pass all remaining windows messages to camera so it can respond to user input
                camera.HandleMessages(hWnd, msg, wParam, lParam);
                return IntPtr.Zero;
            }
    
    OnMsgProc() 関数を呼び出します。
            static int Main() 
            {
                        ・
                        ・
                    // 次の一行を追加します
                    sampleFramework.SetWndProcCallback(new WndProcCallback(sample.OnMsgProc));
    
                    sampleFramework.SetCallbackInterface(sample);
                    try
                    {
                        ・
                        ・
    
  4. View, Projection, World などが camera に保存されているので、これを参照して描画します。
            public void OnFrameRender(Device device, double appTime, float elapsedTime)
            {
                bool beginSceneCalled = false;
    
                device.Transform.World = camera.WorldMatrix;
                device.Transform.View = camera.ViewMatrix;
                device.Transform.Projection = camera.ProjectionMatrix;
    
                // Clear the render target and the zbuffer 
                device.Clear(ClearFlags.ZBuffer | ClearFlags.Target, 0x002D32AA, 1.0f, 0);
                try
                {
                    device.BeginScene();
                    beginSceneCalled = true;
                    mesh.DrawSubset(0);
                }
                finally
                {   if (beginSceneCalled)   device.EndScene();  }
            }
    
  5. マウスを操作して、ティーポットが回転することを確かめて下さい。
    ModelViewerCamera Class は dxmutmisc.cs で定義されています。
    モデルの回転には Camera を使う方法と ArcBall を使う方法があります。
    超初心者のプログラム入門(DirectX10)から ティーポットを ArcBall で操作ティーポットを Camera で操作 を参照して下さい。
    DirectX9 でもティーポットを描画するプログラムを作成しています。
    超初心者のプログラム入門(DirectX9)から Sample Brower でティーポットを描画 を参照して下さい。
    リンクがエラーになるときは「前田稔の超初心者のプログラム入門」から辿って下さい。

超初心者のプログラム入門(C# Frame Work)