UNPKG

@spearwolf/twopoint5d

Version:

a library to create 2.5d realtime graphics and pixelart with three.js

158 lines 7.16 kB
import { createTypedArray } from './createTypedArray.js'; import { createVertexObjectPrototype } from './createVertexObjectPrototype.js'; import { VertexObjectDescriptor } from './VertexObjectDescriptor.js'; export class VertexObjectBuffer { constructor(source, capacityOrBuffersData) { let buffersData; if (typeof capacityOrBuffersData === 'number') { this.capacity = capacityOrBuffersData; } else { buffersData = capacityOrBuffersData; this.capacity = buffersData.capacity; } if (source instanceof VertexObjectBuffer) { this.descriptor = source.descriptor; this.attributeNames = source.attributeNames; this.bufferAttributes = source.bufferAttributes; this.bufferNameAttributes = source.bufferNameAttributes; this.buffers = new Map(); for (const [bufferName, buffer] of source.buffers) { this.buffers.set(bufferName, { bufferName, itemSize: buffer.itemSize, dataType: buffer.dataType, usageType: buffer.usageType, typedArray: createTypedArray(buffer.dataType, this.capacity * this.descriptor.vertexCount * buffer.itemSize), serial: 0, }); } } else { this.descriptor = source; this.buffers = new Map(); this.bufferAttributes = new Map(); this.attributeNames = Object.freeze(Array.from(this.descriptor.attributeNames).sort()); for (const attributeName of this.attributeNames) { const attribute = this.descriptor.getAttribute(attributeName); const { bufferName } = attribute; let offset = 0; if (this.buffers.has(bufferName)) { const buffer = this.buffers.get(bufferName); offset = buffer.itemSize; buffer.itemSize += attribute.size; } else { this.buffers.set(bufferName, { bufferName, itemSize: attribute.size, dataType: attribute.dataType, usageType: attribute.usageType, typedArray: undefined, serial: 0, }); } this.bufferAttributes.set(attributeName, { bufferName, attributeName, offset, }); } for (const buffer of this.buffers.values()) { buffer.typedArray = buffersData?.buffers[buffer.bufferName] ?? createTypedArray(buffer.dataType, this.capacity * this.descriptor.vertexCount * buffer.itemSize); } this.bufferNameAttributes = new Map(); for (const bufAttr of this.bufferAttributes.values()) { const { bufferName } = bufAttr; if (this.bufferNameAttributes.has(bufferName)) { this.bufferNameAttributes.get(bufferName).push(bufAttr); } else { this.bufferNameAttributes.set(bufferName, [bufAttr]); } } } if (!this.descriptor.voPrototype) { this.descriptor.voPrototype = createVertexObjectPrototype(this); } } copy(other, targetObjectOffset = 0) { for (const buf of this.buffers.values()) { buf.typedArray.set(other.buffers.get(buf.bufferName).typedArray, targetObjectOffset * this.descriptor.vertexCount * buf.itemSize); buf.serial++; } return this; } clone() { return new VertexObjectBuffer(this, this.capacity).copy(this); } copyArray(source, bufferName, targetObjectOffset = 0) { const buf = this.buffers.get(bufferName); buf.typedArray.set(source, targetObjectOffset * this.descriptor.vertexCount * buf.itemSize); buf.serial++; } copyWithin(targetIndex, startIndex, endIndex = this.capacity) { const { vertexCount } = this.descriptor; for (const buf of this.buffers.values()) { buf.typedArray.copyWithin(targetIndex * vertexCount * buf.itemSize, startIndex * vertexCount * buf.itemSize, endIndex * vertexCount * buf.itemSize); buf.serial++; } } copyAttributes(attributes, targetObjectOffset = 0) { let copiedObjCount = 0; for (const [attrName, data] of Object.entries(attributes)) { const attr = this.bufferAttributes.get(attrName); if (attr) { let attrObjCount = 0; const buffer = this.buffers.get(attr.bufferName); const { vertexCount } = this.descriptor; const attrSize = this.descriptor.getAttribute(attrName).size; let idx = 0; let bufIdx = targetObjectOffset * vertexCount * buffer.itemSize; while (idx < data.length && attrObjCount + targetObjectOffset < this.capacity) { for (let i = 0; i < vertexCount; i++) { buffer.typedArray.set(Array.prototype.slice.call(data, idx, idx + attrSize), bufIdx + attr.offset); idx += attrSize; bufIdx += buffer.itemSize; } ++attrObjCount; } if (attrObjCount > copiedObjCount) { copiedObjCount = attrObjCount; } buffer.serial++; } } return copiedObjCount; } toAttributeArrays(attributeNames, startIndex = 0, endIndex = this.capacity) { return Object.fromEntries(attributeNames.map((attrName) => { const attr = this.bufferAttributes.get(attrName); if (attr) { const buffer = this.buffers.get(attr.bufferName); const { vertexCount } = this.descriptor; const attrSize = this.descriptor.getAttribute(attrName).size; const targetArray = createTypedArray(buffer.dataType, (endIndex - startIndex) * vertexCount * attrSize); let targetIdx = 0; let bufferIdx = startIndex * vertexCount * buffer.itemSize + attr.offset; for (let objIdx = startIndex; objIdx < endIndex; objIdx++) { for (let i = 0; i < vertexCount; i++) { targetArray.set(buffer.typedArray.subarray(bufferIdx, bufferIdx + attrSize), targetIdx); targetIdx += attrSize; bufferIdx += buffer.itemSize; } } return [attrName, targetArray]; } return [attrName]; })); } touch() { for (const buffer of this.buffers.values()) { buffer.serial++; } } } //# sourceMappingURL=VertexObjectBuffer.js.map