lottie/feature: Added 3D layer support in lottie player. 45/193145/1
authorsubhransu mohanty <sub.mohanty@samsung.com>
Thu, 15 Nov 2018 08:19:13 +0000 (17:19 +0900)
committersubhransu mohanty <sub.mohanty@samsung.com>
Thu, 15 Nov 2018 08:20:16 +0000 (17:20 +0900)
Change-Id: I1f37f299761570d08ef9bda39a66df757b215e5a

example/resource/3d.json [new file with mode: 0755]
src/lottie/lottiemodel.cpp
src/lottie/lottiemodel.h
src/lottie/lottieparser.cpp

diff --git a/example/resource/3d.json b/example/resource/3d.json
new file mode 100755 (executable)
index 0000000..a5babf8
--- /dev/null
@@ -0,0 +1 @@
+{"v":"5.2.1","fr":60,"ip":0,"op":60,"w":500,"h":500,"nm":"Comp 1","ddd":1,"assets":[],"layers":[{"ddd":1,"ind":1,"ty":4,"nm":"Shape Layer 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"rx":{"a":0,"k":0,"ix":8},"ry":{"a":0,"k":0,"ix":9},"rz":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":0,"s":[0],"e":[360]},{"t":55}],"ix":10},"or":{"a":0,"k":[0,0,0],"ix":7},"p":{"a":0,"k":[75,384,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[100,100],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.075893886387,0.175385013223,0.921568632126,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":1,"ind":2,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"rx":{"a":0,"k":0,"ix":8},"ry":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":0,"s":[0],"e":[360]},{"t":55}],"ix":9},"rz":{"a":0,"k":0,"ix":10},"or":{"a":0,"k":[0,0,0],"ix":7},"p":{"a":0,"k":[76,234,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[100,100],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.025943866,0.945098042488,0.134079754353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":1,"ind":3,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"rx":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":0,"s":[0],"e":[360]},{"t":55}],"ix":8},"ry":{"a":0,"k":0,"ix":9},"rz":{"a":0,"k":0,"ix":10},"or":{"a":0,"k":[0,0,0],"ix":7},"p":{"a":0,"k":[76,72,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[100,100],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":60,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
index e5283bedc9e95a8837036836b9c59b4819251a16..1b5cd98cb67a91c00af4279300a33ce840150558 100644 (file)
@@ -75,11 +75,22 @@ VMatrix LOTTransformData::computeMatrix(int frameNo, bool autoOrient) const
     }
 
     float angle = autoOrient ? mPosition.angle(frameNo) : 0;
-    m.translate(position)
-        .rotate(mRotation.value(frameNo))
-        .rotate(angle)
-        .scale(mScale.value(frameNo) / 100.f)
-        .translate(-mAnchor.value(frameNo));
+    if (ddd()) {
+        m.translate(position)
+            .rotate(mRotation.value(frameNo))
+            .rotate(angle)
+            .rotate(m3D->mRz.value(frameNo))
+            .rotate(m3D->mRy.value(frameNo), VMatrix::Axis::Y)
+            .rotate(m3D->mRx.value(frameNo), VMatrix::Axis::X)
+            .scale(mScale.value(frameNo) / 100.f)
+            .translate(-mAnchor.value(frameNo));
+    } else {
+        m.translate(position)
+            .rotate(mRotation.value(frameNo))
+            .rotate(angle)
+            .scale(mScale.value(frameNo) / 100.f)
+            .translate(-mAnchor.value(frameNo));
+    }
     return m;
 }
 
index 73034ebc0c2868af3d0ab2510a33ced6dcf0eb3f..226cee5e2d0abab95b7cc4b5fb53b61da6d4ee64 100644 (file)
@@ -417,6 +417,13 @@ inline int LOTLayerData::timeRemap(int frameNo) const
     return frameNo / mTimeStreatch;
 }
 
+struct LOT3DData
+{
+    LOTAnimatable<float>     mRx{0};
+    LOTAnimatable<float>     mRy{0};
+    LOTAnimatable<float>     mRz{0};
+};
+
 class LOTTransformData : public LOTData
 {
 public:
@@ -425,21 +432,23 @@ public:
     float    opacity(int frameNo) const;
     void cacheMatrix();
     bool staticMatrix() const {return mStaticMatrix;}
+    bool ddd() const {return m3D ? true : false;}
 private:
     VMatrix computeMatrix(int frameNo, bool autoOrient = false) const;
 public:
-    LOTAnimatable<float>     mRotation{0};  /* "r" */
-    LOTAnimatable<VPointF>   mScale;     /* "s" */
-    LOTAnimatable<VPointF>   mPosition;  /* "p" */
-    LOTAnimatable<float>     mX{0};
-    LOTAnimatable<float>     mY{0};
-    LOTAnimatable<VPointF>   mAnchor;    /* "a" */
-    LOTAnimatable<float>     mOpacity{100};   /* "o" */
-    LOTAnimatable<float>     mSkew{0};      /* "sk" */
-    LOTAnimatable<float>     mSkewAxis{0};  /* "sa" */
-    bool                     mStaticMatrix{true};
-    bool                     mSeparate{false};
-    VMatrix                  mCachedMatrix;
+    std::unique_ptr<LOT3DData>    m3D;
+    LOTAnimatable<float>          mRotation{0};  /* "r" */
+    LOTAnimatable<VPointF>        mScale;     /* "s" */
+    LOTAnimatable<VPointF>        mPosition;  /* "p" */
+    LOTAnimatable<float>          mX{0};
+    LOTAnimatable<float>          mY{0};
+    LOTAnimatable<VPointF>        mAnchor;    /* "a" */
+    LOTAnimatable<float>          mOpacity{100};   /* "o" */
+    LOTAnimatable<float>          mSkew{0};      /* "sk" */
+    LOTAnimatable<float>          mSkewAxis{0};  /* "sa" */
+    bool                          mStaticMatrix{true};
+    bool                          mSeparate{false};
+    VMatrix                       mCachedMatrix;
 };
 
 class LOTFillData : public LOTData
