[skottie] Parented camera support

Parent camera layer transforms apply to the camera itself, thus

  T_camera' = T_camera x Inv(T_parent)

To support this composition:

  - introduce sksg::Transform::MakeInverse()

  - allow selectable pre/post parent composition in
    AnimationBuilder::attachMatrix3D()

Change-Id: Ie70b36e4e9bb1b32e60893df5695bdc6c0dc0d00
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/210422
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
This commit is contained in:
Florin Malita 2019-04-25 12:18:19 -04:00 committed by Skia Commit-Bot
parent fd7657cba2
commit 2253c22afb
9 changed files with 94 additions and 13 deletions

View File

@ -118,7 +118,8 @@ sk_sp<sksg::Transform> AnimationBuilder::attachMatrix2D(const skjson::ObjectValu
sk_sp<sksg::Transform> AnimationBuilder::attachMatrix3D(const skjson::ObjectValue& t, sk_sp<sksg::Transform> AnimationBuilder::attachMatrix3D(const skjson::ObjectValue& t,
AnimatorScope* ascope, AnimatorScope* ascope,
sk_sp<sksg::Transform> parent, sk_sp<sksg::Transform> parent,
sk_sp<TransformAdapter3D> adapter) const { sk_sp<TransformAdapter3D> adapter,
bool precompose_parent) const {
static const VectorValue g_default_vec_0 = { 0, 0, 0}, static const VectorValue g_default_vec_0 = { 0, 0, 0},
g_default_vec_100 = {100, 100, 100}; g_default_vec_100 = {100, 100, 100};
@ -167,9 +168,13 @@ sk_sp<sksg::Transform> AnimationBuilder::attachMatrix3D(const skjson::ObjectValu
// TODO: dispatch 3D transform properties // TODO: dispatch 3D transform properties
return (bound) if (!bound) {
? sksg::Transform::MakeConcat(std::move(parent), adapter->refTransform()) return parent;
: parent; }
return precompose_parent
? sksg::Transform::MakeConcat(adapter->refTransform(), std::move(parent))
: sksg::Transform::MakeConcat(std::move(parent), adapter->refTransform());
} }
sk_sp<sksg::RenderNode> AnimationBuilder::attachOpacity(const skjson::ObjectValue& jtransform, sk_sp<sksg::RenderNode> AnimationBuilder::attachOpacity(const skjson::ObjectValue& jtransform,

View File

@ -119,8 +119,6 @@ SkMatrix44 CameraAdapter::totalMatrix() const {
// * point of interest -> anchor point attribute // * point of interest -> anchor point attribute
// * orientation -> rotation attribute // * orientation -> rotation attribute
// //
// Note: the orientation is specified post position/POI adjustment.
//
SkPoint3 pos = { this->getPosition().fX, SkPoint3 pos = { this->getPosition().fX,
this->getPosition().fY, this->getPosition().fY,
-this->getPosition().fZ }, -this->getPosition().fZ },
@ -129,9 +127,11 @@ SkMatrix44 CameraAdapter::totalMatrix() const {
-this->getAnchorPoint().fZ }, -this->getAnchorPoint().fZ },
up = { 0, 1, 0 }; up = { 0, 1, 0 };
// Initial camera vector.
SkMatrix44 cam_t; SkMatrix44 cam_t;
Sk3LookAt(&cam_t, pos, poi, up); Sk3LookAt(&cam_t, pos, poi, up);
// Rotation origin is camera position.
{ {
SkMatrix44 rot; SkMatrix44 rot;
rot.setRotateDegreesAbout(1, 0, 0, this->getRotation().fX); rot.setRotateDegreesAbout(1, 0, 0, this->getRotation().fX);
@ -142,6 +142,9 @@ SkMatrix44 CameraAdapter::totalMatrix() const {
cam_t.postConcat(rot); cam_t.postConcat(rot);
} }
// Flip world Z, as it is opposite of what Sk3D expects.
cam_t.preScale(1, 1, -1);
// View parameters: // View parameters:
// //
// * size -> composition size (TODO: AE seems to base it on width only?) // * size -> composition size (TODO: AE seems to base it on width only?)
@ -151,13 +154,13 @@ SkMatrix44 CameraAdapter::totalMatrix() const {
view_distance = this->getZoom(), view_distance = this->getZoom(),
view_angle = std::atan(view_size * 0.5f / view_distance); view_angle = std::atan(view_size * 0.5f / view_distance);
SkMatrix44 view_t; SkMatrix44 persp_t;
Sk3Perspective(&view_t, 0, view_distance, 2 * view_angle); Sk3Perspective(&persp_t, 0, view_distance, 2 * view_angle);
view_t.postScale(view_size * 0.5f, view_size * 0.5f, 1); persp_t.postScale(view_size * 0.5f, view_size * 0.5f, 1);
SkMatrix44 t; SkMatrix44 t;
t.setTranslate(fViewportSize.width() * 0.5f, fViewportSize.height() * 0.5f, 0); t.setTranslate(fViewportSize.width() * 0.5f, fViewportSize.height() * 0.5f, 0);
t.preConcat(view_t); t.preConcat(persp_t);
t.preConcat(cam_t); t.preConcat(cam_t);
return t; return t;

View File

@ -474,9 +474,17 @@ private:
camera_adapter->setZoom(pe); camera_adapter->setZoom(pe);
}); });
// parent_transform applies to the camera itself => it pre-composes inverted to the
// camera/view/adapter transform.
//
// T_camera' = T_camera x Inv(parent_transform)
//
parent_transform = sksg::Transform::MakeInverse(std::move(parent_transform));
return abuilder->attachMatrix3D(*jtransform, fScope, return abuilder->attachMatrix3D(*jtransform, fScope,
std::move(parent_transform), std::move(parent_transform),
std::move(camera_adapter)); std::move(camera_adapter),
true); // pre-compose parent
} }
return (ParseDefault<int>(jlayer["ddd"], 0) == 0) return (ParseDefault<int>(jlayer["ddd"], 0) == 0)

