Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Impeller Scene] Change how property resolution works to fix Animation blending; add mutation log to nodes; enable backface culling; add vertex color contribution back to meshes #38766

Merged
merged 10 commits into from
Jan 12, 2023
2 changes: 2 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -1614,6 +1614,7 @@ ORIGIN: ../../../flutter/impeller/scene/animation/animation_clip.cc + ../../../f
ORIGIN: ../../../flutter/impeller/scene/animation/animation_clip.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/scene/animation/animation_player.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/scene/animation/animation_player.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/scene/animation/animation_transforms.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/scene/animation/property_resolver.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/scene/animation/property_resolver.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/scene/camera.cc + ../../../flutter/LICENSE
Expand Down Expand Up @@ -4094,6 +4095,7 @@ FILE: ../../../flutter/impeller/scene/animation/animation_clip.cc
FILE: ../../../flutter/impeller/scene/animation/animation_clip.h
FILE: ../../../flutter/impeller/scene/animation/animation_player.cc
FILE: ../../../flutter/impeller/scene/animation/animation_player.h
FILE: ../../../flutter/impeller/scene/animation/animation_transforms.h
FILE: ../../../flutter/impeller/scene/animation/property_resolver.cc
FILE: ../../../flutter/impeller/scene/animation/property_resolver.h
FILE: ../../../flutter/impeller/scene/camera.cc
Expand Down
2 changes: 2 additions & 0 deletions impeller/geometry/quaternion.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ struct Quaternion {
return {x * m, y * m, z * m, w * m};
}

Quaternion Invert() const { return {-x, -y, -z, w}; }

Quaternion Slerp(const Quaternion& to, double time) const;

