You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
214 lines
5.7 KiB
214 lines
5.7 KiB
/*
|
|
* Copyright 2018 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "gm.h"
|
|
|
|
#include "Sk3D.h"
|
|
#include "SkFont.h"
|
|
#include "SkPath.h"
|
|
#include "SkPoint3.h"
|
|
|
|
#ifdef SK_ENABLE_SKOTTIE
|
|
|
|
#include "SkAnimTimer.h"
|
|
#include "Resources.h"
|
|
#include "SkStream.h"
|
|
#include "Skottie.h"
|
|
|
|
static SkMatrix operator*(const SkMatrix& a, const SkMatrix& b) {
|
|
SkMatrix44 c;
|
|
c.setConcat(a, b);
|
|
return c;
|
|
}
|
|
|
|
class GM3d : public skiagm::GM {
|
|
float fNear = 0.5;
|
|
float fFar = 4;
|
|
float fAngle = SK_ScalarPI / 4;
|
|
|
|
SkPoint3 fEye { 0, 0, 4 };
|
|
SkPoint3 fCOA {0,0,0};//{ 0.5f, 0.5f, 0.5f };
|
|
SkPoint3 fUp { 0, 1, 0 };
|
|
|
|
SkPoint3 fP3[8];
|
|
|
|
sk_sp<skottie::Animation> fAnim;
|
|
SkScalar fAnimT = 0;
|
|
|
|
public:
|
|
GM3d() {}
|
|
~GM3d() override {}
|
|
|
|
protected:
|
|
void onOnceBeforeDraw() override {
|
|
if (auto stream = GetResourceAsStream("skottie/skottie_sample_2.json")) {
|
|
fAnim = skottie::Animation::Make(stream.get());
|
|
}
|
|
|
|
int index = 0;
|
|
for (float x = 0; x <= 1; ++x) {
|
|
for (float y = 0; y <= 1; ++y) {
|
|
for (float z = 0; z <= 1; ++z) {
|
|
fP3[index++] = { x, y, z };
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void draw_viewport(SkCanvas* canvas, const SkMatrix& viewport) {
|
|
SkPaint p;
|
|
p.setColor(0x10FF0000);
|
|
|
|
canvas->save();
|
|
canvas->concat(viewport);
|
|
canvas->drawRect({-1, -1, 1, 1}, p);
|
|
|
|
p.setColor(0x80FF0000);
|
|
canvas->drawLine({-1, -1}, {1, 1}, p);
|
|
canvas->drawLine({1, -1}, {-1, 1}, p);
|
|
canvas->restore();
|
|
}
|
|
|
|
static void draw_skia(SkCanvas* canvas, const SkMatrix44& m4, const SkMatrix& vp,
|
|
skottie::Animation* anim) {
|
|
auto proc = [canvas, vp, anim](SkColor c, const SkMatrix44& m4) {
|
|
SkPaint p;
|
|
p.setColor(c);
|
|
SkRect r = { 0, 0, 1, 1 };
|
|
canvas->save();
|
|
canvas->concat(vp * SkMatrix(m4));
|
|
anim->render(canvas, &r);
|
|
// canvas->drawRect({0, 0, 1, 1}, p);
|
|
canvas->restore();
|
|
};
|
|
|
|
SkMatrix44 tmp;
|
|
|
|
proc(0x400000FF, m4);
|
|
tmp.setTranslate(0, 0, 1);
|
|
proc(0xC00000FF, m4 * tmp);
|
|
tmp.setRotateAboutUnit(1, 0, 0, SK_ScalarPI/2);
|
|
proc(0x4000FF00, m4 * tmp);
|
|
tmp.postTranslate(0, 1, 0);
|
|
proc(0xC000FF00, m4 * tmp);
|
|
tmp.setRotateAboutUnit(0, 1, 0, -SK_ScalarPI/2);
|
|
proc(0x40FF0000, m4 * tmp);
|
|
tmp.postTranslate(1, 0, 0);
|
|
proc(0xC0FF0000, m4 * tmp);
|
|
}
|
|
|
|
void onDraw(SkCanvas* canvas) override {
|
|
if (!fAnim) {
|
|
return;
|
|
}
|
|
SkMatrix44 camera,
|
|
perspective,
|
|
mv;
|
|
SkMatrix viewport;
|
|
|
|
{
|
|
float w = this->width();
|
|
float h = this->height();
|
|
float s = std::min(w, h);
|
|
viewport.setTranslate(1, -1);
|
|
viewport.postScale(s/2, -s/2);
|
|
|
|
draw_viewport(canvas, viewport);
|
|
}
|
|
|
|
Sk3Perspective(&perspective, fNear, fFar, fAngle);
|
|
Sk3LookAt(&camera, fEye, fCOA, fUp);
|
|
mv.postConcat(camera);
|
|
mv.postConcat(perspective);
|
|
SkPoint pts[8];
|
|
Sk3MapPts(pts, mv, fP3, 8);
|
|
viewport.mapPoints(pts, 8);
|
|
|
|
SkPaint paint;
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
SkFont font;
|
|
font.setEdging(SkFont::Edging::kAlias);
|
|
|
|
SkPath cube;
|
|
|
|
cube.moveTo(pts[0]);
|
|
cube.lineTo(pts[2]);
|
|
cube.lineTo(pts[6]);
|
|
cube.lineTo(pts[4]);
|
|
cube.close();
|
|
|
|
cube.moveTo(pts[1]);
|
|
cube.lineTo(pts[3]);
|
|
cube.lineTo(pts[7]);
|
|
cube.lineTo(pts[5]);
|
|
cube.close();
|
|
|
|
cube.moveTo(pts[0]); cube.lineTo(pts[1]);
|
|
cube.moveTo(pts[2]); cube.lineTo(pts[3]);
|
|
cube.moveTo(pts[4]); cube.lineTo(pts[5]);
|
|
cube.moveTo(pts[6]); cube.lineTo(pts[7]);
|
|
|
|
canvas->drawPath(cube, paint);
|
|
|
|
{
|
|
SkPoint3 src[4] = {
|
|
{ 0, 0, 0 }, { 2, 0, 0 }, { 0, 2, 0 }, { 0, 0, 2 },
|
|
};
|
|
SkPoint dst[4];
|
|
mv.setConcat(perspective, camera);
|
|
Sk3MapPts(dst, mv, src, 4);
|
|
viewport.mapPoints(dst, 4);
|
|
const char* str[3] = { "X", "Y", "Z" };
|
|
for (int i = 1; i <= 3; ++i) {
|
|
canvas->drawLine(dst[0], dst[i], paint);
|
|
}
|
|
|
|
for (int i = 0; i < 3; ++i) {
|
|
canvas->drawString(str[i], dst[i + 1].fX, dst[i + 1].fY, font, paint);
|
|
}
|
|
}
|
|
|
|
fAnim->seek(fAnimT);
|
|
draw_skia(canvas, mv, viewport, fAnim.get());
|
|
}
|
|
|
|
SkISize onISize() override { return { 1024, 768 }; }
|
|
|
|
SkString onShortName() override { return SkString("3dgm"); }
|
|
|
|
bool onAnimate(const SkAnimTimer& timer) override {
|
|
if (!fAnim) {
|
|
return false;
|
|
}
|
|
SkScalar dur = fAnim->duration();
|
|
fAnimT = fmod(timer.secs(), dur) / dur;
|
|
return true;
|
|
}
|
|
bool onHandleKey(SkUnichar uni) override {
|
|
switch (uni) {
|
|
case 'a': fEye.fX += 0.125f; return true;
|
|
case 'd': fEye.fX -= 0.125f; return true;
|
|
case 'w': fEye.fY += 0.125f; return true;
|
|
case 's': fEye.fY -= 0.125f; return true;
|
|
case 'q': fEye.fZ += 0.125f; return true;
|
|
case 'z': fEye.fZ -= 0.125f; return true;
|
|
default: break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool onGetControls(SkMetaData*) override { return false; }
|
|
void onSetControls(const SkMetaData&) override {
|
|
|
|
}
|
|
};
|
|
|
|
DEF_GM(return new GM3d;)
|
|
|
|
#endif
|
|
|