diff --git a/src/components/auto-box-collider.js b/src/components/auto-box-collider.js
index 139bb57fa94838ab79345aa387f13c07a305a837..2d3d2f53bbbd4cbe18a3f9fd1f19603badd8f907 100644
--- a/src/components/auto-box-collider.js
+++ b/src/components/auto-box-collider.js
@@ -11,8 +11,8 @@ AFRAME.registerComponent("auto-box-collider", {
 
   onLoaded() {
     this.el.removeEventListener("model-loaded", this.onLoaded);
-    const rotation = this.el.getAttribute("rotation");
-    this.el.setAttribute("rotation", { x: 0, y: 0, z: 0 });
+    const rotation = this.el.object3D.rotation.clone();
+    this.el.object3D.rotation.set(0, 0, 0);
     const { min, max } = new THREE.Box3().setFromObject(this.el.object3DMap.mesh);
     const halfExtents = new THREE.Vector3()
       .addVectors(min.clone().negate(), max)
@@ -25,7 +25,7 @@ AFRAME.registerComponent("auto-box-collider", {
     if (this.data.resize) {
       this.resize(min, max);
     }
-    this.el.setAttribute("rotation", rotation);
+    this.el.object3D.rotation.copy(rotation);
     this.el.removeAttribute("auto-box-collider");
   },
 
diff --git a/src/components/auto-scale-cannon-physics-body.js b/src/components/auto-scale-cannon-physics-body.js
index f5ae24b5bb906f623eb1ba52111583884d64ff87..e3ab60400e00f253e670736c2f94c44e301f4658 100644
--- a/src/components/auto-scale-cannon-physics-body.js
+++ b/src/components/auto-scale-cannon-physics-body.js
@@ -1,39 +1,27 @@
-function almostEquals(u, v, epsilon) {
+function almostEquals(epsilon, u, v) {
   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) {
-  let timer = null;
-  return function() {
-    const args = arguments;
-    clearTimeout(timer);
-    timer = setTimeout(() => {
-      fn.apply(this, args);
-    }, delay);
-  };
-}
-
-const autoScaleCannonPhysicsBody = {
+AFRAME.registerComponent("auto-scale-cannon-physics-body", {
   dependencies: ["body"],
 
   init() {
     this.body = this.el.components["body"];
     this.prevScale = this.el.object3D.scale.clone();
-    this.updateCannonScale = debounce(this.updateCannonScale.bind(this), 100);
+    this.nextUpdateTime = -1;
   },
 
-  tick() {
+  tick(t) {
     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();
+    if (!almostEquals(0.001, scale, this.prevScale)) {
       this.prevScale.copy(scale);
+      this.nextUpdateTime = t + 100;
     }
-  },
 
-  updateCannonScale() {
-    this.body.updateCannonScale();
+    if (this.nextUpdateTime > 0 && t > this.nextUpdateTime) {
+      this.nextUpdateTime = -1;
+      this.body.updateCannonScale();
+    }
   }
-};
-
-AFRAME.registerComponent("auto-scale-cannon-physics-body", autoScaleCannonPhysicsBody);
+});
diff --git a/src/components/offset-relative-to.js b/src/components/offset-relative-to.js
index 3cd45b942ed4573ee9b588a467de456af801f62f..82a90717ba22137ac38e045a893804f60a183d3b 100644
--- a/src/components/offset-relative-to.js
+++ b/src/components/offset-relative-to.js
@@ -12,16 +12,38 @@ AFRAME.registerComponent("offset-relative-to", {
     },
     on: {
       type: "string"
+    },
+    selfDestruct: {
+      default: false
     }
   },
   init() {
-    this.updateOffset();
-    this.el.sceneEl.addEventListener(this.data.on, this.updateOffset.bind(this));
+    this.updateOffset = this.updateOffset.bind(this);
+    if (this.data.on) {
+      this.el.sceneEl.addEventListener(this.data.on, this.updateOffset);
+    } else {
+      this.updateOffset();
+    }
   },
-  updateOffset() {
-    const offsetVector = new THREE.Vector3().copy(this.data.offset);
-    this.data.target.object3D.localToWorld(offsetVector);
-    this.el.setAttribute("position", offsetVector);
-    this.data.target.object3D.getWorldQuaternion(this.el.object3D.quaternion);
-  }
+
+  updateOffset: (function() {
+    const offsetVector = new THREE.Vector3();
+    return function() {
+      const obj = this.el.object3D;
+      const target = this.data.target.object3D;
+      offsetVector.copy(this.data.offset);
+      target.localToWorld(offsetVector);
+      if (obj.parent) {
+        obj.parent.worldToLocal(offsetVector);
+      }
+      obj.position.copy(offsetVector);
+      target.getWorldQuaternion(obj.quaternion);
+      if (this.data.selfDestruct) {
+        if (this.data.on) {
+          this.el.sceneEl.removeEventListener(this.data.on, this.updateOffset);
+        }
+        this.el.removeAttribute("offset-relative-to");
+      }
+    };
+  })()
 });
diff --git a/src/components/position-at-box-border.js b/src/components/position-at-box-border.js
deleted file mode 100644
index 273bd1379b35c86edf64571058cc5fd7ec5c5cc2..0000000000000000000000000000000000000000
--- a/src/components/position-at-box-border.js
+++ /dev/null
@@ -1,64 +0,0 @@
-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];
-
-AFRAME.registerComponent("position-at-box-border", {
-  schema: {
-    target: { type: "string" }
-  },
-
-  init() {
-    this.position = new THREE.Vector3();
-    this.prevScale = new THREE.Vector3(-1, -1, -1);
-    this.cam = document.querySelector("[camera]").object3D;
-    this.camWorldPos = new THREE.Vector3();
-  },
-
-  tick() {
-    if (!this.shape) {
-      this.shape = this.el.components["shape"];
-      if (!this.shape) return;
-    }
-    if (!this.target) {
-      this.target = this.el.querySelector(this.data.target).object3D;
-      if (!this.target) return;
-    }
-    const halfExtents = this.shape.data.halfExtents;
-    const halfExtentDirs = [halfExtents.x, halfExtents.x, halfExtents.z, halfExtents.z];
-    this.cam.getWorldPosition(this.camWorldPos);
-
-    let minSquareDistance = Infinity;
-    const targetInfo = {
-      dir: dirs[0],
-      halfExtent: halfExtentDirs[0],
-      rotation: rotations[0]
-    };
-
-    for (let i = 0; i < dirs.length; i++) {
-      const dir = dirs[i];
-      const pointOnBoxFace = dir.clone().multiplyScalar(halfExtentDirs[i]);
-      this.el.object3D.localToWorld(pointOnBoxFace);
-      const squareDistance = pointOnBoxFace.distanceToSquared(this.camWorldPos);
-      if (squareDistance < minSquareDistance) {
-        minSquareDistance = squareDistance;
-        targetInfo.dir = dir;
-        targetInfo.halfExtent = halfExtentDirs[i];
-        targetInfo.rotation = rotations[i];
-      }
-    }
-
-    this.target.position.copy(
-      targetInfo.dir
-        .clone()
-        .multiplyScalar(targetInfo.halfExtent)
-        .add(this.shape.data.offset)
-    );
-    this.target.rotation.set(0, targetInfo.rotation, 0);
-  }
-});
diff --git a/src/components/position-at-box-shape-border.js b/src/components/position-at-box-shape-border.js
new file mode 100644
index 0000000000000000000000000000000000000000..f85d744a9f532290dccc0dfc799e0959831e4d6c
--- /dev/null
+++ b/src/components/position-at-box-shape-border.js
@@ -0,0 +1,65 @@
+const PI = Math.PI;
+const HALF_PI = PI / 2;
+const THREE_HALF_PI = 3 * PI / 2;
+const rotations = [THREE_HALF_PI, HALF_PI, 0, PI];
+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];
+
+AFRAME.registerComponent("position-at-box-shape-border", {
+  schema: {
+    target: { type: "string" }
+  },
+
+  init() {
+    this.cam = this.el.sceneEl.camera.el.object3D;
+  },
+
+  tick: (function() {
+    const camWorldPos = new THREE.Vector3();
+    const targetPosition = new THREE.Vector3();
+    const pointOnBoxFace = new THREE.Vector3();
+    return function() {
+      if (!this.shape) {
+        this.shape = this.el.components["shape"];
+        if (!this.shape) return;
+      }
+      if (!this.target) {
+        this.target = this.el.querySelector(this.data.target).object3D;
+        if (!this.target) return;
+      }
+      const halfExtents = this.shape.data.halfExtents;
+      const halfExtentDirs = ["x", "x", "z", "z"];
+      this.cam.getWorldPosition(camWorldPos);
+
+      let minSquareDistance = Infinity;
+      let targetDir = dirs[0];
+      let targetHalfExtent = halfExtents[halfExtentDirs[0]];
+      let targetRotation = rotations[0];
+
+      for (let i = 0; i < dirs.length; i++) {
+        const dir = dirs[i];
+        const halfExtent = halfExtents[halfExtentDirs[i]];
+        pointOnBoxFace.copy(dir).multiplyScalar(halfExtent);
+        this.el.object3D.localToWorld(pointOnBoxFace);
+        const squareDistance = pointOnBoxFace.distanceToSquared(camWorldPos);
+        if (squareDistance < minSquareDistance) {
+          minSquareDistance = squareDistance;
+          targetDir = dir;
+          targetHalfExtent = halfExtent;
+          targetRotation = rotations[i];
+        }
+      }
+
+      this.target.position.copy(
+        targetPosition
+          .copy(targetDir)
+          .multiplyScalar(targetHalfExtent)
+          .add(this.shape.data.offset)
+      );
+      this.target.rotation.set(0, targetRotation, 0);
+    };
+  })()
+});
diff --git a/src/components/reposition-relative-to-target.js b/src/components/reposition-relative-to-target.js
deleted file mode 100644
index 760c48cac4d591827049d6c11a0d4bcd410b9ed0..0000000000000000000000000000000000000000
--- a/src/components/reposition-relative-to-target.js
+++ /dev/null
@@ -1,28 +0,0 @@
-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/hub.html b/src/hub.html
index 4f49ab735d4b3f2ab6ef92450a3a994ab8cbd767..3d1eb594544eefa98ad90dbb0ce6b2a4566b1664 100644
--- a/src/hub.html
+++ b/src/hub.html
@@ -182,7 +182,7 @@
                     hoverable
                     sticky-object="autoLockOnRelease: true; autoLockOnLoad: true;"
                     auto-box-collider
-                    position-at-box-border="target:.delete-button"
+                    position-at-box-shape-border="target:.delete-button"
                     auto-scale-cannon-physics-body
                 >
                     <a-entity class="delete-button" visible-while-frozen scale="0.08 0.08 0.08">
diff --git a/src/hub.js b/src/hub.js
index 9f48626062c6047b6f187dcb31b1fb42ff53c8d8..5ff26a9e99466432ba9267c84a9d2631fa6e2ade 100644
--- a/src/hub.js
+++ b/src/hub.js
@@ -65,14 +65,13 @@ import "./components/scene-shadow";
 import "./components/avatar-replay";
 import "./components/image-plus";
 import "./components/auto-box-collider";
-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-box-border";
+import "./components/position-at-box-shape-border";
 
 import ReactDOM from "react-dom";
 import React from "react";
@@ -308,10 +307,11 @@ const onReady = async () => {
       if (url.endsWith(".gltf") || url.endsWith(".glb")) {
         const model = document.createElement("a-entity");
         model.id = "interactable-model-" + Date.now();
-        model.setAttribute("reposition-relative-to-target", {
+        model.setAttribute("offset-relative-to", {
           on: "model-loaded",
           target: "#player-camera",
-          offset: offset
+          offset: offset,
+          selfDestruct: true
         });
         model.setAttribute("gltf-model-plus", "src", url);
         model.setAttribute("auto-box-collider", { resize: true });
diff --git a/src/vendor/GLTFLoader.js b/src/vendor/GLTFLoader.js
index 152ce341db5d3a52ef6cbd756eb4552bab7e982a..1df68673f4d773200f36899bba60be7b7c308a21 100644
--- a/src/vendor/GLTFLoader.js
+++ b/src/vendor/GLTFLoader.js
@@ -16,9 +16,7 @@ async function toFarsparkURL(url){
 			"Content-Type": "application/json"
 		},
 		body: JSON.stringify({
-			media: {
-				url: url
-			}
+			media: {url}
 		})
 	}).then(r => r.json());
 	return mediaJson.images.raw;
@@ -1817,11 +1815,12 @@ THREE.GLTFLoader = ( function () {
 		var sourceURI = source.uri;
 		var isObjectURL = false;
 
-		if ( source.bufferView !== undefined ) {
+    var hasBufferView = source.bufferView !== undefined;
+		if ( hasBufferView ) {
 
 			// Load binary image data from bufferView, if provided.
 
-			sourceURI = parser.getDependency( 'bufferView', source.bufferView ).then( function ( bufferView ) {
+			sourceURI = await parser.getDependency( 'bufferView', source.bufferView ).then( function ( bufferView ) {
 
 				isObjectURL = true;
 				var blob = new Blob( [ bufferView ], { type: source.mimeType } );
@@ -1832,7 +1831,10 @@ THREE.GLTFLoader = ( function () {
 
 		}
 
-		var farsparkURL = await toFarsparkURL(resolveURL(sourceURI, options.path));
+    var urlToLoad = resolveURL(sourceURI, options.path);
+    if (!hasBufferView){
+      urlToLoad = await toFarsparkURL(urlToLoad);
+    }
 
 		return Promise.resolve( sourceURI ).then( function ( sourceURI ) {
 
@@ -1842,7 +1844,7 @@ THREE.GLTFLoader = ( function () {
 
 			return new Promise( function ( resolve, reject ) {
 
-				loader.load( farsparkURL, resolve, undefined, reject );
+				loader.load( urlToLoad, resolve, undefined, reject );
 
 			} );