diff --git a/src/core/InternalMeshAttributeBuffer.js b/src/core/InternalMeshAttributeBuffer.js index 9fc1f544..a98758db 100644 --- a/src/core/InternalMeshAttributeBuffer.js +++ b/src/core/InternalMeshAttributeBuffer.js @@ -147,33 +147,50 @@ export class InternalMeshAttributeBuffer { this.#fireBufferChanged(); } + /** + * Asserts that the provided `pos` value adheres to the expected format according to the attributeSettings. + * @param {number | Vec2 | Vec3 | Vec4} pos + * @param {MeshAttributeSettings} attributeSettings + * @param {boolean | undefined} meshHasVertexState + */ + #assertVertexDataTypes(pos, attributeSettings, meshHasVertexState) { + if (attributeSettings.componentCount == 1) { + this.#assertVertexDataType(typeof pos == "number", attributeSettings, "number", pos, meshHasVertexState); + } else if (attributeSettings.componentCount == 2) { + this.#assertVertexDataType(pos instanceof Vec2, attributeSettings, "Vec2", pos, meshHasVertexState); + } else if (attributeSettings.componentCount == 3) { + this.#assertVertexDataType(pos instanceof Vec3, attributeSettings, "Vec3", pos, meshHasVertexState); + } else if (attributeSettings.componentCount == 4) { + this.#assertVertexDataType(pos instanceof Vec4, attributeSettings, "Vec4", pos, meshHasVertexState); + } + } + /** * @param {boolean} assertion * @param {MeshAttributeSettings} attributeSettings * @param {string} expectedText - * @param {number[] | Vec2[] | Vec3[] | Vec4[]} dataArray + * @param {number | Vec2 | Vec3 | Vec4} firstIterableItem * @param {boolean | undefined} meshHasVertexState */ - #assertVertexDataType(assertion, attributeSettings, expectedText, dataArray, meshHasVertexState) { + #assertVertexDataType(assertion, attributeSettings, expectedText, firstIterableItem, meshHasVertexState) { if (!assertion) { let dataType; - const firstArrayItem = dataArray[0]; let receivedComponentCount = null; - if (typeof firstArrayItem == "number") { + if (typeof firstIterableItem == "number") { receivedComponentCount = 1; - } else if (firstArrayItem instanceof Vec2) { + } else if (firstIterableItem instanceof Vec2) { receivedComponentCount = 2; - } else if (firstArrayItem instanceof Vec3) { + } else if (firstIterableItem instanceof Vec3) { receivedComponentCount = 3; - } else if (firstArrayItem instanceof Vec4) { + } else if (firstIterableItem instanceof Vec4) { receivedComponentCount = 4; } else { - throw new Error("Assertion failed, unexpected array type: " + firstArrayItem); + throw new Error("Assertion failed, unexpected iterable type: " + firstIterableItem); } - if (firstArrayItem != null && firstArrayItem != undefined) { - dataType = firstArrayItem.constructor.name; + if (firstIterableItem != null && firstIterableItem != undefined) { + dataType = firstIterableItem.constructor.name; } else { - dataType = String(firstArrayItem); + dataType = String(firstIterableItem); } const fixesList = []; let vertexStateSentence; @@ -187,20 +204,20 @@ export class InternalMeshAttributeBuffer { fixesList.push(`add a VertexState with "${attributeName}" attribute.`); } fixesList.push(`set the \`unusedComponentCount\` option of \`setVertexData()\` to ${receivedComponentCount}.`); - fixesList.push(`provide a ${expectedText} array.`); + fixesList.push(`provide a ${expectedText} iterable.`); } else { vertexStateSentence = `The VertexState for this attribute has a componentCount of ${attributeSettings.componentCount}.`; fixesList.push(`set the componentCount of "${attributeName}" in your VertexState to ${receivedComponentCount}.`); - fixesList.push(`provide a ${expectedText} array.`); + fixesList.push(`provide a ${expectedText} iterable.`); } const fixesStr = fixesList.map((str) => " - " + str).join("\n"); - throw new TypeError(`Expected a ${expectedText} array but received a ${dataType} array.\n${vertexStateSentence}\nPotential fixes:\n${fixesStr}`); + throw new TypeError(`Expected a ${expectedText} iterable but received a ${dataType} iterable.\n${vertexStateSentence}\nPotential fixes:\n${fixesStr}`); } } /** * @param {import("./Mesh.js").AttributeType} attributeType - * @param {ArrayBufferLike | number[] | Vec2[] | Vec3[] | Vec4[]} data + * @param {ArrayBuffer | Iterable} data * @param {boolean} meshHasVertexState A hint that is used to provide more helpful error messages. * Set to true if the linked mesh contains a vertex state. */ @@ -241,42 +258,55 @@ export class InternalMeshAttributeBuffer { new Uint8Array(this.buffer).set(new Uint8Array(data)); } else if (ArrayBuffer.isView(data)) { new Uint8Array(this.buffer).set(new Uint8Array(data.buffer, data.byteOffset, data.byteLength)); - } else if (Array.isArray(data)) { - if (data.length <= 0) { - return; - } else if (attributeSettings.componentCount == 1) { - let i = 0; - this.#assertVertexDataType(typeof data[0] == "number", attributeSettings, "number", data, meshHasVertexState); - const castData = /** @type {number[]} */ (data); - while (i < castData.length) { + } else if (data != null && typeof data[Symbol.iterator] == "function") { + let didAssertType = false; + + /** + * @param {number | Vec2 | Vec3 | Vec4} pos + */ + const assertType = (pos) => { + if (!didAssertType) { + this.#assertVertexDataTypes(pos, attributeSettings, meshHasVertexState); + didAssertType = true; + } + }; + + let i = 0; + if (attributeSettings.componentCount == 1) { + const castData = /** @type {Iterable} */ (data); + for (const pos of castData) { + assertType(pos); for (let j = 0; j < attributeSettings.componentCount; j++) { - setFunction(i * this.arrayStride + attributeSettings.offset + valueByteSize * j, castData[i], true); + setFunction(i * this.arrayStride + attributeSettings.offset + valueByteSize * j, pos, true); } i++; } } else if (attributeSettings.componentCount == 2) { - this.#assertVertexDataType(data[0] instanceof Vec2, attributeSettings, "Vec2", data, meshHasVertexState); - const castData = /** @type {Vec2[]} */ (data); - for (const [i, pos] of castData.entries()) { + const castData = /** @type {Iterable} */ (data); + for (const pos of castData) { + assertType(pos); setFunction(i * this.arrayStride + attributeSettings.offset + valueByteSize * 0, pos.x, true); setFunction(i * this.arrayStride + attributeSettings.offset + valueByteSize * 1, pos.y, true); + i++; } } else if (attributeSettings.componentCount == 3) { - this.#assertVertexDataType(data[0] instanceof Vec3, attributeSettings, "Vec3", data, meshHasVertexState); - const castData = /** @type {Vec3[]} */ (data); - for (const [i, pos] of castData.entries()) { + const castData = /** @type {Iterable} */ (data); + for (const pos of castData) { + assertType(pos); setFunction(i * this.arrayStride + attributeSettings.offset + valueByteSize * 0, pos.x, true); setFunction(i * this.arrayStride + attributeSettings.offset + valueByteSize * 1, pos.y, true); setFunction(i * this.arrayStride + attributeSettings.offset + valueByteSize * 2, pos.z, true); + i++; } } else if (attributeSettings.componentCount == 4) { - this.#assertVertexDataType(data[0] instanceof Vec4, attributeSettings, "Vec4", data, meshHasVertexState); - const castData = /** @type {Vec4[]} */ (data); - for (const [i, pos] of castData.entries()) { + const castData = /** @type {Iterable} */ (data); + for (const pos of castData) { + assertType(pos); setFunction(i * this.arrayStride + attributeSettings.offset + valueByteSize * 0, pos.x, true); setFunction(i * this.arrayStride + attributeSettings.offset + valueByteSize * 1, pos.y, true); setFunction(i * this.arrayStride + attributeSettings.offset + valueByteSize * 2, pos.z, true); setFunction(i * this.arrayStride + attributeSettings.offset + valueByteSize * 3, pos.w, true); + i++; } } } diff --git a/src/core/Mesh.js b/src/core/Mesh.js index b6ced9f8..5b97ada2 100644 --- a/src/core/Mesh.js +++ b/src/core/Mesh.js @@ -298,7 +298,7 @@ export class Mesh { * If you still wish to store vertex data in 'unused' buffers, * make sure to provide a `unusedFormat` and a `unusedComponentCount` to avoid errors. * @param {AttributeType} attributeType - * @param {ArrayBufferLike | number[] | import("../math/Vec2.js").Vec2[] | import("../math/Vec3.js").Vec3[] | import("../math/Vec4.js").Vec4[]} data + * @param {ArrayBuffer | Iterable} data * @param {UnusedAttributeBufferOptions} [opts] */ setVertexData(attributeType, data, opts) { diff --git a/test/unit/src/core/InternalMeshAttributeBuffer/InternalMeshAttributeBuffer.test.js b/test/unit/src/core/InternalMeshAttributeBuffer/InternalMeshAttributeBuffer.test.js index 78c7f379..f80c1dc7 100644 --- a/test/unit/src/core/InternalMeshAttributeBuffer/InternalMeshAttributeBuffer.test.js +++ b/test/unit/src/core/InternalMeshAttributeBuffer/InternalMeshAttributeBuffer.test.js @@ -404,6 +404,59 @@ Deno.test({ }, }); +Deno.test({ + name: "setVertexData() generator of numbers", + fn() { + const buffer = new InternalMeshAttributeBuffer({ + attributeSettings: [{ offset: 0, format: Mesh.AttributeFormat.FLOAT32, componentCount: 1, attributeType: Mesh.AttributeType.POSITION }], + }); + buffer.setVertexCount(3); + + const generatorFn = function *() { + yield 1; + yield 2; + yield 3; + }; + + buffer.setVertexData(Mesh.AttributeType.POSITION, generatorFn(), false); + + assertEquals(Array.from(buffer.getVertexData(Mesh.AttributeType.POSITION)), [1, 2, 3]); + + const dataView = new DataView(buffer.buffer); + assertEquals(dataView.getFloat32(0, true), 1); + assertEquals(dataView.getFloat32(4, true), 2); + assertEquals(dataView.getFloat32(8, true), 3); + }, +}); + +Deno.test({ + name: "setVertexData() generator of Vec2", + fn() { + const buffer = new InternalMeshAttributeBuffer({ + attributeSettings: [{ offset: 0, format: Mesh.AttributeFormat.FLOAT32, componentCount: 2, attributeType: Mesh.AttributeType.POSITION }], + }); + buffer.setVertexCount(2); + + const generatorFn = function *() { + yield new Vec2(1, 2); + yield new Vec2(3, 4); + }; + + buffer.setVertexData(Mesh.AttributeType.POSITION, generatorFn(), false); + + const data = Array.from(buffer.getVertexData(Mesh.AttributeType.POSITION)); + assertEquals(data.length, 2); + assertVecAlmostEquals(data[0], [1, 2]); + assertVecAlmostEquals(data[1], [3, 4]); + + const dataView = new DataView(buffer.buffer); + assertEquals(dataView.getFloat32(0, true), 1); + assertEquals(dataView.getFloat32(4, true), 2); + assertEquals(dataView.getFloat32(8, true), 3); + assertEquals(dataView.getFloat32(12, true), 4); + }, +}); + Deno.test({ name: "setVertexData() should throw when the attribute type is not present", fn() { @@ -425,27 +478,27 @@ Deno.test({ assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [new Vec2(), new Vec2()], false); - }, Error, `Expected a number array but received a Vec2 array. + }, Error, `Expected a number iterable but received a Vec2 iterable. The VertexState for this attribute has a componentCount of 1. Potential fixes: - set the componentCount of "POSITION" in your VertexState to 2. - - provide a number array.`); + - provide a number iterable.`); assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [new Vec3(), new Vec3()], false); - }, Error, `Expected a number array but received a Vec3 array. + }, Error, `Expected a number iterable but received a Vec3 iterable. The VertexState for this attribute has a componentCount of 1. Potential fixes: - set the componentCount of "POSITION" in your VertexState to 3. - - provide a number array.`); + - provide a number iterable.`); assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [new Vec4(), new Vec4()], false); - }, Error, `Expected a number array but received a Vec4 array. + }, Error, `Expected a number iterable but received a Vec4 iterable. The VertexState for this attribute has a componentCount of 1. Potential fixes: - set the componentCount of "POSITION" in your VertexState to 4. - - provide a number array.`); + - provide a number iterable.`); }, }); @@ -460,30 +513,30 @@ Deno.test({ assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [new Vec2(), new Vec2()], false); - }, Error, `Expected a number array but received a Vec2 array. + }, Error, `Expected a number iterable but received a Vec2 iterable. The mesh has no VertexState. Potential fixes: - add a VertexState with "POSITION" attribute. - set the \`unusedComponentCount\` option of \`setVertexData()\` to 2. - - provide a number array.`); + - provide a number iterable.`); assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [new Vec3(), new Vec3()], false); - }, Error, `Expected a number array but received a Vec3 array. + }, Error, `Expected a number iterable but received a Vec3 iterable. The mesh has no VertexState. Potential fixes: - add a VertexState with "POSITION" attribute. - set the \`unusedComponentCount\` option of \`setVertexData()\` to 3. - - provide a number array.`); + - provide a number iterable.`); assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [new Vec4(), new Vec4()], false); - }, Error, `Expected a number array but received a Vec4 array. + }, Error, `Expected a number iterable but received a Vec4 iterable. The mesh has no VertexState. Potential fixes: - add a VertexState with "POSITION" attribute. - set the \`unusedComponentCount\` option of \`setVertexData()\` to 4. - - provide a number array.`); + - provide a number iterable.`); }, }); @@ -497,27 +550,27 @@ Deno.test({ assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [1, 2], false); - }, Error, `Expected a Vec2 array but received a Number array. + }, Error, `Expected a Vec2 iterable but received a Number iterable. The VertexState for this attribute has a componentCount of 2. Potential fixes: - set the componentCount of "POSITION" in your VertexState to 1. - - provide a Vec2 array.`); + - provide a Vec2 iterable.`); assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [new Vec3(), new Vec3()], false); - }, Error, `Expected a Vec2 array but received a Vec3 array. + }, Error, `Expected a Vec2 iterable but received a Vec3 iterable. The VertexState for this attribute has a componentCount of 2. Potential fixes: - set the componentCount of "POSITION" in your VertexState to 3. - - provide a Vec2 array.`); + - provide a Vec2 iterable.`); assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [new Vec4(), new Vec4()], false); - }, Error, `Expected a Vec2 array but received a Vec4 array. + }, Error, `Expected a Vec2 iterable but received a Vec4 iterable. The VertexState for this attribute has a componentCount of 2. Potential fixes: - set the componentCount of "POSITION" in your VertexState to 4. - - provide a Vec2 array.`); + - provide a Vec2 iterable.`); }, }); @@ -532,30 +585,30 @@ Deno.test({ assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [1, 2], false); - }, Error, `Expected a Vec2 array but received a Number array. + }, Error, `Expected a Vec2 iterable but received a Number iterable. The mesh has no VertexState. Potential fixes: - add a VertexState with "POSITION" attribute. - set the \`unusedComponentCount\` option of \`setVertexData()\` to 1. - - provide a Vec2 array.`); + - provide a Vec2 iterable.`); assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [new Vec3(), new Vec3()], false); - }, Error, `Expected a Vec2 array but received a Vec3 array. + }, Error, `Expected a Vec2 iterable but received a Vec3 iterable. The mesh has no VertexState. Potential fixes: - add a VertexState with "POSITION" attribute. - set the \`unusedComponentCount\` option of \`setVertexData()\` to 3. - - provide a Vec2 array.`); + - provide a Vec2 iterable.`); assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [new Vec4(), new Vec4()], false); - }, Error, `Expected a Vec2 array but received a Vec4 array. + }, Error, `Expected a Vec2 iterable but received a Vec4 iterable. The mesh has no VertexState. Potential fixes: - add a VertexState with "POSITION" attribute. - set the \`unusedComponentCount\` option of \`setVertexData()\` to 4. - - provide a Vec2 array.`); + - provide a Vec2 iterable.`); }, }); @@ -569,27 +622,27 @@ Deno.test({ assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [1, 2], false); - }, Error, `Expected a Vec3 array but received a Number array. + }, Error, `Expected a Vec3 iterable but received a Number iterable. The VertexState for this attribute has a componentCount of 3. Potential fixes: - set the componentCount of "POSITION" in your VertexState to 1. - - provide a Vec3 array.`); + - provide a Vec3 iterable.`); assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [new Vec2(), new Vec2()], false); - }, Error, `Expected a Vec3 array but received a Vec2 array. + }, Error, `Expected a Vec3 iterable but received a Vec2 iterable. The VertexState for this attribute has a componentCount of 3. Potential fixes: - set the componentCount of "POSITION" in your VertexState to 2. - - provide a Vec3 array.`); + - provide a Vec3 iterable.`); assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [new Vec4(), new Vec4()], false); - }, Error, `Expected a Vec3 array but received a Vec4 array. + }, Error, `Expected a Vec3 iterable but received a Vec4 iterable. The VertexState for this attribute has a componentCount of 3. Potential fixes: - set the componentCount of "POSITION" in your VertexState to 4. - - provide a Vec3 array.`); + - provide a Vec3 iterable.`); }, }); @@ -604,30 +657,30 @@ Deno.test({ assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [1, 2], false); - }, Error, `Expected a Vec3 array but received a Number array. + }, Error, `Expected a Vec3 iterable but received a Number iterable. The mesh has no VertexState. Potential fixes: - add a VertexState with "POSITION" attribute. - set the \`unusedComponentCount\` option of \`setVertexData()\` to 1. - - provide a Vec3 array.`); + - provide a Vec3 iterable.`); assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [new Vec2(), new Vec2()], false); - }, Error, `Expected a Vec3 array but received a Vec2 array. + }, Error, `Expected a Vec3 iterable but received a Vec2 iterable. The mesh has no VertexState. Potential fixes: - add a VertexState with "POSITION" attribute. - set the \`unusedComponentCount\` option of \`setVertexData()\` to 2. - - provide a Vec3 array.`); + - provide a Vec3 iterable.`); assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [new Vec4(), new Vec4()], false); - }, Error, `Expected a Vec3 array but received a Vec4 array. + }, Error, `Expected a Vec3 iterable but received a Vec4 iterable. The mesh has no VertexState. Potential fixes: - add a VertexState with "POSITION" attribute. - set the \`unusedComponentCount\` option of \`setVertexData()\` to 4. - - provide a Vec3 array.`); + - provide a Vec3 iterable.`); }, }); @@ -641,27 +694,27 @@ Deno.test({ assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [1, 2], false); - }, Error, `Expected a Vec4 array but received a Number array. + }, Error, `Expected a Vec4 iterable but received a Number iterable. The VertexState for this attribute has a componentCount of 4. Potential fixes: - set the componentCount of "POSITION" in your VertexState to 1. - - provide a Vec4 array.`); + - provide a Vec4 iterable.`); assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [new Vec2(), new Vec2()], false); - }, Error, `Expected a Vec4 array but received a Vec2 array. + }, Error, `Expected a Vec4 iterable but received a Vec2 iterable. The VertexState for this attribute has a componentCount of 4. Potential fixes: - set the componentCount of "POSITION" in your VertexState to 2. - - provide a Vec4 array.`); + - provide a Vec4 iterable.`); assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [new Vec3(), new Vec3()], false); - }, Error, `Expected a Vec4 array but received a Vec3 array. + }, Error, `Expected a Vec4 iterable but received a Vec3 iterable. The VertexState for this attribute has a componentCount of 4. Potential fixes: - set the componentCount of "POSITION" in your VertexState to 3. - - provide a Vec4 array.`); + - provide a Vec4 iterable.`); }, }); @@ -676,30 +729,30 @@ Deno.test({ assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [1, 2], false); - }, Error, `Expected a Vec4 array but received a Number array. + }, Error, `Expected a Vec4 iterable but received a Number iterable. The mesh has no VertexState. Potential fixes: - add a VertexState with "POSITION" attribute. - set the \`unusedComponentCount\` option of \`setVertexData()\` to 1. - - provide a Vec4 array.`); + - provide a Vec4 iterable.`); assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [new Vec2(), new Vec2()], false); - }, Error, `Expected a Vec4 array but received a Vec2 array. + }, Error, `Expected a Vec4 iterable but received a Vec2 iterable. The mesh has no VertexState. Potential fixes: - add a VertexState with "POSITION" attribute. - set the \`unusedComponentCount\` option of \`setVertexData()\` to 2. - - provide a Vec4 array.`); + - provide a Vec4 iterable.`); assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [new Vec3(), new Vec3()], false); - }, Error, `Expected a Vec4 array but received a Vec3 array. + }, Error, `Expected a Vec4 iterable but received a Vec3 iterable. The mesh has no VertexState. Potential fixes: - add a VertexState with "POSITION" attribute. - set the \`unusedComponentCount\` option of \`setVertexData()\` to 3. - - provide a Vec4 array.`); + - provide a Vec4 iterable.`); }, }); @@ -714,30 +767,53 @@ Deno.test({ assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [1, 2], true); - }, Error, `Expected a Vec4 array but received a Number array. + }, Error, `Expected a Vec4 iterable but received a Number iterable. The provided VertexState doesn't contain a "POSITION" attribute. Potential fixes: - add a "POSITION" attribute to the VertexState. - set the \`unusedComponentCount\` option of \`setVertexData()\` to 1. - - provide a Vec4 array.`); + - provide a Vec4 iterable.`); assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [new Vec2(), new Vec2()], true); - }, Error, `Expected a Vec4 array but received a Vec2 array. + }, Error, `Expected a Vec4 iterable but received a Vec2 iterable. The provided VertexState doesn't contain a "POSITION" attribute. Potential fixes: - add a "POSITION" attribute to the VertexState. - set the \`unusedComponentCount\` option of \`setVertexData()\` to 2. - - provide a Vec4 array.`); + - provide a Vec4 iterable.`); assertThrows(() => { buffer.setVertexData(Mesh.AttributeType.POSITION, [new Vec3(), new Vec3()], true); - }, Error, `Expected a Vec4 array but received a Vec3 array. + }, Error, `Expected a Vec4 iterable but received a Vec3 iterable. The provided VertexState doesn't contain a "POSITION" attribute. Potential fixes: - add a "POSITION" attribute to the VertexState. - set the \`unusedComponentCount\` option of \`setVertexData()\` to 3. - - provide a Vec4 array.`); + - provide a Vec4 iterable.`); + }, +}); + +Deno.test({ + name: "setVertexData() should throw when data doesn't match the component count (1)", + fn() { + const buffer = new InternalMeshAttributeBuffer({ + attributeSettings: [{ offset: 0, format: Mesh.AttributeFormat.FLOAT32, componentCount: 1, attributeType: Mesh.AttributeType.POSITION }], + }); + buffer.setVertexCount(2); + + const generatorFn = function *() { + yield new Vec2(1, 2); + yield new Vec2(3, 4); + }; + + assertThrows(() => { + buffer.setVertexData(Mesh.AttributeType.POSITION, generatorFn(), false); + }, Error, `Expected a number iterable but received a Vec2 iterable. +The VertexState for this attribute has a componentCount of 1. +Potential fixes: + - set the componentCount of "POSITION" in your VertexState to 2. + - provide a number iterable.`); }, });