Share via


HOW TO:顯示和選取網狀結構

更新:2007 年 11 月

您可以建立和顯示網狀結構的陣列,如此在裝置上選取 (點選) 網狀結構時,它就會變更色彩。

注意事項:

Managed Direct3D Mobile 應用程式需要適用於 Pocket PC 和 Smartphone 的 Windows Mobile 5.0 版軟體。如需 Windows Mobile 軟體和 SDK 的詳細資訊,請參閱 .NET Compact Framework 的外部資源

此程式碼範例的表單具有下列物件:

  • 現用網狀結構的 Mesh 物件。

  • 可以選取的九個不同色彩 Mesh 物件的陣列。

  • 定義網狀結構位置的 Vector3 結構。

  • 定義週框方塊的兩個 Vector3 結構。

  • Device 物件。

表單的建構函式會指定裝置 PresentationParameters 屬性的設定、建立 Device 物件、將 OnDeviceReset 事件處理常式加入裝置的 DeviceReset 事件,然後呼叫 OnDeviceReset 方法,開始建立網狀結構。下表說明呈現網狀結構和啟用使用者互動的方法。

方法

動作

OnDeviceReset

建立網狀結構、將這些網狀結構放在週框方塊中的位置,並定義轉換矩陣。

OnPaint

開始場景、繪製網狀結構,並結束場景。

OnMouseDown

使用建立穿過邏輯 3D 空間的光線,並執行方塊與光線交集的技巧,來示範網狀結構的選取。

光線代表按著尖筆穿過 3D 空間。方塊代表圍繞 3D 物件的週框方塊。如果兩者產生交集,就表示使用者已經在含有 3D 物件的位置按了一下。

範例

下列程式碼範例會提供完整的表單。這份表單會顯示可選取之不同色彩的 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 HOW TO 主題

其他資源

.NET Compact Framework 中的 Mobile Direct3D 程式設計