@spearwolf/twopoint5d
Version:
Create 2.5D realtime graphics and pixelart with WebGL and three.js
157 lines • 7.09 kB
JavaScript
import { createTypedArray } from './createTypedArray.js';
import { createVertexObjectPrototype } from './createVertexObjectPrototype.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