我正在尝试理解四元数,并且在将其转换为实际有用的东西时遇到了很多麻烦。我看过一些 3blue1brown 的视频并阅读了一些教程,但我似乎无法将我看到的东西翻译成简单的东西,这意味着我根本不了解它。
从我能想到的最简单的例子开始,我想从 xyz (1, 0, 0) 处的一个点开始,围绕 Z 轴旋转 90 度。这应该给我点(0、1、0)。使用三角函数,进行旋转很简单(doSimple()
)。
正如我所说,我缺乏对四元数基础知识的理解,但据我所知,3d 空间中的一个点可以用 x、y、z 和 0 表示 w。而且gl-matrix有一个 'quat.rotateZ' 方法,看起来它应该围绕该轴旋转一个角度。我的结果似乎表明它只旋转了 1/2 角度并且方向错误(repl.it):
const { quat } = require('gl-matrix');
const doSimple = () => {
// simple using trig:
const x = 1, y = 0;
const angle = Math.PI / 2; // 15 degrees
const newX = x * Math.cos(angle) - y * Math.sin(angle);
const newY = x * Math.sin(angle) + y * Math.cos(angle);
console.log({ angle, x, y, newX, newY });
}
const doQuat = () => {
let [x, y, z, w] = [1, 0, 0, 0];
const a = quat.fromValues(x, y, z, w);
const ninetyDegrees = Math.PI / 2;
const b = quat.create();
quat.rotateZ(b, a, ninetyDegrees);
const results = { a, b }
console.log(results)
}
const doAngle = () => {
let [x1, y1, z1, w1] = [1, 0, 0, 0];
let [x2, y2, z2, w2] = [0, 1, 0, 0];
const q1 = quat.fromValues(x1, y1, z1, w1);
const q2 = quat.fromValues(x2, y2, z2, w2);
const angle = quat.getAngle(q1, q2);
console.log({ angle });
}
doSimple();
doQuat();
doAngle();
doSimple()
在我看来很好:
{
angle: 1.5707963267948966,
x: 1,
y: 0,
newX: 6.123233995736766e-17,
newY: 1
}
doQuat()
使用quat.rotateZ()
并且似乎只旋转 45 度并且方向错误:
{
a: Float32Array(4) [ 1, 0, 0, 0 ],
b: Float32Array(4) [ 0.7071067690849304, -0.7071067690849304, 0, 0 ]
}
doAngle()
似乎报告在 (1,0,0) 和 (0,1,0) 之间有 180 度:
{ angle: 3.141592653589793 }
所以我知道我完全误解了一些东西,但我不知道它是什么......
- -编辑 - -
我认为我的很多困惑源于示例中的不同术语。 gl-matrix
使用 x,y,z,w。3blue1brown 使用<blank>
, i,j,k。 本文使用 q0,q1,q2,q3。 论文中的这个计算器似乎没有意义,因为 Yaw 围绕 Z 轴旋转,围绕 Y 轴俯仰,围绕 X 轴滚动?
如果我在 3d 空间中思考,我思考事物的正常方式是 Z 面向屏幕外,X 和 Y 代表屏幕上的正常 2d 图形(X 点“右”,Y 点“上”)。偏航应该围绕 Y 轴旋转,俯仰应该围绕 X 轴旋转。
我想错了吗?在尝试学习时,是否有一组(或多组)查看坐标系、旋转和四元数的标准方法?例如我认为由于 gl-matrix 使用 x,y,z,w 而论文使用 q0,q1,q2,q3 而 3b1b 使用空白,i,j,k,我认为转换如下:
- q0 -> 空白 -> w
- q1 -> i -> x
- q2 -> j -> y
- q3 -> k -> z