diff --git a/src/assets/stylesheets/room.scss b/src/assets/stylesheets/room.scss
index 8f3cfb7b5ebf1553653649575d03c5e0a215956c..d042519b31409aa888dde3bbe83e69758fb1cb54 100644
--- a/src/assets/stylesheets/room.scss
+++ b/src/assets/stylesheets/room.scss
@@ -17,3 +17,10 @@
   bottom: 20px;
 }
 
+.a-canvas.a-grab-cursor:hover {
+	cursor: none;
+}
+
+.a-canvas.a-grab-cursor:active {
+	cursor: none;
+}
diff --git a/src/components/super-cursor.js b/src/components/super-cursor.js
index d1b28b0f1566d43fe68e40d1fc0d9e0ecc13be65..e498a1acc2ad9b99c9131134bd17560bee1af531 100644
--- a/src/components/super-cursor.js
+++ b/src/components/super-cursor.js
@@ -2,42 +2,55 @@ AFRAME.registerComponent("super-cursor", {
   dependencies: ["raycaster"],
   schema: {
     cursor: { type: "selector" },
-    maxDistance: { type: "number", default: 3 },
-    minDistance: { type: "number", default: 0.5 }
+    camera: { type: "selector" },
+    maxDistance: { default: 3 },
+    minDistance: { default: 0.5 },
+    cursorColorHovered: { default: "#FF0000" },
+    cursorColorUnhovered: { efault: "#FFFFFF" }
   },
 
   init: function() {
     this.isGrabbing = false;
+    this.isInteractable = false;
     this.wasIntersecting = false;
     this.currentDistance = this.data.maxDistance;
     this.currentDistanceMod = 0;
     this.enabled = true;
-    this.isGrabbing = false;
     this.origin = new THREE.Vector3();
     this.direction = new THREE.Vector3();
     this.point = new THREE.Vector3();
-  },
+    this.mousePos = new THREE.Vector2();
+
+    this.data.cursor.setAttribute("material", { color: this.data.cursorColorUnhovered });
 
-  play: function() {
     this.mouseDownListener = this._handleMouseDown.bind(this);
+    this.mouseMoveListener = this._handleMouseMove.bind(this);
     this.mouseUpListener = this._handleMouseUp.bind(this);
     this.wheelListener = this._handleWheel.bind(this);
     this.enterVRListener = this._handleEnterVR.bind(this);
-    this.exitVRListener = this._handleExitVR.bind(this);   
+    this.exitVRListener = this._handleExitVR.bind(this);
+  },
 
+  play: function() {
     document.addEventListener("mousedown", this.mouseDownListener);
+    document.addEventListener("mousemove", this.mouseMoveListener);
     document.addEventListener("mouseup", this.mouseUpListener);
     document.addEventListener("wheel", this.wheelListener);
     window.addEventListener("enter-vr", this.enterVRListener);
     window.addEventListener("exit-vr", this.exitVRListener);
+
+    this._enable();
   },
 
   pause: function() {
     document.removeEventListener("mousedown", this.mouseDownListener);
+    document.removeEventListener("mousemove", this.mouseMoveListener);
     document.removeEventListener("mouseup", this.mouseUpListener);
     document.removeEventListener("wheel", this.wheelListener);
     window.removeEventListener("enter-vr", this.enterVRListener);
     window.removeEventListener("exit-vr", this.exitVRListener);
+
+    this._disable();
   },
 
   tick: function() {
@@ -46,14 +59,21 @@ AFRAME.registerComponent("super-cursor", {
     }
 
     this.isGrabbing = this.data.cursor.components["super-hands"].state.has("grab-start");
-    let isIntersecting = false;
+
+    const camera = this.data.camera.components.camera.camera;
+    const raycaster = this.el.components.raycaster.raycaster;
+    raycaster.setFromCamera(this.mousePos, camera);
+    this.origin = raycaster.ray.origin;
+    this.direction = raycaster.ray.direction;
+    this.el.setAttribute("raycaster", { origin: this.origin, direction: this.direction });
+
+    let intersection = null;
 
     if (!this.isGrabbing) {
       const intersections = this.el.components.raycaster.intersections;
       if (intersections.length > 0 && intersections[0].distance <= this.data.maxDistance) {
-        isIntersecting = true;
-        this.point = intersections[0].point;
-        this.data.cursor.object3D.position.copy(this.point);
+        intersection = intersections[0];
+        this.data.cursor.object3D.position.copy(intersection.point);
         this.currentDistance = intersections[0].distance;
         this.currentDistanceMod = 0;
       } else {
@@ -61,50 +81,69 @@ AFRAME.registerComponent("super-cursor", {
       }
     }
 
-    if (this.isGrabbing || !isIntersecting) {
-      const head = this.el.object3D;
-      head.getWorldPosition(this.origin);
-      head.getWorldDirection(this.direction);
+    if (this.isGrabbing || !intersection) {
       const distance = Math.min(
         Math.max(this.data.minDistance, this.currentDistance - this.currentDistanceMod),
         this.data.maxDistance
       );
       this.currentDistanceMod = this.currentDistance - distance;
-      this.direction.multiplyScalar(-distance);
+      this.direction.multiplyScalar(distance);
       this.point.addVectors(this.origin, this.direction);
       this.data.cursor.object3D.position.copy(this.point);
     }
 
-    if ((this.isGrabbing || isIntersecting) && !this.wasIntersecting) {
+    this.isInteractable = intersection && intersection.object.el.className === "interactable";
+
+    if ((this.isGrabbing || this.isInteractable) && !this.wasIntersecting) {
       this.wasIntersecting = true;
-      this.data.cursor.setAttribute("material", {color: "#00FF00"});
-    } else if (!this.isGrabbing && !isIntersecting && this.wasIntersecting) {
+      this.data.cursor.setAttribute("material", { color: this.data.cursorColorHovered });
+    } else if (!this.isGrabbing && !this.isInteractable && this.wasIntersecting) {
       this.wasIntersecting = false;
-      this.data.cursor.setAttribute("material", {color: "#00EFFF"});
+      this.data.cursor.setAttribute("material", { color: this.data.cursorColorUnhovered });
     }
   },
 
   _handleMouseDown: function(e) {
+    if (this.isInteractable) {
+      const lookControls = this.data.camera.components["look-controls"];
+      lookControls.pause();
+    }
     this.data.cursor.emit("action_grab", {});
   },
 
+  _handleMouseMove: function(e) {
+    this.mousePos.set(e.clientX / window.innerWidth * 2 - 1, -(e.clientY / window.innerHeight) * 2 + 1);
+  },
+
   _handleMouseUp: function(e) {
+    const lookControls = this.data.camera.components["look-controls"];
+    lookControls.play();
     this.data.cursor.emit("action_release", {});
   },
 
   _handleWheel: function(e) {
     if (this.isGrabbing) this.currentDistanceMod += e.deltaY / 10;
-  }, 
+  },
 
   _handleEnterVR: function(e) {
     if (AFRAME.utils.device.checkHeadsetConnected() || AFRAME.utils.device.isMobile()) {
-      this.enabled = false;
-      this.data.cursor.setAttribute("visible", false);
+      this._disable();
     }
   },
 
   _handleExitVR: function(e) {
+    this._enable();
+  },
+
+  _enable: function() {
     this.enabled = true;
     this.data.cursor.setAttribute("visible", true);
+    this.el.setAttribute("raycaster", { enabled: true });
   },
+
+  _disable: function() {
+    this.enabled = false;
+    this.data.cursor.setAttribute("visible", false);
+    this.el.setAttribute("raycaster", { enabled: false });
+  }
 });
diff --git a/src/components/super-spawner.js b/src/components/super-spawner.js
index 42d7c9b48f3067e87f0242aebc15b7ff07332eca..72d24eff785b9eebed42c60e2e4feb21e659468a 100644
--- a/src/components/super-spawner.js
+++ b/src/components/super-spawner.js
@@ -21,7 +21,7 @@ AFRAME.registerComponent("super-spawner", {
   remove: function() {
     for (let entity of this.entities.keys()) {
       const data = this.entities.get(entity);
-      entity.removeEventListener("componentinitialized", data.componentinItializedListener);
+      entity.removeEventListener("componentinitialized", data.componentinInitializedListener);
       entity.removeEventListener("bodyloaded", data.bodyLoadedListener);
     }
 
@@ -34,18 +34,18 @@ AFRAME.registerComponent("super-spawner", {
 
     entity.setAttribute("networked", "template:" + this.data.template);
 
-    const componentinItializedListener = this._handleComponentInitialzed.bind(this, entity);
+    const componentinInitializedListener = this._handleComponentInitialzed.bind(this, entity);
     const bodyLoadedListener = this._handleBodyLoaded.bind(this, entity);
 
     this.entities.set(entity, {
       hand: hand,
       componentInitialized: false, 
       bodyLoaded: false, 
-      componentinItializedListener: componentinItializedListener, 
+      componentinInitializedListener: componentinInitializedListener, 
       bodyLoadedListener: bodyLoadedListener
     });
     
-    entity.addEventListener("componentinitialized", componentinItializedListener);
+    entity.addEventListener("componentinitialized", componentinInitializedListener);
     entity.addEventListener("body-loaded", bodyLoadedListener);
 
     const pos = this.data.useCustomSpawnPosition ? this.data.spawnPosition : this.el.getAttribute("position");
@@ -71,7 +71,7 @@ AFRAME.registerComponent("super-spawner", {
       data.hand.emit("action_grab", { targetEntity: entity });
       entity.emit("grab-start", { hand: data.hand });
 
-      entity.removeEventListener("componentinitialized", data.componentinItializedListener);
+      entity.removeEventListener("componentinitialized", data.componentinInitializedListener);
       entity.removeEventListener("body-loaded", data.bodyLoadedListener);
 
       this.entities.delete(entity);
diff --git a/src/room.html b/src/room.html
index 0bc4d32f480927adc71b3d6fee8f06ed1891a60b..71e58c59ec504ac1bf619db21bc755e910325894 100644
--- a/src/room.html
+++ b/src/room.html
@@ -96,13 +96,12 @@
                 <a-entity
                     gltf-model="#interactable-duck"
                     scale="2 2 2"
-                    class="collidable" 
+                    class="interactable" 
                     super-networked-interactable="counter: #counter; mass: 5;"
                     body="type: dynamic; mass: 5; shape: box;"
                     grabbable
                     stretchable="useWorldPosition: true;"
-                >
-                </a-entity>
+                ></a-entity>
             </template>
 
             <a-mixin id="super-hands"
@@ -123,21 +122,24 @@
         <a-entity 
             gltf-model="#interactable-duck"
             scale="2 2 2"
-            class="collidable" 
-            class="collidable" 
+            class="interactable" 
             super-spawner="template: #interactable-template;" 
             position="2.5 1.2 0" 
             body="mass: 0; type: static; shape: box;"
         ></a-entity>
 
-        <a-sphere
-            id="3d-cursor"
-            material="color: #00EFFF"
-            radius=0.02
-            static-body="shape: sphere;"
-            mixin="super-hands"
-        ></a-sphere>  
-
+        <a-entity
+            id="super-cursor"
+            super-cursor="cursor: #3d-cursor; camera: #player-camera;"
+            raycaster="objects: .collidable, .interactable; far: 10;"
+        >
+            <a-sphere
+                id="3d-cursor"
+                radius=0.02
+                static-body="shape: sphere;"
+                mixin="super-hands"
+            ></a-sphere>  
+        </a-entity>
 
         <!-- Player Rig -->
         <a-entity
@@ -155,14 +157,8 @@
                 camera
                 position="0 1.6 0"
                 personal-space-bubble
-            >
-                <a-entity
-                    id="super-cursor"
-                    super-cursor="cursor: #3d-cursor"
-                    position="0 0 0"
-                    raycaster="objects: .collidable; direction: 0 0 -1;"
-                ></a-entity>
-            </a-entity>
+                look-controls
+            ></a-entity>
 
             <a-entity
                 id="player-left-controller"
@@ -303,8 +299,8 @@
             height="35" 
             width="35" 
             static-body 
-            class="collidable">
-        </a-plane> 
+            class="collidable"
+        ></a-plane> 
     </a-scene>
 
     <div id="ui-root" class="ui"></div>
diff --git a/src/room.js b/src/room.js
index b8e18315139946b4afb258c256f753466ffe79b8..66314fdf8cf77a81540a963a00f061d35d3cde5e 100644
--- a/src/room.js
+++ b/src/room.js
@@ -152,7 +152,6 @@ async function enterScene(mediaStream, enterInVR) {
   }
 
   AFRAME.registerInputActions(inGameActions, "default");
-  document.querySelector("#player-camera").setAttribute("look-controls", "pointerLockEnabled: true;");
 
   scene.setAttribute("networked-scene", {
     adapter: "janus",