diff --git a/modules/core/src/lib/attribute/attribute.js b/modules/core/src/lib/attribute/attribute.js index 30286b4d7aa..4ea36613260 100644 --- a/modules/core/src/lib/attribute/attribute.js +++ b/modules/core/src/lib/attribute/attribute.js @@ -250,11 +250,14 @@ export default class Attribute extends DataColumn { buffer = {value: buffer}; } assert(ArrayBuffer.isView(buffer.value), `invalid ${settings.accessor}`); + const needsNormalize = buffer.size && buffer.size !== this.size; state.logicalAccessor = getAccessorFromBuffer(buffer.value, { - ...settings, - ...buffer, - startIndices + size: buffer.size || this.size, + stride: buffer.stride, + offset: buffer.offset, + startIndices, + nested: needsNormalize }); // Fall through to auto updater return false; @@ -285,6 +288,7 @@ export default class Attribute extends DataColumn { return shaderAttributes; } + /* eslint-disable max-depth, max-statements */ _autoUpdater(attribute, {data, startRow, endRow, props, numInstances}) { const {settings, state, value, size, startIndices} = attribute; diff --git a/modules/core/src/utils/iterable-utils.js b/modules/core/src/utils/iterable-utils.js index ee5763f6604..5a470adb068 100644 --- a/modules/core/src/utils/iterable-utils.js +++ b/modules/core/src/utils/iterable-utils.js @@ -64,30 +64,45 @@ export function isAsyncIterable(data) { /* * Create an accessor function from a flat buffer that yields the value at each object index */ -export function getAccessorFromBuffer(typedArray, opts) { - const {size, stride, offset, vertexStarts} = opts; +export function getAccessorFromBuffer(typedArray, {size, stride, offset, startIndices, nested}) { const bytesPerElement = typedArray.BYTES_PER_ELEMENT; const elementStride = stride ? stride / bytesPerElement : size; const elementOffset = offset ? offset / bytesPerElement : 0; const vertexCount = Math.floor((typedArray.length - elementOffset) / elementStride); return (_, {index, target}) => { - if (vertexStarts) { - const startVertex = vertexStarts[index]; - const endVertex = vertexStarts[index + 1] || vertexCount; - const result = new typedArray.constructor((endVertex - startVertex) * size); - for (let i = startVertex, targetIndex = 0; i < endVertex; i++) { + if (!startIndices) { + const sourceIndex = index * elementStride + elementOffset; + for (let j = 0; j < size; j++) { + target[j] = typedArray[sourceIndex + j]; + } + return target; + } + const startIndex = startIndices[index]; + const endIndex = startIndices[index + 1] || vertexCount; + let result; + + if (nested) { + result = new Array(endIndex - startIndex); + for (let i = startIndex; i < endIndex; i++) { + const sourceIndex = i * elementStride + elementOffset; + target = new Array(size); + for (let j = 0; j < size; j++) { + target[j] = typedArray[sourceIndex + j]; + } + result[i - startIndex] = target; + } + } else { + result = new typedArray.constructor((endIndex - startIndex) * size); + let targetIndex = 0; + for (let i = startIndex; i < endIndex; i++) { const sourceIndex = i * elementStride + elementOffset; for (let j = 0; j < size; j++) { result[targetIndex++] = typedArray[sourceIndex + j]; } } - return result; } - const sourceIndex = index * elementStride + elementOffset; - for (let j = 0; j < size; j++) { - target[j] = typedArray[sourceIndex + j]; - } - return target; + + return result; }; } diff --git a/test/modules/core/utils/iterable-utils.spec.js b/test/modules/core/utils/iterable-utils.spec.js index 23bdf44ac03..c929fd8edd1 100644 --- a/test/modules/core/utils/iterable-utils.spec.js +++ b/test/modules/core/utils/iterable-utils.spec.js @@ -133,7 +133,7 @@ test('getAccessorFromBuffer', t => { input: { value: new Float32Array([1, 1, 0, 2, 2, 0, 3, 3, 0]), size: 3, - vertexStarts: [0, 2] + startIndices: [0, 2] }, output: [[1, 1, 0, 2, 2, 0], [3, 3, 0]] }, @@ -144,9 +144,19 @@ test('getAccessorFromBuffer', t => { size: 2, stride: 12, offset: 12, - vertexStarts: [0, 2] + startIndices: [0, 2] }, output: [[1, 1, 2, 2], [3, 3]] + }, + { + title: 'variable-width buffer nested', + input: { + value: new Float32Array([1, 1, 0, 2, 2, 0, 3, 3, 0]), + size: 3, + startIndices: [0, 2], + nested: true + }, + output: [[[1, 1, 0], [2, 2, 0]], [[3, 3, 0]]] } ];