Assimp Skinning Global Transforms

В настоящее время я внедряю Skeletal Animation в свой 3D OpenGL Game Engine, используя библиотеку ASSIMP, но, к сожалению, все идет не очень хорошо.
Проблема, с которой я сталкиваюсь в настоящее время, заключается в том, что преобразования сцепленных костей (отношения родитель-ребенок между костями) действуют правильно только тогда, когда преобразуется только один родитель.

Что происходит, так это то, что Преобразование кости бедра осуществляется на глобальных осях, а не на локальных осях таза.

Вот мой класс по скелетону:

class Skeleton
{
public:
Skeleton();

unsigned int numBones;
std::vector<std::string> names;
std::vector<glm::mat4> offsets;std::vector<glm::mat4> transforms;
std::vector<int> parents;

std::string GetName(int bone);
glm::mat4 GetWorldTransform(int bone);
int GetID(std::string bone_name);
};

и вот функция, которую я использую для расчета преобразования мира для каждой кости:

glm::mat4 Skeleton::GetWorldTransform(int bone)
{
int p = parents[bone];
glm::mat4 result = glm::mat4(1.0);

result *= glm::inverse(offsets[bone]);
result *= transforms[bone];
result *= offsets[bone];

while(p >= 0)   //The root bone has a parent of -1
{
result *= glm::inverse(offsets[p]);
result *= transforms[p];    //Apply The Parent's Transform
result *= offsets[p];

p = parents[p];
}
return result;
}

И в моем классе Mesh у меня есть эта функция UpdateSkeleton ():

void Mesh::UpdateSkeleton(unsigned int shaderID)
{
std::vector<glm::mat4> mats;

for(int i = 0; i < skeleton->numBones; i++)
{
glm::mat4 matrix = glm::mat4(1.0);
matrix *= skeleton->GetWorldTransform(i);
mats.push_back(matrix);
}

if(mats.size() > 0)
glUniformMatrix4fv(glGetUniformLocation(shaderID,"gBones"),mats.size(),GL_FALSE,glm::value_ptr(mats[0]));
}

Спасибо!

1

Решение

Так что я исправил это.

https://www.youtube.com/playlist?list=PLi9hkiiZDonvUcT_FRD8rJtuuGltL3xys

В основном проблема заключалась в том, что конкатенации выполнялись в обратном порядке, я делал их первоначально так:

void Bone::UpdateParentTransform()
{
parent_transform = glm::mat4(1.0);

Node* node_id = parent_node;

while(node_id != nullptr)
{
Bone* bone = mesh->FindBone(node_id->name);

if(bone != nullptr)
{
parent_transform *= glm::inverse(bone->offset_matrix);
parent_transform *= node_id->transformation;
parent_transform *= (bone->offset_matrix);
node_id = bone->parent_node;
}
else
node_id = nullptr;
}
}

Теперь я сделал так, чтобы они выполнялись в обратном порядке, вот так:

void Bone::UpdateParentTransform()
{
parent_transform = glm::mat4(1.0);

Node* node_id = node;

std::vector<Bone*> bones;
std::vector<Node*> parents;

while(node_id != nullptr)
{
Bone* bone = mesh->FindBone(node_id->name);

if(bone != nullptr)
{
bones.push_back(bone);
parents.push_back(node_id);

node_id = bone->parent_node;
}
else
node_id = nullptr;
}for(int i = parents.size()-1; i > 0; i--)
{
parent_transform *= glm::inverse(bones.at(i)->offset_matrix);
parent_transform *= parents.at(i)->transformation;
parent_transform *= (bones.at(i)->offset_matrix);
}

}

Если у вас есть какие-либо вопросы по этому или чему-либо еще, касающиеся скелетной анимации с использованием ASSIMP, пожалуйста, не стесняйтесь спрашивать меня, вы можете связаться со мной здесь или на моем канале YouTube: RealityMultiplied

Я собираюсь начать работу над серией учебных пособий о том, как делать скелетную анимацию с использованием ASSIMP прямо сейчас, поэтому я надеюсь, что сегодня вечером выйдет первое видео.

Я надеюсь сделать эту тему легкой для понимания тем, кто только начинает, потому что это может показаться пугающим и просто ужасным в целом.

РЕДАКТИРОВАТЬ:
Поэтому я начал работать над учебными пособиями, но сейчас я переживаю множество трудностей в своей жизни и не думаю, что смогу их закончить.
Я надеюсь, что они помогут хоть немного, извините, я не смог сделать больше.

http://realitymultiplied.blogspot.mx/

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]