Вычисление матрицы bindPose (скелетная анимация)
Я успешно проанализировал формат iqe (Inter Quake Exporter) и теперь застрял при его отображении в bindpose.
Все вершины имеют странное преобразование, где корневая кость (которая охватывает всю сетку для ориентации) не единственная кость, которая влияет на эту вершину. Вы можете видеть это в области руки / должны / шеи сетки. Эта сетка имеет 3 кости. Одна корневая кость перекрывает всю сетку и две кости руки. Вы можете видеть, как сетка должна выглядеть на заднем плане (экспортируется как obj)
Для лучшего понимания у меня есть следующая система:
1. Я загружаю все данные вершин в одно большое vbo (вершины, uvs, нормали, тангенс, битангенс, boneIndicies(4) (индекс списка соединений) и boneWeights (4))
2. Я добавляю все соединения в список соединений и создаю древовидную систему (простой связанный список с позицией, поворотом и родительским указателем)
3. У меня есть отдельный список под названием boneMatrices, где я храню.. ну, мои костные матрицы. в настоящее время каждый кадр, позже я буду предварительно вычислять матрицы для каждого кадра анимации.
Я пытаюсь вычислить матрицу кости следующим образом:
for (int i = 0; i < this->jointList.size(); i++)
{
pixel::CJoint *joint = this->jointList.at(i);
std::cout << "Joint ------- " << joint->name << " -------- values: \n";
std::cout << "Translation: " << joint->position.x << " " << joint->position.y << " " << joint->position.z << "\n";
std::cout << "Quaternion: " << joint->rotation.x << " " << joint->rotation.y << " " << joint->rotation.z << " " << joint->rotation.w << "\n";
pixel::matrix4 rotation = pixel::CMatrix::fromQuaternion(joint->rotation);
pixel::matrix4 offset = pixel::CMatrix::translateMatrix(joint->position);
pixel::matrix4 baseMatrix = rotation * offset; // translation * rotation
joint->bindPose = baseMatrix;
joint->invBindPose = pixel::CMatrix::inverseMatrix(baseMatrix);
if (joint->parent != NULL)
{
std::cout << "Joint: " << joint->name << " is child of " << joint->parent->name << " \n";
joint->bindPose = joint->bindPose * joint->parent->invBindPose;
joint->invBindPose = pixel::CMatrix::inverseMatrix(joint->bindPose);
}
std::cout << "\n";
}
Я сохраняю транспонированный (в противном случае сетка переворачивается) сустава ->invBindPose в boneMatrices и отправляю его в шейдер:
boneMatrix является стандартным вектором матрицы4
this->material.setParameter("boneMatrix", this->boneMatrices.at(0), this->boneMatrices.size());
Расчет связывания корневой кости должен быть правильным (по крайней мере, я так думаю), потому что голова находится в нужном месте, а глаза тоже (которые в настоящее время не влияют на кости)