3D旋转概念以及计算方法

本文详细介绍了如何使用鼠标旋转三维对象,即虚拟轨迹球技术。通过将二维鼠标移动转换为三维旋转,文章阐述了实现过程并提供了示例代码,使读者能够将其应用于自己的WPF应用程序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用鼠标旋转相机

实现一个虚拟轨迹球(原代号为Avalon的Windows Presentation Foundation的)

丹尼尔Lehenbauer http://blogs.msdn.com/danlehen

抽象

一般人想要做的显示三维模型后,他们的第一件事是一下就可以用鼠标旋转。通过鼠标旋转三维对象最常见的技术被称为“虚拟轨迹球”。本文将描述一个轨迹球做什么和步行通过实施机制。在结束示例代码的链接,用鼠标在你自己的WPF应用程序,您可以使用旋转相机。

 

  

图1a

老虎在其原始配置模型

图1b

虎小鼠模型后一直拖到左略有下降。

1。介绍

轨迹球转换成三维旋转的2D鼠标的移动。这是通过投影鼠标的位置上,如图2所示的假想球落后的Viewport3D。随着鼠标移动相机(或场景)旋转,以保持对鼠标指针下方领域的相同点。

 

  

图2a

Viewport3D的立方体,从用户的角度来看,落款轨迹球

图2b

侧视图说明映射到鼠标的位置,球体上的点

 

水平移动鼠标时,必须保持一个关于Y轴的旋转相同的点下鼠标指针。

 

 

图3

垂直移动鼠标旋转的Y轴的场景

 

同样,垂直变化中的X轴旋转的鼠标位置的结果。

 

 

图4

垂直移动鼠标绕X轴旋转场景

 

此接口提供了一个比较直观的方法,其中一个模型可以操纵通过了关于X和Y轴的旋转组合成任何方向。

2。计算旋转

在每个鼠标移动事件中,我们需要计算出一个旋转,以保持相同的点下鼠标指针。这样做有两个步骤。首先是搞清楚什么球体上的点下鼠标指针。二是计算需要改造旧了点的新的起点上旋转。

2.1寻找球点

为了找到球体上的点下鼠标指针,我们需要 刻在Viewport3D的球体投射在二维点的UIElement的坐标系。图5显示了两个坐标系统。

 

  

图5a

鼠标报告UIElement的,其中有(0,0)在左上角的坐标空间中的位置。

图5b

我们预计在这个二维点刻在Viewport3D的球体。请注意,这个结果在一个三维坐标。

 

由于我们只计算的旋转,我们可以选择两者协调的领域,对我们来说是最方便的系统感兴趣。这是最简单的使用了球形半径 = 1原点(0,0,0)为中心。这使得发现的X和Y分量在两个如图6所示的二维坐标系统之间的转换的工作。

 

  

图6a

坐标系统的UIElement

图6b

协调系统,我们的轨迹球

 

要做到这一点,我们构建了一个规模将映射Viewport3D的界限范围[0,0] - [2,2]。然后,我们应用翻译从左上角移动到中心的起源。这使得我们的观点,在范围[1,1] - [1,-1]。最后,我们占为Y轴朝下,而不是在二维坐标系统。

 

 

/ / [0,0]规模界限 - [2,2]

双X = PX /(宽/ 2);

双Y = PY /(身高/ 2);

 

/ /翻译0,0中心

X = X - 1;

 

/ /翻转+ Y是,而不是向下

Y = 1 - Y;

 

现在,我们已经发现我们的x和y位置上球体,我们可以发现ž。由于我们的球半径 = 1,我们知道。以解决ž我们得到:

 

 

双Z2 = 1 - X * X - Y * Y;

双?Z = Z2> 0 数学 ​​SQRT (Z2):0;

 

的Vector3D

p.Normalize();

 

现在,我们有 X  Y  Z 球体上的点)下方的鼠标指针的坐标。

2.2旋转点之间的

在每个鼠标移动,我们要构建一个旋转,将保持对鼠标指针下方领域的相同点。为此,我们从上次鼠标移动事件记忆球体上的点和建设,将改变目前点下鼠标指针旋转。

 

计算旋转,我们需要两件事情:

 

  1. 旋转轴
  2. 旋转角度θ

 

 

图7

我们需要找到轴和旋转角度θ,将改变V 1到V 2

 

在以原点为中心,因为我们的球,我们可以解释我们的观点,作为载体。它这样做是微不足道的轴和旋转角度分别使用交叉的产品和网点产品:

 

 

的Vector3D 轴的Vector3D(V1,V2);

双θ= 的Vector3D,。AngleBetween(V1,V2);

 

一旦我们拥有了这一切仍然是当前方向申请新的旋转轴和角度:

 

/ /我们否定的角度,因为我们正在旋转的摄像头。

/ /不要做,如果你正在旋转的场景代替。

四元三角= 新 四元数(轴角);

 

/ /获取当前orientantion的RotateTransform3D

RotateTransform3D RT =(RotateTransform3D)camera.Transform ;

AxisAngleRotation3D R =(AxisAngleRotation3D)rt.Rotation的的 ;           

四元数Q = 新 四元(r.Axis, r.Angle)

 

/ /构图方向与以往的三角洲

Q * =三角洲;

 

/ /写入新的方向返回到Rotation3D

r.Axis = q.Axis ;

r.Angle = q.Angle ;

3。其他细节

也有一些细节,我们在第2掩饰。首先是投射到球体的鼠标指针,计算假设Viewport3D的是方形的。Viewport3D的如果是椭圆形刻轨迹球实际上是一个椭球:

 

 

图8

如果Viewport3D的是椭圆形的题写的轨迹球,实际上是一个椭球

 

这种效果是通常不引人注目,但如果长宽比是极端的,这将导致旋转速度沿较短的轴移动时速度明显加快。为了纠正这个问题,你可以申请一个统一的尺度时二维点映射到球体,而不是(宽度, 高度)。例如,分(宽度高度)会的工作。无论你选择,记得翻译的起源时,此帐户。

 

另一个问题是如何处理的情况下,当鼠标指针不映射到轨迹球定位:

 

 

图9

阴影区域不映射到一个点上的轨迹球

 

一个可行的办法是打击Z在这种情况下为零,然后年底的2.1节所示:

 

双?Z = Z2> 0 数学 ​​SQRT (Z2):0;

 

从技术上讲,我们也应该正常化x  y 找到轨迹球最近在点Z = 0平面的,否则我们返回的是不球体上的:

 

 

 

然而,在2.2节中,我们使用的Vector3D 。AngleBetween(V1,V2)占 ​​非规范化的载体。这是正常化的产量x  y 相同的结果如上图所示。

 

我们还没有讨论的模型和摄像机的初始位置。此实现假定该模型为中心的起源和相机正在研究的起源和定位在距离该模型是可见的。

 

最后,本文不讨论如何实现变焦,虽然示例代码包含一个合理的实施。

4。示例代码

示例代码包含三个可重用件:

 

trackball.cs

观察一个FrameworkElement的鼠标事件,由此产生的旋转和尺度,以更新的Transform3D 实用程序类。

 

trackport.proj

一个UserControl的加载和显示XAML从松散。Model3D 允许的观点,通过鼠标(例如使用的操纵Trackball.cs)

 

ModelViewer.proj

模型查看器应用程序图,在图1(使用例如Trackport.proj的)。

 

这些都包含在“3D工具的Windows Presentation Foundation”在此URL的工作区:http://workspaces.gotdotnet.com/3DTools

 

下载的版本,其中既包括二进制和源代码(在这里)你不必参加工作区。

转载于:https://www.cnblogs.com/zhihai/archive/2012/02/03/2337123.html

基于谷歌官方提供的3D翻转示例进行修改,修复了在不同设备上显示效果差异过大的问题。项目地址:https://github.com/GcsSloop/Rotate3dAnimation 效果图:如何使用:// 计算中心点(这里是使用view的中心作为旋转的中心点)         final float centerX = view.getWidth() / 2.0f;                 final float centerY = view.getHeight() / 2.0f;        //括号内参数分别为(上下文,开始角度,结束角度,x轴中心点,y轴中心点,深度,是否扭曲)         final Rotate3dAnimation rotation = new Rotate3dAnimation(this, start, end, centerX, centerY, 1.0f, true);         rotation.setDuration(1500);                               //设置动画时长         rotation.setFillAfter(true);                              //保持旋转后效果         rotation.setInterpolator(new AccelerateInterpolator());   //设置插值器         rotation.setAnimationListener(new AnimationListener() {   //设置监听器             @Override             public void onAnimationStart(Animation animation) {             }            @Override             public void onAnimationRepeat(Animation animation) {             }            @Override             public void onAnimationEnd(Animation animation) {             }         });         view.startAnimation(rotation);                            //开始动画
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值