屏幕旋转之后的触摸坐标_欧拉变换、 单个变换矩阵拆分、绕任意轴旋转

本文首先讲解欧拉变换(Euler transform)以及它的参数提取(extraction of parameters)。欧拉变换是描述朝向(orientation)的一个直观的方法。然后,会讲到如何从单个矩阵中提取出一系列变换。最后,讲述一个绕任意轴旋转实体(entity,即点、线、面或者物体)的方法。

如果不熟悉旋转变换,建议先看这篇文章:图形学中的基本变换(Basic Transforms)

1 欧拉变换(The Euler Transform)

欧拉变换是一个直观的方法,用于构造一个矩阵设置你自己(即照相机camera)或者任何别的实体朝向某个方向。其名字来源于伟大的瑞士数学家莱昂哈德·欧拉(Leonhard Euler,1707–1783).

首先,某个默认的观察方向(或者视线方向view direction)需要被确立。它经常是沿着-z轴,使头部朝向正y轴,如图4.7所示。这里可以想像一下右手坐标系,正y轴朝向电脑屏幕正上方,正z轴,从垂直电脑屏幕指向屏幕外,而负z轴指向屏幕里。也就是默认观察方向指向屏幕里。

3be39fdd5541840da997c535b4893fd1.png
图4.7 欧拉变换及其与改变欧拉角head, pitch, roll的关系。默认观察方向为负z轴,up direction为y轴。
欧拉变换涉及到三个角度,即欧拉角(Euler angles): head, pitch, roll,如图4.7所示。它们分别简称为
,分别表示应该绕对应的轴旋转的角度。有时它们也会被称为"rolls",例如,"head"对应"y-roll","pitch"对应"x-roll"。"head"有时也没称为"yaw",表示偏航角。

怎么记住三个欧拉角各自的作用(对应的轴)?

答案: 想像一下,静止状态时一个观察者站立,双臂向两边平伸展开,目视前方,其视线方向为负z轴(roll),头顶方向为正y轴(head),右臂所指的方向为正x轴(pitch)。改变head会使观察者做出摇头的动作(即绕y轴旋转head弧度),改变pitch为使观察者做出点头的动作(即绕x轴旋转pitch弧度),改变roll会使观察者的头部倾斜(即绕z轴旋转roll弧度)。

欧拉变换是三个旋转矩阵的乘积。用

表示欧拉变换,则:

矩阵的顺序多达24种。这里我们仅展示方程4.21里的这种,因为它是常为常用。因为

是多个旋转的连接,则它也是一个旋转矩阵,是正交的。因此它的逆阵可表示为

注意欧拉变换不仅可以用于设置照相机的朝向,也可以设置任何物体或实体的朝向。这些变换可以在全局的世界坐标系下完成,也可以在相对于某个物体的局部坐标系完成。

需要注意的是,欧拉角的某些情形下,把z轴作为初始的up direction(即上方向,而我们这里使用y轴作为up direction)。这种差异仅仅是一个符号改变,但可能会令人困惑。在计算机图形学中,如何看待世界(the world)和如何排列内容,有一个区分(a division)或者说有两种方式: y-up或者z-up。大多数生产过程(Most manufacturing processes),包括3D打印,把z-direction作为世界空间(world space)的up方向。航空和海上运输工具认为−z是up方向。而媒体相关的建模系经常认为y-direction为世界坐系下的up方向,这和图形学中描述照相机屏幕上方向(a camera's screen up direction)的方式一致。在本文中,我们使用y-up。

这里需要指出观察空间(view space)内的照相机的上方向(camera's up direction)世界空间的上方向(world's up direction)没有什么特别的关系。毕竟处于两个坐标系中。

尽管对于小的角度或者观察者朝向改变,欧拉角很有用,但它也有一些严重的限制。同时结合使用两个欧拉角集合(tow sets of Euler angles)是困难的。例如,在两个欧拉角集合间进行插值不是简单地对两组集合的三个角度分别进行插值。因为两个不同的欧拉角集合可能给出相同的朝向,此时任何插值都不会旋转物体。这些是考虑用四元数(Quaternion)等来代替欧拉角的原因。

2 从欧拉变换中提取参数(Extracting Parameters from the Euler Transform)

有时从一个正交矩阵,即欧拉变换矩阵,提交出欧拉角

是有用的。过程如下:

这里我们放弃了

矩阵,代之以
矩阵,因为后者提交了所有关于旋转矩阵的必要信息。也就是说,对应的4D矩阵的剩余部分之是0,其右下角的元素为1。

连接方程4.22中的三个旋转矩阵,可以得到:

显然,

,且有:

因此可解出三个欧拉角分别为:

有一个特殊的情形需要处理。如果

,则会出现万向节锁(gimbal lock),旋转角度
将会绕相同的轴旋转(可能方向相反,这取决于
的值为
还是
),这样只有一个角度(
中的一个)需要推导。如果我们任意地设
,则

因为

不影响第一列,所以当
时,我们可以使用
,可以得到

注意arcsin的定义域为

,这意味着如果
创建时包含了一个在此定义域范围外的
,则不能提取出原始参数。
不同的
组合可能产生相同的欧拉变换。

当使用欧拉变换时,万向节锁(gimbal lock)可能会出现。当某个旋转使得三个自由度(对应r, p, h或者说对应x, y, z轴)中的一个消失时,万向节锁会出现。例如,变换顺序为

,假设第一个旋转变换为绕y轴旋转
弧度,然后再进行第二个旋转变换。但第一个旋转变换已经导致z轴和原始的x轴对齐,这样最后绕z轴的旋转就是冗余(redundant)的了。

使用案例: 限制一个变换(Constraining a Transform)

设想你正拿着一个虚拟的扳手,正在拧紧一个螺栓。为了使螺栓拧紧,你必须使扳手绕x轴旋转。现在假设你的输入设备(鼠标、VR手套、空间球等)给你一个旋转矩阵,即,一个关于扳手运动的旋转。问题是对扳手施加这个transform很可能是错误的,因为应该只绕x轴旋转。为了限制输入变换(the input transform)仅绕x轴旋转,只需要用上面的方法提取(extract)出欧拉角

,然后创建一个新的矩阵
,用它来对扳手进行旋转变换就行了,扳手只会在x轴旋转。

3 矩阵分解(Matrix Decomposition)

到目前为止,我们总是假设我们知道当前使用的变换矩阵的原始形态及变化历史(the origin and history of the transformation matrix)。但通常的情形并不是这样的。例如,有时我只有一个由多个变换矩阵相乘得到的最终的矩阵(concatenated matrix),而不知道别的任何信息。从一个concatenated matrix中提取出各种变换的任务被称为矩阵分解(matrix decomposition)。

有许多原因需要从concatenated matrix中提取各种变换。包括:

  • 提取出一个物体的缩放因子
  • 找到一个特殊系统需要的变换。(例如,有些系统可能不允许使用任意
    矩阵)
  • 检测一个模型是否只经历了刚体变换(only rigid-body transforms)
  • 在一个动画的关键帧之间插值只对该物体可用的矩阵
  • 从一个旋转矩阵中移除错切变换

提取平移矩阵也是简单直观的,只需要原始

变换矩阵的最后一列元素。我们也可以确定是否发生了镜像变换,只需要检测矩阵的行列式是否为负。而要剥离出roattion, scaling以及shear,则需要更多的操作。

目前网上已有相关的文章和代码:

  1. Thomas, Spencer W., “Decomposing a Matrix into Simple Transformations,” in James Arvo, ed., Graphics Gems II, Academic Press, pp. 320–323, 1991. Cited on p. 72, 74
  2. Goldman, Ronald, “Recovering the Data from the Transformation Matrix,” in James Arvo, ed., Graphics Gems II, Academic Press, pp. 324–331, 1991. Cited on p. 74
  3. Goldman, Ronald, “Decomposing Linear and Affine Transformations,” in David Kirk, ed., Graphics Gems III, Academic Press, pp. 108–116, 1992. Cited on p. 74
  4. Sloan, Peter-Pike, Ben Luna, and John Snyder, “Local, Deformable Precomputed Radiance Transfer,” ACM Transactions on Graphics (SIGGRAPH 2005), vol. 24, no. 3, pp. 1216–1224, Aug. 2005. Cited on p. 431, 481

4 绕任意轴旋转(Rotation about an Arbitrary Axis)

有时能够使一个实体绕任意旋转轴旋转是很有用的。假设旋转轴

是一个归一化(normalized)的向量,我们要创建一个变换使得物体绕
旋转
弧度。

为了达到此目的,我们首先需要变换坐标空间,在新的坐标空间中,

为新坐标系的x轴。这一变换需要一个旋转矩阵
完成。然后,在新坐标空间中对物体施加旋转
弧度的变换。最后,利用
的逆阵
把物体变换到原始的坐标空间。这一过程如图4.8所示。

01e81b83f530bb0aa32c8a29c79105f1.png
图4.8 绕任意轴旋转

关键的问题是: 怎么计算

呢?

为了计算

,我们需要找到另外两个坐标轴
,使得
相互垂直。我们只需要专注于如何找到第二个坐标轴
,因为找到它之后,只需要用前两个的叉积就能计算第三个坐标轴
。一种数值稳定的方法是找到找到
的绝对值最小的分量,将其设置为0,然后交换另外两个分量的值,再把被交换的两个分量的值中的第一个值取负(negate. 实际上,把二者中任意非零分量取负都行)。可用数学语言表示为:

这能确保

是归一化的,且与
是正交的,使得
是一组正交基。则可得:

关于
为什么长这样,请参看上篇文章中在构造相机变换矩阵时提到的问题:“思考一个问题:为什么方程4.20中的变基矩阵(change of basis)长这样?”

提示:显示可以看到
, 即
分别把
变成了x, y, z坐标轴。

因此最终把物体绕归一化的轴

旋转
弧度的变换矩阵为:

总之,就是先通过坐标空间变换把

变换成x轴,然后进行
弧度旋转(用
),最后再通过坐标空间变换,回到原始坐标系。

另外一篇文章 四元数和旋转(Quaternion & rotation)也介绍过一种方法来计算绕任意轴旋转,它直接给出了一个绕任意轴旋转的矩阵。此处不再单独说明。那篇文章中也说明了用四元数做任意轴旋转会更新加高效、便捷。

Reference:

  1. Real-Time Rendering 4th 第4.2节
  2. 四元数和旋转(Quaternion & rotation)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值