UNPKG

@spearwolf/twopoint5d

Version:

Create 2.5D realtime graphics and pixelart with WebGL and three.js

129 lines 4.65 kB
import { BufferGeometry } from 'three/webgpu'; import { VOBufferPool } from './VOBufferPool.js'; import { initializeAttributes } from './initializeAttributes.js'; import { selectAttributes } from './selectAttributes.js'; import { selectBuffers } from './selectBuffers.js'; import { updateUpdateRange } from './updateUpdateRange.js'; export class VOBufferGeometry extends BufferGeometry { constructor(source, capacity) { super(); this.buffers = new Map(); this.bufferSerials = new Map(); this.#serials = new Map(); this.#updateAttributes = new Map(); this.#firstAutoTouch = true; this.pool = source instanceof VOBufferPool ? source : new VOBufferPool(source, capacity); this.name = 'VOBufferGeometry'; initializeAttributes(this, this.pool, this.buffers, this.bufferSerials); } dispose() { this.pool.clear(); super.dispose(); } touchAttributes(...attrNames) { selectAttributes(this.pool, this.buffers, attrNames).forEach((buffer) => { buffer.needsUpdate = true; }); } touchBuffers(bufferTypes) { selectBuffers(this.buffers, bufferTypes).forEach((buffer) => { buffer.needsUpdate = true; }); } touch(...args) { const attrNames = []; let buffers = undefined; args.forEach((arg) => { if (typeof arg === 'string') { attrNames.push(arg); } else { buffers = { ...buffers, ...arg }; } }); if (attrNames.length) { this.touchAttributes(...attrNames); } if (buffers) { this.touchBuffers(buffers); } } update() { this.#updateDrawRange(); this.#checkBufferSerials(); this.#autoTouchAttributes(); this.#updateBuffersUpdateRange(); this.#syncAttributeArrays(); } #serials; #updateAttributes; #syncAttributeArrays() { this.#updateAttributes.clear(); for (const [attrName, attr] of Object.entries(this.attributes)) { const bufAttr = attr.isInterleavedBufferAttribute ? attr.data : attr; const version = bufAttr.version; if (this.#serials.has(attrName)) { if (this.#serials.get(attrName) !== version) { this.#updateAttributes.set(attrName, bufAttr); this.#serials.set(attrName, version); } } else { this.#updateAttributes.set(attrName, bufAttr); this.#serials.set(attrName, version); } } for (const [attrName, bufAttr] of this.#updateAttributes) { const poolBufInfo = this.pool.buffer.bufferAttributes.get(attrName); if (poolBufInfo) { const poolBuf = this.pool.buffer.buffers.get(poolBufInfo.bufferName); if (poolBuf) { bufAttr.array = poolBuf.typedArray; } } } } #checkBufferSerials() { for (const [bufferName, buffer] of this.buffers) { const serial = this.bufferSerials.get(bufferName); const bufSerial = this.pool.buffer.buffers.get(bufferName).serial; if (serial !== bufSerial) { buffer.needsUpdate = true; this.bufferSerials.set(bufferName, bufSerial); } } } #updateBuffersUpdateRange() { updateUpdateRange(this.pool, this.buffers); } #updateDrawRange() { this.setDrawRange(0, this.pool.descriptor.hasIndices ? this.pool.usedCount * this.pool.descriptor.indices.length : this.pool.usedCount * this.pool.descriptor.vertexCount); } #firstAutoTouch; #autoTouchAttributes() { if (this.pool.usedCount === 0) return; if (this.#firstAutoTouch) { this.touchBuffers({ static: true }); this.#firstAutoTouch = false; } const autoTouchAttrs = this.#getAutoTouchAttributeNames(); if (autoTouchAttrs.length) { this.touchAttributes(...autoTouchAttrs); } } #autoTouchAttrNames; #getAutoTouchAttributeNames() { if (!this.#autoTouchAttrNames) { this.#autoTouchAttrNames = Array.from(this.pool.descriptor.attributes.values()) .filter((attr) => attr.autoTouch) .map((attr) => attr.name); } return this.#autoTouchAttrNames; } } //# sourceMappingURL=VOBufferGeometry.js.map