• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "gm.h"
9 
10 #include "Sk3D.h"
11 #include "SkFont.h"
12 #include "SkPath.h"
13 #include "SkPoint3.h"
14 
15 #ifdef SK_ENABLE_SKOTTIE
16 
17 #include "SkAnimTimer.h"
18 #include "Resources.h"
19 #include "SkStream.h"
20 #include "Skottie.h"
21 
operator *(const SkMatrix & a,const SkMatrix & b)22 static SkMatrix operator*(const SkMatrix& a, const SkMatrix& b) {
23     SkMatrix44 c;
24     c.setConcat(a, b);
25     return c;
26 }
27 
28 class GM3d : public skiagm::GM {
29     float   fNear = 0.5;
30     float   fFar = 4;
31     float   fAngle = SK_ScalarPI / 4;
32 
33     SkPoint3    fEye { 0, 0, 4 };
34     SkPoint3    fCOA {0,0,0};//{ 0.5f, 0.5f, 0.5f };
35     SkPoint3    fUp  { 0, 1, 0 };
36 
37     SkPoint3    fP3[8];
38 
39     sk_sp<skottie::Animation> fAnim;
40     SkScalar fAnimT = 0;
41 
42 public:
GM3d()43     GM3d() {}
~GM3d()44     ~GM3d() override {}
45 
46 protected:
onOnceBeforeDraw()47     void onOnceBeforeDraw() override {
48         if (auto stream = GetResourceAsStream("skottie/skottie_sample_2.json")) {
49             fAnim = skottie::Animation::Make(stream.get());
50         }
51 
52         int index = 0;
53         for (float x = 0; x <= 1; ++x) {
54             for (float y = 0; y <= 1; ++y) {
55                 for (float z = 0; z <= 1; ++z) {
56                     fP3[index++] = { x, y, z };
57                 }
58             }
59         }
60     }
61 
draw_viewport(SkCanvas * canvas,const SkMatrix & viewport)62     static void draw_viewport(SkCanvas* canvas, const SkMatrix& viewport) {
63         SkPaint p;
64         p.setColor(0x10FF0000);
65 
66         canvas->save();
67         canvas->concat(viewport);
68         canvas->drawRect({-1, -1, 1, 1}, p);
69 
70         p.setColor(0x80FF0000);
71         canvas->drawLine({-1, -1}, {1, 1}, p);
72         canvas->drawLine({1, -1}, {-1, 1}, p);
73         canvas->restore();
74     }
75 
draw_skia(SkCanvas * canvas,const SkMatrix44 & m4,const SkMatrix & vp,skottie::Animation * anim)76     static void draw_skia(SkCanvas* canvas, const SkMatrix44& m4, const SkMatrix& vp,
77                           skottie::Animation* anim) {
78         auto proc = [canvas, vp, anim](SkColor c, const SkMatrix44& m4) {
79             SkPaint p;
80             p.setColor(c);
81             SkRect r = { 0, 0, 1, 1 };
82             canvas->save();
83             canvas->concat(vp * SkMatrix(m4));
84             anim->render(canvas, &r);
85 //            canvas->drawRect({0, 0, 1, 1}, p);
86             canvas->restore();
87         };
88 
89         SkMatrix44 tmp;
90 
91         proc(0x400000FF, m4);
92         tmp.setTranslate(0, 0, 1);
93         proc(0xC00000FF, m4 * tmp);
94         tmp.setRotateAboutUnit(1, 0, 0, SK_ScalarPI/2);
95         proc(0x4000FF00, m4 * tmp);
96         tmp.postTranslate(0, 1, 0);
97         proc(0xC000FF00, m4 * tmp);
98         tmp.setRotateAboutUnit(0, 1, 0, -SK_ScalarPI/2);
99         proc(0x40FF0000, m4 * tmp);
100         tmp.postTranslate(1, 0, 0);
101         proc(0xC0FF0000, m4 * tmp);
102     }
103 
onDraw(SkCanvas * canvas,SkString * errorMsg)104     DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
105         if (!fAnim) {
106             *errorMsg = "No animation.";
107             return DrawResult::kFail;
108         }
109         SkMatrix44  camera,
110                     perspective,
111                     mv;
112         SkMatrix    viewport;
113 
114         {
115             float w = this->width();
116             float h = this->height();
117             float s = std::min(w, h);
118             viewport.setTranslate(1, -1);
119             viewport.postScale(s/2, -s/2);
120 
121             draw_viewport(canvas, viewport);
122         }
123 
124         Sk3Perspective(&perspective, fNear, fFar, fAngle);
125         Sk3LookAt(&camera, fEye, fCOA, fUp);
126         mv.postConcat(camera);
127         mv.postConcat(perspective);
128         SkPoint pts[8];
129         Sk3MapPts(pts, mv, fP3, 8);
130         viewport.mapPoints(pts, 8);
131 
132         SkPaint paint;
133         paint.setStyle(SkPaint::kStroke_Style);
134         SkFont font;
135         font.setEdging(SkFont::Edging::kAlias);
136 
137         SkPath cube;
138 
139         cube.moveTo(pts[0]);
140         cube.lineTo(pts[2]);
141         cube.lineTo(pts[6]);
142         cube.lineTo(pts[4]);
143         cube.close();
144 
145         cube.moveTo(pts[1]);
146         cube.lineTo(pts[3]);
147         cube.lineTo(pts[7]);
148         cube.lineTo(pts[5]);
149         cube.close();
150 
151         cube.moveTo(pts[0]);    cube.lineTo(pts[1]);
152         cube.moveTo(pts[2]);    cube.lineTo(pts[3]);
153         cube.moveTo(pts[4]);    cube.lineTo(pts[5]);
154         cube.moveTo(pts[6]);    cube.lineTo(pts[7]);
155 
156         canvas->drawPath(cube, paint);
157 
158         {
159             SkPoint3 src[4] = {
160                 { 0, 0, 0 }, { 2, 0, 0 }, { 0, 2, 0 }, { 0, 0, 2 },
161             };
162             SkPoint dst[4];
163             mv.setConcat(perspective, camera);
164             Sk3MapPts(dst, mv, src, 4);
165             viewport.mapPoints(dst, 4);
166             const char* str[3] = { "X", "Y", "Z" };
167             for (int i = 1; i <= 3; ++i) {
168                 canvas->drawLine(dst[0], dst[i], paint);
169             }
170 
171             for (int i = 0; i < 3; ++i) {
172                 canvas->drawString(str[i], dst[i + 1].fX, dst[i + 1].fY, font, paint);
173             }
174         }
175 
176         fAnim->seek(fAnimT);
177         draw_skia(canvas, mv, viewport, fAnim.get());
178         return DrawResult::kOk;
179     }
180 
onISize()181     SkISize onISize() override { return { 1024, 768 }; }
182 
onShortName()183     SkString onShortName() override { return SkString("3dgm"); }
184 
onAnimate(const SkAnimTimer & timer)185     bool onAnimate(const SkAnimTimer& timer) override {
186         if (!fAnim) {
187             return false;
188         }
189         SkScalar dur = fAnim->duration();
190         fAnimT = fmod(timer.secs(), dur) / dur;
191         return true;
192     }
onHandleKey(SkUnichar uni)193     bool onHandleKey(SkUnichar uni) override {
194         switch (uni) {
195             case 'a': fEye.fX += 0.125f; return true;
196             case 'd': fEye.fX -= 0.125f; return true;
197             case 'w': fEye.fY += 0.125f; return true;
198             case 's': fEye.fY -= 0.125f; return true;
199             case 'q': fEye.fZ += 0.125f; return true;
200             case 'z': fEye.fZ -= 0.125f; return true;
201             default: break;
202         }
203         return false;
204     }
205 
onGetControls(SkMetaData *)206     bool onGetControls(SkMetaData*) override { return false; }
onSetControls(const SkMetaData &)207     void onSetControls(const SkMetaData&) override {
208 
209     }
210 };
211 
212 DEF_GM(return new GM3d;)
213 
214 #endif
215 
216