blob: c628ef9018c10424ebfc9b7cc879e16686ba9447 [file] [log] [blame]
Mike Reed27714a02018-05-30 16:02:48 -04001/*
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"
Hal Canarya70ae1a2019-01-08 15:04:23 -05009
Mike Reed27714a02018-05-30 16:02:48 -040010#include "Sk3D.h"
Hal Canarya70ae1a2019-01-08 15:04:23 -050011#include "SkFont.h"
Mike Reed27714a02018-05-30 16:02:48 -040012#include "SkPath.h"
13#include "SkPoint3.h"
14
Mike Reed2f0edd52018-05-31 14:22:30 -040015#ifdef SK_ENABLE_SKOTTIE
16
17#include "SkAnimTimer.h"
18#include "Resources.h"
19#include "SkStream.h"
20#include "Skottie.h"
21
22static SkMatrix operator*(const SkMatrix& a, const SkMatrix& b) {
23 SkMatrix44 c;
24 c.setConcat(a, b);
25 return c;
26}
27
Mike Reed27714a02018-05-30 16:02:48 -040028class 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
Mike Reed27714a02018-05-30 16:02:48 -040037 SkPoint3 fP3[8];
Mike Reed2f0edd52018-05-31 14:22:30 -040038
39 sk_sp<skottie::Animation> fAnim;
40 SkScalar fAnimT = 0;
41
Mike Reed27714a02018-05-30 16:02:48 -040042public:
Mike Reed2f0edd52018-05-31 14:22:30 -040043 GM3d() {}
Mike Reed27714a02018-05-30 16:02:48 -040044 ~GM3d() override {}
45
46protected:
47 void onOnceBeforeDraw() override {
Florin Malita26870722018-09-20 14:35:30 -040048 if (auto stream = GetResourceAsStream("skottie/skottie_sample_2.json")) {
Florin Malita527a2972018-06-13 13:03:04 -040049 fAnim = skottie::Animation::Make(stream.get());
50 }
Mike Reed2f0edd52018-05-31 14:22:30 -040051
Mike Reed27714a02018-05-30 16:02:48 -040052 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 }
Mike Reed27714a02018-05-30 16:02:48 -040060 }
61
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
Mike Reed2f0edd52018-05-31 14:22:30 -040076 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
Mike Klein4429a4f2018-10-04 09:06:00 -040089 SkMatrix44 tmp;
Mike Reed2f0edd52018-05-31 14:22:30 -040090
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
Chris Dalton50e24d72019-02-07 16:20:09 -0700104 DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
Florin Malita527a2972018-06-13 13:03:04 -0400105 if (!fAnim) {
Chris Dalton50e24d72019-02-07 16:20:09 -0700106 *errorMsg = "No animation.";
107 return DrawResult::kFail;
Florin Malita527a2972018-06-13 13:03:04 -0400108 }
Mike Klein4429a4f2018-10-04 09:06:00 -0400109 SkMatrix44 camera,
110 perspective,
111 mv;
Mike Reed27714a02018-05-30 16:02:48 -0400112 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);
Hal Canarya70ae1a2019-01-08 15:04:23 -0500134 SkFont font;
135 font.setEdging(SkFont::Edging::kAlias);
Mike Reed27714a02018-05-30 16:02:48 -0400136
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);
Hal Canarya70ae1a2019-01-08 15:04:23 -0500166 const char* str[3] = { "X", "Y", "Z" };
Mike Reed27714a02018-05-30 16:02:48 -0400167 for (int i = 1; i <= 3; ++i) {
168 canvas->drawLine(dst[0], dst[i], paint);
169 }
170
Hal Canarya70ae1a2019-01-08 15:04:23 -0500171 for (int i = 0; i < 3; ++i) {
172 canvas->drawString(str[i], dst[i + 1].fX, dst[i + 1].fY, font, paint);
Mike Reed27714a02018-05-30 16:02:48 -0400173 }
174 }
Mike Reed2f0edd52018-05-31 14:22:30 -0400175
176 fAnim->seek(fAnimT);
177 draw_skia(canvas, mv, viewport, fAnim.get());
Chris Dalton50e24d72019-02-07 16:20:09 -0700178 return DrawResult::kOk;
Mike Reed27714a02018-05-30 16:02:48 -0400179 }
180
181 SkISize onISize() override { return { 1024, 768 }; }
182
183 SkString onShortName() override { return SkString("3dgm"); }
184
Mike Reed2f0edd52018-05-31 14:22:30 -0400185 bool onAnimate(const SkAnimTimer& timer) override {
Jim Van Verth70276912018-06-01 13:46:46 -0400186 if (!fAnim) {
187 return false;
188 }
Mike Reed2f0edd52018-05-31 14:22:30 -0400189 SkScalar dur = fAnim->duration();
190 fAnimT = fmod(timer.secs(), dur) / dur;
191 return true;
192 }
Mike Reed27714a02018-05-30 16:02:48 -0400193 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
206 bool onGetControls(SkMetaData*) override { return false; }
207 void onSetControls(const SkMetaData&) override {
208
209 }
210};
211
212DEF_GM(return new GM3d;)
Mike Reed2f0edd52018-05-31 14:22:30 -0400213
214#endif
215