diff --git a/src/components/auto-box-collider.js b/src/components/auto-box-collider.js
index 9930dc0f2957000603c512d48439869db663c601..e6a78c6b086b85086eb8af3fb55294b707cf1a1f 100644
--- a/src/components/auto-box-collider.js
+++ b/src/components/auto-box-collider.js
@@ -1,41 +1,43 @@
 AFRAME.registerComponent("auto-box-collider", {
   schema: {
-    setInitialScale: { default: false }
+    resize: { default: false },
+    resizeLength: { default: 0.5 }
   },
+
   init() {
     this.onLoaded = this.onLoaded.bind(this);
     this.el.addEventListener("model-loaded", this.onLoaded);
-    window.autobox = this;
+    window.auto = this;
   },
+
   onLoaded() {
     this.el.removeEventListener("model-loaded", this.onLoaded);
-    const initialRotation = this.el.object3D.rotation.clone();
-    const initialScale = this.el.object3D.scale.clone();
-    const { min, max } = new THREE.Box3().setFromObject(this.el.object3DMap.mesh);
+    const rotation = this.el.getAttribute("rotation");
     this.el.setAttribute("rotation", { x: 0, y: 0, z: 0 });
-    let halfExtents = new THREE.Vector3().addVectors(min.negate(), max).multiplyScalar(0.5);
+    const { min, max } = new THREE.Box3().setFromObject(this.el.object3DMap.mesh);
+    let halfExtents = new THREE.Vector3()
+      .addVectors(min.clone().negate(), max)
+      .multiplyScalar(0.5 / this.el.object3D.scale.x);
     this.el.setAttribute("shape", {
       shape: "box",
-      halfExtents: halfExtents.multiplyScalar(1 / initialScale.x),
+      halfExtents: halfExtents,
       offset: new THREE.Vector3(0, halfExtents.y, 0)
     });
-    if (this.data.setInitialScale) {
-      this.setInitialScale();
+    if (this.data.resize) {
+      this.resize(min, max);
     }
-    this.el.setAttribute("rotation", initialRotation);
+    this.el.setAttribute("rotation", rotation);
+    this.el.removeAttribute("auto-box-collider");
   },
-  // Adjust the scale such that the object fits within a box whose longest component axis is lengthOfLongestComponent meters.
-  // In other words, a tall model will be scaled down to be only half a meter tall, a wide model will be scaled down to be only
-  // half a meter wide, a long model will be scaled down to be only half a meter long.
-  setInitialScale() {
-    const worldBox = new THREE.Box3().setFromObject(this.el.object3DMap.mesh);
-    const dX = Math.abs(worldBox.max.x - worldBox.min.x);
-    const dY = Math.abs(worldBox.max.y - worldBox.min.y);
-    const dZ = Math.abs(worldBox.max.z - worldBox.min.z);
-    const max = Math.max(dX, dY, dZ);
+
+  // Adjust the scale such that the object fits within a box of a specified size.
+  resize(min, max) {
+    const dX = Math.abs(max.x - min.x);
+    const dY = Math.abs(max.y - min.y);
+    const dZ = Math.abs(max.z - min.z);
+    const lengthOfLongestComponent = Math.max(dX, dY, dZ);
+    const correctiveFactor = this.data.resizeLength / lengthOfLongestComponent;
     const scale = this.el.object3D.scale;
-    const lengthOfLongestComponent = 0.5;
-    const correctiveFactor = lengthOfLongestComponent / max;
     this.el.setAttribute("scale", {
       x: scale.x * correctiveFactor,
       y: scale.y * correctiveFactor,
diff --git a/src/components/auto-scale-cannon-physics-body.js b/src/components/auto-scale-cannon-physics-body.js
index 578ad1123de86806af071f6bb48afd7e97cc27a6..f5ae24b5bb906f623eb1ba52111583884d64ff87 100644
--- a/src/components/auto-scale-cannon-physics-body.js
+++ b/src/components/auto-scale-cannon-physics-body.js
@@ -1,5 +1,5 @@
-function almostEquals(u, v, eps) {
-  return Math.abs(u.x - v.x) < eps && Math.abs(u.y - v.y) < eps && Math.abs(u.z - v.z) < eps;
+function almostEquals(u, v, epsilon) {
+  return Math.abs(u.x - v.x) < epsilon && Math.abs(u.y - v.y) < epsilon && Math.abs(u.z - v.z) < epsilon;
 }
 
 function debounce(fn, delay) {
@@ -13,25 +13,27 @@ function debounce(fn, delay) {
   };
 }
 
-AFRAME.registerComponent("auto-scale-cannon-physics-body", {
+const autoScaleCannonPhysicsBody = {
   dependencies: ["body"],
 
-  init: function() {
+  init() {
     this.body = this.el.components["body"];
     this.prevScale = this.el.object3D.scale.clone();
-    this.updateCannonScale = debounce(this.updateCannonScale.bind(this), 200);
+    this.updateCannonScale = debounce(this.updateCannonScale.bind(this), 100);
   },
 
-  tick: function() {
+  tick() {
     const scale = this.el.object3D.scale;
+    // Note: This only checks if the LOCAL scale of the object3D changes.
     if (!almostEquals(scale, this.prevScale, 0.001)) {
       this.updateCannonScale();
       this.prevScale.copy(scale);
     }
   },
 
-  updateCannonScale: function() {
+  updateCannonScale() {
     this.body.updateCannonScale();
-    console.log("updating?");
   }
-});
+};
+
+AFRAME.registerComponent("auto-scale-cannon-physics-body", autoScaleCannonPhysicsBody);
diff --git a/src/components/position-at-bounding-radius.js b/src/components/position-at-box-border.js
similarity index 60%
rename from src/components/position-at-bounding-radius.js
rename to src/components/position-at-box-border.js
index 96d3aa9486d731316a42fa1527553645e217ecd8..8485b496a757d2fb486cff8a2015ead31629332f 100644
--- a/src/components/position-at-bounding-radius.js
+++ b/src/components/position-at-box-border.js
@@ -1,55 +1,43 @@
-const PI_HALF = Math.PI / 2;
+const PI = Math.PI;
+const PI_HALF = PI / 2;
+const THREE_PI_HALF = 3 * PI / 2;
 const right = new THREE.Vector3(1, 0, 0);
 const forward = new THREE.Vector3(0, 0, 1);
 const left = new THREE.Vector3(-1, 0, 0);
 const back = new THREE.Vector3(0, 0, -1);
+const dirs = [left, right, forward, back];
+const rotations = [THREE_PI_HALF, PI_HALF, 0, PI];
 function almostEquals(u, v, eps) {
   return Math.abs(u.x - v.x) < eps && Math.abs(u.y - v.y) < eps && Math.abs(u.z - v.z) < eps;
 }
 
 AFRAME.registerComponent("position-at-box-border", {
-  dependencies: ["shape"],
   schema: {
     target: { type: "string" }
   },
 
   init() {
-    window.p = this;
-    this.body = this.el.components["shape"];
     this.position = new THREE.Vector3();
     this.prevScale = new THREE.Vector3(-1, -1, -1);
-    this.rotation = this.el.object3D.rotation.clone();
-    this.el.addEventListener("model-loaded", () => {
-      this.modelLoaded = true;
-      this.target = this.el.querySelector(this.data.target).object3D;
-    });
-    this.worldPos = new THREE.Vector3();
     this.cam = document.querySelector("[camera]").object3D;
     this.camWorldPos = new THREE.Vector3();
   },
 
   tick() {
-    if (!this.modelLoaded) return;
+    if (!this.shape) {
+      this.shape = this.el.components["shape"];
+      if (!this.shape) return;
+    }
     if (!this.target) {
-      console.log("uh oh");
       this.target = this.el.querySelector(this.data.target).object3D;
+      if (!this.target) return;
     }
-
-    const scale = this.el.object3D.scale;
-    if (!almostEquals(scale, this.prevScale, 0.001)) {
-      this.target.scale.set(1 / (2 * scale.x), 1 / (2 * scale.y), 1 / (2 * scale.z));
-      this.prevScale.copy(scale);
-    }
-
-    this.el.object3D.getWorldPosition(this.worldPos);
+    const halfExtents = this.shape.data.halfExtents;
+    const halfExtentDirs = [halfExtents.x, halfExtents.x, halfExtents.z, halfExtents.z];
     this.cam.getWorldPosition(this.camWorldPos);
 
-    const halfExtents = this.body.data.halfExtents;
-    const dirs = [left, right, forward, back];
-    const rotations = [3 * PI_HALF, PI_HALF, 0, 2 * PI_HALF];
-    const halfExtentDirs = [halfExtents.x, halfExtents.x, halfExtents.z, halfExtents.z];
     let minDistance = Infinity;
-    let minDir = left;
+    let minDir = dirs[0];
     let minHalfExtentDir = halfExtentDirs[0];
     let minRotation = rotations[0];
     for (let i = 0; i < dirs.length; i++) {
@@ -64,14 +52,13 @@ AFRAME.registerComponent("position-at-box-border", {
         minRotation = rotations[i];
       }
     }
+
     this.target.position.copy(
       minDir
         .clone()
         .multiplyScalar(minHalfExtentDir)
-        .add(this.body.data.offset)
+        .add(this.shape.data.offset)
     );
-    // this.lookTarget = minDir.clone().multiplyScalar(30000);
-    // this.el.object3D.localToWorld(this.lookTarget);
     this.target.rotation.set(0, minRotation, 0);
   }
 });
diff --git a/src/components/reposition-relative-to-target.js b/src/components/reposition-relative-to-target.js
new file mode 100644
index 0000000000000000000000000000000000000000..760c48cac4d591827049d6c11a0d4bcd410b9ed0
--- /dev/null
+++ b/src/components/reposition-relative-to-target.js
@@ -0,0 +1,28 @@
+AFRAME.registerComponent("reposition-relative-to-target", {
+  schema: {
+    on: { type: "string" },
+    target: { type: "selector" },
+    offset: { type: "vec3" }
+  },
+
+  init() {
+    this.reposition = this.reposition.bind(this);
+    if (this.data.on) {
+      this.el.addEventListener(this.data.on, this.reposition);
+    } else {
+      this.reposition();
+    }
+  },
+
+  reposition() {
+    const obj = this.el.object3D;
+    const target = this.data.target.object3D;
+    const position = new THREE.Vector3().copy(this.data.offset);
+    target.localToWorld(position);
+    obj.position.copy(position);
+    target.getWorldQuaternion(obj.quaternion);
+
+    this.el.removeEventListener(this.data.on, this.reposition);
+    this.el.removeAttribute("reposition-relative-to-target");
+  }
+});
diff --git a/src/components/spawn-in-front-of-object.js b/src/components/spawn-in-front-of-object.js
deleted file mode 100644
index 0a5d0c0d6a63aab2e845acdae548fde881d317cb..0000000000000000000000000000000000000000
--- a/src/components/spawn-in-front-of-object.js
+++ /dev/null
@@ -1,14 +0,0 @@
-AFRAME.registerComponent("spawn-in-front-of-object", {
-  schema: {},
-  init() {
-    this.onLoaded = this.onLoaded.bind(this);
-    this.el.addEventListener("model-loaded", this.onLoaded);
-  },
-  onLoaded() {
-    const billboardTarget = document.querySelector("#player-camera").object3D;
-    const worldPos = new THREE.Vector3().copy({ x: 0, y: 0, z: -1.5 });
-    billboardTarget.localToWorld(worldPos);
-    this.el.object3D.position.copy(worldPos);
-    billboardTarget.getWorldQuaternion(this.el.object3D.quaternion);
-  }
-});
diff --git a/src/hub.html b/src/hub.html
index 2c473fd18bc8a054e18eb14e2e504966218c5de8..221240c6b8863ece4f137e26d7d6d38a6d991ea7 100644
--- a/src/hub.html
+++ b/src/hub.html
@@ -182,11 +182,11 @@
                     stretchable="useWorldPosition: true; usePhysics: never"
                     hoverable
                     sticky-object="autoLockOnRelease: true; autoLockOnLoad: true;"
-                    auto-scale-cannon-physics-body
                     auto-box-collider
                     position-at-box-border="target:.deleteButton"
+                    auto-scale-cannon-physics-body
                 >
-                    <a-entity class="deleteButton" visible-while-frozen>
+                    <a-entity class="deleteButton" visible-while-frozen scale="0.08 0.08 0.08">
                         <a-entity mixin="rounded-text-button" remove-object-button position="0 0 0"> </a-entity>
                         <a-entity text=" value:Delete; width:2.5; align:center;" text-raycast-hack position="0 0 0.01"></a-entity>
                     </a-entity>
@@ -361,7 +361,6 @@
                     collisionEntities: [nav-mesh];
                     drawIncrementally: true;
                     incrementalDrawMs: 600;
-                    curveShootingSpeed: 5;
                     hitOpacity: 0.3;
                     missOpacity: 0.2;"
                 haptic-feedback
diff --git a/src/hub.js b/src/hub.js
index c0d0687b0606a69ad975ff3d34cf165c95b61b33..9dfac3c7d01615318b31ea1a075f7d814c2f9123 100644
--- a/src/hub.js
+++ b/src/hub.js
@@ -65,14 +65,14 @@ import "./components/scene-shadow";
 import "./components/avatar-replay";
 import "./components/image-plus";
 import "./components/auto-box-collider";
-import "./components/spawn-in-front-of-object";
+import "./components/reposition-relative-to-target";
 import "./components/pinch-to-move";
 import "./components/look-on-mobile";
 import "./components/pitch-yaw-rotator";
 import "./components/input-configurator";
 import "./components/sticky-object";
 import "./components/auto-scale-cannon-physics-body";
-import "./components/position-at-bounding-radius";
+import "./components/position-at-box-border";
 
 import ReactDOM from "react-dom";
 import React from "react";
@@ -302,15 +302,19 @@ const onReady = async () => {
       NAF.connection.entities.completeSync(ev.detail.clientId);
     });
 
+    const offset = { x: 0, y: 0, z: -1.5 };
     const addMedia = mediaUrl => {
       const scene = AFRAME.scenes[0];
       if (mediaUrl.endsWith(".gltf") || mediaUrl.endsWith(".glb")) {
         const model = document.createElement("a-entity");
         model.id = "interactable-model-" + Date.now();
-        model.setAttribute("position", { x: 0, y: 2, z: 1 });
-        model.setAttribute("spawn-in-front-of-object", "");
+        model.setAttribute("reposition-relative-to-target", {
+          on: "model-loaded",
+          target: "#player-camera",
+          offset: offset
+        });
         model.setAttribute("gltf-model-plus", "src", mediaUrl);
-        model.setAttribute("auto-box-collider", "setInitialScale", true);
+        model.setAttribute("auto-box-collider", { resize: true });
         model.setAttribute("networked", { template: "#interactable-model" });
         scene.appendChild(model);
       } else {
diff --git a/yarn.lock b/yarn.lock
index 22aa09c6bab961a20f5d21463c5f60fbafb269cf..7e9cfcb55b2e8b5622d3ec4af2cf62a56cc678d0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -184,11 +184,11 @@ aframe-physics-extras@^0.1.3:
 
 "aframe-physics-system@https://github.com/mozillareality/aframe-physics-system#monitor-scale-on-body":
   version "3.1.2"
-  resolved "https://github.com/mozillareality/aframe-physics-system#4c83e7bdd666b054e31e229576404bbc069595b6"
+  resolved "https://github.com/mozillareality/aframe-physics-system#7cd2bf83d125194cc76aa48bce700884de113215"
   dependencies:
     browserify "^14.3.0"
     budo "^10.0.3"
-    cannon "https://github.com/mozillareality/cannon.js#resize-cylinder"
+    cannon "github:donmccurdy/cannon.js#v0.6.2-dev1"
     three-to-cannon "^1.3.0"
     webworkify "^1.4.0"
 
@@ -1748,9 +1748,9 @@ caniuse-lite@^1.0.30000792:
   version "1.0.30000810"
   resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000810.tgz#47585fffce0e9f3593a6feea4673b945424351d9"
 
-"cannon@https://github.com/mozillareality/cannon.js#resize-cylinder":
+"cannon@github:donmccurdy/cannon.js#v0.6.2-dev1":
   version "0.6.2"
-  resolved "https://github.com/mozillareality/cannon.js#b401ccbec3b9996e31d6ad060028065a432fcff7"
+  resolved "https://codeload.github.com/donmccurdy/cannon.js/tar.gz/022e8ba53fa83abf0ad8a0e4fd08623123838a17"
 
 caseless@~0.11.0:
   version "0.11.0"