Quaternion operator*(const Quaternion& o) const {
Expand Down
1 change: 1 addition & 0 deletions impeller/scene/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ impeller_component("scene") {
"animation/animation_clip.h",
"animation/animation_player.cc",
"animation/animation_player.h",
"animation/animation_transforms.h",
"animation/property_resolver.cc",
"animation/property_resolver.h",
"camera.cc",
Expand Down
13 changes: 10 additions & 3 deletions impeller/scene/animation/animation_clip.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Scalar AnimationClip::GetWeight() const {
}

void AnimationClip::SetWeight(Scalar weight) {
weight_ = weight;
weight_ = std::max(0.0f, weight);
}

SecondsF AnimationClip::GetPlaybackTime() const {
Expand Down Expand Up @@ -110,9 +110,16 @@ void AnimationClip::Advance(SecondsF delta_time) {
}
}

void AnimationClip::ApplyToBindings() const {
void AnimationClip::ApplyToBindings(
std::unordered_map<Node*, AnimationTransforms>& transform_decomps,
Scalar weight_multiplier) const {
for (auto& binding : bindings_) {
binding.channel.resolver->Apply(*binding.node, playback_time_, weight_);
auto transforms = transform_decomps.find(binding.node);
if (transforms == transform_decomps.end()) {
continue;
}
binding.channel.resolver->Apply(transforms->second, playback_time_,
weight_ * weight_multiplier);
}
}

Expand Down
5 changes: 4 additions & 1 deletion impeller/scene/animation/animation_clip.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "flutter/fml/macros.h"
#include "impeller/scene/animation/animation.h"
#include "impeller/scene/animation/animation_transforms.h"

namespace impeller {
namespace scene {
Expand Down Expand Up @@ -60,7 +61,9 @@ class AnimationClip final {
void Advance(SecondsF delta_time);

/// @brief Applies the animation to all binded properties in the scene.
void ApplyToBindings() const;
void ApplyToBindings(
std::unordered_map<Node*, AnimationTransforms>& transform_decomps,
Scalar weight_multiplier) const;

private:
void BindToTarget(Node* node);
Expand Down
57 changes: 42 additions & 15 deletions impeller/scene/animation/animation_player.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "impeller/scene/animation/animation_player.h"

#include <memory>
#include <unordered_map>

#include "flutter/fml/time/time_point.h"
#include "impeller/base/timing.h"
Expand All @@ -19,20 +20,37 @@ AnimationPlayer::~AnimationPlayer() = default;
AnimationPlayer::AnimationPlayer(AnimationPlayer&&) = default;
AnimationPlayer& AnimationPlayer::operator=(AnimationPlayer&&) = default;

AnimationClip& AnimationPlayer::AddAnimation(
std::shared_ptr<Animation> animation,
AnimationClip* AnimationPlayer::AddAnimation(
const std::shared_ptr<Animation>& animation,
Node* bind_target) {
AnimationClip clip(std::move(animation), bind_target);
if (!animation) {
VALIDATION_LOG << "Cannot add null animation.";
return nullptr;
}

AnimationClip clip(animation, bind_target);

// Record all of the unique default transforms that this AnimationClip
// will mutate.
for (const auto& binding : clip.bindings_) {
default_target_transforms_.insert(
{binding.node, binding.node->GetLocalTransform()});
auto decomp = binding.node->GetLocalTransform().Decompose();
if (!decomp.has_value()) {
continue;
}
target_transforms_.insert(
{binding.node, AnimationTransforms{.bind_pose = decomp.value()}});
}

clips_.push_back(std::move(clip));
return clips_.back();
auto result = clips_.insert({animation->GetName(), std::move(clip)});
return &result.first->second;
}

AnimationClip* AnimationPlayer::GetClip(const std::string& name) const {
auto result = clips_.find(name);
if (result == clips_.end()) {
return nullptr;
}
return const_cast<AnimationClip*>(&result->second);
}

void AnimationPlayer::Update() {
Expand All @@ -43,18 +61,27 @@ void AnimationPlayer::Update() {
auto delta_time = new_time - previous_time_.value();
previous_time_ = new_time;

Reset();
// Reset the animated pose state.
for (auto& [node, transforms] : target_transforms_) {
transforms.animated_pose = transforms.bind_pose;
}

// Compute a weight multiplier for normalizing the animation.
Scalar total_weight = 0;
for (auto& [_, clip] : clips_) {
total_weight += clip.GetWeight();
}
Scalar weight_multiplier = total_weight > 1 ? 1 / total_weight : 1;

// Update and apply all clips.
for (auto& clip : clips_) {
// Update and apply all clips to the animation pose state.
for (auto& [_, clip] : clips_) {
clip.Advance(delta_time);
clip.ApplyToBindings();
clip.ApplyToBindings(target_transforms_, weight_multiplier);
}
}

void AnimationPlayer::Reset() {
for (auto& [node, transform] : default_target_transforms_) {
node->SetLocalTransform(Matrix());
// Apply the animated pose to the bound joints.
for (auto& [node, transforms] : target_transforms_) {
node->SetLocalTransform(Matrix(transforms.animated_pose));
}
}

Expand Down
14 changes: 7 additions & 7 deletions impeller/scene/animation/animation_player.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@

#pragma once

#include <map>
#include <memory>
#include <optional>
#include <unordered_map>
#include <vector>

#include "flutter/fml/hash_combine.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/time/time_delta.h"
#include "impeller/base/timing.h"
#include "impeller/geometry/matrix.h"
#include "impeller/geometry/matrix_decomposition.h"
#include "impeller/scene/animation/animation_clip.h"

namespace impeller {
Expand All @@ -29,19 +30,18 @@ class AnimationPlayer final {
AnimationPlayer(AnimationPlayer&&);
AnimationPlayer& operator=(AnimationPlayer&&);

AnimationClip& AddAnimation(std::shared_ptr<Animation> animation,
AnimationClip* AddAnimation(const std::shared_ptr<Animation>& animation,
Node* bind_target);

AnimationClip* GetClip(const std::string& name) const;

/// @brief Advanced all clips and updates animated properties in the scene.
void Update();

/// @brief Reset all bound animation target transforms.
void Reset();

private:
std::unordered_map<Node*, Matrix> default_target_transforms_;
std::unordered_map<Node*, AnimationTransforms> target_transforms_;

std::vector<AnimationClip> clips_;
std::map<std::string, AnimationClip> clips_;

std::optional<TimePoint> previous_time_;

Expand Down
18 changes: 18 additions & 0 deletions impeller/scene/animation/animation_transforms.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#pragma once

#include "impeller/geometry/matrix_decomposition.h"

namespace impeller {
namespace scene {

struct AnimationTransforms {
MatrixDecomposition bind_pose;
MatrixDecomposition animated_pose;
};

} // namespace scene
} // namespace impeller
25 changes: 16 additions & 9 deletions impeller/scene/animation/property_resolver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <iterator>
#include <memory>

#include "impeller/geometry/matrix_decomposition.h"
#include "impeller/geometry/point.h"
#include "impeller/scene/node.h"

Expand Down Expand Up @@ -78,7 +79,7 @@ TranslationTimelineResolver::TranslationTimelineResolver() = default;

TranslationTimelineResolver::~TranslationTimelineResolver() = default;

void TranslationTimelineResolver::Apply(Node& target,
void TranslationTimelineResolver::Apply(AnimationTransforms& target,
SecondsF time,
Scalar weight) {
if (values_.empty()) {
Expand All @@ -89,15 +90,16 @@ void TranslationTimelineResolver::Apply(Node& target,
if (key.lerp < 1) {
value = values_[key.index - 1].Lerp(value, key.lerp);
}
target.SetLocalTransform(target.GetLocalTransform() *
Matrix::MakeTranslation(value * weight));

target.animated_pose.translation +=
(value - target.bind_pose.translation) * weight;
}

RotationTimelineResolver::RotationTimelineResolver() = default;

RotationTimelineResolver::~RotationTimelineResolver() = default;

void RotationTimelineResolver::Apply(Node& target,
void RotationTimelineResolver::Apply(AnimationTransforms& target,
SecondsF time,
Scalar weight) {
if (values_.empty()) {
Expand All @@ -108,15 +110,19 @@ void RotationTimelineResolver::Apply(Node& target,
if (key.lerp < 1) {
value = values_[key.index - 1].Slerp(value, key.lerp);
}
target.SetLocalTransform(target.GetLocalTransform() *
Matrix::MakeRotation(value * weight));

target.animated_pose.rotation =
target.animated_pose.rotation *
Quaternion().Slerp(target.bind_pose.rotation.Invert() * value, weight);
}

ScaleTimelineResolver::ScaleTimelineResolver() = default;

ScaleTimelineResolver::~ScaleTimelineResolver() = default;

void ScaleTimelineResolver::Apply(Node& target, SecondsF time, Scalar weight) {
void ScaleTimelineResolver::Apply(AnimationTransforms& target,
SecondsF time,
Scalar weight) {
if (values_.empty()) {
return;
}
Expand All @@ -125,8 +131,9 @@ void ScaleTimelineResolver::Apply(Node& target, SecondsF time, Scalar weight) {
if (key.lerp < 1) {
value = values_[key.index - 1].Lerp(value, key.lerp);
}
target.SetLocalTransform(target.GetLocalTransform() *
Matrix::MakeScale(value * weight));

target.animated_pose.scale *=
Vector3(1, 1, 1).Lerp(value / target.bind_pose.scale, weight);
}

} // namespace scene
Expand Down
18 changes: 14 additions & 4 deletions impeller/scene/animation/property_resolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@
#include "flutter/fml/hash_combine.h"
#include "flutter/fml/macros.h"
#include "impeller/base/timing.h"
#include "impeller/geometry/matrix_decomposition.h"
#include "impeller/geometry/quaternion.h"
#include "impeller/geometry/scalar.h"
#include "impeller/geometry/vector.h"
#include "impeller/scene/animation/animation_transforms.h"

namespace impeller {
namespace scene {
Expand Down Expand Up @@ -46,7 +48,9 @@ class PropertyResolver {
/// many different PropertyResolvers prior to rendering. For example,
/// an AnimationPlayer may blend multiple Animations together by
/// applying several AnimationClips.
virtual void Apply(Node& target, SecondsF time, Scalar weight) = 0;
virtual void Apply(AnimationTransforms& target,
SecondsF time,
Scalar weight) = 0;
};

class TimelineResolver : public PropertyResolver {
Expand Down Expand Up @@ -74,7 +78,9 @@ class TranslationTimelineResolver final : public TimelineResolver {
~TranslationTimelineResolver();

// |Resolver|
void Apply(Node& target, SecondsF time, Scalar weight) override;
void Apply(AnimationTransforms& target,
SecondsF time,
Scalar weight) override;

private:
TranslationTimelineResolver();
Expand All @@ -91,7 +97,9 @@ class RotationTimelineResolver final : public TimelineResolver {
~RotationTimelineResolver();

// |Resolver|
void Apply(Node& target, SecondsF time, Scalar weight) override;
void Apply(AnimationTransforms& target,
SecondsF time,
Scalar weight) override;

private:
RotationTimelineResolver();
Expand All @@ -108,7 +116,9 @@ class ScaleTimelineResolver final : public TimelineResolver {
~ScaleTimelineResolver();

// |Resolver|
void Apply(Node& target, SecondsF time, Scalar weight) override;
void Apply(AnimationTransforms& target,
SecondsF time,
Scalar weight) override;

private:
ScaleTimelineResolver();
Expand Down
2 changes: 1 addition & 1 deletion impeller/scene/geometry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ std::shared_ptr<Geometry> Geometry::MakeFromFlatbuffer(
}

DeviceBufferDescriptor buffer_desc;
buffer_desc.size = vertices_bytes * indices_bytes;
buffer_desc.size = vertices_bytes + indices_bytes;
buffer_desc.storage_mode = StorageMode::kHostVisible;

auto buffer = allocator.CreateBuffer(buffer_desc);
Expand Down
2 changes: 0 additions & 2 deletions impeller/scene/material.cc
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,11 @@ std::unique_ptr<UnlitMaterial> UnlitMaterial::MakeFromFlatbuffer(

if (material.base_color_factor()) {
result->SetColor(importer::ToColor(*material.base_color_factor()));
result->SetVertexColorWeight(0);
}

if (material.base_color_texture() >= 0 &&
material.base_color_texture() < static_cast<int32_t>(textures.size())) {
result->SetColorTexture(textures[material.base_color_texture()]);
result->SetVertexColorWeight(0);
}

return result;
Expand Down
Loading