gpt4 book ai didi

c++ - 从四元数计算 vector 有效,从 vector 计算四元数不

转载 作者:行者123 更新时间:2023-12-02 10:08:54 25 4
gpt4 key购买 nike

所以我使用四元数在 3D 空间中创建一个由两个点组成的段,并稍后尝试重新计算一个类似的四元数(一个表示穿过空间的相同 vector ;我知道该段围绕自身的旋转是未定义的)。我正在创建这样的 segmentation :

sf::Vector3<float> Start(0, 0, 0);
sf::Vector3<float> End = Start;

//Create a vector from the start to the end
sf::Vector3<float> Translation = Orientation.MultVect(sf::Vector3<float>(0, 1, 0));

//Add that vector onto the start position
End.x += Translation.x * Length;
End.y += Translation.y * Length;
End.z += Translation.z * Length;

Orientation::MultVect() 看起来像这样:
sf::Vector3<float> Quaternion::MultVect(sf::Vector3<float> Vector)
{
//From http://www.idevgames.com/articles/quaternions
Quaternion VectorQuat = Quaternion();
VectorQuat.x = Vector.x;
VectorQuat.y = Vector.y;
VectorQuat.z = Vector.z;
VectorQuat.w = 0.0;

Quaternion Inverse = (*this);
Inverse.Invert();

Quaternion Result = Inverse * VectorQuat * (*this);

sf::Vector3<float> ResultVector;
ResultVector.x = Result.x;
ResultVector.y = Result.y;
ResultVector.z = Result.z;

return ResultVector;
}

现在这个函数似乎在其他情况下工作得相当好,所以我认为问题不在这里,但你永远不知道。我还应该提到,考虑到我提供的四元数 if (我从欧拉角构造,有时与其他四元数相乘),这一点最终会在我期望的地方结束。

对我来说,问题似乎在于从 Start 重新计算四元数。和 End .为此,我使用了这个函数,它在将场景中的对象定向到其他对象时效果很好(除非有问题的对象沿着完全相同的 Y 轴,在这种情况下,我得到具有 NaN 值的四元数)。我是这样做的:
Quaternion Quaternion::FromLookVector(sf::Vector3<float> FromPoint, sf::Vector3<float> ToPoint)
{
///Based on this post:
///http://stackoverflow.com/questions/13014973/quaternion-rotate-to
//Get the normalized vector from origin position to ToPoint
sf::Vector3<double> VectorTo(ToPoint.x - FromPoint.x,
ToPoint.y - FromPoint.y,
ToPoint.z - FromPoint.z);
//Get the length of VectorTo
double VectorLength = sqrt(VectorTo.x*VectorTo.x +
VectorTo.y*VectorTo.y +
VectorTo.z*VectorTo.z);
//Normalize VectorTo
VectorTo.x /= -VectorLength;
VectorTo.y /= -VectorLength;
VectorTo.z /= -VectorLength;

//Define a unit up vector
sf::Vector3<double> VectorUp(0, -1, 0);

//The X axis is the cross product of both
//Get the cross product as the axis of rotation
sf::Vector3<double> AxisX(VectorTo.y*VectorUp.z - VectorTo.z*VectorUp.y,
VectorTo.z*VectorUp.x - VectorTo.x*VectorUp.z,
VectorTo.x*VectorUp.y - VectorTo.y*VectorUp.x);
//Normalize the axis
//Get the length of VectorTo
double AxisXLength = sqrt(AxisX.x*AxisX.x +
AxisX.y*AxisX.y +
AxisX.z*AxisX.z);

//Normalize VectorTo
AxisX.x /= AxisXLength;
AxisX.y /= AxisXLength;
AxisX.z /= AxisXLength;

//Get the adjusted Y vector
//Get the cross product of the other two axes
sf::Vector3<double> AxisY(VectorTo.y*AxisX.z - VectorTo.z*AxisX.y,
VectorTo.z*AxisX.x - VectorTo.x*AxisX.z,
VectorTo.x*AxisX.y - VectorTo.y*AxisX.x);
//Normalize the axis
//Get the length of VectorTo
double AxisYLength = sqrt(AxisY.x*AxisY.x +
AxisY.y*AxisY.y +
AxisY.z*AxisY.z);
//Normalize VectorTo
AxisY.x /= AxisYLength;
AxisY.y /= AxisYLength;
AxisY.z /= AxisYLength;

//A matrix representing the Thing's orientation
GLfloat RotationMatrix[16] = {(float)AxisX.x,
(float)AxisX.y,
(float)AxisX.z,
0,
(float)AxisY.x,
(float)AxisY.y,
(float)AxisY.z,
0,
(float)VectorTo.x,
(float)VectorTo.y,
(float)VectorTo.z,
0,
0,
0,
0,
1};

Quaternion LookQuat = Quaternion::FromMatrix(RotationMatrix);

//Reset the quaternion orientation
return LookQuat;
}

因此,当我计算段时,我还会检查它们的重构值,如下所示:
sf::Vector3<float> Start(0, 0, 0);
sf::Vector3<float> End = Start;

