方法 : メッシュを表示し、選択する

更新 : 2007 年 11 月

デバイスでメッシュが選択 (タップ) されると色が変更されるように、メッシュの配列を作成して表示できます。

ms229645.alert_note(ja-jp,VS.90).gifメモ :

マネージ Direct3D モバイル アプリケーションでは、Windows Mobile Version 5.0 Software for Pocket PC と Windows Mobile Version 5.0 Software for Smartphone が必要です。Windows Mobile ソフトウェアおよび SDK については、「.NET Compact Framework の外部資料」を参照してください。

このコード例のフォームには、次のオブジェクトがあります。

  • アクティブ メッシュの Mesh オブジェクト

  • さまざまな色を持ち、選択できる 9 つの Mesh オブジェクトから成る配列

  • メッシュの位置を定義する Vector3 構造体

  • 外接するボックスを定義する 2 つの Vector3 構造体

  • Device オブジェクト

フォームのコンストラクタでは、デバイスの PresentationParameters プロパティ設定を指定し、Device オブジェクトを作成し、OnDeviceReset イベント ハンドラをデバイスの DeviceReset イベントに追加してから、OnDeviceReset メソッドを呼び出してメッシュの作成を開始します。次の表は、メッシュを描画したり、ユーザーとのやり取りを可能にしたりするメソッドの説明です。

メソッド

アクション

OnDeviceReset

メッシュを作成し、外接するボックス内に配置し、変換行列を定義します。

OnPaint

シーンを開始し、メッシュを描画し、シーンを終了します。

OnMouseDown

論理 3-D 空間に光線を作成し、ボックスと光線を交差させることで、メッシュの選択をデモします。

光線は、3-D 空間でスタイラスをタップしたことを表します。ボックスは、3-D オブジェクトの周囲に外接するボックスを表します。この 2 つが交差すると、ユーザーは 3-D オブジェクトを含む位置でクリックしたことになります。

使用例

完全なフォームを次のコード例に示します。さまざまな色を持ち、選択できる 9 つの Mesh オブジェクトが表示されます。メッシュは、選択されると色が変化します。

Imports System
Imports System.Drawing
Imports System.Windows.Forms
Imports Microsoft.WindowsMobile.DirectX
Imports Microsoft.WindowsMobile.DirectX.Direct3D
Imports Microsoft.VisualBasic