index 18e576b7343799f19e7fb2485d3831252415e979..3f42d114f244d920394e9a576b68f7fb9403bcdb 100644 (file)
@@ -208,7 +208,7 @@ public:
     std::shared_ptr<LOTData>     parseShapeObject();
     std::shared_ptr<LOTData>     parsePolystarObject();
 
-    std::shared_ptr<LOTTransformData> parseTransformObject();
+    std::shared_ptr<LOTTransformData> parseTransformObject(bool ddd = false);
     std::shared_ptr<LOTData>          parseFillObject();
     std::shared_ptr<LOTData>          parseGFillObject();
     std::shared_ptr<LOTData>          parseStrokeObject();
@@ -738,6 +738,7 @@ std::shared_ptr<LOTData> LottieParserImpl::parseLayer()
     LOTLayerData *layer = sharedLayer.get();
     curLayerRef = layer;
     bool hasLayerRef = false;
+    bool ddd = true;
     EnterObject();
     while (const char *key = NextObjectKey()) {
         if (0 == strcmp(key, "ty")) { /* Type of layer*/
@@ -746,6 +747,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseLayer()
                                                  parenting and expressions.*/
             RAPIDJSON_ASSERT(PeekType() == kNumberType);
             layer->mId = GetInt();
+        } else if (0 == strcmp(key, "ddd")) { /*3d layer */
+            RAPIDJSON_ASSERT(PeekType() == kNumberType);
+            ddd = GetInt();
         } else if (0 == strcmp(key, "parent")) { /*Layer Parent. Uses "ind" of parent.*/
             RAPIDJSON_ASSERT(PeekType() == kNumberType);
             layer->mParentId = GetInt();
@@ -776,7 +780,7 @@ std::shared_ptr<LOTData> LottieParserImpl::parseLayer()
         } else if (0 == strcmp(key, "ks")) {
             RAPIDJSON_ASSERT(PeekType() == kObjectType);
             EnterObject();
-            layer->mTransform = parseTransformObject();
+            layer->mTransform = parseTransformObject(ddd);
         } else if (0 == strcmp(key, "shapes")) {
             parseShapesAttr(layer);
         } else if (0 == strcmp(key, "sw")) {
@@ -1174,12 +1178,14 @@ std::shared_ptr<LOTData> LottieParserImpl::parseReapeaterObject()
 /*
  * https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/transform.json
  */
-std::shared_ptr<LOTTransformData> LottieParserImpl::parseTransformObject()
+std::shared_ptr<LOTTransformData> LottieParserImpl::parseTransformObject(bool ddd)
 {
     std::shared_ptr<LOTTransformData> sharedTransform =
         std::make_shared<LOTTransformData>();
     LOTTransformData *obj = sharedTransform.get();
 
+    if (ddd) obj->m3D = std::make_unique<LOT3DData>();
+
     while (const char *key = NextObjectKey()) {
         if (0 == strcmp(key, "a")) {
             parseProperty(obj->mAnchor);
@@ -1210,6 +1216,12 @@ std::shared_ptr<LOTTransformData> LottieParserImpl::parseTransformObject()
             parseProperty(obj->mOpacity);
         } else if (0 == strcmp(key, "hd")) {
             obj->mHidden = GetBool();
+        } else if (0 == strcmp(key, "rx")) {
+            parseProperty(obj->m3D->mRx);
+        } else if (0 == strcmp(key, "ry")) {
+            parseProperty(obj->m3D->mRy);
+        } else if (0 == strcmp(key, "rz")) {
+            parseProperty(obj->m3D->mRz);
         } else {
             Skip(key);
         }
@@ -1218,6 +1230,10 @@ std::shared_ptr<LOTTransformData> LottieParserImpl::parseTransformObject()
                          obj->mRotation.isStatic() && obj->mScale.isStatic() &&
                          obj->mSkew.isStatic() && obj->mSkewAxis.isStatic() &&
                          obj->mX.isStatic() && obj->mY.isStatic();
+    if (obj->m3D) {
+        obj->mStaticMatrix = obj->mStaticMatrix && obj->m3D->mRx.isStatic() &&
+                             obj->m3D->mRy.isStatic() && obj->m3D->mRz.isStatic();
+    }
 
     obj->setStatic(obj->mStaticMatrix && obj->mOpacity.isStatic());
 
@@ -1919,6 +1935,7 @@ public:
                << ", stFm:" << obj->mStartFrame
                << ", ts:" << obj->mTimeStreatch
                << ", ao:" << obj->autoOrient()
+               << ", ddd:" << obj->mTransform->ddd()
                << "\n";
         visitChildren(static_cast<LOTGroupData *>(obj), level);
         vDebug << level