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="" FarPlaneDistance="" FieldOfView="">
<PerspectiveCamera.Transform>
<Transform3DGroup>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="CameraRotate" Axis="0,1,0" Angle=""/>
</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="" 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="" 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="" 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="" 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="" 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="" 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="" FarPlaneDistance="" FieldOfView="">
<PerspectiveCamera.Transform>
<Transform3DGroup>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="CameraRotate" Axis="0,1,0" Angle=""/>
</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#
源码下载:

WPF 3D Cube及点击交互的更多相关文章
- WPF 3D 知识点大全以及实例
引言 现在物联网概念这么火,如果监控的信息能够实时在手机的客服端中以3D形式展示给我们,那种体验大家可以发挥自己的想象. 那生活中我们还有很多地方用到这些,如上图所示的Kinect 在医疗上的应用,当 ...
- WPF 3D 小小小小引擎 - ·WPF 3D变换应用
原文:WPF 3D 小小小小引擎 - ·WPF 3D变换应用 WPF可以提供的3D模型使我们可以轻松地创建3D实体,虽然目前来看还很有一些性能上的问题,不过对于一些简单的3D应用应该是可取的,毕竟其开 ...
- TextView + Spanned实现图文混排以及图片点击交互
最近要实现图文混排的需求,webview过大,所以想到了用SpannableStringBuilder来实现. 不过参考了大量国内文章,大多数是教你如何实现图文混排,并没有提及图片点击交互的.有翻阅了 ...
- WPF MVVM UI分离之《交互与数据分离》 基础才是重中之重~delegate里的Invoke和BeginInvoke 将不确定变为确定系列~目录(“机器最能证明一切”) 爱上MVC3系列~全局异常处理与异常日志 基础才是重中之重~lock和monitor的区别 将不确定变成确定~我想监视我的对象,如果是某个值,就叫另一些方法自动运行 将不确定变成确定~LINQ DBML模型可以对
WPF MVVM UI分离之<交互与数据分离> 在我们使用WPF过程中,不可避免并且超级喜欢使用MVVM框架. 那么,使用MVVM的出发点是视觉与业务逻辑分离,即UI与数据分离 诸如下 ...
- WPF 3D变换应用
WPF可以提供的3D模型使我们可以轻松地创建3D实体,虽然目前来看还很有一些性能上的问题,不过对于一些简单的3D应用应该是可取的,毕竟其开发效率高,而且也容易上手. 下面给大家演示的是使用在WPF 3 ...
- WPF 3D中多个模型如何设置某一个在最前?
原文:WPF 3D中多个模型如何设置某一个在最前? 问题:我们的模型包括导入的3D solid模型和axis坐标轴模型,当模型旋转的时候,3D会将axis挡住. 期望:axis一直在最前面,不会被3D ...
- WPF 3D 获取鼠标在场景的3d坐标
原文:WPF 3D 获取鼠标在场景的3d坐标 上一篇中我们谈到了WPF 3d做图的一些简单原理,这里我们简单介绍一下怎样获得鼠标在场景中的3d坐标,知道了3d坐标就可以进行很多操作了: 首先介绍一下3 ...
- 最优化WPF 3D性能(基于“Tier-2”硬件)
原文:最优化WPF 3D性能(基于"Tier-2"硬件) 原文地址:Maximizing WPF 3D Performance on Tier-2 Hardware 开发人员在应用 ...
- 优化WPF 3D性能
Maximize WPF 3D Performance .NET Framework 4.5 As you use the Windows Presentation Foundation (WPF ...
随机推荐
- 《Windows内核安全与驱动开发》 2.3 重要的数据结构
<Windows内核安全与驱动开发>阅读笔记 -- 索引目录 <Windows内核安全与驱动开发> 2.3 重要的数据结构 一.驱动对象 Windows内核采用__的编程方式 ...
- jQuery 判断页面对象是否存在
不能用 if($("#id")){}else{} 因为 $("#id") 不管对象是否存在都会返回 object. 正确使用判断对象是否存在应该用: if( ...
- [转载]C++中四种强制类型转换方式
C++中四种强制类型转换方式 原文地址:http://www.cnblogs.com/home123/p/6763967.html 类型转换有c风格的,当然还有c++风格的.c风格的转换的格式很简单( ...
- MySQL的存储(一、连接数据库)
准备工作: 确保安装MySql 安装PyMySQL库 连接数据库: 这里首先尝试连接下数据库,假设当前MySQL运行在本地,用户名为root,密码为123456,运行端口为3306. 通过PyMySQ ...
- idea建立项目关联到git仓库操作步骤
eg:创建一个名为demo的git项目 创建git远程项目,命名为[/demo] 在[D:\workspace\gf]创建本地项目[demo] 在idea里选择[VCS]->[Checkout ...
- 常用的iOS第三方资源
一:第三方插件 1:基于响应式编程思想的oc 地址:https://github.com/ReactiveCocoa/ReactiveCocoa pod 'ReactiveCocoa', '~> ...
- react文本溢出hover气泡显示全部文本——JS判断文本溢出
需求: 在文本溢出的时候,显示气泡 JS相关知识 // target js元素 const containerLength = target.width; //当前容器的宽度 const textLe ...
- JavaScript+HTML+CSS 无缝滚动轮播图的两种方式
第一种方式 在轮播图最后添加第一张,一张重复的图片. 点击前一张,到了第一张,将父级oList移动到最后一张(也就是添加的重复的第一张),在进行后续动画. 点击下一张,到了最后一张(也就是添加的重复的 ...
- Dubbo初步
Dubbo 介绍 : Dubbo 是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的RPC 实现服务的输出和输入功能,可以和 Spring 框架无缝集成.Dubbo 框架,是基于容器 ...
- jquery (对内容,元素,属性,class的操作)
对内容的操作: 捕获:获得内容 text() - 设置或返回所选元素的文本内容html() - 设置或返回所选元素的内容(包括 HTML 标记)val() - 设置或返回表单字段的值. 设置:设置内容 ...