Подобно классам двухмерных элементов в WPF имеются их трехмерные аналоги - Visual3D и UIElement3D. И мы можем использовать два их класса-наследника: ModelUIElement3D и ContainerUIElement3D. В чем их преимущество перед ModelVisual3D? Поскольку ModelUIElement3D является фактически своего рода элементом управления, мы можем прикрутить к нему события и, например, проверять нажатия мыши по нему. Иначе нам пришлось бы писать гораздо больше кода. Например, изменим код с кубом, применив ModelUIElement3D:
<Window x:Class="_3DApp.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:_3DApp" mc:Ignorable="d" Title="MainWindow" Height="250" Width="350"> <Grid> <Viewport3D> <Viewport3D.Camera> <PerspectiveCamera x:Name="camera" Position="0.5,0.5,3.5" LookDirection="0,0,-3.5" /> </Viewport3D.Camera> <Viewport3D.Children> <ModelVisual3D> <ModelVisual3D.Content> <DirectionalLight Color="White" Direction="-1,-1,-2" /> </ModelVisual3D.Content> </ModelVisual3D> <ModelUIElement3D MouseDown="ModelUIElement3D_MouseDown"> <ModelUIElement3D.Model> <GeometryModel3D> <GeometryModel3D.Geometry> <MeshGeometry3D Positions="0,0,0 1,0,0 0,1,0 1,1,0 0,0,1 1,0,1 0,1,1 1,1,1" TriangleIndices="0,2,1 1,2,3 0,4,2 2,4,6 0,1,4 1,5,4 1,7,5 1,3,7 4,5,6 7,6,5 2,6,3 3,6,7"/> </GeometryModel3D.Geometry> <GeometryModel3D.Material> <DiffuseMaterial Brush="Blue" /> </GeometryModel3D.Material> </GeometryModel3D> </ModelUIElement3D.Model> <ModelUIElement3D.Transform> <Transform3DGroup> <RotateTransform3D> <RotateTransform3D.Rotation> <AxisAngleRotation3D x:Name="rotate" Axis="0 1 0" Angle="30" /> </RotateTransform3D.Rotation> </RotateTransform3D> </Transform3DGroup> </ModelUIElement3D.Transform> </ModelUIElement3D> </Viewport3D.Children> </Viewport3D> </Grid> </Window>
Таким образом, мы связываем нажатие по кубу с обработчиком события MouseDown, в котором затем мы можем определить все необходимые действия:
private void ModelUIElement3D_MouseDown(object sender, MouseButtonEventArgs e) { MessageBox.Show("Произошло нажатие"); }
Элемент ContainerUIElement3D является контейнером для других элементов Visual3D, то есть он может вмещать несколько различных элементов ModelUIElement3D, ModelVisual3D и Viewport2DVisual3D
Элемент Viewport2DVisual3D позволяет помещать на поверхности трехмерного объекта двухмерный интерактивный контент, например, кнопки или текстовые поля. При этом данный интерактивный контент может реагировать на действия пользователя. Например, кнопка может реагировать на нажатия.
У элемента Viewport2DVisual3D можно выделить следующие свойства:
Geometry: определяет меш, который устанавливает поверхность трехмерного объекта
Visual: определяет двухмерные элементы, которые будут помещаться на трехмерный объект
Material: материал, используемый для рендеринга двухмерных элементов
Transform: трасформация, применяемая к 3D-объекту
Изменим приложение, применив Viewport2DVisual3D:
<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <Slider Minimum="0" Maximum="360" Value="{Binding ElementName=rotate, Path= Angle}" /> <Viewport3D Grid.Row="1"> <Viewport3D.Camera> <PerspectiveCamera x:Name="camera" Position="0.5,0.5,3.5" LookDirection="0,0,-3.5" /> </Viewport3D.Camera> <Viewport3D.Children> <ModelVisual3D> <ModelVisual3D.Content> <DirectionalLight Color="White" Direction="-1,-1,-2" /> </ModelVisual3D.Content> </ModelVisual3D> <Viewport2DVisual3D> <Viewport2DVisual3D.Geometry> <MeshGeometry3D Positions="0,0,0 1,0,0 0,1,0 1,1,0 0,0,1 1,0,1 0,1,1 1,1,1" TriangleIndices="0,2,1 1,2,3 0,4,2 2,4,6 0,1,4 1,5,4 1,7,5 1,3,7 4,5,6 7,6,5 2,6,3 3,6,7" TextureCoordinates="0,1 1,1 0,0 1,0 0,1 1,1 0,0 1,0"/> </Viewport2DVisual3D.Geometry> <Viewport2DVisual3D.Material> <DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial="True" /> </Viewport2DVisual3D.Material> <Viewport2DVisual3D.Visual> <Border BorderBrush="Black" BorderThickness="1"> <StackPanel> <Button Content="Hello World" /> <TextBox>Введи текст</TextBox> </StackPanel> </Border> </Viewport2DVisual3D.Visual> <Viewport2DVisual3D.Transform> <RotateTransform3D> <RotateTransform3D.Rotation> <AxisAngleRotation3D x:Name="rotate" Axis="0 1 0" Angle="30" /> </RotateTransform3D.Rotation> </RotateTransform3D> </Viewport2DVisual3D.Transform> </Viewport2DVisual3D> </Viewport3D.Children> </Viewport3D> </Grid>