From 19649ac3d4e4f2eca770e003fd3aeb951867ddb0 Mon Sep 17 00:00:00 2001 From: Dave Pagurek Date: Wed, 21 Jun 2023 18:35:41 -0400 Subject: [PATCH 1/4] Improve performance of line rendering --- src/app.js | 1 + src/webgl/p5.DataVector.js | 52 +++++++++++++++++++ src/webgl/p5.Geometry.js | 77 ++++++++++++++-------------- src/webgl/p5.RenderBuffer.js | 4 +- src/webgl/p5.RendererGL.Immediate.js | 13 ++--- src/webgl/p5.RendererGL.Retained.js | 12 ++--- src/webgl/p5.RendererGL.js | 29 +++++++---- src/webgl/p5.Shader.js | 4 +- test/unit/webgl/p5.RendererGL.js | 6 +-- 9 files changed, 125 insertions(+), 73 deletions(-) create mode 100644 src/webgl/p5.DataVector.js diff --git a/src/app.js b/src/app.js index 763ed82a15..4cd7b6fc07 100644 --- a/src/app.js +++ b/src/app.js @@ -88,6 +88,7 @@ import './webgl/light'; import './webgl/loading'; import './webgl/material'; import './webgl/p5.Camera'; +import './webgl/p5.DataVector'; import './webgl/p5.Geometry'; import './webgl/p5.Matrix'; import './webgl/p5.RendererGL.Immediate'; diff --git a/src/webgl/p5.DataVector.js b/src/webgl/p5.DataVector.js new file mode 100644 index 0000000000..a259160857 --- /dev/null +++ b/src/webgl/p5.DataVector.js @@ -0,0 +1,52 @@ +import p5 from '../core/main'; + +p5.DataVector = class DataVector { + constructor(initialLength = 128) { + this.length = 0; + this.data = new Float32Array(initialLength); + this.initialLength = initialLength; + } + + clear() { + this.length = 0; + } + + rescale() { + if (this.length < this.data.length / 2) { + // Find the power of 2 size that fits the data + const targetLength = 1 << Math.ceil(Math.log2(this.length)); + const newData = new Float32Array(targetLength); + newData.set(this.data.subarray(0, this.length), 0); + this.data = newData; + } + } + + reset() { + this.clear(); + this.data = new Float32Array(this.initialLength); + } + + push(...values) { + this.ensureLength(this.length + values.length); + this.data.set(values, this.length); + this.length += values.length; + } + + slice(from, to) { + return this.data.slice(from, Math.min(to, this.length)); + } + + subArray(from, to) { + return this.data.subarray(from, Math.min(to, this.length)); + } + + ensureLength(target) { + while (this.data.length < target) { + const newData = new Float32Array(this.data.length * 2); + newData.set(this.data, 0); + this.data = newData; + } + } +}; + +export default p5.DataVector; diff --git a/src/webgl/p5.Geometry.js b/src/webgl/p5.Geometry.js index 4d05315bf5..f6828cbeeb 100644 --- a/src/webgl/p5.Geometry.js +++ b/src/webgl/p5.Geometry.js @@ -17,28 +17,28 @@ import p5 from '../core/main'; * @param {Integer} [detailY] number of vertices along the y-axis. * @param {function} [callback] function to call upon object instantiation. */ -p5.Geometry = class { +p5.Geometry = class Geometry { constructor(detailX, detailY, callback){ //an array containing every vertex //@type [p5.Vector] this.vertices = []; //an array containing every vertex for stroke drawing - this.lineVertices = []; + this.lineVertices = new p5.DataVector(); // The tangents going into or out of a vertex on a line. Along a straight // line segment, both should be equal. At an endpoint, one or the other // will not exist and will be all 0. In joins between line segments, they // may be different, as they will be the tangents on either side of the join. - this.lineTangentsIn = []; - this.lineTangentsOut = []; + this.lineTangentsIn = new p5.DataVector(); + this.lineTangentsOut = new p5.DataVector(); // When drawing lines with thickness, entries in this buffer represent which // side of the centerline the vertex will be placed. The sign of the number // will represent the side of the centerline, and the absolute value will be // used as an enum to determine which part of the cap or join each vertex // represents. See the doc comments for _addCap and _addJoin for diagrams. - this.lineSides = []; + this.lineSides = new p5.DataVector(); //an array containing 1 normal per vertex //@type [p5.Vector] @@ -60,7 +60,7 @@ p5.Geometry = class { // One color per line vertex, generated automatically based on // vertexStrokeColors in _edgesToVertices() - this.lineVertexColors = []; + this.lineVertexColors = new p5.DataVector(); this.detailX = detailX !== undefined ? detailX : 1; this.detailY = detailY !== undefined ? detailY : 1; this.dirtyFlags = {}; @@ -72,16 +72,16 @@ p5.Geometry = class { } reset() { - this.lineVertices.length = 0; - this.lineTangentsIn.length = 0; - this.lineTangentsOut.length = 0; - this.lineSides.length = 0; + this.lineVertices.clear(); + this.lineTangentsIn.clear(); + this.lineTangentsOut.clear(); + this.lineSides.clear(); this.vertices.length = 0; this.edges.length = 0; this.vertexColors.length = 0; this.vertexStrokeColors.length = 0; - this.lineVertexColors.length = 0; + this.lineVertexColors.clear(); this.vertexNormals.length = 0; this.uvs.length = 0; @@ -261,14 +261,14 @@ p5.Geometry = class { * @chainable */ _edgesToVertices() { - this.lineVertices.length = 0; - this.lineTangentsIn.length = 0; - this.lineTangentsOut.length = 0; - this.lineSides.length = 0; + this.lineVertices.clear(); + this.lineTangentsIn.clear(); + this.lineTangentsOut.clear(); + this.lineSides.clear(); const closed = - this.edges.length > 1 && - this.edges[0][0] === this.edges[this.edges.length - 1][1]; + this.edges.length > 1 && + this.edges[0][0] === this.edges[this.edges.length - 1][1]; let addedStartingCap = false; let lastValidDir; for (let i = 0; i < this.edges.length; i++) { @@ -374,18 +374,20 @@ p5.Geometry = class { const a = begin.array(); const b = end.array(); const dirArr = dir.array(); - this.lineSides.push(1, -1, 1, 1, -1, -1); + this.lineSides.push(1, 1, -1, 1, -1, -1); for (const tangents of [this.lineTangentsIn, this.lineTangentsOut]) { - tangents.push(dirArr, dirArr, dirArr, dirArr, dirArr, dirArr); + for (let i = 0; i < 6; i++) { + tangents.push(...dirArr); + } } - this.lineVertices.push(a, a, b, b, a, b); + this.lineVertices.push(...a, ...b, ...a, ...b, ...b, ...a); this.lineVertexColors.push( - fromColor, - fromColor, - toColor, - toColor, - fromColor, - toColor + ...fromColor, + ...toColor, + ...fromColor, + ...toColor, + ...toColor, + ...fromColor ); return this; } @@ -411,12 +413,12 @@ p5.Geometry = class { const tanInArray = tangent.array(); const tanOutArray = [0, 0, 0]; for (let i = 0; i < 6; i++) { - this.lineVertices.push(ptArray); - this.lineTangentsIn.push(tanInArray); - this.lineTangentsOut.push(tanOutArray); - this.lineVertexColors.push(color); + this.lineVertices.push(...ptArray); + this.lineTangentsIn.push(...tanInArray); + this.lineTangentsOut.push(...tanOutArray); + this.lineVertexColors.push(...color); } - this.lineSides.push(-1, -2, 2, 2, 1, -1); + this.lineSides.push(-1, 2, -2, 1, 2, -1); return this; } @@ -453,14 +455,13 @@ p5.Geometry = class { const tanInArray = fromTangent.array(); const tanOutArray = toTangent.array(); for (let i = 0; i < 12; i++) { - this.lineVertices.push(ptArray); - this.lineTangentsIn.push(tanInArray); - this.lineTangentsOut.push(tanOutArray); - this.lineVertexColors.push(color); - } - for (const side of [-1, 1]) { - this.lineSides.push(side, 2 * side, 3 * side, side, 3 * side, 0); + this.lineVertices.push(...ptArray); + this.lineTangentsIn.push(...tanInArray); + this.lineTangentsOut.push(...tanOutArray); + this.lineVertexColors.push(...color); } + this.lineSides.push(-1, -3, -2, -1, 0, -3); + this.lineSides.push(3, 1, 2, 3, 0, 1); return this; } diff --git a/src/webgl/p5.RenderBuffer.js b/src/webgl/p5.RenderBuffer.js index 246bc8fa29..79851e485f 100644 --- a/src/webgl/p5.RenderBuffer.js +++ b/src/webgl/p5.RenderBuffer.js @@ -61,11 +61,11 @@ p5.RenderBuffer = class { shader.enableAttrib(attr, this.size); } else { const loc = attr.location; - if (loc === -1 || !this._renderer.registerEnabled[loc]) { return; } + if (loc === -1 || !this._renderer.registerEnabled.has(loc)) { return; } // Disable register corresponding to unused attribute gl.disableVertexAttribArray(loc); // Record register availability - this._renderer.registerEnabled[loc] = false; + this._renderer.registerEnabled.delete(loc); } } }; diff --git a/src/webgl/p5.RendererGL.Immediate.js b/src/webgl/p5.RendererGL.Immediate.js index 442d37ddfa..63b40702fb 100644 --- a/src/webgl/p5.RendererGL.Immediate.js +++ b/src/webgl/p5.RendererGL.Immediate.js @@ -195,12 +195,12 @@ p5.RendererGL.prototype.endShape = function( this._processVertices(...arguments); this.isProcessingVertices = false; if (this._doFill) { - if (this.immediateMode.geometry.vertices.length > 1) { + if (this.immediateMode.geometry.vertices.length >= 3) { this._drawImmediateFill(); } } if (this._doStroke) { - if (this.immediateMode.geometry.lineVertices.length > 1) { + if (this.immediateMode.geometry.edges.length >= 1) { this._drawImmediateStroke(); } } @@ -415,10 +415,6 @@ p5.RendererGL.prototype._drawImmediateFill = function() { p5.RendererGL.prototype._drawImmediateStroke = function() { const gl = this.GL; - const faceCullingEnabled = gl.isEnabled(gl.CULL_FACE); - // Prevent strokes from getting removed by culling - gl.disable(gl.CULL_FACE); - const shader = this._getImmediateStrokeShader(); this._useLineColor = (this.immediateMode.geometry.vertexStrokeColors.length > 0); @@ -430,11 +426,8 @@ p5.RendererGL.prototype._drawImmediateStroke = function() { gl.drawArrays( gl.TRIANGLES, 0, - this.immediateMode.geometry.lineVertices.length + this.immediateMode.geometry.lineVertices.length / 3 ); - if (faceCullingEnabled) { - gl.enable(gl.CULL_FACE); - } shader.unbindShader(); }; diff --git a/src/webgl/p5.RendererGL.Retained.js b/src/webgl/p5.RendererGL.Retained.js index a6f9931333..95304ad035 100644 --- a/src/webgl/p5.RendererGL.Retained.js +++ b/src/webgl/p5.RendererGL.Retained.js @@ -103,7 +103,9 @@ p5.RendererGL.prototype.createBuffers = function(gId, model) { buffers.vertexCount = model.vertices ? model.vertices.length : 0; } - buffers.lineVertexCount = model.lineVertices ? model.lineVertices.length : 0; + buffers.lineVertexCount = model.lineVertices + ? model.lineVertices.length / 3 + : 0; return buffers; }; @@ -118,7 +120,7 @@ p5.RendererGL.prototype.drawBuffers = function(gId) { const gl = this.GL; const geometry = this.retainedMode.geometry[gId]; - if (this._doFill) { + if (this._doFill && this.retainedMode.geometry[gId].vertexCount > 0) { this._useVertexColor = (geometry.model.vertexColors.length > 0); const fillShader = this._getRetainedFillShader(); this._setFillUniforms(fillShader); @@ -135,9 +137,6 @@ p5.RendererGL.prototype.drawBuffers = function(gId) { } if (this._doStroke && geometry.lineVertexCount > 0) { - const faceCullingEnabled = gl.isEnabled(gl.CULL_FACE); - // Prevent strokes from getting removed by culling - gl.disable(gl.CULL_FACE); const strokeShader = this._getRetainedStrokeShader(); this._useLineColor = (geometry.model.vertexStrokeColors.length > 0); this._setStrokeUniforms(strokeShader); @@ -146,9 +145,6 @@ p5.RendererGL.prototype.drawBuffers = function(gId) { } this._applyColorBlend(this.curStrokeColor); this._drawArrays(gl.TRIANGLES, gId); - if (faceCullingEnabled) { - gl.enable(gl.CULL_FACE); - } strokeShader.unbindShader(); } diff --git a/src/webgl/p5.RendererGL.js b/src/webgl/p5.RendererGL.js index c85c873303..423c968fbf 100644 --- a/src/webgl/p5.RendererGL.js +++ b/src/webgl/p5.RendererGL.js @@ -465,7 +465,7 @@ p5.RendererGL = class RendererGL extends p5.Renderer { this._useLineColor = false; this._useVertexColor = false; - this.registerEnabled = []; + this.registerEnabled = new Set(); this._tint = [255, 255, 255, 255]; @@ -517,10 +517,10 @@ p5.RendererGL = class RendererGL extends p5.Renderer { geometry: {}, buffers: { stroke: [ - new p5.RenderBuffer(4, 'lineVertexColors', 'lineColorBuffer', 'aVertexColor', this, this._flatten), - new p5.RenderBuffer(3, 'lineVertices', 'lineVerticesBuffer', 'aPosition', this, this._flatten), - new p5.RenderBuffer(3, 'lineTangentsIn', 'lineTangentsInBuffer', 'aTangentIn', this, this._flatten), - new p5.RenderBuffer(3, 'lineTangentsOut', 'lineTangentsOutBuffer', 'aTangentOut', this, this._flatten), + new p5.RenderBuffer(4, 'lineVertexColors', 'lineColorBuffer', 'aVertexColor', this), + new p5.RenderBuffer(3, 'lineVertices', 'lineVerticesBuffer', 'aPosition', this), + new p5.RenderBuffer(3, 'lineTangentsIn', 'lineTangentsInBuffer', 'aTangentIn', this), + new p5.RenderBuffer(3, 'lineTangentsOut', 'lineTangentsOutBuffer', 'aTangentOut', this), new p5.RenderBuffer(1, 'lineSides', 'lineSidesBuffer', 'aSide', this) ], fill: [ @@ -555,10 +555,10 @@ p5.RendererGL = class RendererGL extends p5.Renderer { new p5.RenderBuffer(2, 'uvs', 'uvBuffer', 'aTexCoord', this, this._flatten) ], stroke: [ - new p5.RenderBuffer(4, 'lineVertexColors', 'lineColorBuffer', 'aVertexColor', this, this._flatten), - new p5.RenderBuffer(3, 'lineVertices', 'lineVerticesBuffer', 'aPosition', this, this._flatten), - new p5.RenderBuffer(3, 'lineTangentsIn', 'lineTangentsInBuffer', 'aTangentIn', this, this._flatten), - new p5.RenderBuffer(3, 'lineTangentsOut', 'lineTangentsOutBuffer', 'aTangentOut', this, this._flatten), + new p5.RenderBuffer(4, 'lineVertexColors', 'lineColorBuffer', 'aVertexColor', this), + new p5.RenderBuffer(3, 'lineVertices', 'lineVerticesBuffer', 'aPosition', this), + new p5.RenderBuffer(3, 'lineTangentsIn', 'lineTangentsInBuffer', 'aTangentIn', this), + new p5.RenderBuffer(3, 'lineTangentsOut', 'lineTangentsOutBuffer', 'aTangentOut', this), new p5.RenderBuffer(1, 'lineSides', 'lineSidesBuffer', 'aSide', this) ], point: this.GL.createBuffer() @@ -1622,7 +1622,16 @@ p5.RendererGL = class RendererGL extends p5.Renderer { if (!target) target = this.GL.ARRAY_BUFFER; this.GL.bindBuffer(target, buffer); if (values !== undefined) { - const data = new (type || Float32Array)(values); + if (values.data) { + // bufferData seems to send the whole Float32Array to the GPU even if + // it only uses a small part of it, so if we have a DataVector whose size is + // way larger than its data, we need to scale it back down + values.rescale(); + } + let data = values.data || values; + if (!(data instanceof (type || Float32Array))) { + data = new (type || Float32Array)(data); + } this.GL.bufferData(target, data, usage || this.GL.STATIC_DRAW); } } diff --git a/src/webgl/p5.Shader.js b/src/webgl/p5.Shader.js index ac4bf11bf2..5d6f258841 100644 --- a/src/webgl/p5.Shader.js +++ b/src/webgl/p5.Shader.js @@ -565,10 +565,10 @@ p5.Shader = class { if (loc !== -1) { const gl = this._renderer.GL; // Enable register even if it is disabled - if (!this._renderer.registerEnabled[loc]) { + if (!this._renderer.registerEnabled.has(loc)) { gl.enableVertexAttribArray(loc); // Record register availability - this._renderer.registerEnabled[loc] = true; + this._renderer.registerEnabled.add(loc); } this._renderer.GL.vertexAttribPointer( loc, diff --git a/test/unit/webgl/p5.RendererGL.js b/test/unit/webgl/p5.RendererGL.js index 0201eb440f..1872175e9e 100644 --- a/test/unit/webgl/p5.RendererGL.js +++ b/test/unit/webgl/p5.RendererGL.js @@ -1660,13 +1660,13 @@ suite('p5.RendererGL', function() { const attributes = renderer._curShader.attributes; const loc = attributes.aTexCoord.location; - assert.equal(renderer.registerEnabled[loc], true); + assert.equal(renderer.registerEnabled.has(loc), true); myp5.model(myGeom); - assert.equal(renderer.registerEnabled[loc], false); + assert.equal(renderer.registerEnabled.has(loc), false); myp5.triangle(-8, -8, 8, 8, -8, 8); - assert.equal(renderer.registerEnabled[loc], true); + assert.equal(renderer.registerEnabled.has(loc), true); done(); }); From 26f491f02b88735c7df11b60e0ecd2fa1bfae16e Mon Sep 17 00:00:00 2001 From: Dave Pagurek Date: Wed, 21 Jun 2023 19:17:06 -0400 Subject: [PATCH 2/4] Add comments --- src/webgl/p5.DataVector.js | 42 ++++++++++++++++++++++++++++++++++++++ src/webgl/p5.RendererGL.js | 12 ++++------- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/webgl/p5.DataVector.js b/src/webgl/p5.DataVector.js index a259160857..5c2aa360c2 100644 --- a/src/webgl/p5.DataVector.js +++ b/src/webgl/p5.DataVector.js @@ -1,5 +1,14 @@ import p5 from '../core/main'; +/** + * An internal class to store data that will be sent to a p5.RenderBuffer. + * Those need to eventually go into a Float32Array, so this class provides a + * variable-length array container backed by a Float32Array so that it can be + * sent to the GPU without allocating a new array each frame. + * + * Like a C++ vector, its fixed-length Float32Array backing its contents will + * double in size when it goes over its capacity. + */ p5.DataVector = class DataVector { constructor(initialLength = 128) { this.length = 0; @@ -7,10 +16,24 @@ p5.DataVector = class DataVector { this.initialLength = initialLength; } + /** + * Returns a Float32Array window sized to the exact length of the data + */ + dataArray() { + return this.subArray(0, this.length); + } + + /** + * A "soft" clear, which keeps the underlying storage size the same, but + * empties the contents of its dataArray() + */ clear() { this.length = 0; } + /** + * Can be used to scale a DataVector back down to fit its contents. + */ rescale() { if (this.length < this.data.length / 2) { // Find the power of 2 size that fits the data @@ -21,25 +44,44 @@ p5.DataVector = class DataVector { } } + /** + * A full reset, which allocates a new underlying Float32Array at its initial + * length + */ reset() { this.clear(); this.data = new Float32Array(this.initialLength); } + /** + * Adds values to the DataVector, expanding its internal storage to + * accommodate the new items. + */ push(...values) { this.ensureLength(this.length + values.length); this.data.set(values, this.length); this.length += values.length; } + /** + * Returns a copy of the data from the index `from`, inclusive, to the index + * `to`, exclusive + */ slice(from, to) { return this.data.slice(from, Math.min(to, this.length)); } + /** + * Returns a mutable Float32Array window from the index `from`, inclusive, to + * the index `to`, exclusive + */ subArray(from, to) { return this.data.subarray(from, Math.min(to, this.length)); } + /** + * Expand capacity of the internal storage until it can fit a target size + */ ensureLength(target) { while (this.data.length < target) { const newData = new Float32Array(this.data.length * 2); diff --git a/src/webgl/p5.RendererGL.js b/src/webgl/p5.RendererGL.js index 423c968fbf..afe0451d22 100644 --- a/src/webgl/p5.RendererGL.js +++ b/src/webgl/p5.RendererGL.js @@ -1622,14 +1622,10 @@ p5.RendererGL = class RendererGL extends p5.Renderer { if (!target) target = this.GL.ARRAY_BUFFER; this.GL.bindBuffer(target, buffer); if (values !== undefined) { - if (values.data) { - // bufferData seems to send the whole Float32Array to the GPU even if - // it only uses a small part of it, so if we have a DataVector whose size is - // way larger than its data, we need to scale it back down - values.rescale(); - } - let data = values.data || values; - if (!(data instanceof (type || Float32Array))) { + let data = values; + if (values instanceof p5.DataVector) { + data = values.dataArray(); + } else if (!(data instanceof (type || Float32Array))) { data = new (type || Float32Array)(data); } this.GL.bufferData(target, data, usage || this.GL.STATIC_DRAW); From 7f43aea5b62aeb0daac3ae9355fa654e3f0b1005 Mon Sep 17 00:00:00 2001 From: Dave Pagurek Date: Thu, 22 Jun 2023 07:53:07 -0400 Subject: [PATCH 3/4] Rename DataVector to DataArray --- src/app.js | 2 +- src/webgl/{p5.DataVector.js => p5.DataArray.js} | 8 ++++---- src/webgl/p5.Geometry.js | 10 +++++----- src/webgl/p5.RendererGL.js | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) rename src/webgl/{p5.DataVector.js => p5.DataArray.js} (92%) diff --git a/src/app.js b/src/app.js index 4cd7b6fc07..1bbb7d1be2 100644 --- a/src/app.js +++ b/src/app.js @@ -88,7 +88,7 @@ import './webgl/light'; import './webgl/loading'; import './webgl/material'; import './webgl/p5.Camera'; -import './webgl/p5.DataVector'; +import './webgl/p5.DataArray'; import './webgl/p5.Geometry'; import './webgl/p5.Matrix'; import './webgl/p5.RendererGL.Immediate'; diff --git a/src/webgl/p5.DataVector.js b/src/webgl/p5.DataArray.js similarity index 92% rename from src/webgl/p5.DataVector.js rename to src/webgl/p5.DataArray.js index 5c2aa360c2..7aa240c107 100644 --- a/src/webgl/p5.DataVector.js +++ b/src/webgl/p5.DataArray.js @@ -9,7 +9,7 @@ import p5 from '../core/main'; * Like a C++ vector, its fixed-length Float32Array backing its contents will * double in size when it goes over its capacity. */ -p5.DataVector = class DataVector { +p5.DataArray = class DataArray { constructor(initialLength = 128) { this.length = 0; this.data = new Float32Array(initialLength); @@ -32,7 +32,7 @@ p5.DataVector = class DataVector { } /** - * Can be used to scale a DataVector back down to fit its contents. + * Can be used to scale a DataArray back down to fit its contents. */ rescale() { if (this.length < this.data.length / 2) { @@ -54,7 +54,7 @@ p5.DataVector = class DataVector { } /** - * Adds values to the DataVector, expanding its internal storage to + * Adds values to the DataArray, expanding its internal storage to * accommodate the new items. */ push(...values) { @@ -91,4 +91,4 @@ p5.DataVector = class DataVector { } }; -export default p5.DataVector; +export default p5.DataArray; diff --git a/src/webgl/p5.Geometry.js b/src/webgl/p5.Geometry.js index f6828cbeeb..65fee0a7f7 100644 --- a/src/webgl/p5.Geometry.js +++ b/src/webgl/p5.Geometry.js @@ -24,21 +24,21 @@ p5.Geometry = class Geometry { this.vertices = []; //an array containing every vertex for stroke drawing - this.lineVertices = new p5.DataVector(); + this.lineVertices = new p5.DataArray(); // The tangents going into or out of a vertex on a line. Along a straight // line segment, both should be equal. At an endpoint, one or the other // will not exist and will be all 0. In joins between line segments, they // may be different, as they will be the tangents on either side of the join. - this.lineTangentsIn = new p5.DataVector(); - this.lineTangentsOut = new p5.DataVector(); + this.lineTangentsIn = new p5.DataArray(); + this.lineTangentsOut = new p5.DataArray(); // When drawing lines with thickness, entries in this buffer represent which // side of the centerline the vertex will be placed. The sign of the number // will represent the side of the centerline, and the absolute value will be // used as an enum to determine which part of the cap or join each vertex // represents. See the doc comments for _addCap and _addJoin for diagrams. - this.lineSides = new p5.DataVector(); + this.lineSides = new p5.DataArray(); //an array containing 1 normal per vertex //@type [p5.Vector] @@ -60,7 +60,7 @@ p5.Geometry = class Geometry { // One color per line vertex, generated automatically based on // vertexStrokeColors in _edgesToVertices() - this.lineVertexColors = new p5.DataVector(); + this.lineVertexColors = new p5.DataArray(); this.detailX = detailX !== undefined ? detailX : 1; this.detailY = detailY !== undefined ? detailY : 1; this.dirtyFlags = {}; diff --git a/src/webgl/p5.RendererGL.js b/src/webgl/p5.RendererGL.js index afe0451d22..dd02e1b9ff 100644 --- a/src/webgl/p5.RendererGL.js +++ b/src/webgl/p5.RendererGL.js @@ -1623,7 +1623,7 @@ p5.RendererGL = class RendererGL extends p5.Renderer { this.GL.bindBuffer(target, buffer); if (values !== undefined) { let data = values; - if (values instanceof p5.DataVector) { + if (values instanceof p5.DataArray) { data = values.dataArray(); } else if (!(data instanceof (type || Float32Array))) { data = new (type || Float32Array)(data); From 3efab94f2e4da8d227ae1dc2eac50745ce6725d2 Mon Sep 17 00:00:00 2001 From: Dave Pagurek Date: Thu, 22 Jun 2023 07:59:39 -0400 Subject: [PATCH 4/4] Add docs example --- src/webgl/p5.DataArray.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/webgl/p5.DataArray.js b/src/webgl/p5.DataArray.js index 7aa240c107..9ab0c2eaf2 100644 --- a/src/webgl/p5.DataArray.js +++ b/src/webgl/p5.DataArray.js @@ -8,6 +8,22 @@ import p5 from '../core/main'; * * Like a C++ vector, its fixed-length Float32Array backing its contents will * double in size when it goes over its capacity. + * + * @example + *
+ * + * // Initialize storage with a capacity of 4 + * const storage = new DataArray(4); + * console.log(storage.data.length); // 4 + * console.log(storage.length); // 0 + * console.log(storage.dataArray()); // Empty Float32Array + * + * storage.push(1, 2, 3, 4, 5, 6); + * console.log(storage.data.length); // 8 + * console.log(storage.length); // 6 + * console.log(storage.dataArray()); // Float32Array{1, 2, 3, 4, 5, 6} + * + *
*/ p5.DataArray = class DataArray { constructor(initialLength = 128) {