我有两组向量(旋转前和旋转后)。
旋转前: [x1,y1,z1] [x2,y2,z2]
旋转后: [x1',y1',z1'] [x2',y2',z2']
如何创建表示此旋转的四元数?
我有两组向量(旋转前和旋转后)。
旋转前: [x1,y1,z1] [x2,y2,z2]
旋转后: [x1',y1',z1'] [x2',y2',z2']
如何创建表示此旋转的四元数?
Quaternion q2 = Quaternion::fromTwoVectors(u0, u2);
Vector v1 = v2.rotate(q2.conjugate());
Vector v0_proj = v0.projectPlane(u0);
Vector v1_proj = v1.projectPlane(u0);
Quaternion q1 = Quaternion::fromTwoVectors(v0_proj, v1_proj);
return (q2 * q1).normalized();
我将marcv81非常有帮助的博客文章翻译成了Three.js:
const rotateVectorsSimultaneously = (u0, v0, u2, v2) => {
const q2 = new THREE.Quaternion().setFromUnitVectors(u0, u2);
const v1 = v2.clone().applyQuaternion(q2.clone().conjugate());
const v0_proj = v0.projectOnPlane(u0);
const v1_proj = v1.projectOnPlane(u0);
let angleInPlane = v0_proj.angleTo(v1_proj);
if (v1_proj.dot(new THREE.Vector3().crossVectors(u0, v0)) < 0) {
angleInPlane *= -1;
}
const q1 = new THREE.Quaternion().setFromAxisAngle(u0, angleInPlane);
const q = new THREE.Quaternion().multiplyQuaternions(q2, q1);
return q;
};
angleTo
总是返回正值,我需要手动翻转角度的符号,具体取决于 v1
在 u0
-v0
平面的哪一侧。首先,您可以使用向量乘法(叉乘)找到旋转轴:
axis = v1 x v2;
然后您可以计算旋转角度:
sinA = |axis| / |v1|*|v2|
cosA = v1 . v2 / |v1|*|v2|
这里的 || 表示向量长度操作,. 表示点乘
最终,你的四元数是:
Q(w,x,y,z) = (cosA, axis.x * sinA, axis.y * sinA, axis.z * sinA)
从v1到v2找到四元数是可以的。
最终的q = (cos A/2, sin A/2 * axis)
,其中A是v1和v2之间的角度,axis是归一化的轴。
两边都乘以2 * cos A/2
,
然后我们有
2 * cos A/2 *q = (1+cos A, sin A * axis)
(其中cos A = dot(v1, v2)/|v1|/|v2|
和
axis = cross(v1, v2).normalize() = cross(v1, v2)/|v1|/|v2|/sin A
.)
然后2 * cos A/2 *q = (1+dot(v1, v2)/|v1|/|v2|, cross(v1, v2)/|v1|/|v2|)
最后q = (1+dot(v1, v2)/|v1|/|v2|, cross(v1, v2)/|v1|/|v2|).normalize()
qw = √(1 + m00 + m11 + m22) /2
qx = (m21 - m12)/( 4 *qw)
qy = (m02 - m20)/( 4 *qw)
qz = (m10 - m01)/( 4 *qw)
通常,为了使四元数的转换更加稳健,您应该考虑查看矩阵的迹,如此处所讨论的:http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/
最后,考虑使用直接计算最优四元数的Triad的替代方法,称为QUEST。