我有一个4x4的转换矩阵M,我想找出通过M转换后的球体的形状。(球体在原点,半径为1。)
我知道只要将M乘以(0,0,0,1)就可以找到中心。
但是,由于M可以挤压和旋转球体,因此半径成为问题。如何找出所得椭球的新半径?有什么办法找出方向吗?
更具体地说,我需要知道包围转换后的球体的边界球体的大小。换句话说,| M * V-M *(0,0,0,1)|的最大值是多少,其中V是单位矢量(原始球体上的一个点)。
我有一个4x4的转换矩阵M,我想找出通过M转换后的球体的形状。(球体在原点,半径为1。)
我知道只要将M乘以(0,0,0,1)就可以找到中心。
但是,由于M可以挤压和旋转球体,因此半径成为问题。如何找出所得椭球的新半径?有什么办法找出方向吗?
更具体地说,我需要知道包围转换后的球体的边界球体的大小。换句话说,| M * V-M *(0,0,0,1)|的最大值是多少,其中V是单位矢量(原始球体上的一个点)。
Answers:
在数学上,您要询问的数量称为算子范数。不幸的是,没有简单的公式可以解决。如果这是一个完全通用的仿射变换-例如,如果它可以具有任意顺序的旋转和不均匀比例的任意组合,那么恐怕没有什么可以使用奇异值分解了。如果将SVD应用于矩阵,则最大的奇异值将是所得椭球的最大半径。其他奇异值也将是其其他两个半径,并且SVD过程也可以为您提取轴的方向。
实施SVD并非出于胆小,因为它涉及寻找特征值。如果您只需要奇异值本身,它们就是M ^ T * M特征值的平方根。因此,如果您有一个3x3特征值求解器,或者您不介意编写一个,则可以使用它。如果您还想提取轴的方向,那么它也将涉及更多,因为您也必须找到特征向量。在该Wikipedia文章上,列出了用于执行SVD的库的链接列表,您可以在项目中使用其中的一个。
如果矩阵的形式受到限制,使得不均匀缩放最多发生一次,并且是应用的第一个变换,即在使用列向量时最右边,那么您可以简化此过程,只需查看转换后的轴向量。仅在那种情况下(即单个不均匀的比例尺,然后是旋转,反射和均匀比例尺的任何序列),仅查看轴矢量将为您提供正确的答案。
也许从矩阵中提取比例因子,然后使用其分量的最大值。使用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,然后得到边界球体。