Jump to content

[SOLVED] Проблема с костями в новой системе анимации


photo

Recommended Posts

Всем привет!

Столкнулся с проблемой с костями в новой системе анимации. Вот мой код:

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

Это я что-то неправильно делаю или это недоработка?

Link to comment

Здравствуйте.

Попытался воспроизвести проблему как у Вас, но пока что без результатов. Использую такой же код, весь контент тоже с mixamo. С in place и root motion анимацией получаю корректное воспроизведение. Можно получить минимальный проект с такой проблемой? И какая у Вас версия sdk? Для примера, вот мой результат.

Link to comment

С этим примером проблема воспроизвелась. Она оказалась в том, что не учитывается сопоставление имён костей в меше и в анимации. Поэтому анимируются некорректные кости. Данная функциональность экспериментальная, поэтому не проверялась на большом количестве контента. Вот пример корректной конвертации:

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);

Можете проверить такое решение?

  • Like 1
Link to comment
  • bmyagkov changed the title to [SOLVED] Проблема с костями в новой системе анимации
×
×
  • Create New...