From b1391495b02b5879a93b79415332cc1678f8ee85 Mon Sep 17 00:00:00 2001
From: Robert Long <robert@robertlong.me>
Date: Mon, 30 Oct 2017 18:28:47 -0700
Subject: [PATCH] Split personal space bubble out into two components. Perf
 improvements.

---
 public/index.html                    |  6 +-
 src/systems/personal-space-bubble.js | 94 +++++++++++++++++-----------
 2 files changed, 60 insertions(+), 40 deletions(-)

diff --git a/public/index.html b/public/index.html
index 718096f24..e2b306f7f 100644
--- a/public/index.html
+++ b/public/index.html
@@ -35,12 +35,12 @@
                     matcolor-audio-feedback="objectName: DodecAvatar_Head_0"
                     scale-audio-feedback
                     avatar-customization
-                    personal-space-bubble
+                    personal-space-invader
                 ></a-entity>
             </script>
 
             <script id="hand-template" type="text/html">
-                <a-box class="hand" personal-space-bubble scale="0.2 0.1 0.3"></a-box>
+                <a-box class="hand" personal-space-invader scale="0.2 0.1 0.3"></a-box>
             </script>
 
             <script id="nametag-template" type="text/html">
@@ -55,7 +55,7 @@
 
         <a-entity id="player-rig" networked wasd-controls snap-rotation="pivotSrc: #head">
             <a-sphere scale="0.1 0.1 0.1"></a-sphere>
-            <a-entity id="head" camera="userHeight: 1.6" look-controls networked="template:#head-template;showLocalTemplate:false;"></a-entity>
+            <a-entity id="head" camera="userHeight: 1.6" personal-space-bubble look-controls networked="template:#head-template;showLocalTemplate:false;"></a-entity>
 
             <a-entity id="nametag" networked="template:#nametag-template;showLocalTemplate:false;"></a-entity>
 
diff --git a/src/systems/personal-space-bubble.js b/src/systems/personal-space-bubble.js
index 5b8121ad9..9087ec5a4 100644
--- a/src/systems/personal-space-bubble.js
+++ b/src/systems/personal-space-bubble.js
@@ -1,73 +1,93 @@
-var posA = new AFRAME.THREE.Vector3();
-var posB = new AFRAME.THREE.Vector3();
-
-function distance(entityA, entityB) {
-  entityA.object3D.getWorldPosition(posA);
-  entityB.object3D.getWorldPosition(posB);
-  return posA.distanceTo(posB);
-}
+var invaderPos = new AFRAME.THREE.Vector3();
+var bubblePos = new AFRAME.THREE.Vector3();
 
 AFRAME.registerSystem("personal-space-bubble", {
   init() {
-    this.myEntities = [];
-    this.entities = [];
+    this.invaders = [];
+    this.bubbles = [];
   },
 
-  registerEntity(el) {
-    var networkedEl = NAF.utils.getNetworkedEntity(el);
-    var owner = NAF.utils.getNetworkOwner(networkedEl);
+  registerBubble(el) {
+    this.bubbles.push(el);
+  },
 
-    if (owner !== NAF.clientId) {
-      this.entities.push(el);
-    } else {
-      this.myEntities.push(el);
+  unregisterBubble(el) {
+    var index = this.bubbles.indexOf(el);
+
+    if (index !== -1) {
+      this.bubbles.splice(index, 1);
     }
   },
 
-  unregisterEntity(el) {
+  registerInvader(el) {
     var networkedEl = NAF.utils.getNetworkedEntity(el);
     var owner = NAF.utils.getNetworkOwner(networkedEl);
 
     if (owner !== NAF.clientId) {
-      var index = this.entities.indexOf(el);
-      this.entities.splice(index, 1);
-    } else {
-      var index = this.myEntities.indexOf(el);
-      this.myEntities.splice(index, 1);
+      this.invaders.push(el);
+    }
+  },
+
+  unregisterInvader(el) {
+    var index = this.invaders.indexOf(el);
+
+    if (index !== -1) {
+      this.invaders.splice(index, 1);
     }
   },
 
   tick() {
-    for (var j = 0; j < this.entities.length; j++) {
-      var otherEntity = this.entities[j];
+    // Update matrix positions once for each space bubble and space invader
+    for (var i = 0; i < this.bubbles.length; i++) {
+      this.bubbles[i].object3D.updateMatrixWorld(true);
+    }
+
+    for (var i = 0; i < this.invaders.length; i++) {
+      this.invaders[i].object3D.updateMatrixWorld(true);
+    }
 
-      var visible = true;
+    // Loop through all of the space bubbles (usually one)
+    for (var i = 0; i < this.bubbles.length; i++) {
+      var bubble = this.bubbles[i];
 
-      for (var i = 0; i < this.myEntities.length; i++) {
-        var myEntity = this.myEntities[i];
+      bubblePos.setFromMatrixPosition(bubble.object3D.matrixWorld);
 
-        var d = distance(myEntity, otherEntity);
+      var radius = bubble.components["personal-space-bubble"].data.radius;
+      var radiusSquared = radius * radius;
 
-        if (d < myEntity.components["personal-space-bubble"].data.radius) {
-          visible = false;
-          break;
-        }
-      }
+      // Hide the invader if inside the bubble
+      for (var j = 0; j < this.invaders.length; j++) {
+        var invader = this.invaders[j];
+
+        invaderPos.setFromMatrixPosition(invader.object3D.matrixWorld);
 
-      otherEntity.object3D.visible = visible;
+        var distanceSquared = bubblePos.distanceTo(invaderPos);
+
+        invader.object3D.visible = distanceSquared > radiusSquared;
+      }
     }
   }
 });
 
+AFRAME.registerComponent("personal-space-invader", {
+  init() {
+    this.el.sceneEl.systems["personal-space-bubble"].registerInvader(this.el);
+  },
+
+  remove() {
+    this.el.sceneEl.systems["personal-space-bubble"].unregisterInvader(this.el);
+  }
+});
+
 AFRAME.registerComponent("personal-space-bubble", {
   schema: {
     radius: { type: "number", default: 0.8 }
   },
   init() {
-    this.system.registerEntity(this.el);
+    this.system.registerBubble(this.el);
   },
 
   remove() {
-    this.system.unregisterEntity(this.el);
+    this.system.unregisterBubble(this.el);
   }
 });
-- 
GitLab