aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Mike Reed <reed@google.com>2018-05-30 16:02:48 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-05-30 20:36:08 +0000
commit27714a026d9178ff7834b87677cbd10bf5150dc7 (patch)
tree424afe8d98ea19b18d6a3833950bcae9c80fa34c
parenta15cedbc26fee1ba23465aaa0dc46dd0e69996cc (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.cpp147
-rw-r--r--gn/gm.gni1
-rw-r--r--gn/utils.gni1
-rw-r--r--src/utils/Sk3D.cpp64
-rw-r--r--src/utils/Sk3D.h19
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;)
diff --git a/gn/gm.gni b/gn/gm.gni
index d978e9d216..a4074c29ec 100644
--- a/gn/gm.gni
+++ b/gn/gm.gni
@@ -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
+