У меня есть иерархический скелет, в котором переводы и повороты выражаются в глобальном пространстве. Мне нужно преобразовать скелет в локальные координаты и обратно. У меня нет проблем с переводами, но я не могу заставить работать вращения.
Изначально у меня есть матрицы вращения, но я могу легко преобразовать их в эйлеровы или кватернионы и пробовал работать с каждым из них. Я использую математическую библиотеку двигателя Irrlicht.
Итак, мой код проходит через каждую кость и применяет преобразование до тех пор, пока у кости есть следующий родитель.
От глобального к локальному:
for(; iter != absolutePose.end(); iter++)
{
if(hierarchy->find(iter->boneID) != hierarchy->end())
{
BoneID parentNodeID = hierarchy[iter->boneID];
relativePose[iter->boneID].position.X = iter->position.X - absolutePose[parentNodeId].position.X;
relativePose[iter->boneID].position.Y = iter->position.Y - absolutePose[parentNodeId].position.Y;
relativePose[iter->boneID].position.Z = iter->position.Z - absolutePose[parentNodeId].position.Z;
////Rotation Part/////////
float pq[4] ={0.0,0.0,0.0,0.0};
MatrixToQuaternion(absolutePose[parentNodeId].orientation, pq);
irr::core::quaternion quat(q[0],q[1],q[2],q[3]);
irr::core::quaternion parentquat(pq[0],pq[1],pq[2],pq[3]);
quat = quat.makeInverse();
quat = quat*parentquat;
float newQuat[4] = {quat.X, quat.Y, quat.Z, quat.W};
QuaternionToMatrix(newQuat,relativePose[iter->first].orientation);
}
else // top bone
{
relativePose[iter->boneID].position.X = iter->position.X;
relativePose[iter->boneID].position.Y = iter->position.Y;
relativePose[iter->boneID].position.Z = iter->position.Z;
relativePose[iter->boneID].orientation = iter->second.orientation;
}
}
Затем от локального к глобальному:
for(; iter != relativePose.end(); iter++)
{
absolutePose[iter->boneID].position.position = iter->position;
auto nextParent = hierarchy->find(iter->boneID);
while(nextParent != hierarchy->end())
{
absolutePose[iter->boneID].position.X += relativePose[nextParent->boneID].position.X;
absolutePose[iter->boneID].position.Y += relativePose[nextParent->boneID].position.Y;
absolutePose[iter->boneID].position.Z += relativePose[nextParent->boneID].position.Z;
////Rotation part///
float q[4] ={0.0,0.0,0.0,0.0};
MatrixToQuaternion(relativePose[iter->boneID].orientation, q);
float pq[4] ={0.0,0.0,0.0,0.0};
MatrixToQuaternion(relativePose[nextParent->boneID].orientation, pq);
irr::core::quaternion quat(q[0],q[1],q[2],q[3]);
irr::core::quaternion parentquat(pq[0],pq[1],pq[2],pq[3]);
quat = parentquat*quat;
float newQuat[4] = {quat.X, quat.Y, quat.Z, quat.W};
QuaternionToMatrix(newQuat,absolutePose[iter->boneID].orientation);
//////
nextParent = hierarchy->find(nextParent->boneID);
}
}
У меня были проблемы с этим некоторое время, и я также пытался оставаться в матричном режиме и переключаться на углы Эйлера. Может ли кто-нибудь помочь мне понять, что я делаю неправильно?