From 4b949c07c0ff383e20f007534da34f25f7c545ba Mon Sep 17 00:00:00 2001 From: Lucas Dower Date: Mon, 21 Mar 2022 19:38:22 +0000 Subject: [PATCH] Added support for merging AttributeData --- src/buffer.ts | 39 ++++++++++++++++++++++++ test/buffer.test.ts | 74 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 test/buffer.test.ts diff --git a/src/buffer.ts b/src/buffer.ts index 53ccf32..bb9524b 100644 --- a/src/buffer.ts +++ b/src/buffer.ts @@ -25,6 +25,45 @@ export interface AttributeData { } } +export function MergeAttributeData(...data: AttributeData[]): AttributeData { + if (data.length === 0) { + return { + indices: new Uint32Array(), + custom: {}, + }; + } + // Check custom attributes match + const requiredAttributes = Object.keys(data[0].custom); + for (let i = 1; i < data.length; ++i) { + const customAttributes = Object.keys(data[i].custom); + const isAllRequiredInCustom = requiredAttributes.every((attr) => { + return customAttributes.includes(attr); + }); + const isAllCustomInRequired = customAttributes.every((attr) => { + return requiredAttributes.includes(attr); + }); + ASSERT(isAllRequiredInCustom && isAllCustomInRequired, 'Attributes to merge do not match'); + } + // Merge data + const indices = Array.from(data[0].indices); + const custom = data[0].custom; + for (let i = 1; i < data.length; ++i) { + const nextIndex = Math.max(...indices) + 1; + const d = data[i]; + const newIndices = d.indices.map((index) => index + nextIndex); + indices.push(...Array.from(newIndices)); + for (const attr of requiredAttributes) { + const attrData = d.custom[attr]; + custom[attr].push(...attrData); + } + } + + return { + indices: new Uint32Array(indices), + custom: custom, + }; +} + export class RenderBuffer { private _WebGLBuffer?: { buffer: twgl.BufferInfo, diff --git a/test/buffer.test.ts b/test/buffer.test.ts new file mode 100644 index 0000000..f17e499 --- /dev/null +++ b/test/buffer.test.ts @@ -0,0 +1,74 @@ +import { AttributeData, MergeAttributeData } from '../src/buffer'; + +test('MergeAttributeData #1', () => { + const a: AttributeData = { + indices: new Uint32Array([0, 1, 2]), + custom: { + position: [1, 2, 3, 4, 5, 6, 7, 8, 9], + colour: [1, 0, 0, 0, 1, 0, 0, 0, 1], + }, + }; + const b = MergeAttributeData(a); + expect(JSON.stringify(a)).toEqual(JSON.stringify(b)); +}); + +test('MergeAttributeData #2', () => { + const a: AttributeData = { + indices: new Uint32Array([0, 1, 2]), + custom: { + position: [1, 2, 3, 4, 5, 6, 7, 8, 9], + colour: [1, 0, 0, 0, 1, 0, 0, 0, 1], + }, + }; + const b: AttributeData = { + indices: new Uint32Array([0, 1, 2]), + custom: { + position: [10, 11, 12, 13, 14, 15, 16, 17, 18], + colour: [0, 1, 1, 1, 0, 1, 1, 1, 0], + }, + }; + const cActual = MergeAttributeData(a, b); + const cExpect: AttributeData = { + indices: new Uint32Array([0, 1, 2, 3, 4, 5]), + custom: { + position: [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, + ], + colour: [ + 1, 0, 0, 0, 1, 0, 0, 0, 1, + 0, 1, 1, 1, 0, 1, 1, 1, 0, + ], + }, + }; + expect(JSON.stringify(cActual)).toEqual(JSON.stringify(cExpect)); +}); + +test('MergeAttributeData #3', () => { + const a: AttributeData = { + indices: new Uint32Array([0, 1]), + custom: { + data: [1, 2], + }, + }; + const b: AttributeData = { + indices: new Uint32Array([0, 1]), + custom: { + data: [3, 4], + }, + }; + const c: AttributeData = { + indices: new Uint32Array([0, 1]), + custom: { + data: [5, 6], + }, + }; + const dActual = MergeAttributeData(a, b, c); + const dExpect: AttributeData = { + indices: new Uint32Array([0, 1, 2, 3, 4, 5]), + custom: { + data: [1, 2, 3, 4, 5, 6], + }, + }; + expect(JSON.stringify(dActual)).toEqual(JSON.stringify(dExpect)); +});