虽然我已经找到了2个解决方案,但我很好奇是否有众所周知的方法来执行此操作,因为它似乎是一个相当常见的任务.
这里有两个明显的方法psudo-code ...
这是非常合乎逻辑的,但是调用sin两次和cos一次(在角度计算和轴角度到矩阵转换).
Matrix3x3 rotation_between_vectors_to_matrix(const Vector v1, const Vector v2)
{
angle = v1.angle(v2);
axis = v1.cross(v2);
/* maths for this is well known */
Matrix3x3 matrix = axis_angle_to_matrix(axis, angle);
return matrix;
}
Run Code Online (Sandbox Code Playgroud)
编辑:最简单的功能是相当慢的,但正如在这里的回复中所指出的那样:通过分别从轴长度和点积得到angle_sin和可以避免计算角度.angle_cosv1,v2
这是我发现的另一种方法,它从向量构造两个3x3矩阵并返回差异.
然而,这比可以优化的轴/角度计算慢(如上所述).
注意.假设两个向量都是标准化的,矩阵是列主要的(OpenGL).
Matrix3x3 rotation_between_vectors_to_matrix(const Vector v1, const Vector v2)
{
Matrix3x3 m1, m2;
axis = v1.cross(v2);
axis.normalize();
/* construct 2 matrices */
m1[0] = v1;
m2[0] = v2;
m1[1] = axis;
m2[1] = axis;
m1[2] = m1[1].cross(m1[0]);
m2[2] = m2[1].cross(m2[0]);
/* calculate the difference between m1 and m2 */
m1.transpose();
Matrix3x3 matrix = m2 * m1;
return matrix;
}
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来执行此计算?
编辑:这个问题的目的不是微观优化和基准测试每个方法.相反 - 我很好奇是否有一些我不知道的完全不同和优越的方法.
注意:我故意省略了对共线向量(其中轴为零长度)的退化情况的检查,以保持示例简单.
您发布的两种方法都可以优化。
与其使用acos求两个向量之间的角度,不如完全避免求角度。如何?Rodrigues的轴角公式只需要sin ?,cos ?和1 - cos ?,因此找到实际角度是多余的。
我们知道v1和v2是单位向量;v1 · v2 = |v1| |v2| cos ?因为|v1| = |v2| = 1,v1 · v2直接给我们cos ?,寻找1 - cos ?并不昂贵。v1 × v2 = |v1| |v2| sin ? n = sin ? n,其中n是垂直于v1和的单位向量v2,找到|v1 × v2|叉积的大小将直接给出sin ?。
现在我们已经sin ?和cos ?,我们可以直接使用 Rodrigues forumla 形成旋转矩阵;这是一个简单的实现(尽管页面声称使用四元数数学,但它是轴角到矩阵的转换公式)。
在将两个正交框架构造为矩阵后,您可以避免进行第二次转置。这是证据。
说A并B成为两个矩阵,因为你想从A到B我们需要一些矩阵X,当乘以时A会给出B:
XA = B
X = BA?¹
这就是你所需要的;当你预乘X到A你会得到B。然而,你发现的是Y
Y = AB?¹
YB = A
然后你转置Y得到Y?¹即
Y?¹YB = Y?¹A
B = Y?¹A
您可以只执行上述仅涉及一个转置的方法,而不是执行两次反转(此处转置)。
我仍然会说,如果不对优化形式的方法进行基准测试,我们不能说方法 2 比方法 1 快。一个结论。
| 归档时间: |
|
| 查看次数: |
13734 次 |
| 最近记录: |