WPF 3D Cube及点击交互

       在WPF中构建一个简单的立方体比较容易实现,可参考资料也比较众多。比较麻烦的是处理点击交互。

       我在WPF中用两种方式实现了3DCube,效果图如下:

Cube3D1.gif

Cube3D2.gif

 

方式一: 最常见的3D内容构建模式,结构如下图。

image.png

参考

 <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附加事件,如下图

image.png

 

方式二: 使用3DTools.dll构建,结构如下图

image.png

参考

        <!-- 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);

          image.png

    工具:Visual Studio 2017

    工程:WPF C#

    源码下载:

             

posted @ 2019-12-13 17:41  DuelCode  阅读(1780)  评论(1编辑  收藏  举报