Ingvarus Posted May 23, 2024 Posted May 23, 2024 Всем привет! Столкнулся с проблемой с костями в новой системе анимации. Вот мой код: mesh = checked_ptr_cast<ObjectMeshSkinned>(mesh_param.get()); mesh->setID(123); AnimationTrackPtr track = AnimationTrack::create(); AnimationObjectNodePtr anim_obj = AnimationObjectNode::create("character"); track->addObject(anim_obj); AnimationBindNodePtr bind = anim_obj->getBind(); bind->setNodeDescription(123, "character"); anim_obj->setBind(bind); AnimationModifierBonesPtr bones = AnimationModifierBones::create(); Animations::animToBonesModifier("Character Mesh\\Walking.anim", bones, 1); track->addObjectModifier(anim_obj, bones); AnimationPlaybackPtr playback = AnimationPlayback::create(); playback->setTrack(track); playback->setLoop(true); playback->play(); Анимация воспроизводится крайне криво. Записал видео с демонстрацией этой кривизны)))) видео тут: https://youtu.be/G9eGWvpOoww?si=sL5mvJSI5i3JHNIi Это я что-то неправильно делаю или это недоработка?
karpych11 Posted May 27, 2024 Posted May 27, 2024 Здравствуйте. Попытался воспроизвести проблему как у Вас, но пока что без результатов. Использую такой же код, весь контент тоже с mixamo. С in place и root motion анимацией получаю корректное воспроизведение. Можно получить минимальный проект с такой проблемой? И какая у Вас версия sdk? Для примера, вот мой результат.
Ingvarus Posted May 28, 2024 Author Posted May 28, 2024 Прикрепил файл пакета с проектом. Отсюда можно скачать полностью проект. Версия UNIGINE SDK Browser 2.0.15, версия UNIGINE 2.18.1. animation_test.upackage
karpych11 Posted May 29, 2024 Posted May 29, 2024 С этим примером проблема воспроизвелась. Она оказалась в том, что не учитывается сопоставление имён костей в меше и в анимации. Поэтому анимируются некорректные кости. Данная функциональность экспериментальная, поэтому не проверялась на большом количестве контента. Вот пример корректной конвертации: bool convertAnimForMesh(const char *anim_path, const char *mesh_path, AnimationModifierBonesPtr &out_modifier, float duration) { out_modifier->setNumBones(0); if (anim_path == nullptr || mesh_path == nullptr) return false; MeshPtr anim = Mesh::create(); if (anim->load(anim_path) == 0) return false; if (anim->getNumAnimations() == 0) return false; MeshPtr mesh = Mesh::create(); if (mesh->load(mesh_path) == 0) return false; // bones remap const int num_bones = mesh->getNumBones(); HashMap<int, int> mesh_to_anim_bone; for (int i = 0; i < num_bones; i++) { const char *name = mesh->getBoneName(i); int anim_bone = anim->findBone(name); if (anim_bone != -1) mesh_to_anim_bone.append(i, anim_bone); } Vector<short> animated_bones; anim->getAnimationBones(0, animated_bones); const int num_frames = anim->getNumAnimationFrames(0); AnimationCurveFloatPtr pos_x = AnimationCurveFloat::create(); AnimationCurveFloatPtr pos_y = AnimationCurveFloat::create(); AnimationCurveFloatPtr pos_z = AnimationCurveFloat::create(); AnimationCurveQuatPtr rot = AnimationCurveQuat::create(); AnimationCurveFloatPtr scale_x = AnimationCurveFloat::create(); AnimationCurveFloatPtr scale_y = AnimationCurveFloat::create(); AnimationCurveFloatPtr scale_z = AnimationCurveFloat::create(); out_modifier->setNumBones(num_bones); for (int i = 0; i < num_bones; i++) { pos_x->clear(); pos_y->clear(); pos_z->clear(); rot->clear(); scale_x->clear(); scale_y->clear(); scale_z->clear(); int anim_bone = -1; if (mesh_to_anim_bone.contains(i)) anim_bone = mesh_to_anim_bone[i]; int anim_bone_index = animated_bones.findIndex(anim_bone); if (anim_bone == -1 || anim_bone_index == -1) { // bone without animation, use bind transform float time = 0.0f; Math::vec3 pos = Math::vec3_zero; Math::quat rotation = Math::quat_identity; Math::vec3 scale = Math::vec3_one; decomposeTransform(mesh->getBoneTransform(i), pos, rotation, scale); pos_x->addKey(time, pos.x); pos_y->addKey(time, pos.y); pos_z->addKey(time, pos.z); rot->addKey(time, rotation); scale_x->addKey(time, scale.x); scale_y->addKey(time, scale.y); scale_z->addKey(time, scale.z); } else { // create bone animation for (int j = 0; j < num_frames; j++) { float time = (num_frames > 1 ? (Math::itof(j) / (num_frames - 1) * duration) : 0.0f); Vector<Math::mat4> frames; anim->getAnimationFrame(0, j, frames); Math::vec3 pos = Math::vec3_zero; Math::quat rotation = Math::quat_identity; Math::vec3 scale = Math::vec3_one; decomposeTransform(frames[anim_bone_index], pos, rotation, scale); pos_x->addKey(time, pos.x); pos_y->addKey(time, pos.y); pos_z->addKey(time, pos.z); rot->addKey(time, rotation); scale_x->addKey(time, scale.x); scale_y->addKey(time, scale.y); scale_z->addKey(time, scale.z); } } out_modifier->setCurvePosX(i, pos_x); out_modifier->setCurvePosY(i, pos_y); out_modifier->setCurvePosZ(i, pos_z); out_modifier->setCurveRot(i, rot); out_modifier->setCurveScaleX(i, scale_x); out_modifier->setCurveScaleY(i, scale_y); out_modifier->setCurveScaleZ(i, scale_z); } } convertAnimForMesh("Character\\Fast Run.fbx\\Fast Run.anim", mesh->getMeshName(), bones, 1.0f); Можете проверить такое решение? 1
Recommended Posts