如何从转换矩阵中提取方向?


10

我有一个4x4的转换矩阵M,我想找出通过M转换后的球体的形状。(球体在原点,半径为1。)

我知道只要将M乘以(0,0,0,1)就可以找到中心。

但是,由于M可以挤压和旋转球体,因此半径成为问题。如何找出所得椭球的新半径?有什么办法找出方向吗?

更具体地说,我需要知道包围转换后的球体的边界球体的大小。换句话说,| M * V-M *(0,0,0,1)|的最大值是多少,其中V是单位矢量(原始球体上的一个点)。


1
您不能只计算转换后的轴矢量的长度吗?(矩阵旋转部分的3列)边界球的半径等于最长向量的长度。
巴特2013年

不,我认为那是不对的。最长方向可能未与轴对齐。(想象一下,如果您压扁,旋转,再次压扁,再旋转其他,等等)
CaptainCodeman 2013年

嗯,不确定这很重要。如果我能说服自己,我今天晚些时候会写下答案。;)
巴特

问题是,如果执行SCALE转换,则M矩阵的基向量不必彼此正交。
GPUquant

Answers:


6

在数学上,您要询问的数量称为算子范数。不幸的是,没有简单的公式可以解决。如果这是一个完全通用的仿射变换-例如,如果它可以具有任意顺序的旋转和不均匀比例的任意组合,那么恐怕没有什么可以使用奇异值分解了。如果将SVD应用于矩阵,则最大的奇异值将是所得椭球的最大半径。其他奇异值也将是其其他两个半径,并且SVD过程也可以为您提取轴的方向。

实施SVD并非出于胆小,因为它涉及寻找特征值。如果您只需要奇异值本身,它们就是M ^ T * M特征值的平方根。因此,如果您有一个3x3特征值求解器,或者您不介意编写一个,则可以使用它。如果您还想提取轴的方向,那么它也将涉及更多,因为您也必须找到特征向量。在该Wikipedia文章上,列出了用于执行SVD的库的链接列表,您可以在项目中使用其中的一个。

如果矩阵的形式受到限制,使得不均匀缩放最多发生一次,并且是应用的第一个变换,即在使用列向量时最右边,那么您可以简化此过程,只需查看转换后的轴向量。仅在那种情况下(即单个不均匀的比例尺,然后是旋转,反射和均匀比例尺的任何序列),仅查看轴矢量将为您提供正确的答案。


谢谢,我感谢您的详细答复。其他答案中提供的分解在哪里无效?
CaptainCodeman

2
@CaptainCodeman另一个答案就是看变换后的轴矢量(即矩阵的列),就像我在第三段中描述的那样。如果旋转后缩放比例不一致,则失败,因为这样缩放比例就不会沿原始轴应用。
内森·里德

2

也许从矩阵中提取比例因子,然后使用其分量的最大值。使用SRT(缩放-旋转-平移)矩阵,您可以这样做:

glm::mat4 m = ...;
// Extract col vectors of the matrix
glm::vec3 col1(m[0][0], m[0][1], m[0][2]);
glm::vec3 col2(m[1][0], m[1][1], m[1][2]);
glm::vec3 col3(m[2][0], m[2][1], m[2][2]);
//Extract the scaling factors
glm::vec3 scaling;
scaling.x = glm::length(col1);
scaling.y = glm::length(col2);
scaling.z = glm::length(col3);

float scaleFactor = MAX(scaling.x, MAX(scaling.y, scaling.z));

(基于http://wklej.org/id/950061/-名称是decomposeTRS而不是decomposeSRT,因为我使用的名称是按es顺序排列的,在OpenGL中矩阵被乘以)。

现在,您可以将原始球体半径乘以scaleFactor,然后得到边界球体。

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.