Class MeshPickingHowto
    Inherits Form
    Private Const numberOfMeshes As Integer = 9
    Private meshes() As Mesh
    Private meshColors() As Color = {Color.Green, Color.Orange, Color.Purple, Color.Pink, Color.Violet, Color.Blue, Color.Yellow, Color.Brown, Color.Aquamarine}

    Private meshLocations() As Vector3
    Private meshBoundingBoxMinValues() As Vector3
    Private meshBoundingBoxMaxValues() As Vector3
    Private activeMesh As Mesh

    Private device As Device


    Public Sub New() 
        Dim present As PresentParameters

        Me.Text = "Mesh Picking"

        ' Enable the form to be closed.
        ' This is required so that Hwnd of the form changes.
        Me.MinimizeBox = False

        present = New PresentParameters()
        present.Windowed = True
        present.AutoDepthStencilFormat = DepthFormat.D16
        present.EnableAutoDepthStencil = True
        present.SwapEffect = SwapEffect.Discard

        device = New Device(0, DeviceType.Default, Me, CreateFlags.None, present)
        AddHandler device.DeviceReset, AddressOf OnDeviceReset
        OnDeviceReset(Nothing, EventArgs.Empty)

    End Sub


    Private Sub OnDeviceReset(ByVal sender As Object, ByVal e As EventArgs) 
        ' Meshes must be recreated whenever the device
        ' is reset, no matter which pool they are created in.
        meshes = New Mesh(numberOfMeshes) {}
        meshLocations = New Vector3(numberOfMeshes) {}
        meshBoundingBoxMinValues = New Vector3(numberOfMeshes) {}
        meshBoundingBoxMaxValues = New Vector3(numberOfMeshes) {}
        activeMesh = Nothing

        ' Create several meshes and associated data.
        Dim i As Integer
        For i = 0 To numberOfMeshes
            Dim vertexData As GraphicsStream

            meshes(i) = Mesh.Box(device, 1F, 1F, 1F)

            ' Arrange the boxes in a grid, with each
            ' successive box farther in the distance.
            meshLocations(i) = New Vector3((i Mod 3) * 2 - 2, i / 3 * 2 - 2, i)

            ' Compute the bounding box for a mesh.
            Dim description As VertexBufferDescription = meshes(i).VertexBuffer.Description
            vertexData = meshes(i).VertexBuffer.Lock(0, 0, LockFlags.ReadOnly)
            Geometry.ComputeBoundingBox(vertexData, meshes(i).NumberVertices, description.VertexFormat, meshBoundingBoxMinValues(i), meshBoundingBoxMaxValues(i))
            meshes(i).VertexBuffer.Unlock()
        Next i
        ' Set the transformation matrices.
        device.Transform.Projection = Matrix.PerspectiveFovRH(System.Convert.ToSingle(Math.PI) / 4F, System.Convert.ToSingle(Me.ClientSize.Width) / System.Convert.ToSingle(Me.ClientSize.Height), 0.001F, 40)

        device.Transform.View = Matrix.LookAtRH(New Vector3(0, 2, - 7), New Vector3(0, 0, 0), New Vector3(0, 1, 0))

        device.RenderState.Ambient = Color.White

    End Sub


    Protected Overrides Sub OnPaintBackground(ByVal e As PaintEventArgs) 
        ' Do nothing.
    End Sub

    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs) 
        Dim material As New Material()

        ' Begin the scene and clear the back buffer to black.
        device.BeginScene()
        device.Clear(ClearFlags.Target Or ClearFlags.ZBuffer, Color.Black, 1F, 0)

        ' Draw each mesh to the screen.
        ' The active mesh is drawn in red.
        Dim i As Integer
        For i = 0 To numberOfMeshes
            If activeMesh Is meshes(i) Then
                material.Ambient = Color.Red
            Else
                material.Ambient = meshColors(i)
            End If
            device.Transform.World = Matrix.Translation(meshLocations(i))
            device.Material = material
            meshes(i).DrawSubset(0)
        Next i

        ' Finish the scene and present it on the screen.
        device.EndScene()
        device.Present()

    End Sub


    ' This method demonstrates picking.
    Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs) 
        ' The technique used here is to create a ray through the entire
        ' logical 3-D space, and then perform an intersection test
        ' for the bounding box and ray.
        Dim i As Integer
        For i = 0 To numberOfMeshes
            Dim nearVector As New Vector3(e.X, e.Y, 0)
            Dim farVector As New Vector3(e.X, e.Y, 1)

            ' Create ray.
            nearVector.Unproject(device.Viewport, device.Transform.Projection, device.Transform.View, Matrix.Translation(meshLocations(i)))

            farVector.Unproject(device.Viewport, device.Transform.Projection, device.Transform.View, Matrix.Translation(meshLocations(i)))

            farVector.Subtract(nearVector)

            ' Perform intersection test for the bounding box and ray.
            If Geometry.BoxBoundProbe(meshBoundingBoxMinValues(i), meshBoundingBoxMaxValues(i), nearVector, farVector) Then
                ' Perform operation on detection of click on mesh object.
                ' In this case, you designate the mesh as the active
                ' mesh and invalidate the window so that it is redrawn.
                activeMesh = meshes(i)
                Me.Invalidate()
                Exit For
            End If
        Next i

    End Sub


    Shared Sub Main() 
        Application.Run(New MeshPickingHowto())

    End Sub
End Class
using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.WindowsMobile.DirectX;
using Microsoft.WindowsMobile.DirectX.Direct3D;

namespace MeshPick
{
    class MeshPickingHowto : Form
    {
        const int numberOfMeshes = 9;
        Mesh [] meshes;
        Color [] meshColors = new Color [] { Color.Green, Color.Orange,
            Color.Purple, Color.Pink, Color.Violet, Color.Blue, Color.Yellow,
            Color.Brown, Color.Aquamarine };

        Vector3 [] meshLocations;
        Vector3 [] meshBoundingBoxMinValues;
        Vector3 [] meshBoundingBoxMaxValues;
        Mesh activeMesh;

        Device device;

        public MeshPickingHowto()
        {
            PresentParameters present;

            this.Text = "Mesh Picking";

            // Enable the form to be closed.
            // This is required so that Hwnd of the form changes.
            this.MinimizeBox = false;

            present = new PresentParameters();
            present.Windowed = true;
            present.AutoDepthStencilFormat = DepthFormat.D16;
            present.EnableAutoDepthStencil = true;
            present.SwapEffect = SwapEffect.Discard;

            device = new Device(0, DeviceType.Default, this,
                                CreateFlags.None, present);
            device.DeviceReset += new EventHandler(OnDeviceReset);
            OnDeviceReset(null, EventArgs.Empty);
        }

