在WPF中構建一個簡單的立方體比較容易實現,可參考資料也比較衆多。比較麻煩的是處理點擊交互。
我在WPF中用兩種方式實現了3DCube,效果圖如下:
方式一: 最常見的3D內容構建模式,結構如下圖。
參考
<Viewport3D SnapsToDevicePixels="True" ClipToBounds="True"
RenderTransformOrigin="0.5 0.5" RenderOptions.EdgeMode="Aliased"
RenderOptions.CachingHint="Cache">
<!--Camera-->
<Viewport3D.Camera>
<PerspectiveCamera x:Name="CameraMain" Position="4,4,6" UpDirection="0,1,0" LookDirection="-4,-4,-6"
NearPlaneDistance="1" FarPlaneDistance="100" FieldOfView="120">
<PerspectiveCamera.Transform>
<Transform3DGroup>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="CameraRotate" Axis="0,1,0" Angle="0"/>
</RotateTransform3D.Rotation>
</RotateTransform3D>
<ScaleTransform3D />
</Transform3DGroup>
</PerspectiveCamera.Transform>
</PerspectiveCamera>
</Viewport3D.Camera>
<!--Light-->
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup>
<AmbientLight Color="White"></AmbientLight>
<DirectionalLight Color="White" Direction="4,6,-6"/>
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
<!--六個面-->
<ModelVisual3D x:Name="CubeSlaveContainer">
<ModelUIElement3D>
<GeometryModel3D x:Name="TopPanel">
<GeometryModel3D.Material>
<DiffuseMaterial x:Name="MaterialTop">
<DiffuseMaterial.Brush>
<VisualBrush>
<VisualBrush.Visual>
<TextBlock Text="1" Foreground="White"/>
</VisualBrush.Visual>
</VisualBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<GeometryModel3D.BackMaterial>
<DiffuseMaterial Brush="Transparent"/>
</GeometryModel3D.BackMaterial>
<GeometryModel3D.Geometry>
<MeshGeometry3D Positions="-2,2,2 2,2,2 2,2,-2 -2,2,-2"
TriangleIndices="0,1,2 0,2,3"
TextureCoordinates="-2,2 2,2 2,-2 -2,-2">
</MeshGeometry3D>
</GeometryModel3D.Geometry>
</GeometryModel3D>
</ModelUIElement3D>
<ModelUIElement3D>
<GeometryModel3D x:Name="BottomPanel">
<GeometryModel3D.Material>
<DiffuseMaterial x:Name="MaterialBottom">
<DiffuseMaterial.Brush>
<VisualBrush>
<VisualBrush.Visual>
<TextBlock Text="2" Foreground="White"/>
</VisualBrush.Visual>
</VisualBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<GeometryModel3D.BackMaterial>
<DiffuseMaterial Brush="Transparent"/>
</GeometryModel3D.BackMaterial>
<GeometryModel3D.Geometry>
<MeshGeometry3D Positions="-2,-2,2 2,-2,2 2,-2,-2 -2,-2,-2"
TriangleIndices="0,2,1 0,3,2"
TextureCoordinates="-2,2 2,2 2,-2 -2,-2">
</MeshGeometry3D>
</GeometryModel3D.Geometry>
</GeometryModel3D>
</ModelUIElement3D>
<ModelUIElement3D>
<GeometryModel3D x:Name="LeftPanel">
<GeometryModel3D.Material>
<DiffuseMaterial x:Name="MaterialLeft">
<DiffuseMaterial.Brush>
<VisualBrush>
<VisualBrush.Visual>
<TextBlock Text="3" Foreground="White"/>
</VisualBrush.Visual>
</VisualBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<GeometryModel3D.BackMaterial>
<DiffuseMaterial Brush="Transparent"/>
</GeometryModel3D.BackMaterial>
<GeometryModel3D.Geometry>
<MeshGeometry3D Positions="-2,-2,-2 -2,-2,2 -2,2,2 -2,2,-2"
TriangleIndices="0,1,2 0,2,3"
TextureCoordinates="-2,2 2,2 2,-2 -2,-2">
</MeshGeometry3D>
</GeometryModel3D.Geometry>
</GeometryModel3D>
</ModelUIElement3D>
<ModelUIElement3D>
<GeometryModel3D x:Name="RightPanel">
<GeometryModel3D.Material>
<DiffuseMaterial x:Name="MaterialRight">
<DiffuseMaterial.Brush>
<VisualBrush>
<VisualBrush.Visual>
<TextBlock Text="4" Foreground="White"/>
</VisualBrush.Visual>
</VisualBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<GeometryModel3D.BackMaterial>
<DiffuseMaterial Brush="Transparent"/>
</GeometryModel3D.BackMaterial>
<GeometryModel3D.Geometry>
<MeshGeometry3D Positions="2,-2,2 2,-2,-2 2,2,-2 2,2,2"
TriangleIndices="0,1,2 0,2,3"
TextureCoordinates="-2,2 2,2 2,-2 -2,-2">
</MeshGeometry3D>
</GeometryModel3D.Geometry>
</GeometryModel3D>
</ModelUIElement3D>
<ModelUIElement3D>
<GeometryModel3D x:Name="FrontPanel">
<GeometryModel3D.Material>
<DiffuseMaterial x:Name="MaterialFront">
<DiffuseMaterial.Brush>
<VisualBrush>
<VisualBrush.Visual>
<TextBlock Text="5" Foreground="White"/>
</VisualBrush.Visual>
</VisualBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<GeometryModel3D.BackMaterial>
<DiffuseMaterial Brush="Transparent"/>
</GeometryModel3D.BackMaterial>
<GeometryModel3D.Geometry>
<MeshGeometry3D Positions="-2,-2,2 2,-2,2 2,2,2 -2,2,2"
TriangleIndices="0,1,2 0,2,3"
TextureCoordinates="-2,2 2,2 2,-2 -2,-2">
</MeshGeometry3D>
</GeometryModel3D.Geometry>
</GeometryModel3D>
</ModelUIElement3D>
<ModelUIElement3D>
<GeometryModel3D x:Name="BackPanel">
<GeometryModel3D.Material>
<DiffuseMaterial x:Name="MaterialBack">
<DiffuseMaterial.Brush>
<VisualBrush>
<VisualBrush.Visual>
<TextBlock Text="6" Foreground="White"></TextBlock>
</VisualBrush.Visual>
</VisualBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<GeometryModel3D.BackMaterial>
<DiffuseMaterial Brush="Transparent"/>
</GeometryModel3D.BackMaterial>
<GeometryModel3D.Geometry>
<MeshGeometry3D Positions="2,-2,-2 -2,-2,-2 -2,2,-2 2,2,-2"
TriangleIndices="0,1,2 0,2,3"
TextureCoordinates="-2,2 2,2 2,-2 -2,-2">
</MeshGeometry3D>
</GeometryModel3D.Geometry>
</GeometryModel3D>
</ModelUIElement3D>
</ModelVisual3D>
</Viewport3D>
點擊交互:
給ModelUIElement3D附加事件,如下圖
方式二: 使用3DTools.dll構建,結構如下圖
參考
<!-- xmlns:Plugin3D="clr-namespace:_3DTools;assembly=3DTools" -->
<Plugin3D:Interactive3DDecorator HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Viewport3D x:Name="Viewport3DMain" Margin="0,-50,0,50"
SnapsToDevicePixels="True" ClipToBounds="True"
RenderTransformOrigin="0.5 0.5" RenderOptions.EdgeMode="Aliased"
RenderOptions.CachingHint="Cache">
<!--攝像機-->
<Viewport3D.Camera>
<PerspectiveCamera x:Name="CameraMain" Position="4,4,6"
UpDirection="0,1,0" LookDirection="-4,-4,-6"
NearPlaneDistance="1" FarPlaneDistance="100" FieldOfView="120">
<PerspectiveCamera.Transform>
<Transform3DGroup>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="CameraRotate" Axis="0,1,0" Angle="0"/>
</RotateTransform3D.Rotation>
</RotateTransform3D>
</Transform3DGroup>
</PerspectiveCamera.Transform>
</PerspectiveCamera>
</Viewport3D.Camera>
<!--Light-->
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup>
<AmbientLight Color="White"></AmbientLight>
<DirectionalLight Color="White" Direction="4,6,-6"/>
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
<!--六個面-->
<Plugin3D:InteractiveVisual3D x:Name="TopPanel" IsBackVisible="True">
<Plugin3D:InteractiveVisual3D.Geometry>
<MeshGeometry3D Positions="-2,2,2 2,2,2 2,2,-2 -2,2,-2"
TriangleIndices="0,1,2 0,2,3"
TextureCoordinates="0,0 0,1 1,1 1,0"
Normals="0,1,0 0,1,0 0,1,0 0,1,0"/>
</Plugin3D:InteractiveVisual3D.Geometry>
</Plugin3D:InteractiveVisual3D>
<Plugin3D:InteractiveVisual3D x:Name="BottomPanel" IsBackVisible="True">
<Plugin3D:InteractiveVisual3D.Geometry>
<MeshGeometry3D Positions="-2,-2,2 2,-2,2 2,-2,-2 -2,-2,-2"
TriangleIndices="0,2,1 0,3,2"
TextureCoordinates="0,0 0,1 1,1 1,0"
Normals="0,1,0 0,1,0 0,1,0 0,1,0"/>
</Plugin3D:InteractiveVisual3D.Geometry>
</Plugin3D:InteractiveVisual3D>
<Plugin3D:InteractiveVisual3D x:Name="LeftPanel" IsBackVisible="True">
<Plugin3D:InteractiveVisual3D.Geometry>
<MeshGeometry3D Positions="-2,-2,-2 -2,-2,2 -2,2,2 -2,2,-2"
TriangleIndices="0,1,2 0,2,3"
TextureCoordinates="0,0 0,1 1,1 1,0"
Normals="0,1,0 0,1,0 0,1,0 0,1,0"/>
</Plugin3D:InteractiveVisual3D.Geometry>
</Plugin3D:InteractiveVisual3D>
<Plugin3D:InteractiveVisual3D x:Name="RightPanel" IsBackVisible="True">
<Plugin3D:InteractiveVisual3D.Geometry>
<MeshGeometry3D Positions="2,-2,2 2,-2,-2 2,2,-2 2,2,2"
TriangleIndices="0,1,2 0,2,3"
TextureCoordinates="0,0 0,1 1,1 1,0"
Normals="0,1,0 0,1,0 0,1,0 0,1,0"/>
</Plugin3D:InteractiveVisual3D.Geometry>
</Plugin3D:InteractiveVisual3D>
<Plugin3D:InteractiveVisual3D x:Name="FrontPanel" IsBackVisible="True">
<Plugin3D:InteractiveVisual3D.Geometry>
<MeshGeometry3D Positions="-2,-2,2 2,-2,2 2,2,2 -2,2,2"
TriangleIndices="0,1,2 0,2,3"
TextureCoordinates="0,0 0,1 1,1 1,0"
Normals="0,1,0 0,1,0 0,1,0 0,1,0"/>
</Plugin3D:InteractiveVisual3D.Geometry>
</Plugin3D:InteractiveVisual3D>
<Plugin3D:InteractiveVisual3D x:Name="BackPanel" IsBackVisible="True">
<Plugin3D:InteractiveVisual3D.Geometry>
<MeshGeometry3D Positions="2,-2,-2 -2,-2,-2 -2,2,-2 2,2,-2"
TriangleIndices="0,1,2 0,2,3"
TextureCoordinates="0,0 0,1 1,1 1,0"
Normals="0,1,0 0,1,0 0,1,0 0,1,0"/>
</Plugin3D:InteractiveVisual3D.Geometry>
</Plugin3D:InteractiveVisual3D>
</Viewport3D>
</Plugin3D:Interactive3DDecorator>
點擊交互:
給Plugin3D:InteractiveVisual3D對象的Visual對象附加點擊事件,如創建一個Grid, 將Grid作爲Plugin3D:InteractiveVisual3D的Visual值。
調用: this.SetCubeMaterialBrush(this.FrontPanel, "定義的ImageBrush資源的Key值", 5);
工具:Visual Studio 2017
工程:WPF C#
源碼下載: