如何围绕3D中的任意点(而不是原点)旋转?


15

我有一些模型,我希望使用四元数以正常方式旋转,除了希望绕原点旋转以外,我希望它稍微偏移一些。我知道您并不是说在3D空间中绕点旋转。你说你绕轴旋转。因此,我将其可视化为围绕尾部不在本地原点的向量旋转。

我的渲染/物理引擎中的所有仿射变换都使用SQT(比例尺,四元数,平移;从Game Engine Architecture一书中借来的一个想法)存储。因此,我从这些组件中构建每个帧的矩阵,并将其传递给顶点着色器。在此系统中,先平移,然后缩放,然后旋转。

在一种特定情况下,我需要在世界空间中平移对象,对其进行缩放并围绕不以该对象的本地原点为中心的顶点旋转它。

问题:考虑到上述当前系统的限制,如何实现围绕原点以外的点进行局部旋转?自动支持任何可以仅使用矩阵描述如何执行此操作的人:)


四元数已经描述了围绕任意轴的旋转。您是否有从数据中构造这样的四元数的问题?
Martin Sojka

3
认真地,支持答案的人能真正阅读它们吗?我提供了一种方法,一个有效的公式,甚至是一个演示。然而,唯一被赞成的答案在提供一些有价值的信息(以及一些明显错误的信息)的同时,却没有提供这些信息,甚至无法回答问题!
sam hocevar

@MartinSojka,这是关于任意点,而不是任意轴。
notlesh 2011年

@SamHocevar您的回答都很有帮助。我选择您的方法是因为它更全面,并帮助我找到了解决方案。谢谢你俩。
notlesh 2011年

啊,对不起-我把它与双重四元数混淆了(那些四元数也使您“免费”获得了翻译)。稍后我将写出我在答案中的意思;也许其他人会发现它很有用,特别是因为您可以将三个组成部分简化为一个,尽管这要复杂一些。
Martin Sojka

Answers:


17

简而言之

您只需要在SQT表单中更改T。

更换平移向量vv' = v-invscale(p-invrotate(p))地方v是初始平移矢量,p大约要发生旋转的点,invrotate并且invscale是你的旋转和缩放的逆。

快速示范

让它p成为应用旋转的点r。让s是你的缩放参数和v您的翻译载体。最后的矩阵变换是T(p)R(r)T(-p)S(s)T(v)不是R(r)S(s)T(v)

你需要的是新的转换参数v'r's'使得最终矩阵变换是R(r')S(s')T(v'),我们有:

T(p)R(r)T(-p)S(s)T(v) = R(r')S(s')T(v')

无穷大的行为表示旋转参数和缩放参数不能更改(可以证明)。因此r = r',我们有和s = s'。因此v',唯一缺少的参数是,新的翻译向量:

T(p)R(r)T(-p)S(s)T(v) = R(r)S(s)T(v')

如果这些矩阵相等,则它们的逆相等:

T(-v)S(-s)T(p)R(-r)T(-p) = T(-v')S(-s)R(-r)

对于原产地尤其如此O

T(-v)S(-s)T(p)R(-r)T(-p)O = T(-v')S(-s)R(-r)O

缩放并旋转原点可得出原点,从而得到:

T(-v)S(-s)T(p)R(-r)(-p) = -v'

v'是您正在寻找的新翻译向量,可用于以SQT格式存储转换。可能可以简化计算。但至少不增加所需的存储空间


感谢您的解释。顺便说一句,您是否知道任何资源可以阅读有关SQT表示技巧的更多信息?
pachanga

如果我错了,请纠正我,但似乎另一种解决方案是将四元数正常存储,如果您需要考虑围绕任意点/轴的平移,然后用包含的四角形构建Q矩阵,只需提取平移矢量从这个矩阵(通常是最后一列)中添加到对象转换向量中,然后抛出临时矩阵。
johnbakers

15

用于导出旋转矩阵的所有规范旋转公式都用于绕原点旋转。如果要改为围绕特定点应用该旋转,则必须首先偏移原点-或等效地移动对象,以便要围绕其旋转的点位于原点。

首先考虑2D情况,因为它更简单且技术可扩展。如果您有一个以原点为中心的宽度为2的立方体,并且想要将其绕其原点旋转45度,则这将是2D旋转矩阵的简单应用。

但是,如果您想绕它的右上角(位于1,1)旋转它,则首先必须对其进行平移,以使该角位于原点。可以通过翻译来完成-1,-1。然后,您可以像以前一样旋转对象,但是您必须通过将其平移回(by 1,1)来进行后续操作。因此,通常来说,要获得大约点R旋转的旋转矩阵,请执行以下操作:rP

R = translate(-P) * rotate(r) * translate(P)

其中translaterotate是分别为标准平移/旋转矩阵。碰巧的是,这只是微不足道地缩放到3D,除了必须同时为旋转提供轴外,您还可以始终选择标准的X,Y或Z轴旋转矩阵,但这很乏味。您将要使用任意的轴角旋转矩阵。因此,您R在3D中的最终成绩是:

R = translate(-P) * rotate(a,r) * translate(P)

其中a是代表旋转轴的单位向量,P现在是模型空间中代表旋转点的3D点。

碰巧,四元数可以被转换矩阵表示,所以你可以做你的串联这样,你应该选择这样做。或者,您也可以将所有内容都保留为矩阵(四元数具有一些不错的优点,例如更容易以理智的方式进行插值,但是是否需要由您自己决定)。

也:

因此,我将其可视化为围绕尾部不在本地原点的向量旋转。

严格来说,虽然向量可以通过将其视为从原点的位移来表示位置,但向量本身没有位置,因此可视化这样的位置有点不寻常。


谢谢,这是一个很好的答复。但是,它不适合我的系统的限制。我应该在我的问题中加入“鉴于这些限制是否可以做到这一点?”,我认为答案是没有,因为这需要两种翻译,而我只提供一种。这是使用SQT表示仿射变换的不可避免的缺点吗?
notlesh

它完全适合您的约束。矩阵R(作为平移-旋转-反向平移生成)是您的旋转矩阵。在您的“ SQT”系统中将Q替换为R,这样您就可以使用更常见的比例-旋转-平移范例。最后的平移与完成以产生所需旋转的两个中间平移无关。

您是在提议用矩阵替换四元数吗?每个对象还有12个字节(如果我将其存储为4x3矩阵,则为8个字节)!不过,我会让内心的乐观主义者保持沉默,然后旋转一下。(实际上可能甚至不会增加2kb的占用空间...)感谢您的回复。
notlesh 2011年

您可以-也可以在它们之间进行转换,以这种方式构造旋转四元数,然后重新插入现有系统。

1
@SamHocevar:或者,可以将它们的任何组合表示为单个螺钉
马丁·索卡
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.