//Create a vector from the start to the end
sf::Vector3<float> Translation = Orientation.MultVect(sf::Vector3<float>(0, 1, 0));
//Add that vector onto the start position
End.x += Translation.x * Length;
End.y += Translation.y * Length;
End.z += Translation.z * Length;

std::cout << "STATIC END (";
std::cout << End.x << ",";
std::cout << End.y << ",";
std::cout << End.z << ")\n";

///TEST
Quaternion Reconstructed = Quaternion::FromLookVector(Start, End);
Translation = Reconstructed.MultVect(sf::Vector3<float>(0, 1, 0));
sf::Vector3<float> TestEnd = Start;
TestEnd.x += Translation.x * Length;
TestEnd.y += Translation.y * Length;
TestEnd.z += Translation.z * Length;

std::cout << "RECONSTRUCTED END (";
std::cout << TestEnd.x << ",";
std::cout << TestEnd.y << ",";
std::cout << TestEnd.z << ")\n";

而且两者不相配。例如,如果静态终点是 (0,14.3998,0.0558498),那么重新计算的点是 (0,8.05585,-6.39976)。不过,两者应该是相同的。旋转的未定义部分不应该改变终点的位置,只有滚动(或 Z 旋转,或任何你想称之为的),因为这是一个片段,所以无关紧要。

请注意,当我最终将它用于除简单线段以外的其他事物时,滚动将很重要,这就是为什么我使用向上 vector 来确保我沿着这些线段放置的对象将始终使其顶部尽可能朝上(如果需要,可以单独确定垂直向上或向下看的物体的特殊任意滚动)。另一个目标是创建多个串在一起的片段,每个片段都相对于它之前的片段的方向旋转,而不是相对于全局空间旋转。

那么我在这里做错了什么?为什么我不能重新计算与第一个执行相同翻译的第二个四元数?

最佳答案

我不完全确定您如何计算两个 vector 之间的“旋转”四元数,但我很确定它非常麻烦。至少,如果我理解正确的话,你有指向某个方向的“看” vector ,并且对象从原点(0,0,0)沿着那个方向“看”,对吗?

如果是上述情况,应该不会太难。我觉得很奇怪的一件事是你的四元数 - vector 乘法似乎是相反的顺序。我将四元数 * vector 定义为:

quat qt = *this * quat(0, vec.x, vec.y, vec.z) * inverse();
return vec3(qt.x, qt.y, qt.z);

其中 quat 构造函数定义为 quat(w, x, y, z) 并且 inverse() 方法返回一个拷贝。逆等于共轭,定义为(w, -x, -y, -z)。但是,要做到这一点,你的四元数必须被归一化,只有这样它们才能真正代表一个方向(只有这样,逆才会等于共轭)。然后我将四元数乘法定义如下:
// This describes A * B (not communative!)
w = A.w * B.w - A.x * B.x - A.y * B.y - A.z * B.z;
x = A.w * B.x + A.x * B.w + A.y * B.z - A.z * B.y;
y = A.w * B.y + A.y * B.w + A.z * B.x - A.x * B.z;
z = A.w * B.z + A.z * B.w + A.x * B.y - A.y * B.x;

有了这个,你希望能够从“角轴”构造一个四元数。这意味着它应该采用一个旋转轴,以及一个围绕该轴旋转的角度(以弧度为单位)。我将只给你那个算法,因为它在直觉上没有多大意义:
// if axis is already unit length, remove the division
double halfAngle = angle * 0.5f; // In radians
double scale = sin(halfAngle) / axis.magnitude();

w = cos(halfAngle);
x = axis.x * scale;
y = axis.y * scale;
z = axis.z * scale;

所以现在我们只需要计算一个要旋转的轴,以及我们想要围绕它旋转多少,以弧度为单位。乍一看,这可能看起来很复杂,但这只是了解正在发生的事情的一个例子。你有两个 vector ,A 和 B。你想计算一个描述从 A 到 B 的旋转的四元数。为了让轴旋转,我们只需要一个与两者垂直的轴,显然这可以通过取交叉产品。如果您使用右手坐标系,它将是:
axis = A × B

如果您使用的是左手坐标系,我认为您应该颠倒顺序,但不要相信我的话。现在得到两个 vector 之间的角度。这可以通过采用点积来非常简单地完成。唯一的问题是您必须对两个 vector 进行归一化,因此它们的长度为 1,并且不会改变点积的结果。这样,点积将返回角度的余弦,因此要获得实际角度,我们可以这样做:
angle = acos(normalize(A) * normalize(B))

乘号当然代表点积。现在我们只需将轴和角度插入我上面给你的算法中,我们有一个四元数描述从外观 vector A 到外观 vector B 的“旋转”。现在如果 vector 指向完全相同的方向,那将是不明智的应用算法,因为轴将是(0,0,0)。如果您查看算法,我希望您看到它要么尝试除以零,要么简单地输出全零。因此,每当我应用该算法时,我首先检查轴是否不全为零。

您当前使用的公式对我来说似乎很奇怪且效率低下。我也不明白你为什么要先计算矩阵,从矩阵计算四元数是一项相当昂贵的计算。事实上,我相信计算相反的四元数矩阵会更快。

无论如何,祝它工作顺利!

关于c++ - 从四元数计算 vector 有效,从 vector 计算四元数不,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14939657/

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