gpt4 book ai didi

quaternions - 使用向上向量查看四元数

转载 作者:行者123 更新时间:2023-12-04 12:16:15 25 4
gpt4 key购买 nike

我有一个相机(在自定义 3D 引擎中),它接受旋转变换的四元数。我有两个 3D 点代表一个相机和一个要查看的对象。我想计算从相机到物体的四元数,同时尊重世界上轴 .

This question在没有“向上”向量的情况下要求相同的东西。所有三个答案都会导致相机指向正确的方向,但会滚动(如偏航/俯仰/滚动;想象在看东西时将头靠在耳朵上)。

我可以通过以下方式计算与所需坐标系匹配的向量的正交基:

lookAt = normalize(target - camera)
sideaxis = cross(lookAt, worldUp)
rotatedup = cross(sideaxis, lookAt)

如何从这三个向量创建四元数? This question要求同样的事情......但不幸的是,唯一且被接受的答案说〜“假设你不关心滚动”,然后忽略向上轴。我确实关心滚动。我不想忽略向上轴。

最佳答案

以前的答案使用角度给出了有效的解决方案。这个答案将提供另一种方法。

正交基向量,将它们重命名 F = lookAt, R = sideaxis, U = rotatedup , 直接形成 3x3 旋转矩阵的列,相当于您想要的四元数:

enter image description here

与向量相乘等效于使用所述向量的分量作为相机基础中的坐标。

3x3 旋转矩阵可以转换为四元数,而无需转换为角度/使用昂贵的三角函数。下面是一个数值稳定的 C++ 片段,它执行此操作,返回一个规范化的四元数:

inline void CalculateRotation( Quaternion& q ) const {
float trace = a[0][0] + a[1][1] + a[2][2];
if( trace > 0 ) {
float s = 0.5f / sqrtf(trace + 1.0f);
q.w = 0.25f / s;
q.x = ( a[2][1] - a[1][2] ) * s;
q.y = ( a[0][2] - a[2][0] ) * s;
q.z = ( a[1][0] - a[0][1] ) * s;
} else {
if ( a[0][0] > a[1][1] && a[0][0] > a[2][2] ) {
float s = 2.0f * sqrtf( 1.0f + a[0][0] - a[1][1] - a[2][2]);
q.w = (a[2][1] - a[1][2] ) / s;
q.x = 0.25f * s;
q.y = (a[0][1] + a[1][0] ) / s;
q.z = (a[0][2] + a[2][0] ) / s;
} else if (a[1][1] > a[2][2]) {
float s = 2.0f * sqrtf( 1.0f + a[1][1] - a[0][0] - a[2][2]);
q.w = (a[0][2] - a[2][0] ) / s;
q.x = (a[0][1] + a[1][0] ) / s;
q.y = 0.25f * s;
q.z = (a[1][2] + a[2][1] ) / s;
} else {
float s = 2.0f * sqrtf( 1.0f + a[2][2] - a[0][0] - a[1][1] );
q.w = (a[1][0] - a[0][1] ) / s;
q.x = (a[0][2] + a[2][0] ) / s;
q.y = (a[1][2] + a[2][1] ) / s;
q.z = 0.25f * s;
}
}
}

来源: http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion

将其转换为适合您的情况当然只是将矩阵元素与相应的向量分量交换的问题:
// your code from before
F = normalize(target - camera); // lookAt
R = normalize(cross(F, worldUp)); // sideaxis
U = cross(R, F); // rotatedup

// note that R needed to be re-normalized
// since F and worldUp are not necessary perpendicular
// so must remove the sin(angle) factor of the cross-product
// same not true for U because dot(R, F) = 0

// adapted source
Quaternion q;
double trace = R.x + U.y + F.z;
if (trace > 0.0) {
double s = 0.5 / sqrt(trace + 1.0);
q.w = 0.25 / s;
q.x = (U.z - F.y) * s;
q.y = (F.x - R.z) * s;
q.z = (R.y - U.x) * s;
} else {
if (R.x > U.y && R.x > F.z) {
double s = 2.0 * sqrt(1.0 + R.x - U.y - F.z);
q.w = (U.z - F.y) / s;
q.x = 0.25 * s;
q.y = (U.x + R.y) / s;
q.z = (F.x + R.z) / s;
} else if (U.y > F.z) {
double s = 2.0 * sqrt(1.0 + U.y - R.x - F.z);
q.w = (F.x - R.z) / s;
q.x = (U.x + R.y) / s;
q.y = 0.25 * s;
q.z = (F.y + U.z) / s;
} else {
double s = 2.0 * sqrt(1.0 + F.z - R.x - U.y);
q.w = (R.y - U.x) / s;
q.x = (F.x + R.z) / s;
q.y = (F.y + U.z) / s;
q.z = 0.25 * s;
}
}

(不用说交换 yz 如果您使用的是 OpenGL。)

关于quaternions - 使用向上向量查看四元数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52413464/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com