        private void OnDeviceReset(object sender, EventArgs e)
        {
            // Meshes must be recreated whenever the device
            // is reset, no matter which pool they are created in.

            meshes = new Mesh[numberOfMeshes];
            meshLocations = new Vector3[numberOfMeshes];
            meshBoundingBoxMinValues = new Vector3[numberOfMeshes];
            meshBoundingBoxMaxValues = new Vector3[numberOfMeshes];
            activeMesh = null;
            // Create several meshes and associated data.
            for (int i = 0; i < numberOfMeshes; i++)
            {
                GraphicsStream vertexData;

                meshes[i] = Mesh.Box(device, 1.0f, 1.0f, 1.0f);

                // Arrange the boxes in a grid, with each
                // successive box farther in the distance.
                meshLocations[i] = new Vector3(((i % 3) * 2) - 2,
                                            ((i / 3) * 2) - 2, i);

                // Compute the bounding box for a mesh.
                VertexBufferDescription description =
                    meshes[i].VertexBuffer.Description;
                vertexData = meshes[i].VertexBuffer.Lock
                                         (0, 0, LockFlags.ReadOnly);
                Geometry.ComputeBoundingBox(vertexData,
                    meshes[i].NumberVertices,description.VertexFormat,
                    out meshBoundingBoxMinValues[i],
                    out meshBoundingBoxMaxValues[i]);
                meshes[i].VertexBuffer.Unlock();
            }
            // Set the transformation matrices.
            device.Transform.Projection = Matrix.PerspectiveFovRH(
               (float)Math.PI/4.0F,
               (float)this.ClientSize.Width / (float)this.ClientSize.Height,
               0.001f, 40);

            device.Transform.View = Matrix.LookAtRH(new Vector3(0, 2, -7),
                new Vector3(0, 0, 0), new Vector3(0, 1, 0));

            device.RenderState.Ambient = Color.White;
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
            // Do nothing.
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            Material material = new Material();

            // Begin the scene and clear the back buffer to black.
            device.BeginScene();
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer,
                        Color.Black, 1.0f, 0);

            // Draw each mesh to the screen.
            // The active mesh is drawn in red.
            for (int i = 0; i < numberOfMeshes; i++)
            {
                if (activeMesh == meshes[i])
                    material.Ambient = Color.Red;
                else
                    material.Ambient = meshColors[i];

                device.Transform.World = Matrix.Translation(meshLocations[i]);
                device.Material = material;
                meshes[i].DrawSubset(0);
            }

            // Finish the scene and present it on the screen.
            device.EndScene();
            device.Present();
        }

        // This method demonstrates picking.
        protected override void OnMouseDown(MouseEventArgs e)
        {
            // The technique used here is to create a ray through the entire
            // logical 3-D space, and then perform an intersection test
            // for the bounding box and ray.
            for (int i = 0; i < numberOfMeshes; i++)
            {
                Vector3 nearVector = new Vector3(e.X, e.Y, 0);
                Vector3 farVector = new Vector3(e.X, e.Y, 1);

                // Create ray.

                nearVector.Unproject(device.Viewport,
                            device.Transform.Projection,
                            device.Transform.View,
                            Matrix.Translation(meshLocations[i]));

                farVector.Unproject(device.Viewport,
                            device.Transform.Projection,
                            device.Transform.View,
                            Matrix.Translation(meshLocations[i]));

                farVector.Subtract(nearVector);

                // Perform intersection test for the bounding box and ray.

                if (Geometry.BoxBoundProbe(meshBoundingBoxMinValues[i],
                    meshBoundingBoxMaxValues[i], nearVector, farVector))
                {
                    // Perform operation on detection of click on mesh object.
                    // In this case, you designate the mesh as the active
                    // mesh and invalidate the window so that it is redrawn.

                    activeMesh = meshes[i];
                    this.Invalidate();
                    break;
                }
            }
        }

        static void Main()
        {
            Application.Run(new MeshPickingHowto());
        }
    }
}

コードのコンパイル方法

この例では、次の名前空間への参照が必要です。

参照

概念

.NET Compact Framework に関する「方法」トピック

その他の技術情報

.NET Compact Framework での Mobile Direct3D プログラミング