allow removing animation components and dont stash initial joint transforms when creating bone animations

This commit is contained in:
Nick Fisher
2024-06-01 12:31:59 +08:00
parent 5db72f15ea
commit 7d54eadaa8

View File

@@ -71,7 +71,6 @@ namespace flutter_filament
struct BoneAnimation : AnimationStatus struct BoneAnimation : AnimationStatus
{ {
size_t boneIndex; size_t boneIndex;
std::vector<utils::Entity> meshTargets;
size_t skinIndex = 0; size_t skinIndex = 0;
int lengthInFrames; int lengthInFrames;
float frameLengthInMs = 0; float frameLengthInMs = 0;
@@ -113,15 +112,15 @@ namespace flutter_filament
if (std::holds_alternative<FilamentInstance *>(target)) if (std::holds_alternative<FilamentInstance *>(target))
{ {
auto instance = std::get<FilamentInstance *>(target); auto instance = std::get<FilamentInstance *>(target);
const auto joints = instance->getJointsAt(0); // const auto joints = instance->getJointsAt(0);
for (int i = 0; i < instance->getJointCountAt(0); i++) // for (int i = 0; i < instance->getJointCountAt(0); i++)
{ // {
const auto joint = joints[i]; // const auto joint = joints[i];
const auto &jointTransformInstance = _transformManager.getInstance(joint); // const auto &jointTransformInstance = _transformManager.getInstance(joint);
const auto &jointTransform = _transformManager.getTransform(jointTransformInstance); // const auto &jointTransform = _transformManager.getTransform(jointTransformInstance);
animationComponent.initialJointTransforms.push_back(jointTransform); // animationComponent.initialJointTransforms.push_back(jointTransform);
} // }
componentInstance = addComponent(instance->getRoot()); componentInstance = addComponent(instance->getRoot());
} }
else else
@@ -132,6 +131,26 @@ namespace flutter_filament
this->elementAt<0>(componentInstance) = animationComponent; this->elementAt<0>(componentInstance) = animationComponent;
} }
void removeAnimationComponent(std::variant<FilamentInstance *, Entity> target)
{
AnimationComponent animationComponent;
animationComponent.target = target;
EntityInstanceBase::Type componentInstance;
if (std::holds_alternative<FilamentInstance *>(target))
{
auto instance = std::get<FilamentInstance *>(target);
if(hasComponent(instance->getRoot())) {
removeComponent(instance->getRoot());
}
} else {
auto entity = std::get<Entity>(target);
if(hasComponent(entity)) {
removeComponent(entity);
}
}
}
void update() void update()
{ {
auto now = high_resolution_clock::now(); auto now = high_resolution_clock::now();
@@ -152,34 +171,36 @@ namespace flutter_filament
auto &gltfAnimations = animationComponent.gltfAnimations; auto &gltfAnimations = animationComponent.gltfAnimations;
auto &boneAnimations = animationComponent.boneAnimations; auto &boneAnimations = animationComponent.boneAnimations;
for (int i = ((int)gltfAnimations.size()) - 1; i >= 0; i--) if(gltfAnimations.size() > 0) {
{ for (int i = ((int)gltfAnimations.size()) - 1; i >= 0; i--)
auto animationStatus = animationComponent.gltfAnimations[i];
auto elapsedInSecs = float(std::chrono::duration_cast<std::chrono::milliseconds>(now - animationStatus.start).count()) / 1000.0f;
if (!animationStatus.loop && elapsedInSecs >= animationStatus.durationInSecs)
{ {
animator->applyAnimation(animationStatus.index, animationStatus.durationInSecs - 0.001);
animator->updateBoneMatrices();
gltfAnimations.erase(gltfAnimations.begin() + i);
animationComponent.fadeGltfAnimationIndex = -1;
continue;
}
animator->applyAnimation(animationStatus.index, elapsedInSecs);
if (animationComponent.fadeGltfAnimationIndex != -1 && elapsedInSecs < animationComponent.fadeDuration) auto animationStatus = animationComponent.gltfAnimations[i];
{
// cross-fade auto elapsedInSecs = float(std::chrono::duration_cast<std::chrono::milliseconds>(now - animationStatus.start).count()) / 1000.0f;
auto fadeFromTime = animationComponent.fadeOutAnimationStart + elapsedInSecs;
auto alpha = elapsedInSecs / animationComponent.fadeDuration; if (!animationStatus.loop && elapsedInSecs >= animationStatus.durationInSecs)
animator->applyCrossFade(animationComponent.fadeGltfAnimationIndex, fadeFromTime, alpha); {
animator->applyAnimation(animationStatus.index, animationStatus.durationInSecs - 0.001);
animator->updateBoneMatrices();
gltfAnimations.erase(gltfAnimations.begin() + i);
animationComponent.fadeGltfAnimationIndex = -1;
continue;
}
animator->applyAnimation(animationStatus.index, elapsedInSecs);
if (animationComponent.fadeGltfAnimationIndex != -1 && elapsedInSecs < animationComponent.fadeDuration)
{
// cross-fade
auto fadeFromTime = animationComponent.fadeOutAnimationStart + elapsedInSecs;
auto alpha = elapsedInSecs / animationComponent.fadeDuration;
animator->applyCrossFade(animationComponent.fadeGltfAnimationIndex, fadeFromTime, alpha);
}
} }
animator->updateBoneMatrices();
} }
animator->updateBoneMatrices();
for (int i = (int)boneAnimations.size() - 1; i >= 0; i--) for (int i = (int)boneAnimations.size() - 1; i >= 0; i--)
{ {
auto animationStatus = boneAnimations[i]; auto animationStatus = boneAnimations[i];
@@ -188,6 +209,7 @@ namespace flutter_filament
if (!animationStatus.loop && elapsedInSecs >= animationStatus.durationInSecs) if (!animationStatus.loop && elapsedInSecs >= animationStatus.durationInSecs)
{ {
Log("Bone animation %d finished", i);
boneAnimations.erase(boneAnimations.begin() + i); boneAnimations.erase(boneAnimations.begin() + i);
continue; continue;
} }
@@ -197,7 +219,6 @@ namespace flutter_filament
int currFrame = static_cast<int>(elapsedFrames) % animationStatus.lengthInFrames; int currFrame = static_cast<int>(elapsedFrames) % animationStatus.lengthInFrames;
float delta = elapsedFrames - currFrame; float delta = elapsedFrames - currFrame;
int nextFrame = currFrame; int nextFrame = currFrame;
auto restLocalTransform = animationComponent.initialJointTransforms[animationStatus.boneIndex];
// offset from the end if reverse // offset from the end if reverse
if (animationStatus.reverse) if (animationStatus.reverse)
@@ -225,8 +246,8 @@ namespace flutter_filament
} }
// simple linear interpolation // simple linear interpolation
math::mat4f curr = (1 - delta) * (restLocalTransform * animationStatus.frameData[currFrame]); math::mat4f curr = (1 - delta) * animationStatus.frameData[currFrame];
math::mat4f next = delta * (restLocalTransform * animationStatus.frameData[nextFrame]); math::mat4f next = delta * animationStatus.frameData[nextFrame];
math::mat4f localTransform = curr + next; math::mat4f localTransform = curr + next;
const Entity joint = target->getJointsAt(animationStatus.skinIndex)[animationStatus.boneIndex]; const Entity joint = target->getJointsAt(animationStatus.skinIndex)[animationStatus.boneIndex];