Практическое руководство. Отображение и выбор сеток
Обновлен: Ноябрь 2007
Можно создать и отобразить массив сеток, чтобы при выборе сетки в устройстве изменялся ее цвет.
Примечание. |
---|
Для управляемых мобильных приложений Direct3D требуется программа карманных ПК и смартфонов Windows Mobile версии 5.0. Сведения о программе Windows Mobile и пакетах SDK см. в разделе Внешние ресурсы для платформы .NET Compact Framework. |
Форма для этого примера кода содержит следующие объекты:
Объект Mesh для активной сетки.
Массив из девяти объектов Mesh различного цвета, который можно выбрать.
Структура Vector3, которая определяет расположения сетки.
Две структуры Vector3, которые определяют ограничивающее поле.
Объект Device.
Конструктор формы определяет параметры для свойства PresentationParameters устройства, создает объект Device, добавляет обработчик событий OnDeviceReset к событию DeviceReset устройства и затем вызывает метод OnDeviceReset, чтобы начать создание сеток. В следующей таблице описываются методы, которые отображают сетки и включают взаимодействие пользователя.
Метод |
Действия |
---|---|
OnDeviceReset |
Создает сетки, размещает их в ограничивающем поле и определяет матрицы преобразования. |
OnPaint |
Запускает сцену, рисует сетку и завершает сцену. |
OnMouseDown |
Демонстрирует выбор сетки с помощью метода, который создает луч через логическое 3-D пространство и выполняет пересечение поля лучом. Луч представляет черту, проведенную пером через 3-D пространство. Окно представляет ограничивающее поле вокруг 3-D объекта. Если они пересекаются, пользователь выбрал местоположение, которое содержит 3-D объект. |
Пример
В следующем примере кода приведена полная форма. Она отображает объекты 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
Другие ресурсы
Мобильное программирование Direct3D в .NET Compact Framework