View File

@ -79,7 +79,8 @@ public:
sk_sp<sksg::Transform>) const; sk_sp<sksg::Transform>) const;
sk_sp<sksg::Transform> attachMatrix3D(const skjson::ObjectValue&, AnimatorScope*, sk_sp<sksg::Transform> attachMatrix3D(const skjson::ObjectValue&, AnimatorScope*,
sk_sp<sksg::Transform>, sk_sp<sksg::Transform>,
sk_sp<TransformAdapter3D> = nullptr) const; sk_sp<TransformAdapter3D> = nullptr,
bool precompose_parent = false) const;
sk_sp<sksg::RenderNode> attachOpacity(const skjson::ObjectValue&, AnimatorScope*, sk_sp<sksg::RenderNode> attachOpacity(const skjson::ObjectValue&, AnimatorScope*,
sk_sp<sksg::RenderNode>) const; sk_sp<sksg::RenderNode>) const;
sk_sp<sksg::Path> attachPath(const skjson::Value&, AnimatorScope*) const; sk_sp<sksg::Path> attachPath(const skjson::Value&, AnimatorScope*) const;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -20,9 +20,12 @@ namespace sksg {
*/ */
class Transform : public Node { class Transform : public Node {
public: public:
// Compose T = A x B // Compose T' = A x B
static sk_sp<Transform> MakeConcat(sk_sp<Transform> a, sk_sp<Transform> b); static sk_sp<Transform> MakeConcat(sk_sp<Transform> a, sk_sp<Transform> b);
// T' = Inv(T)
static sk_sp<Transform> MakeInverse(sk_sp<Transform> t);
protected: protected:
Transform(); Transform();

View File

@ -46,10 +46,12 @@ protected:
bool is44() const override { return std::is_same<T, SkMatrix44>::value; } bool is44() const override { return std::is_same<T, SkMatrix44>::value; }
SkMatrix asMatrix() const override { SkMatrix asMatrix() const override {
SkASSERT(!this->hasInval());
return fComposed; return fComposed;
} }
SkMatrix44 asMatrix44() const override { SkMatrix44 asMatrix44() const override {
SkASSERT(!this->hasInval());
return fComposed; return fComposed;
} }
@ -60,6 +62,52 @@ private:
using INHERITED = Transform; using INHERITED = Transform;
}; };
template <typename T>
class Inverse final : public Transform {
public:
template <typename = std::enable_if<std::is_same<T, SkMatrix >::value ||
std::is_same<T, SkMatrix44>::value >>
explicit Inverse(sk_sp<Transform> t)
: fT(std::move(t)) {
SkASSERT(fT);
this->observeInval(fT);
}
~Inverse() override {
this->unobserveInval(fT);
}
protected:
SkRect onRevalidate(InvalidationController* ic, const SkMatrix& ctm) override {
fT->revalidate(ic, ctm);
if (!TransformPriv::As<T>(fT).invert(&fInverted)) {
fInverted.reset();
}
return SkRect::MakeEmpty();
}
bool is44() const override { return std::is_same<T, SkMatrix44>::value; }
SkMatrix asMatrix() const override {
SkASSERT(!this->hasInval());
return fInverted;
}
SkMatrix44 asMatrix44() const override {
SkASSERT(!this->hasInval());
return fInverted;
}
private:
const sk_sp<Transform> fT;
T fInverted;
using INHERITED = Transform;
};
} // namespace } // namespace
// Transform nodes don't generate damage on their own, but via ancestor TransformEffects. // Transform nodes don't generate damage on their own, but via ancestor TransformEffects.
@ -79,6 +127,16 @@ sk_sp<Transform> Transform::MakeConcat(sk_sp<Transform> a, sk_sp<Transform> b) {
: sk_sp<Transform>(new Concat<SkMatrix >(std::move(a), std::move(b))); : sk_sp<Transform>(new Concat<SkMatrix >(std::move(a), std::move(b)));
} }
sk_sp<Transform> Transform::MakeInverse(sk_sp<Transform> t) {
if (!t) {
return nullptr;
}
return TransformPriv::Is44(t)
? sk_sp<Transform>(new Inverse<SkMatrix44>(std::move(t)))
: sk_sp<Transform>(new Inverse<SkMatrix >(std::move(t)));
}
TransformEffect::TransformEffect(sk_sp<RenderNode> child, sk_sp<Transform> transform) TransformEffect::TransformEffect(sk_sp<RenderNode> child, sk_sp<Transform> transform)
: INHERITED(std::move(child)) : INHERITED(std::move(child))
, fTransform(std::move(transform)) { , fTransform(std::move(transform)) {