diff options
author | Mike Reed <reed@google.com> | 2018-05-30 16:02:48 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-05-30 20:36:08 +0000 |
commit | 27714a026d9178ff7834b87677cbd10bf5150dc7 (patch) | |
tree | 424afe8d98ea19b18d6a3833950bcae9c80fa34c | |
parent | a15cedbc26fee1ba23465aaa0dc46dd0e69996cc (diff) |
3d
Bug: skia:
Change-Id: I10e56f08a2463fcac2b7813d43d0aae35268ac27
Reviewed-on: https://skia-review.googlesource.com/130842
Commit-Queue: Brian Salomon <bsalomon@google.com>
Auto-Submit: Mike Reed <reed@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
-rw-r--r-- | gm/3dgm.cpp | 147 | ||||
-rw-r--r-- | gn/gm.gni | 1 | ||||
-rw-r--r-- | gn/utils.gni | 1 | ||||
-rw-r--r-- | src/utils/Sk3D.cpp | 64 | ||||
-rw-r--r-- | src/utils/Sk3D.h | 19 |
5 files changed, 232 insertions, 0 deletions
diff --git a/gm/3dgm.cpp b/gm/3dgm.cpp new file mode 100644 index 0000000000..37830ae878 --- /dev/null +++ b/gm/3dgm.cpp @@ -0,0 +1,147 @@ +/* + * 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 "SkPath.h" +#include "SkPoint3.h" + +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 }; + + SkMatrix44 fMV; + + SkPoint3 fP3[8]; +public: + GM3d() : fMV(SkMatrix44::kIdentity_Constructor) {} + ~GM3d() override {} + +protected: + void onOnceBeforeDraw() override { + 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 }; + } + } + } + fMV.setIdentity(); + } + + 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(); + } + + void onDraw(SkCanvas* canvas) override { + SkMatrix44 camera(SkMatrix44::kIdentity_Constructor), + perspective(SkMatrix44::kIdentity_Constructor), + mv = fMV; + 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); + + 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[] = "XYZ"; + for (int i = 1; i <= 3; ++i) { + canvas->drawLine(dst[0], dst[i], paint); + } + + for (int i = 1; i <= 3; ++i) { + canvas->drawText(&str[i-1], 1, dst[i].fX, dst[i].fY, paint); + } + } + } + + SkISize onISize() override { return { 1024, 768 }; } + + SkString onShortName() override { return SkString("3dgm"); } + + bool onAnimate(const SkAnimTimer&) override { return false; } + 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;) @@ -7,6 +7,7 @@ _gm = get_path_info("../gm", "abspath") gm_sources = [ + "$_gm/3dgm.cpp", "$_gm/aaa.cpp", "$_gm/aaclip.cpp", "$_gm/aarectmodes.cpp", diff --git a/gn/utils.gni b/gn/utils.gni index 01d31364d5..ff8f60a56c 100644 --- a/gn/utils.gni +++ b/gn/utils.gni @@ -22,6 +22,7 @@ skia_utils_sources = [ "$_include/utils/SkRandom.h", "$_include/utils/SkShadowUtils.h", + "$_src/utils/Sk3D.cpp", "$_src/utils/SkBase64.cpp", "$_src/utils/SkBase64.h", "$_src/utils/SkBitSet.h", diff --git a/src/utils/Sk3D.cpp b/src/utils/Sk3D.cpp new file mode 100644 index 0000000000..b1b5d6c0ea --- /dev/null +++ b/src/utils/Sk3D.cpp @@ -0,0 +1,64 @@ +/* + * 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 "Sk3D.h" + +static void set_col(SkMatrix44* m, int col, const SkPoint3& v) { + m->set(0, col, v.fX); + m->set(1, col, v.fY); + m->set(2, col, v.fZ); +} + +static SkPoint3 cross(const SkPoint3& a, const SkPoint3& b) { + return { + a.fY * b.fZ - a.fZ * b.fY, + a.fZ * b.fX - a.fX * b.fZ, + a.fX * b.fY - a.fY * b.fX, + }; +} + +void Sk3LookAt(SkMatrix44* dst, const SkPoint3& eye, const SkPoint3& center, const SkPoint3& up) { + SkPoint3 f = center - eye; + f.normalize(); + SkPoint3 u = up; + u.normalize(); + SkPoint3 s = cross(f, u); + s.normalize(); + u = cross(s, f); + + dst->setIdentity(); + set_col(dst, 0, s); + set_col(dst, 1, u); + set_col(dst, 2, -f); + set_col(dst, 3, eye); + dst->invert(dst); +} + +bool Sk3Perspective(SkMatrix44* dst, float near, float far, float angle) { + SkASSERT(far > near); + + float denomInv = sk_ieee_float_divide(1, far - near); + float halfAngle = angle * 0.5f; + float cot = sk_float_cos(halfAngle) / sk_float_sin(halfAngle); + + dst->setIdentity(); + dst->set(0, 0, cot); + dst->set(1, 1, cot); + dst->set(2, 2, (far + near) * denomInv); + dst->set(2, 3, 2 * far * near * denomInv); + dst->set(3, 2, -1); + return true; +} + +void Sk3MapPts(SkPoint dst[], const SkMatrix44& m4, const SkPoint3 src[], int count) { + for (int i = 0; i < count; ++i) { + SkVector4 v = m4 * SkVector4{ src[i].fX, src[i].fY, src[i].fZ, 1 }; + // clip v; + dst[i] = { v.fData[0] / v.fData[3], v.fData[1] / v.fData[3] }; + } +} + diff --git a/src/utils/Sk3D.h b/src/utils/Sk3D.h new file mode 100644 index 0000000000..46bb5cce80 --- /dev/null +++ b/src/utils/Sk3D.h @@ -0,0 +1,19 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef Sk3D_DEFINED +#define Sk3D_DEFINED + +#include "SkPoint3.h" +#include "SkMatrix44.h" + +void Sk3LookAt(SkMatrix44* dst, const SkPoint3& eye, const SkPoint3& center, const SkPoint3& up); +bool Sk3Perspective(SkMatrix44* dst, float near, float far, float angle); +void Sk3MapPts(SkPoint dst[], const SkMatrix44& m4, const SkPoint3 src[], int count); + +#endif + |