From 2621784e941a7a63d38714eb147f5eb242f31876 Mon Sep 17 00:00:00 2001 From: Kevin Lee <kevin@infinite-lee.com> Date: Mon, 10 Sep 2018 17:55:13 -0700 Subject: [PATCH] Memory optimizations. Only use the amount of memory needed in sharedbuffergeometry based on networked-drawing configuration. Only create a sharedbuffergeometry object when a pen is first spawned. Also, reduce the amount of memory used by primitive entities (cursor, spawned pens, teleport-controls) --- package-lock.json | 2 +- src/components/tools/drawing-manager.js | 20 +++++++++----- src/components/tools/networked-drawing.js | 12 ++++----- src/components/tools/pen.js | 1 + src/hub.html | 6 +++-- src/utils/sharedbuffergeometry.js | 32 +++++------------------ src/utils/sharedbuffergeometrymanager.js | 18 ++++++------- 7 files changed, 41 insertions(+), 50 deletions(-) diff --git a/package-lock.json b/package-lock.json index 596dc4cd3..b69466449 100644 --- a/package-lock.json +++ b/package-lock.json @@ -629,7 +629,7 @@ "integrity": "sha1-+w+EQdrdHosRzCRRK6eqaS1iK+E=" }, "aframe-teleport-controls": { - "version": "github:mozillareality/aframe-teleport-controls#14f296cad85cea6d15ee5ba08b142526ff9573f4", + "version": "github:mozillareality/aframe-teleport-controls#65dec4805ac9b710c98e7294db72c0bbf22dbd0b", "from": "github:mozillareality/aframe-teleport-controls#hubs/master" }, "after": { diff --git a/src/components/tools/drawing-manager.js b/src/components/tools/drawing-manager.js index 8f7c8a8a5..08d1ef5e0 100644 --- a/src/components/tools/drawing-manager.js +++ b/src/components/tools/drawing-manager.js @@ -9,16 +9,12 @@ AFRAME.registerComponent("drawing-manager", { this._onComponentInitialized = this._onComponentInitialized.bind(this); this.drawingToPen = new Map(); - - this.drawingEl = document.createElement("a-entity"); - this.drawingEl.setAttribute("networked", "template: #interactable-drawing"); - this.el.sceneEl.appendChild(this.drawingEl); - - this.drawingEl.addEventListener("componentinitialized", this._onComponentInitialized); }, remove() { - this.drawingEl.removeEventListener("componentinitialized", this._onComponentInitialized); + if (this.drawingEl) { + this.drawingEl.removeEventListener("componentinitialized", this._onComponentInitialized); + } }, _onComponentInitialized(e) { @@ -27,6 +23,16 @@ AFRAME.registerComponent("drawing-manager", { } }, + createDrawing() { + if (!this.drawingEl) { + this.drawingEl = document.createElement("a-entity"); + this.drawingEl.setAttribute("networked", "template: #interactable-drawing"); + this.el.sceneEl.appendChild(this.drawingEl); + + this.drawingEl.addEventListener("componentinitialized", this._onComponentInitialized); + } + }, + getDrawing(pen) { //TODO: future handling of multiple drawings if (this.drawing && (!this.drawingToPen.has(this.drawing) || this.drawingToPen.get(this.drawing) === pen)) { diff --git a/src/components/tools/networked-drawing.js b/src/components/tools/networked-drawing.js index 61b024f9c..19b3c4855 100644 --- a/src/components/tools/networked-drawing.js +++ b/src/components/tools/networked-drawing.js @@ -24,7 +24,6 @@ AFRAME.registerComponent("networked-drawing", { schema: { segments: { default: 8 }, //the number of "sides" the procedural tube should have defaultRadius: { default: 0.01 }, //the radius of the procedural tube - minDrawTimeout: { default: 5000 }, //the minimum time a drawn line will live maxDrawTimeout: { default: 600000 }, //the maximum time a drawn line will live maxLines: { default: 50 }, //how many lines can persist before lines older than minDrawTime are removed maxPointsPerLine: { default: 250 } //the max number of points a single line can have @@ -56,7 +55,11 @@ AFRAME.registerComponent("networked-drawing", { const material = new THREE.MeshStandardMaterial(options); this.sharedBufferGeometryManager = new SharedBufferGeometryManager(); - this.sharedBufferGeometryManager.addSharedBuffer(0, material, THREE.TriangleStripDrawMode); + // NOTE: 20 is approximate for how many floats per line are added. + // maxLines + 1 because a line can be currently drawing while at maxLines. + // Multiply by 1/3 (0.333) because 3 floats per vertex (x, y, z). + const maxBufferSize = Math.round(this.data.maxPointsPerLine * 20 * (this.data.maxLines + 1) * 0.333); + this.sharedBufferGeometryManager.addSharedBuffer(0, material, THREE.TriangleStripDrawMode, maxBufferSize); this.lastPoint = new THREE.Vector3(); @@ -195,10 +198,7 @@ AFRAME.registerComponent("networked-drawing", { if (length > 0) { const now = Date.now(); const time = this.networkBufferHistory[0].time; - if ( - (length > this.data.maxLines && time + this.data.minDrawTimeout <= now) || - time + this.data.maxDrawTimeout <= now - ) { + if (length > this.data.maxLines || time + this.data.maxDrawTimeout <= now) { const datum = this.networkBufferHistory[0]; if (length > 1) { datum.idxLength += 2 - (this.segments % 2); diff --git a/src/components/tools/pen.js b/src/components/tools/pen.js index 06e0272ae..855c94e0a 100644 --- a/src/components/tools/pen.js +++ b/src/components/tools/pen.js @@ -64,6 +64,7 @@ AFRAME.registerComponent("pen", { play() { this.drawingManager = document.querySelector(this.data.drawingManager).components["drawing-manager"]; + this.drawingManager.createDrawing(); this.el.parentNode.addEventListener("stateadded", this._stateAdded); this.el.parentNode.addEventListener("stateremoved", this._stateRemoved); diff --git a/src/hub.html b/src/hub.html index 5238645f0..aafccdf20 100644 --- a/src/hub.html +++ b/src/hub.html @@ -191,6 +191,8 @@ radius="0.02" color="#FF0033" pen="camera: #player-camera; drawingManager: #drawing-manager" + widthSegments="8" + heightSegments="6" ></a-sphere> <a-entity class="delete-button" visible-while-frozen> <a-entity mixin="rounded-text-button" remove-networked-object-button position="0 0 0"> </a-entity> @@ -277,6 +279,8 @@ id="cursor" material="depthTest: false; opacity:0.9;" radius="0.02" + widthSegments="8" + heightSegments="6" static-body="shape: sphere;" collision-filter="collisionForces: false" super-hands=" @@ -292,8 +296,6 @@ dragDropEndButtons: cursor-release, primary_hand_release, secondary_hand_release; activateStartButtons: secondary-cursor-grab, secondary_hand_grab, next_color, previous_color, increase_radius, decrease_radius, scroll_up, scroll_down, scroll_left, scroll_right; activateEndButtons: secondary-cursor-release, secondary_hand_release, vertical_scroll_release, horizontal_scroll_release, thumb_up;" - segments-height="9" - segments-width="9" event-repeater="events: raycaster-intersection, raycaster-intersection-cleared; eventSource: #cursor-controller" ></a-sphere> diff --git a/src/utils/sharedbuffergeometry.js b/src/utils/sharedbuffergeometry.js index 0b044be87..d04f1ff0a 100644 --- a/src/utils/sharedbuffergeometry.js +++ b/src/utils/sharedbuffergeometry.js @@ -1,18 +1,19 @@ export default class SharedBufferGeometry { - constructor(material, primitiveMode) { + constructor(material, primitiveMode, maxBufferSize) { this.material = material; this.primitiveMode = primitiveMode; - this.maxBufferSize = 1000000; + console.log("maxBufferSize", maxBufferSize); + this.maxBufferSize = maxBufferSize; this.geometries = []; this.current = null; this.drawing = new THREE.Object3D(); - this.addBuffer(false); + this.addBuffer(); } restartPrimitive() { if (this.idx.position >= this.current.attributes.position.count) { - this.addBuffer(false); + console.error("maxBufferSize limit exceeded"); } else if (this.idx.position !== 0) { let prev = (this.idx.position - 1) * 3; const position = this.current.attributes.position.array; @@ -52,7 +53,7 @@ export default class SharedBufferGeometry { this.update(); } - addBuffer(copyLast) { + addBuffer() { const geometry = new THREE.BufferGeometry(); const vertices = new Float32Array(this.maxBufferSize * 3); @@ -88,24 +89,6 @@ export default class SharedBufferGeometry { this.geometries.push(geometry); this.current = geometry; - - if (this.previous && copyLast) { - let prev = (this.maxBufferSize - 2) * 3; - let col = (this.maxBufferSize - 2) * 3; - let norm = (this.maxBufferSize - 2) * 3; - - const position = this.previous.attributes.position.array; - this.addVertex(position[prev++], position[prev++], position[prev++]); - this.addVertex(position[prev++], position[prev++], position[prev++]); - - const normal = this.previous.attributes.normal.array; - this.addNormal(normal[norm++], normal[norm++], normal[norm++]); - this.addNormal(normal[norm++], normal[norm++], normal[norm++]); - - const color = this.previous.attributes.color.array; - this.addColor(color[col++], color[col++], color[col++]); - this.addColor(color[col++], color[col++], color[col++]); - } } addColor(r, g, b) { @@ -119,8 +102,7 @@ export default class SharedBufferGeometry { addVertex(x, y, z) { let buffer = this.current.attributes.position; if (this.idx.position === buffer.count) { - this.addBuffer(true); - buffer = this.current.attributes.position; + console.error("maxBufferSize limit exceeded"); } buffer.setXYZ(this.idx.position++, x, y, z); } diff --git a/src/utils/sharedbuffergeometrymanager.js b/src/utils/sharedbuffergeometrymanager.js index 1c5b37d9e..e96552a33 100644 --- a/src/utils/sharedbuffergeometrymanager.js +++ b/src/utils/sharedbuffergeometrymanager.js @@ -1,15 +1,15 @@ import SharedBufferGeometry from "./sharedbuffergeometry"; export default class SharedBufferGeometryManager { - constructor() { - this.sharedBuffers = {}; - } + constructor() { + this.sharedBuffers = {}; + } - addSharedBuffer(name, material, primitiveMode) { - this.sharedBuffers[name] = new SharedBufferGeometry(material, primitiveMode); - } + addSharedBuffer(name, material, primitiveMode, maxBufferSize) { + this.sharedBuffers[name] = new SharedBufferGeometry(material, primitiveMode, maxBufferSize); + } - getSharedBuffer(name) { - return this.sharedBuffers[name]; - } + getSharedBuffer(name) { + return this.sharedBuffers[name]; + } } -- GitLab