我正在與IK一起開發一個程序,並遇到了我最初認爲的問題,這是一個微不足道的問題,但自那時起就無法解決問題。向量旋轉問題
背景:
一切都在3d空間中。 我使用三維矢量和四元數來表示變換。
我有一個肢體,我們會打電話給V1。 我想旋轉到V2。
我得到了V1和V2之間的角度。 然後V1的旋轉軸與V2交叉。
然後從軸和角度製作一個四元數。
然後我採取四肢目前的方向,並乘以軸角四元數。
這我相信是我期望的肢體局部空間。
該肢體附着於一系列其他鏈接。爲了獲得世界空間,我將根據父母本地空間與孩子的本地空間結合起來,直到達到根。
如果我旋轉的矢量包含在X和Y平面內,或者肢體所連接的身體沒有被修改,這似乎工作得很好。如果有任何修改,例如旋轉根節點,那麼在第一次迭代時,矢量將非常接近所需的矢量。在那之後,儘管它將開始在所有地方旋轉,從未達到目標。
我已經通過所有的數學線逐行,它似乎都是正確的。我不確定是否有某些我不知道的或者僅僅是過度看的東西。我的邏輯聲音是?或者我不知道什麼?任何幫助是極大的讚賞!
Quaternion::Quaternion(const Vector& axis, const float angle)
{
float sin_half_angle = sinf(angle/2);
v.set_x(axis.get_x() * sin_half_angle);
v.set_y(axis.get_y() * sin_half_angle);
v.set_z(axis.get_z() * sin_half_angle);
w = cosf(angle/2);
}
Quaternion Quaternion::operator* (const Quaternion& quat) const
{
Quaternion result;
Vector v1(this->v);
Vector v2(quat.v );
float s1 = this->w;
float s2 = quat.w;
result.w = s1 * s2 - v1.Dot(v2);
result.v = v2 * s1 + v1 * s2 + v1.Cross(v2);
result.Normalize();
return result;
}
Vector Quaternion::operator* (const Vector& vec) const
{
Quaternion quat_vec(vec.get_x(), vec.get_y(), vec.get_z(), 0.0f);
Quaternion rotation(*this);
Quaternion rotated_vec = rotation * (quat_vec * rotation.Conjugate());
return rotated_vec.v;
}
Quaternion Quaternion::Conjugate()
{
Quaternion result(*this);
result.v = result.v * -1.0f;
return result;
}
Transform Transform::operator*(const Transform tran)
{
return Transform(mOrient * transform.getOrient(), mTrans + (mOrient * tran.getTrans());
}
Transform Joint::GetWorldSpace()
{
Transform world = local_space;
Joint* par = GetParent();
while (par)
{
world = par->GetLocalSpace() * world;
par = par->GetParent();
}
return world;
}
void RotLimb()
{
Vector end_effector_worldspace_pos = end_effector->GetWorldSpace().get_Translation();
Vector parent_worldspace_pos = parent->GetWorldSpace().get_Translation();
Vector parent_To_end_effector = (end_effector_worldspace_pos - parent_worldspace_pos).Normalize();
Vector parent_To_goal = (goal_pos - parent_worldspace_pos).Normalize();
float dot = parent_To_end_effector.Dot(parent_To_goal);
Vector rot_axis(0.0f,0.0f,1.0f);
float angle = 0.0f;
if (1.0f - fabs(dot) > EPSILON)
{
//angle = parent_To_end_effector.Angle(parent_To_goal);
rot_axis = parent_To_end_effector.Cross(parent_To_goal).Normalize();
parent->RotateJoint(rot_axis, acos(dot));
}
}
void Joint::Rotate(const Vector& axis, const float rotation)
{
mLocalSpace = mlocalSpace * Quaternion(axis, rotation);
}
你確定它不是一個數值精度問題嗎?我不知道你正在使用哪種迭代算法,但它可能不會在出現數字錯誤時收斂。也許你需要使最低可接受的誤差更高,或考慮使用另一種數字數據類型 – sinelaw
我同意sinelaw。在某些時候,您的算法必須說「足夠接近」,並將值分配爲等於目標值。 –
你能提供公式還是(僞)代碼?沒有更多細節,很難猜出出了什麼問題。我能給你的唯一的事情就是2d空間中的旋轉是可交換的,也許你在某處混淆了乘法的順序? – 2011-09-26 06:21:33