[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:
parent
fd7657cba2
commit
2253c22afb
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
1
modules/skottie/tests/camera-parent-1.json
Normal file
1
modules/skottie/tests/camera-parent-1.json
Normal file
File diff suppressed because one or more lines are too long
1
modules/skottie/tests/camera-parent-2.json
Normal file
1
modules/skottie/tests/camera-parent-2.json
Normal file
File diff suppressed because one or more lines are too long
1
modules/skottie/tests/camera-parent-3.json
Normal file
1
modules/skottie/tests/camera-parent-3.json
Normal file
File diff suppressed because one or more lines are too long
@ -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();
|
||||||
|
|
||||||
|
@ -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)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user