From 4a0d90bb605a32086d36b0785864a4f76a94079a Mon Sep 17 00:00:00 2001
From: Kevin Lee <kevin@infinite-lee.com>
Date: Mon, 2 Jul 2018 17:14:44 -0700
Subject: [PATCH] first pass at networking drawings (unoptimzied)

---
 src/components/tools/networked-drawing.js | 189 +++++++++++++---------
 src/components/tools/pen.js               |  27 +++-
 src/hub.html                              |   8 +-
 src/network-schemas.js                    |  15 ++
 4 files changed, 159 insertions(+), 80 deletions(-)

diff --git a/src/components/tools/networked-drawing.js b/src/components/tools/networked-drawing.js
index 71e31c58f..47bb170b0 100644
--- a/src/components/tools/networked-drawing.js
+++ b/src/components/tools/networked-drawing.js
@@ -8,7 +8,7 @@ import SharedBufferGeometryManager from "../../vendor/sharedbuffergeometrymanage
 
 AFRAME.registerComponent("networked-drawing", {
   schema: {
-    drawPoints: { default: [] },
+    drawBuffer: { default: [] },
     segments: { default: 8 },
     radius: { default: 0.02 }
   },
@@ -35,36 +35,139 @@ AFRAME.registerComponent("networked-drawing", {
     this.lastPoint = new THREE.Vector3();
     this.lastPointSet = false;
     this.initialized = false;
+
+    this.bufferIndex = 0;
+
+    NAF.utils.getNetworkedEntity(this.el).then(networkedEl => {
+      this.networkedEl = networkedEl;
+    });
+  },
+
+  tick: (() => {
+    const position = new THREE.Vector3();
+    const direction = new THREE.Vector3();
+    const normal = new THREE.Vector3();
+    return function() {
+      if (this.networkedEl) {
+        const isMine = NAF.utils.isMine(this.networkedEl);
+        if (!isMine) {
+          // console.log(this.data.drawBuffer);
+          if (this.peekBuffer() != null) {
+            position.set(this.getNextFromBuffer(), this.getNextFromBuffer(), this.getNextFromBuffer());
+            direction.set(this.getNextFromBuffer(), this.getNextFromBuffer(), this.getNextFromBuffer());
+            normal.set(this.getNextFromBuffer(), this.getNextFromBuffer(), this.getNextFromBuffer());
+
+            if (!this.lastPointSet) {
+              this.startDraw(position, direction, normal);
+            } else {
+              this.draw(position, direction, normal);
+            }
+          } else if (this.data.drawBuffer.length > this.bufferIndex) {
+            if (this.lastPointSet) {
+              this.endDraw(position, direction, normal);
+            }
+            this.bufferIndex++;
+          }
+        } else if (this.data.drawBuffer.length > 0) {
+          this.bufferIndex = this.data.drawBuffer.length - 1;
+        }
+      }
+    };
+  })(),
+
+  peekBuffer() {
+    return this.data.drawBuffer[this.bufferIndex];
+  },
+
+  getNextFromBuffer() {
+    return this.data.drawBuffer[this.bufferIndex++];
   },
 
   getLastPoint() {
     return this.lastPoint;
   },
 
-  startDraw: (() => {
+  draw: (() => {
     const normal = new THREE.Vector3();
-    return function(position, direction) {
-      this.addPoint(position, direction);
-      this.getNormal(position);
-      this.drawStart(normal, direction);
+    return function(position, direction, normal) {
+      if (this.lastPointSet) {
+        this.addSegments(this.currentSegments, position, direction, normal);
+
+        //draw the triangle strip
+        for (let i = 0; i <= this.data.segments; i++) {
+          this.addVertex(this.lastSegments[i % this.data.segments]);
+          this.addVertex(this.currentSegments[i % this.data.segments]);
+        }
+
+        //update the drawing
+        this.sharedBuffer.update();
+
+        //copy the currentSegments to lastSegments
+        for (var j = 0; j < this.data.segments; j++) {
+          this.lastSegments[j].copy(this.currentSegments[j]);
+        }
+      }
+
+      this.lastPoint.copy(position);
+      this.lastPointSet = true;
+
+      if (this.networkedEl && NAF.utils.isMine(this.networkedEl)) {
+        this.data.drawBuffer.push(position.x);
+        this.data.drawBuffer.push(position.y);
+        this.data.drawBuffer.push(position.z);
+        this.data.drawBuffer.push(direction.x);
+        this.data.drawBuffer.push(direction.y);
+        this.data.drawBuffer.push(direction.z);
+        this.data.drawBuffer.push(normal.x);
+        this.data.drawBuffer.push(normal.y);
+        this.data.drawBuffer.push(normal.z);
+      }
+    };
+  })(),
+
+  startDraw: (() => {
+    const startPoint = new THREE.Vector3();
+    const inverseDirection = new THREE.Vector3();
+    return function(position, direction, normal) {
+      //add the first point and cap
+      this.draw(position, direction, normal);
+      this.addSegments(this.lastSegments, this.getLastPoint(), direction, normal);
+
+      inverseDirection
+        .copy(direction)
+        .negate()
+        .multiplyScalar(this.data.radius);
+      startPoint.copy(this.getLastPoint()).add(inverseDirection);
+
+      //add the first vertex of the lastSegments if this drawing has already been initialized
+      if (this.initialized) {
+        this.addVertex(this.lastSegments[0]);
+      }
+
+      this.drawCap(startPoint, this.lastSegments);
+
+      this.sharedBuffer.restartPrimitive();
+      this.addVertex(this.lastSegments[0]);
     };
   })(),
 
   endDraw: (() => {
     const endPoint = new THREE.Vector3();
     const direction = new THREE.Vector3();
-    return function(position, direction) {
-      //add the final point  and cap
-      this.addPoint(position, direction);
+    return function(position, direction, normal) {
+      //add the final point and cap
+      this.draw(position, direction, normal);
       direction.copy(direction).multiplyScalar(this.data.radius);
       endPoint.copy(position).add(direction);
       this.drawCap(endPoint, this.currentSegments);
 
       //reset
       this.sharedBuffer.restartPrimitive();
+      if (this.networkedEl && NAF.utils.isMine(this.networkedEl)) {
+        this.data.drawBuffer.push(null);
+      }
       this.lastPointSet = false;
       this.lastSegmentsSet = false;
-      this.timeSinceLastDraw = 0;
     };
   })(),
 
@@ -97,72 +200,6 @@ AFRAME.registerComponent("networked-drawing", {
     this.sharedBuffer.addVertex(point.x, point.y, point.z);
   },
 
-  //get lastSegments, draw the start cap
-  drawStart: (() => {
-    const startPoint = new THREE.Vector3();
-    const inverseDirection = new THREE.Vector3();
-    return function(normal, direction) {
-      this.addSegments(this.lastSegments, this.lastPoint, direction, normal);
-
-      inverseDirection
-        .copy(direction)
-        .negate()
-        .multiplyScalar(this.data.radius);
-      startPoint.copy(this.lastPoint).add(inverseDirection);
-
-      //add the first vertex of the lastSegments if this drawing has already been initialized
-      if (this.initialized) {
-        this.addVertex(this.lastSegments[0]);
-      }
-
-      this.drawCap(startPoint, this.lastSegments);
-
-      this.sharedBuffer.restartPrimitive();
-      this.addVertex(this.lastSegments[0]);
-    };
-  })(),
-
-  //helper function to get normal of direction of drawing cross direction to camera
-  getNormal: (() => {
-    const directionToCamera = new THREE.Vector3();
-    return function(normal, position, direction) {
-      if (this.data.camera) {
-        directionToCamera.subVectors(position, this.data.camera.object3D.position).normalize();
-        normal.crossVectors(direction, directionToCamera);
-      } else {
-        normal.copy(this.el.object3D.up);
-      }
-    };
-  })(),
-
-  addPoint: (() => {
-    const normal = new THREE.Vector3();
-    return function(position, direction) {
-      if (this.lastPointSet) {
-        this.getNormal(normal, position);
-
-        this.addSegments(this.currentSegments, position, direction, normal);
-
-        //draw the triangle strip
-        for (let j = 0; j <= this.data.segments; j++) {
-          this.addVertex(this.lastSegments[j % this.data.segments]);
-          this.addVertex(this.currentSegments[j % this.data.segments]);
-        }
-
-        //update the drawing
-        this.sharedBuffer.update();
-
-        //copy the currentSegments to lastSegments
-        for (var j = 0; j < this.data.segments; j++) {
-          this.lastSegments[j].copy(this.currentSegments[j]);
-        }
-      }
-
-      this.lastPoint.copy(position);
-      this.lastPointSet = true;
-    };
-  })(),
-
   rotatePointAroundAxis: (() => {
     const calculatedDirection = new THREE.Vector3();
     return function(out, point, axis, up, angle, radius) {
diff --git a/src/components/tools/pen.js b/src/components/tools/pen.js
index a62981f24..6e35c7cc9 100644
--- a/src/components/tools/pen.js
+++ b/src/components/tools/pen.js
@@ -29,6 +29,8 @@ AFRAME.registerComponent("pen", {
     this.handleDrawingInitialized = this.handleDrawingInitialized.bind(this);
 
     this.data.drawing.addEventListener("componentinitialized", this.handleDrawingInitialized);
+
+    this.normal = new THREE.Vector3();
   },
 
   remove() {
@@ -60,13 +62,27 @@ AFRAME.registerComponent("pen", {
         time >= this.data.drawFrequency &&
         drawing.getLastPoint().distanceTo(currentPosition) >= this.data.minDistanceBetweenPoints
       ) {
-        drawing.addPoint(currentPosition, this.direction);
+        this.getNormal(this.normal, currentPosition, this.direction);
+        drawing.draw(currentPosition, this.direction, this.normal);
       }
 
       this.timeSinceLastDraw = time % this.data.drawFrequency;
     }
   },
 
+  //helper function to get normal of direction of drawing cross direction to camera
+  getNormal: (() => {
+    const directionToCamera = new THREE.Vector3();
+    return function(normal, position, direction) {
+      if (this.data.camera) {
+        directionToCamera.subVectors(position, this.data.camera.object3D.position).normalize();
+        normal.crossVectors(direction, directionToCamera);
+      } else {
+        normal.copy(this.el.object3D.up);
+      }
+    };
+  })(),
+
   handleDrawingInitialized(e) {
     if (e.detail.name === "networked-drawing") {
       this.currentDrawing = this.data.drawing.components["networked-drawing"];
@@ -76,14 +92,19 @@ AFRAME.registerComponent("pen", {
   onMouseDown(e) {
     if (this.currentDrawing && e.button === 0) {
       this.isDrawing = true;
-      this.currentDrawing.startDraw(this.el.object3D.position, this.direction);
+      const position = this.el.object3D.position;
+      this.getNormal(this.normal, position, this.direction);
+      this.currentDrawing.startDraw(position, this.direction, this.normal);
     }
   },
 
   onMouseUp(e) {
     if (this.currentDrawing && e.button === 0) {
       this.isDrawing = false;
-      this.currentDrawing.endDraw(this.el.object3D.position, this.direction);
+      this.timeSinceLastDraw = 0;
+      const position = this.el.object3D.position;
+      this.getNormal(this.normal, position, this.direction);
+      this.currentDrawing.endDraw(position, this.direction, this.normal);
     }
   }
 });
diff --git a/src/hub.html b/src/hub.html
index 85177b70c..05ba6eff2 100644
--- a/src/hub.html
+++ b/src/hub.html
@@ -190,6 +190,12 @@
                 ></a-entity>
             </template>
 
+            <template id="drawing-template">
+                <a-entity
+                    networked-drawing
+                ></a-entity>
+            </template>
+
             <a-mixin id="controller-super-hands"
                 super-hands="
                     colliderEvent: collisions; colliderEventProperty: els;
@@ -372,7 +378,7 @@
 
         <a-entity
             id="my-first-drawing"
-            networked-drawing
+            networked="template: #drawing-template;"
         ></a-entity>
     </a-scene>
 
diff --git a/src/network-schemas.js b/src/network-schemas.js
index 2b7c7bdb0..e9aff09c0 100644
--- a/src/network-schemas.js
+++ b/src/network-schemas.js
@@ -83,6 +83,21 @@ function registerNetworkSchemas() {
 
   NAF.schemas.add({
     template: "#interactable-template",
+    components: [
+      {
+        component: "position",
+        requiresNetworkUpdate: vectorRequiresUpdate(0.001)
+      },
+      {
+        component: "rotation",
+        requiresNetworkUpdate: vectorRequiresUpdate(0.5)
+      },
+      "scale"
+    ]
+  });
+
+  NAF.schemas.add({
+    template: "#drawing-template",
     components: [
       {
         component: "position",
-- 
GitLab