From 9aeff16d977d78d3b2703cb1adfccaf1538569a0 Mon Sep 17 00:00:00 2001 From: Kevin Lee <kevin@infinite-lee.com> Date: Mon, 6 Aug 2018 18:52:45 -0700 Subject: [PATCH] fixed faceculling order on geometry for lines and caps, both even and odd segments. Added timed delete per line. Fixed networking bug where line data could be sent before remote clients were fully initialized. Adding drawing manager that prevents multiple pens from drawing on the same drawing at the same time. --- src/components/tools/drawing-manager.js | 49 +++- src/components/tools/networked-drawing.js | 278 ++++++++++++++-------- src/components/tools/pen.js | 116 +++------ src/hub.html | 4 +- src/hub.js | 1 + src/vendor/sharedbuffergeometry.js | 31 ++- 6 files changed, 287 insertions(+), 192 deletions(-) diff --git a/src/components/tools/drawing-manager.js b/src/components/tools/drawing-manager.js index 9b4da53e1..34d8f6488 100644 --- a/src/components/tools/drawing-manager.js +++ b/src/components/tools/drawing-manager.js @@ -3,11 +3,52 @@ * @component drawing-manager */ AFRAME.registerComponent("drawing-manager", { - schema: {}, + schema: { + drawing: { type: "string" } + }, - init() {}, + init() { + this.handleDrawingInitialized = this.handleDrawingInitialized.bind(this); - play() {}, + // this.drawingEl = document.querySelector(this.data.drawing); + this.drawingToPen = new Map(); - pause() {} + // if (this.drawingEl.hasLoaded) { + // this.drawing = this.drawingEl.components["networked-drawing"]; + // } else { + // this.drawingEl.addEventListener("componentinitialized", this.handleDrawingInitialized); + // } + }, + + remove() { + // this.drawingEl.removeEventListener("componentinitialized", this.handleDrawingInitialized); + }, + + play() { + this.drawing = document.querySelector(this.data.drawing).components["networked-drawing"]; + }, + + pause() {}, + + handleDrawingInitialized(e) { + if (e.detail.name === "networked-drawing") { + this.drawing = this.drawingEl.components["networked-drawing"]; + } + }, + + getDrawing(pen) { + //TODO: future handling of multiple drawings + if (this.drawing && (!this.drawingToPen.has(this.drawing) || this.drawingToPen.get(this.drawing) === pen)) { + this.drawingToPen.set(this.drawing, pen); + return this.drawing; + } + + return null; + }, + + returnDrawing(pen) { + if (this.drawingToPen.has(this.drawing) && this.drawingToPen.get(this.drawing) === pen) { + this.drawingToPen.delete(this.drawing); + } + } }); diff --git a/src/components/tools/networked-drawing.js b/src/components/tools/networked-drawing.js index efb7a424e..d1b9e564f 100644 --- a/src/components/tools/networked-drawing.js +++ b/src/components/tools/networked-drawing.js @@ -6,6 +6,9 @@ import SharedBufferGeometryManager from "../../vendor/sharedbuffergeometrymanager"; +const MSG_CONFIRM_CONNECT = 0; +const MSG_BUFFER_DATA = 1; + function round(x) { return Math.round(x * 100000) / 100000; } @@ -20,28 +23,26 @@ function copyData(fromArray, toArray, fromIndex, toIndex) { AFRAME.registerComponent("networked-drawing", { schema: { - segments: { default: 8 }, - radius: { default: 0.02 }, - color: { type: "color", default: "#FF0000" } + segments: { default: 3 }, + radius: { default: 0.2 }, + color: { type: "color", default: "#FF0000" }, + drawTimeout: { default: 5000 } }, init() { this.drawBuffer = []; + this.bufferIndex = 0; + this.drawBufferHistory = []; const options = { - //seems to require calling computeVertexNormals() if > 0 - roughness: 0, - metalness: 0, - vertexColors: THREE.VertexColors, - side: THREE.DoubleSide + vertexColors: THREE.VertexColors }; this.color = new THREE.Color(this.data.color); this.radius = this.data.radius; this.segments = this.data.segments; - const material = new THREE.MeshBasicMaterial(options); - console.log(material); + const material = new THREE.MeshStandardMaterial(options); this.sharedBufferGeometryManager = new SharedBufferGeometryManager(); this.sharedBufferGeometryManager.addSharedBuffer(0, material, THREE.TriangleStripDrawMode); @@ -53,7 +54,7 @@ AFRAME.registerComponent("networked-drawing", { } this.sharedBuffer = this.sharedBufferGeometryManager.getSharedBuffer(0); - this.drawing = this.sharedBuffer.getDrawing(); + this.drawing = this.sharedBuffer.drawing; const sceneEl = document.querySelector("a-scene"); this.scene = sceneEl.object3D; this.scene.add(this.drawing); @@ -62,31 +63,32 @@ AFRAME.registerComponent("networked-drawing", { this.remoteLineStarted = false; this.lastPoint = new THREE.Vector3(); - this.initialized = false; + this.lastDrawTime = -1; - this.bufferIndex = 0; + this.connectedToOwner = false; - this.sendDrawBuffer = this.sendDrawBuffer.bind(this); - this.receiveDrawBuffer = this.receiveDrawBuffer.bind(this); + this.prevIdx = Object.assign({}, this.sharedBuffer.idx); + this.idx = Object.assign({}, this.sharedBuffer.idx); + this.vertexCount = 0; - document.body.addEventListener("clientConnected", this.sendDrawBuffer); + this.receiveData = this.receiveData.bind(this); NAF.connection.onConnect(() => { NAF.utils.getNetworkedEntity(this.el).then(networkedEl => { this.networkedEl = networkedEl; - - this.drawingId = "drawing-" + NAF.utils.getNetworkId(this.networkedEl); - - if (!NAF.utils.isMine(this.networkedEl)) { - NAF.connection.subscribeToDataChannel(this.drawingId, this.receiveDrawBuffer); + this.networkId = NAF.utils.getNetworkId(this.networkedEl); + if (!this.networkId) { + console.error("No networkId for", this.networkedEl); } + this.drawingId = "drawing-" + this.networkId; + + NAF.connection.subscribeToDataChannel(this.drawingId, this.receiveData); }); }); }, remove() { - document.body.removeEventListener("clientConnected", this.sendDrawBuffer); - NAF.connection.unsubscribeToDataChannel(this.drawingId, this.receiveDrawBuffer); + NAF.connection.unsubscribeToDataChannel(this.drawingId, this.receiveData); this.scene.remove(this.drawing); }, @@ -97,60 +99,82 @@ AFRAME.registerComponent("networked-drawing", { const normal = new THREE.Vector3(); const copyArray = []; return function() { - if (this.bufferIndex < this.drawBuffer.length && NAF.connection.isConnected() && this.networkedEl) { + if (!this.connectedToOwner && NAF.connection.isConnected() && this.networkedEl) { + const owner = NAF.utils.getNetworkOwner(this.networkedEl); + if (!NAF.utils.isMine(this.networkedEl) && NAF.connection.hasActiveDataChannel(owner)) { + NAF.connection.sendDataGuaranteed(owner, this.drawingId, { + type: MSG_CONFIRM_CONNECT, + clientId: NAF.clientId + }); + } + this.connectedToOwner = true; + } + + if (this.drawBuffer.length > 0 && NAF.connection.isConnected() && this.networkedEl) { if (!NAF.utils.isMine(this.networkedEl)) { - const head = this.drawBuffer[this.bufferIndex]; - if (head != null && typeof head === "string") { + const head = this.drawBuffer[0]; + if (head !== null && typeof head === "string") { //TODO: check radius and segments as well, somehow this.color.set(head); - } else if (head != null && this.bufferIndex + 9 <= this.drawBuffer.length) { - --this.bufferIndex; - position.set( - this.drawBuffer[++this.bufferIndex], - this.drawBuffer[++this.bufferIndex], - this.drawBuffer[++this.bufferIndex] - ); - direction.set( - this.drawBuffer[++this.bufferIndex], - this.drawBuffer[++this.bufferIndex], - this.drawBuffer[++this.bufferIndex] - ); - normal.set( - this.drawBuffer[++this.bufferIndex], - this.drawBuffer[++this.bufferIndex], - this.drawBuffer[++this.bufferIndex] - ); + this.drawBuffer.shift(); + } else if (head != null && this.drawBuffer.length >= 9) { + position.set(this.drawBuffer[0], this.drawBuffer[1], this.drawBuffer[2]); + direction.set(this.drawBuffer[3], this.drawBuffer[4], this.drawBuffer[5]); + normal.set(this.drawBuffer[6], this.drawBuffer[7], this.drawBuffer[8]); if (!this.remoteLineStarted) { this.startDraw(position, direction, normal); this.remoteLineStarted = true; } else { this.draw(position, direction, normal); } + this.drawBuffer.splice(0, 9); } else if (head === null) { this.endDraw(position, direction, normal); this.remoteLineStarted = false; + this.drawBuffer.shift(); } - ++this.bufferIndex; - } else if (this.drawBuffer.length > 0) { + } else if (this.bufferIndex < this.drawBuffer.length) { //TODO: don't do this on every tick? copyArray.length = 0; copyData(this.drawBuffer, copyArray, this.bufferIndex, this.drawBuffer.length - 1); - NAF.connection.broadcastDataGuaranteed(this.drawingId, copyArray); this.bufferIndex = this.drawBuffer.length; + NAF.connection.broadcastDataGuaranteed(this.drawingId, { type: MSG_BUFFER_DATA, buffer: copyArray }); } } + + this.deleteLines(); }; })(), + deleteLines() { + if (this.drawBufferHistory.length > 0 && this.drawBufferHistory[0].time + this.data.drawTimeout <= Date.now()) { + const datum = this.drawBufferHistory[0]; + if (this.drawBufferHistory.length > 1) { + datum.idxLength += 2 - (this.segments % 2); + this.drawBufferHistory[1].idxLength -= 2 - (this.segments % 2); + } + console.log("remove", datum.idxLength, this.sharedBuffer.idx); + this.idx.position = datum.idxLength; + this.idx.uv = datum.idxLength; + this.idx.normal = datum.idxLength; + this.idx.color = datum.idxLength; + this.sharedBuffer.remove(this.prevIdx, this.idx); + this.drawBufferHistory.shift(); + } + }, + sendDrawBuffer: (() => { const copyArray = []; //This number needs to be approx. < ~6000 based on napkin math //see: https://github.com/webrtc/adapter/blob/682e0f2439e139da6c0c406370eae820637b8c1a/src/js/common_shim.js#L157 const chunkAmount = 3000; - return function(evt) { + return function(clientId) { if (NAF.utils.isMine(this.networkedEl)) { if (this.drawBuffer.length <= chunkAmount) { - NAF.connection.sendDataGuaranteed(evt.detail.clientId, this.drawingId, this.drawBuffer); + NAF.connection.sendDataGuaranteed(clientId, this.drawingId, { + type: MSG_BUFFER_DATA, + buffer: this.drawBuffer + }); } else { //TODO: do this in tick? let x = 0; @@ -158,53 +182,80 @@ AFRAME.registerComponent("networked-drawing", { x = Math.min(x + chunkAmount, this.drawBuffer.length); copyArray.length = 0; copyData(this.drawBuffer, copyArray, x - chunkAmount, x - 1); - NAF.connection.sendDataGuaranteed(evt.detail.clientId, this.drawingId, copyArray); + NAF.connection.sendDataGuaranteed(clientId, this.drawingId, { + type: MSG_BUFFER_DATA, + buffer: copyArray + }); } } } }; })(), - receiveDrawBuffer(_, dataType, data) { - this.drawBuffer.push.apply(this.drawBuffer, data); + receiveData(_, dataType, data) { + switch (data.type) { + case MSG_CONFIRM_CONNECT: + this.sendDrawBuffer(data.clientId); + break; + case MSG_BUFFER_DATA: + this.drawBuffer.push.apply(this.drawBuffer, data.buffer); + break; + } }, getLastPoint() { return this.lastPoint; }, - draw(position, direction, normal) { + startDraw(position, direction, normal, color, radius, segments) { if (!NAF.connection.isConnected()) { return; } - if (!this.lineStarted) { - this.addSegments(this.lastSegments, position, direction, normal, this.radius); - if (this.initialized) { - this.addVertex(this.lastSegments[0]); //discarded - } - this.drawCap(this.lastPoint, this.lastSegments); - this.lineStarted = true; - } else { - this.addSegments(this.currentSegments, position, direction, normal, this.radius); - this.drawCylinder(); + if (color && color != "#" + this.color.getHex()) { + this.color.set(color); + this.drawBuffer.push(color); } + if (radius) this.radius = radius; + if (segments) this.segments = segments; + this.lastPoint.copy(position); this.addToDrawBuffer(position, direction, normal); + this.lastDrawTime = Date.now(); }, - startDraw(position, direction, normal, color, radius, segments) { + draw(position, direction, normal, radiusMultiplier = 1.0) { if (!NAF.connection.isConnected()) { return; } - if (color && color != "#" + this.color.getHex()) { - this.color.set(color); - this.drawBuffer.push(color); - } - if (radius) this.radius = radius; - if (segments) this.segments = segments; + if (!this.lineStarted) { + this.addSegments(this.lastSegments, position, direction, normal, this.radius * radiusMultiplier); + + if (this.drawBufferHistory.length === 0) { + //start with CW faceculling order + this.addDegenerateTriangle(); + } else { + //only do the following if the sharedBuffer is not empty + this.restartPrimitive(); + this.addDegenerateTriangle(); + if (this.segments % 2 === 0) { + //flip faceculling order if even numbered segments + this.addDegenerateTriangle(); + } + } + + this.drawCap(this.lastPoint, this.lastSegments); + if (this.segments % 2 !== 0) { + //flip faceculling order if odd numbered segments + this.addDegenerateTriangle(); + } + this.lineStarted = true; + } else { + this.addSegments(this.currentSegments, position, direction, normal, this.radius * radiusMultiplier); + this.drawCylinder(position); + } this.lastPoint.copy(position); this.addToDrawBuffer(position, direction, normal); }, @@ -223,12 +274,22 @@ AFRAME.registerComponent("networked-drawing", { this.draw(position, direction, normal); projectedDirection.copy(direction).multiplyScalar(this.radius); projectedPoint.copy(position).add(projectedDirection); + + //flip faceculling order before drawing end-cap + this.addDegenerateTriangle(); + this.drawCap(projectedPoint, this.lastSegments); } - if (this.networkedEl && NAF.utils.isMine(this.networkedEl)) { + if (this.lineStarted && this.networkedEl && NAF.utils.isMine(this.networkedEl)) { this.drawBuffer.push(null); + this.drawBufferHistory.push({ + drawBufferIndex: this.drawBuffer.length, + idxLength: this.vertexCount - 1, + time: Date.now() + }); } + this.vertexCount = 0; this.lineStarted = false; }; })(), @@ -248,17 +309,12 @@ AFRAME.registerComponent("networked-drawing", { }, //draw a cylinder from last to current segments - drawCylinder() { - this.addVertex(this.lastSegments[0]); //discarded + drawCylinder(position) { for (let i = 0; i != this.segments + 1; i++) { - this.addVertex(this.lastSegments[i % this.segments]); - this.addVertex(this.currentSegments[i % this.segments]); + this.addVertex(this.lastSegments[i % this.segments], position); + this.addVertex(this.currentSegments[i % this.segments], position); } - - this.sharedBuffer.restartPrimitive(); - this.sharedBuffer.update(); - for (let j = 0; j < this.segments; j++) { this.lastSegments[j].copy(this.currentSegments[j]); } @@ -272,24 +328,24 @@ AFRAME.registerComponent("networked-drawing", { const projectedDirection = new THREE.Vector3(); const projectedPoint = new THREE.Vector3(); return function(position) { - projectedDirection.copy(up).multiplyScalar(this.radius * 0.5); - projectedPoint.copy(position).add(projectedDirection); - this.addSegments(this.lastSegments, projectedPoint, up, left, this.radius * 0.5); - if (this.initialized) { - this.addVertex(this.lastSegments[0]); //discarded - } projectedDirection.copy(up).multiplyScalar(this.radius * 0.75); projectedPoint.copy(position).add(projectedDirection); - this.drawCap(projectedPoint, this.lastSegments); - this.addVertex(this.lastSegments[0]); //discared - this.addSegments(this.currentSegments, position, up, left, this.radius * 0.75); - this.drawCylinder(); + this.lastPoint.copy(projectedPoint); + + projectedDirection.copy(up).multiplyScalar(this.radius * 0.5); + projectedPoint.copy(position).add(projectedDirection); + this.draw(projectedPoint, down, left, 0.75); + + this.draw(position, down, left); + projectedDirection.copy(down).multiplyScalar(this.radius * 0.5); projectedPoint.copy(position).add(projectedDirection); - this.addSegments(this.currentSegments, projectedPoint, up, left, this.radius * 0.5); - this.drawCylinder(); + this.draw(projectedPoint, down, left, 0.75); + projectedDirection.copy(down).multiplyScalar(this.radius * 0.75); projectedPoint.copy(position).add(projectedDirection); + + this.addDegenerateTriangle(); //discarded this.drawCap(projectedPoint, this.lastSegments); }; })(), @@ -297,22 +353,48 @@ AFRAME.registerComponent("networked-drawing", { //draw a cap to start/end a line drawCap(point, segments) { let segmentIndex = 0; - for (let i = 0; i < this.segments + 4; i++) { - if ((i - 1) % 4 === 0) { + for (let i = 0; i < this.segments * 2 - (this.segments % 2); i++) { + if ((i - 2) % 4 === 0) { this.addVertex(point); } else { this.addVertex(segments[segmentIndex % this.segments]); - ++segmentIndex; + if ((i + 1) % 5 !== 0) { + ++segmentIndex; + } } } - this.sharedBuffer.restartPrimitive(); this.sharedBuffer.update(); }, - addVertex(point) { - this.initialized = true; - this.sharedBuffer.addVertex(point.x, point.y, point.z); - this.sharedBuffer.addColor(this.color.r, this.color.g, this.color.b); + restartPrimitive() { + this.sharedBuffer.restartPrimitive(); + ++this.vertexCount; + console.log("restartPrimitive", this.vertexCount); + }, + + addVertex: (() => { + const normal = new THREE.Vector3(); + return function(point, position) { + this.sharedBuffer.addVertex(point.x, point.y, point.z); + this.sharedBuffer.addColor(this.color.r, this.color.g, this.color.b); + if (position) { + normal.subVectors(point, position).normalize(); + this.sharedBuffer.addNormal(normal.x, normal.y, normal.z); + } else { + ++this.sharedBuffer.idx.normal; + } + + ++this.sharedBuffer.idx.uv; + ++this.vertexCount; + console.error("addVertex", point.x, point.y, point.z, this.vertexCount); + + //TODO: normals + }; + })(), + + addDegenerateTriangle() { + console.error("addDegenerateTriangle"); + this.addVertex(this.lastSegments[0]); }, //calculate the segments for a given point diff --git a/src/components/tools/pen.js b/src/components/tools/pen.js index cbd1407be..ba7610487 100644 --- a/src/components/tools/pen.js +++ b/src/components/tools/pen.js @@ -10,21 +10,17 @@ function almostEquals(epsilon, u, v) { AFRAME.registerComponent("pen", { schema: { drawFrequency: { default: 20 }, - minDistanceBetweenPoints: { default: 0.04 }, + minDistanceBetweenPoints: { default: 0.4 }, defaultDirection: { default: { x: 1, y: 0, z: 0 } }, camera: { type: "selector" }, drawing: { type: "string" }, - useMouse: { defualt: false } + drawingManager: { type: "string" } }, init() { - this.onMouseDown = this.onMouseDown.bind(this); - this.onMouseUp = this.onMouseUp.bind(this); - this.startDraw = this.startDraw.bind(this); this.endDraw = this.endDraw.bind(this); - this.isDrawing = false; this.timeSinceLastDraw = 0; this.lastPosition = new THREE.Vector3(); @@ -33,68 +29,41 @@ AFRAME.registerComponent("pen", { this.direction = new THREE.Vector3(); this.direction.copy(this.data.defaultDirection); - this.handleDrawingInitialized = this.handleDrawingInitialized.bind(this); - - this.drawing = document.querySelector(this.data.drawing); - - if (this.drawing.hasLoaded) { - this.currentDrawing = this.drawing.components["networked-drawing"]; - } else { - this.drawing.addEventListener("componentinitialized", this.handleDrawingInitialized); - } + this.currentDrawing = null; this.normal = new THREE.Vector3(); this.worldPosition = new THREE.Vector3(); }, - remove() { - this.drawing.removeEventListener("componentinitialized", this.handleDrawingInitialized); - }, - play() { - // if (this.data.useMouse && false) { - // document.addEventListener("mousedown", this.onMouseDown); - // document.addEventListener("mouseup", this.onMouseUp); - // } + this.drawingManager = document.querySelector(this.data.drawingManager).components["drawing-manager"]; - // this.el.parentNode.addEventListener("index_down", this.startDraw); - // this.el.parentNode.addEventListener("index_up", this.endDraw); - - if (!this.data.useMouse) { - this.el.parentNode.addEventListener("activate-start", this.startDraw); - this.el.parentNode.addEventListener("activate-end", this.endDraw); - } + this.el.parentNode.addEventListener("activate-start", this.startDraw); + this.el.parentNode.addEventListener("activate-end", this.endDraw); }, pause() { - document.removeEventListener("mousedown", this.onMouseDown); - document.removeEventListener("mouseup", this.onMouseUp); - - this.el.parentNode.removeEventListener("index_down", this.startDraw); - this.el.parentNode.removeEventListener("index_up", this.endDraw); - this.el.parentNode.removeEventListener("activate-start", this.startDraw); this.el.parentNode.removeEventListener("activate-end", this.endDraw); }, tick(t, dt) { this.el.object3D.getWorldPosition(this.worldPosition); - const drawing = this.currentDrawing; if (!almostEquals(0.005, this.worldPosition, this.lastPosition)) { this.direction.subVectors(this.worldPosition, this.lastPosition).normalize(); this.lastPosition.copy(this.worldPosition); } - if (drawing && this.isDrawing) { + if (this.currentDrawing) { const time = this.timeSinceLastDraw + dt; if ( time >= this.data.drawFrequency && - drawing.getLastPoint().distanceTo(this.worldPosition) >= this.data.minDistanceBetweenPoints + this.currentDrawing.getLastPoint().distanceTo(this.worldPosition) >= this.data.minDistanceBetweenPoints ) { this.getNormal(this.normal, this.worldPosition, this.direction); - drawing.draw(this.worldPosition, this.direction, this.normal); + this.currentDrawing.draw(this.worldPosition, this.direction, this.normal); } this.timeSinceLastDraw = time % this.data.drawFrequency; @@ -104,56 +73,47 @@ AFRAME.registerComponent("pen", { //helper function to get normal of direction of drawing cross direction to camera getNormal: (() => { const directionToCamera = new THREE.Vector3(); - const worldQuaternion = new THREE.Quaternion(); + // const worldQuaternion = new THREE.Quaternion(); return function(normal, position, direction) { - if (this.data.camera) { - directionToCamera.subVectors(position, this.data.camera.object3D.position).normalize(); - normal.crossVectors(direction, directionToCamera); - } else { - //TODO remove? - this.el.object3D.getWorldQuaternion(worldQuaternion); - normal - .copy(this.el.object3D.up) - .applyQuaternion(worldQuaternion) - .normalize(); - } + // if (this.data.camera) { + directionToCamera.subVectors(position, this.data.camera.object3D.position).normalize(); + normal.crossVectors(direction, directionToCamera); + // normal.set(normal.x, Math.abs(normal.y), normal.z); + // console.log(normal); + // } else { + //TODO remove? + // this.el.object3D.getWorldQuaternion(worldQuaternion); + // normal + // .copy(this.el.object3D.up) + // .applyQuaternion(worldQuaternion) + // .normalize(); + // } }; })(), - handleDrawingInitialized(e) { - if (e.detail.name === "networked-drawing") { - this.currentDrawing = this.drawing.components["networked-drawing"]; - } - }, - - onMouseDown(e) { - if (this.currentDrawing && e.button === 0) { - this.startDraw(); - } - }, - - onMouseUp(e) { - if (this.currentDrawing && e.button === 0) { - this.endDraw(); - } - }, - startDraw() { - this.isDrawing = true; - this.el.object3D.getWorldPosition(this.worldPosition); - this.getNormal(this.normal, this.worldPosition, this.direction); - const color = "#" + Math.floor(Math.random() * 16777215).toString(16); - this.el.setAttribute("material", { color: color }); - this.currentDrawing.startDraw(this.worldPosition, this.direction, this.normal, color); + this.currentDrawing = this.drawingManager.getDrawing(this); + if (this.currentDrawing) { + this.el.object3D.getWorldPosition(this.worldPosition); + this.getNormal(this.normal, this.worldPosition, this.direction); + const color = + "#" + + Math.random() + .toString(16) + .slice(2, 8); + this.el.setAttribute("material", { color: color }); + this.currentDrawing.startDraw(this.worldPosition, this.direction, this.normal, color); + } }, endDraw() { - if (this.isDrawing) { - this.isDrawing = false; + if (this.currentDrawing) { this.timeSinceLastDraw = 0; this.el.object3D.getWorldPosition(this.worldPosition); this.getNormal(this.normal, this.worldPosition, this.direction); this.currentDrawing.endDraw(this.worldPosition, this.direction, this.normal); + this.drawingManager.returnDrawing(this); + this.currentDrawing = null; } } }); diff --git a/src/hub.html b/src/hub.html index ea17335f6..dcb69281d 100644 --- a/src/hub.html +++ b/src/hub.html @@ -211,7 +211,7 @@ position="0 -0.18 0" radius="0.02" color="red" - pen="camera: #player-camera; drawing: #my-first-drawing;" + pen="camera: #player-camera; drawingManager: #drawing-manager" ></a-sphere> </a-entity> </template> @@ -266,6 +266,8 @@ <a-entity id="pen-counter" networked-counter="max: 3;"></a-entity> + <a-entity id="drawing-manager" drawing-manager="drawing: #my-first-drawing;"></a-entity> + <a-entity id="cursor-controller" cursor-controller=" diff --git a/src/hub.js b/src/hub.js index 8df7a69f9..e869eec93 100644 --- a/src/hub.js +++ b/src/hub.js @@ -134,6 +134,7 @@ import ConcurrentLoadDetector from "./utils/concurrent-load-detector.js"; import "./components/tools/pen"; import "./components/tools/networked-drawing"; +import "./components/tools/drawing-manager"; function qsTruthy(param) { const val = qs.get(param); diff --git a/src/vendor/sharedbuffergeometry.js b/src/vendor/sharedbuffergeometry.js index 343a77b07..0f8f0985b 100644 --- a/src/vendor/sharedbuffergeometry.js +++ b/src/vendor/sharedbuffergeometry.js @@ -11,14 +11,10 @@ export default class SharedBufferGeometry { this.addBuffer(false); } - getDrawing () { - return this.drawing; - } - restartPrimitive () { if (this.idx.position >= this.current.attributes.position.count) { this.addBuffer(false); - } else if (this.idx.position !== 0) { + } else if (this.idx.position !== 0) { let prev = (this.idx.position - 1) * 3; const position = this.current.attributes.position.array; this.addVertex(position[prev++], position[prev++], position[prev++]); @@ -30,7 +26,7 @@ export default class SharedBufferGeometry { } remove (prevIdx, idx) { - const pos = this.current.attributes.position.array; + // const pos = this.current.attributes.position.array; // Loop through all the attributes: position, color, uv, normal,... if (this.idx.position > idx.position) { @@ -41,14 +37,26 @@ export default class SharedBufferGeometry { const end = this.idx[key] * componentSize; for (let i = start; i < end; i++) { this.current.attributes[key].array[pos++] = this.current.attributes[key].array[i]; + // this.current.attributes[key].array[i] = Number.NEGATIVE_INFINITY; } + const diff = (idx[key] - prevIdx[key] + 1); + this.idx[key] -= diff; } - } + } else { + for (let key in this.idx) { + // const componentSize = key === 'uv' ? 2 : 3; + // for (let i = 0; i < this.idx.position * componentSize; i++) { + // this.current.attributes[key].array[i] = Number.NEGATIVE_INFINITY; + // } + const diff = (idx[key] - prevIdx[key]); + this.idx[key] -= diff; + } + } - for (key in this.idx) { - const diff = (idx[key] - prevIdx[key]); - this.idx[key] -= diff; - } + // for (let key in this.idx) { + // const diff = (idx[key] - prevIdx[key]); + // this.idx[key] -= diff; + // } this.update(); } @@ -59,6 +67,7 @@ export default class SharedBufferGeometry { } addBuffer (copyLast) { + console.log("addBuffer", copyLast) const geometry = new THREE.BufferGeometry(); const vertices = new Float32Array(this.maxBufferSize * 3); -- GitLab