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