From 409bfe48c1a3e4df15b688ff0e2412e3ae400445 Mon Sep 17 00:00:00 2001
From: Greg Fodor <gfodor@gmail.com>
Date: Wed, 26 Sep 2018 01:20:55 +0000
Subject: [PATCH] Add preview camera

---
 src/assets/stylesheets/scene.scss      |  5 +++
 src/components/scene-preview-camera.js | 51 ++++++++++++++++++++++++++
 src/scene.html                         |  2 +
 src/scene.js                           | 12 +++++-
 4 files changed, 69 insertions(+), 1 deletion(-)
 create mode 100644 src/components/scene-preview-camera.js

diff --git a/src/assets/stylesheets/scene.scss b/src/assets/stylesheets/scene.scss
index 44e6591aa..39c9092e8 100644
--- a/src/assets/stylesheets/scene.scss
+++ b/src/assets/stylesheets/scene.scss
@@ -1,2 +1,7 @@
 @import 'shared';
 @import 'loader';
+
+.brightened {
+  filter: saturate(1.1) brightness(1.1) contrast(1.1);
+}
+
diff --git a/src/components/scene-preview-camera.js b/src/components/scene-preview-camera.js
new file mode 100644
index 000000000..17024305c
--- /dev/null
+++ b/src/components/scene-preview-camera.js
@@ -0,0 +1,51 @@
+/**
+ * Nicely pans the camera for previewing a scene. There's some weirdness with this right now
+ * since it ends up panning in a direction dependent upon the start camera orientation,
+ * but it's good enough for now.
+ */
+function lerp(start, end, t) {
+  return (1 - t) * start + t * end;
+}
+
+const DURATION = 90.0;
+
+AFRAME.registerComponent("scene-preview-camera", {
+  init: function() {
+    this.startPoint = this.el.object3D.position.clone();
+    this.startRotation = new THREE.Quaternion();
+    this.startRotation.setFromEuler(this.el.object3D.rotation);
+
+    this.targetPoint = new THREE.Vector3(1, 0.5, -0.5);
+    this.targetPoint.applyMatrix4(this.el.object3D.matrix);
+    this.targetPoint.add(new THREE.Vector3(0, 0, -2));
+
+    const targetRotDelta = new THREE.Euler(-0.15, 0.0, 0.15);
+    this.targetRotation = new THREE.Quaternion();
+    this.targetRotation.setFromEuler(targetRotDelta);
+    this.targetRotation.premultiply(this.startRotation);
+
+    this.startTime = new Date().getTime();
+    this.backwards = false;
+  },
+
+  tick: function() {
+    let t = (new Date().getTime() - this.startTime) / (1000.0 * DURATION);
+    t = (Math.sin(t * Math.PI * 2) + 1.0) / 2.0;
+
+    const from = this.backwards ? this.targetPoint : this.startPoint;
+    const to = this.backwards ? this.startPoint : this.targetPoint;
+    const fromRot = this.backwards ? this.targetRotation : this.startRotation;
+    const toRot = this.backwards ? this.startRotation : this.targetRotation;
+    const newRot = new THREE.Quaternion();
+
+    THREE.Quaternion.slerp(fromRot, toRot, newRot, t);
+
+    this.el.object3D.position.set(lerp(from.x, to.x, t), lerp(from.y, to.y, t), lerp(from.z, to.z, t));
+    this.el.object3D.rotation.setFromQuaternion(newRot);
+
+    if (t >= 1.0) {
+      this.backwards = !this.backwards;
+      this.startTime = new Date().getTime();
+    }
+  }
+});
diff --git a/src/scene.html b/src/scene.html
index 6a4ebaa0f..a492ba13d 100644
--- a/src/scene.html
+++ b/src/scene.html
@@ -22,6 +22,8 @@
             id="scene-root"
             static-body="shape: none;"
         ></a-entity>
+
+        <a-camera id="camera" fov="80" look-controls="enabled: false" wasd-controls="enabled: false"></a-camera>
     </a-scene>
 
     <div id="ui-root"></div>
diff --git a/src/scene.js b/src/scene.js
index 3211cad81..8c77d2364 100644
--- a/src/scene.js
+++ b/src/scene.js
@@ -26,6 +26,7 @@ import "./components/media-loader";
 import "./components/point-light";
 import "./components/quack";
 import "./components/scene-shadow";
+import "./components/scene-preview-camera";
 import "./components/skybox";
 import "./components/spawn-controller";
 import "./components/spot-light";
@@ -86,6 +87,7 @@ function mountUI(scene, props = {}) {
 const onReady = async () => {
   const scene = document.querySelector("a-scene");
   window.APP.scene = scene;
+  document.querySelector("canvas").classList.add("brightened");
 
   const sceneId = qs.get("scene_id") || document.location.pathname.substring(1).split("/")[0];
   console.log(`Scene ID: ${sceneId}`);
@@ -101,9 +103,18 @@ const onReady = async () => {
 
   const sceneRoot = document.querySelector("#scene-root");
   const sceneModelEntity = document.createElement("a-entity");
+  const gltfEl = document.createElement("a-entity");
+  const camera = document.getElementById("camera");
 
   sceneModelEntity.addEventListener("scene-loaded", () => {
     remountUI({ sceneLoaded: true });
+    const previewCamera = gltfEl.object3D.getObjectByName("scene-preview-camera");
+
+    if (previewCamera) {
+      camera.object3D.applyMatrix(previewCamera.matrixWorld);
+    }
+
+    camera.setAttribute("scene-preview-camera", "");
   });
 
   sceneRoot.appendChild(sceneModelEntity);
@@ -114,7 +125,6 @@ const onReady = async () => {
   const modelUrl = sceneInfo.model_url;
   console.log(`Scene Model URL: ${modelUrl}`);
 
-  const gltfEl = document.createElement("a-entity");
   gltfEl.setAttribute("gltf-model-plus", { src: modelUrl, useCache: false, inflate: true });
   gltfEl.addEventListener("model-loaded", () => sceneModelEntity.emit("scene-loaded"));
   sceneModelEntity.appendChild(gltfEl);
-- 
GitLab