WPF 3D Cube及点击交互
在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#
源码下载: