原文:WPF 3D 模型旋转

WPF 是 Microsoft 在 Framework3.0 中支持的一种技术,它能作出很绚丽的界面,同时它也支持3D的操作。在3D操作主要包括平移(Translate)、旋转(Rotation)、缩放(Scale)。

本文中主要是讨论3D 模型的旋转。对于旋转操作可以采用旋转模型,通过模型的Transform属性来完成;也可以通过第一人称的摄像机通过旋转摄像机来完成旋转。当然处于对性能的考虑本文选择第二种方法的方式来旋转模型。

完成摄像机的旋转需要通过以下几个步骤:

1. 对于不同的模型,设置摄像机的位置(Position),远焦距(FarPlaneDistance),近焦距(NearPlaneDistance),看的方向(LookDirection),向上的向量(UpDirection)。

2. 旋转围绕的旋转抽和围绕旋转的中心。

首先,对于不同的模型放入到世界坐标中摄像机的位置肯定会不同。如何确定摄像机的位置呢?在XNA中XNA框架提供了一个SphereBounding的属性来获得模型的外切圆,从而得到了圆心。然而在WPF中却没有发现SphereBounding的身影。不过仔细想想,Microsoft 不可能在XNA中提供了计算外切圆的方法,在WPF中不可能不提供类似的方法。然后我们仔细寻找,你会发现在MeshGeometry3D有一个Bounds的属性,该属性是返回MesheGeometry3D的边界Rect3D。Rect3D表示一个三维矩形,也就是模型的外切矩形。

对于一个模型很有可能是由多个ModelVisual3D组成,这就预味着要把这些ModelVisual3D的外切矩形合并,好在在Rect3D中提供了Union方法(MSDN: 已重载。 更新指定的 Rect3D 以反映该 Rect3D 与第二个指定 Rect3D 的联合)。最后通过对三维矩形的Size 和 Location 来计算出矩形的中心。

 private void UnionRect(ModelVisual3D model, ref Rect3D rect3D)
{
for (int i = ; i < model.Children.Count; i++)
{
var child = model.Children[i] as ModelVisual3D;
UnionRect(child, ref rect3D); }
if (model.Content != null)
rect3D.Union(model.Content.Bounds);
}

通过上面获得的中心和矩形的对角线来计算出矩形外切圆的半径。在本例中我们让模型围绕Y轴以自己为中心旋转,所以只需要通过中心点和半径来设置摄像机的Z或者X,通过设置摄像机的X和Z。这样就使得中心点 X,Z在同一个平面中,同时还在同一个圆形中,这样就是的摄像机的旋转围绕着圆点做圆心运动。

 public void MeasureModel(ModelVisual3D model)
{
var camera = _baseModel.Camera;
var rect3D = Rect3D.Empty;
UnionRect(model, ref rect3D); _center = new Point3D((rect3D.X + rect3D.SizeX / 2), (rect3D.Y + rect3D.SizeY / 2),
(rect3D.Z + rect3D.SizeZ / 2)); double radius = (_center - rect3D.Location).Length;
Point3D position = _center;
position.Z += radius * 1.2;
position.X = position.Z;
camera.Position = position;
camera.LookDirection = _center - position;
camera.NearPlaneDistance = radius / 100;
camera.FarPlaneDistance = radius * 100;
}

  设置摄像机的相关属性后,接下来就该是对摄像机做旋转操作了。WPF中旋转提供了两个类AxisAngleRotation3D 和 QuaternionRotation3D。本例中我们选择最常用的AxisAngleRotation3D来完成。在AxisAngleRotation3D提供了CenterX,CenterY,CenterZ这几个属性,用来设置旋转围绕的中心,默认的中心点为(0,0,0),本例中为了实现模型以自己为中心旋转,因此我们需要设置旋转中心。

public void Yaw(bool leftRight, double angleDeltaFactor)
{
var camera = _baseModel.Camera;
var axis = new AxisAngleRotation3D(camera.UpDirection, leftRight ? angleDeltaFactor : -angleDeltaFactor);
var rt3D = new RotateTransform3D(axis) { CenterX = _center.X, CenterY = _center.Y, CenterZ = _center.Z };
Matrix3D matrix3D = rt3D.Value;
Point3D point3D = camera.Position;
Point3D position = matrix3D.Transform(point3D);
camera.Position = position;
camera.LookDirection = camera.LookDirection = _center - position;
}

  源码下载

WPF 3D 模型旋转的更多相关文章

  1. WPF 3D模型的一个扩展方法

    原文:WPF 3D模型的一个扩展方法 在WPF 3D中,我们常常需要改变一个ModelVisual3D对象的颜色. 先说说ModelVisual3D,本质上3D模型都是由一个个的三角形构成的,并且经过 ...

  2. WPF 3D模型 3D场景

    1.首先得说明的是这并不是真正的3D,模型被导出为一系列的单个图片,例如一个3D户型图,以某个视角旋转360°,渲染出一系列连续的单个图片文件. 2.在Image.MouseMove事件中添加相应代码 ...

  3. WPF动态加载3D 放大-旋转-平移

    原文:WPF动态加载3D 放大-旋转-平移 WavefrontObjLoader.cs 第二步:ModelVisual3DWithName.cs public class ModelVisual3DW ...

  4. WPF 3D中多个模型如何设置某一个在最前?

    原文:WPF 3D中多个模型如何设置某一个在最前? 问题:我们的模型包括导入的3D solid模型和axis坐标轴模型,当模型旋转的时候,3D会将axis挡住. 期望:axis一直在最前面,不会被3D ...

  5. WPF 3D 平移模型+动画(桥梁检测系统)

    原文:WPF 3D 平移模型+动画(桥梁检测系统) 关于WPF 3D,网上有很多旋转的例子,但是关于平移的例子并不是太多.本文并非WPF 3D扫盲篇,因此需要对WPF 3D有一定了解,至少知道View ...

  6. WPF 3D:简单的Point3D和Vector3D动画创造一个旋转的正方体

    原文:WPF 3D:简单的Point3D和Vector3D动画创造一个旋转的正方体 运行结果: 事实上很简单,定义好一个正方体,处理好纹理.关于MeshGeometry3D的正确定义和纹理这里就不多讲 ...

  7. cesium编程入门(七)3D Tiles,模型旋转

    cesium编程入门(七)3D Tiles,模型旋转 上一节介绍了3D Tiles模型的位置移动,和贴地的操作,这一节来聊一聊模型的旋转, 参考<WebGl编程指南>的第四章 假设在X轴和 ...

  8. Unity在UI界面上显示3D模型/物体,控制模型旋转

    Unity3D物体在UI界面的显示 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- ...

  9. cesium编程入门(七)3D Tiles,模型旋转

    cesium编程入门(七)3D Tiles,模型旋转 上一节介绍了3D Tiles模型的位置移动,和贴地的操作,这一节来聊一聊模型的旋转, 参考<WebGl编程指南>的第四章 假设在X轴和 ...

随机推荐

  1. boost::asio的http client应用笔记

    1 踩过的坑 1.1 io_service boost::asio::io_service::run()会一直运行到没有任务为止,假设中途调用stop().则全部等待中的任务会立马运行.要在停止的时候 ...

  2. javascrit开发的基本代码结构的

    今天看到群里一个demo,简单看了一下. 然后自己就写了一个通用的javascrit开发的基本代码结构的js文件. 代码例如以下: (function($,win){ //定义全局变量对象 var o ...

  3. swift学习第十一天:类的定义

    一: 主要内容 类的介绍和定义 类的属性 类的构造函数 一. 类的介绍和定义 Swift也是一门面向对象开发的语言 面向对象的基础是类,类产生了对象 在Swift中如何定义类呢? class是Swif ...

  4. css3-11 如何设置文字的阴影

    css3-11 如何设置文字的阴影 一.总结 一句话总结:text-shadow属性.text-shadow:3px 3px 3px #f0f; 1.text-shadow属性的参数依次是什么意思? ...

  5. 附加数据库 对于server XXX失败

            近期在学习MVC+EF,看着视频做小demo.EF这一块须要涉及到数据库的连接,视频中所讲的样例与先前牛腩新闻系统数据库挺类似的. 所以,就偷个懒,利用这个数据库,可是在附加的时候出错 ...

  6. 【solr专题之一】Solr快速入门 分类: H4_SOLR/LUCENCE 2014-07-02 14:59 2403人阅读 评论(0) 收藏

    一.Solr学习相关资料 1.官方材料 (1)快速入门:http://lucene.apache.org/solr/4_9_0/tutorial.html,以自带的example项目快速介绍发Solr ...

  7. 使用Opencv中matchTemplate模板匹配方法跟踪移动目标

    模板匹配是一种在图像中定位目标的方法,通过把输入图像在实际图像上逐像素点滑动,计算特征相似性,以此来判断当前滑块图像所在位置是目标图像的概率. 在Opencv中,模板匹配定义了6种相似性对比方式: C ...

  8. [Compose] 18. Maintaining structure whilst asyncing

    We take our Promise.all() analogy further by using traversable on a Map(). Then we use two traversal ...

  9. 解决Centos7 下 root账号 远程连接FTP,vsftpd 提示 530 Login incorrect 问题

    原文:解决Centos7 下 root账号 远程连接FTP,vsftpd 提示 530 Login incorrect 问题 三步走: 1.vim /etc/vsftpd/user_list 注释掉 ...

  10. ArcEngine开发之Command控件使用篇

    转自原文 ArcEngine开发之Command控件使用篇 在ArcEngine类库中有大量的Command控件用来与地图控件进行操作和交互.比如有一系列的地图浏览控件.地图查询控件.图斑选取控件.编 ...