UNPKG

@tolokoban/tgd

Version:

ToloGameDev library for WebGL2

354 lines 34.3 kB
export class TgdDataset { constructor(attributesDefinition, options = {}) { this.attributesDefinition = attributesDefinition; this.options = options; this.stride = 0; this.definitions = {}; this._count = 0; this.name = options.name ?? `TgdDataset#${TgdDataset.id++}`; this.divisor = options.divisor ?? 0; this.buffer = options.buffer; this.target = options.target ?? "ARRAY_BUFFER"; this.usage = options.usage ?? "STATIC_DRAW"; this._data = options.data ?? new ArrayBuffer(0); this.initialize(attributesDefinition, options); } getType(attribName) { const { attributesDefinition } = this; const type = attributesDefinition[attribName]; if (!type) throw new Error(`[TgdDataset.getType] Attribute name not found in this dataset: "${attribName}"!\nAvailable attributes names are: ${Object.keys(attributesDefinition).join(", ")}.`); return type; } getTypeRecord() { const types = {}; for (const attribName of this.attributesNames) { types[attribName] = this.getType(attribName); } return types; } initialize(attributesDefinition, options = {}) { for (const name of Object.keys(attributesDefinition)) { const definition = attributesDefinition[name]; this.attributesDefinition[name] = definition; } const divisor = options.divisor ?? 0; let stride = 0; const data = {}; const definitions = {}; for (const name of Object.keys(attributesDefinition)) { data[name] = new ArrayBuffer(0); const definition = { dimension: DIMS[attributesDefinition[name]], byteOffset: stride, bytesPerElement: Float32Array.BYTES_PER_ELEMENT, divisor, getter(view, byteOffset) { const offset = byteOffset >= view.byteLength ? byteOffset % view.byteLength : byteOffset; return view.getFloat32(offset, true); }, setter(view, byteOffset, value) { view.setFloat32(byteOffset, value, true); }, }; definitions[name] = definition; stride += definition.bytesPerElement * definition.dimension; } this.definitions = definitions; this.stride = stride; if (options.data) { if (options.data.byteLength % stride !== 0) { console.error(options); throw new Error(`[TgdDataset] Invalid size for data: ${options.data.byteLength}, must be a multiple of ${stride} (stride)!`); } this._count = options.data.byteLength / stride; } else { this._data = resize(this._data, this.count * this.stride); } } assertAttributes(attributesDefinition) { if (JSON.stringify(attributesDefinition) !== JSON.stringify(this.attributesDefinition)) { throw new Error(`This TgdDataset was expected to have these attributes:\n${JSON.stringify(attributesDefinition, null, 2)}\nbut it has these attributes instead:\n${JSON.stringify(this.attributesDefinition, null, 2)}`); } } /** * Throw an exception if the attribute `attribName` does not exist, * or if it is not of any of the `types`. * @param attribName * @param types */ assertAttribType(attribName, ...types) { const type = this.attributesDefinition[attribName]; if (!type) throw new Error(`Attribute "${attribName}" does not exist! Available names are: ${Object.keys(this.attributesDefinition) .sort() .join(", ")}.`); if (!types.includes(type)) { throw new Error(`Attribute "${attribName}" is of type "${type}", which is not ${types.join(" nor ")}!`); } return this; } renameAttributes(newNames) { const { definitions } = this; const oldNames = Object.keys(definitions); if (oldNames.length !== newNames.length) { throw new Error(`[TgdDataset] This dataset has ${oldNames.length} attributes, but ${newNames.length} new names were given!`); } const newDefinitions = {}; let index = 0; for (const oldName of oldNames) { const newName = newNames[index]; newDefinitions[newName] = definitions[oldName]; index++; } this.definitions = newDefinitions; return this; } addAttributes(attributesDefinition) { const oldDataset = this.clone(); for (const key of Object.keys(attributesDefinition)) { const oldType = this.attributesDefinition[key]; const newType = attributesDefinition[key]; if (oldType && oldType !== newType) { throw new Error(`It is not allowed to change the type of attribute "${key}" from "${oldType}" to "${newType}"! Prefer removing the attribute first.`); } } this.initialize({ ...this.attributesDefinition, ...attributesDefinition, }, this.options); this.count = oldDataset.count; for (const attribName of oldDataset.attributesNames) { try { const { get } = oldDataset.getAttribAccessor(attribName); const { set } = this.getAttribAccessor(attribName); for (let index = 0; index < oldDataset.count; index++) { const definition = this.getDef(attribName); for (let dim = 0; dim < definition.dimension; dim++) { set(get(index, dim), index, dim); } } } catch (error) { const message = error instanceof Error ? error.message : JSON.stringify(error); throw new Error(`Unable to clone attribute "${attribName}"!\n${message}`); } } return this; } clone() { const ds = new TgdDataset(structuredClone(this.attributesDefinition), this.options); ds.count = this.count; const source = new DataView(this._data); const definition = new DataView(ds._data); for (let offset = 0; offset < source.byteLength; offset++) { definition.setUint8(offset, source.getUint8(offset)); } return ds; } copyAttributes({ fromIndex, toIndex, toDataset = this, }) { const { stride } = this; if (stride !== toDataset.stride) { console.error("Failed to copy attributes between datasets!"); this.debug("From:"); toDataset.debug("To:"); throw new Error(`[TgdDataset.copyAttributes] Unable to copy attributes from a dataset with stride ${stride} to one with stride ${toDataset.stride}!`); } const fromData = this._data; const fromOffset = fromIndex * stride; const fromArray = new Uint8Array(fromData); const toData = toDataset._data; const toOffset = toIndex * stride; const toArray = new Uint8Array(toData); const size = stride; toArray.set(fromArray.subarray(fromOffset, fromOffset + size), toOffset); } /** * Warning! * * This ArrayBuffer will be detached as soon as its * size is changed! */ get data() { return this._data; } /** * Dataset does not own any GL Buffer. * So setting its data won't change anything in WebGL. * You can use a `TgdVertexArray` for this. */ set data(arrayBuffer) { if (this._data === arrayBuffer) return; this._data = arrayBuffer; this.count = Math.floor(arrayBuffer.byteLength / this.stride); } /** Get number of attributes. */ get count() { return this._count; } /** Set number of attributes (reallocate data accordingly) */ set count(count) { if (this._count === count) return; this._count = count; this._data = resize(this._data, count * this.stride); } get attributesNames() { return Object.keys(this.attributesDefinition); } hasAttribute(attribName) { const def = this.attributesDefinition[attribName]; return !!def; } getAttribAccessor(attribName) { const definition = this.getDef(attribName); const view = new DataView(this.data); const stride = this.stride; return { get(index, dimension = 0) { const byteOffset = definition.byteOffset + stride * index + dimension * definition.bytesPerElement; return definition.getter(view, byteOffset); }, set(value, index, dimension = 0) { const byteOffset = definition.byteOffset + stride * index + dimension * definition.bytesPerElement; definition.setter(view, byteOffset, value); }, }; } get(attribName, target) { const values = target ?? []; const { dimension } = this.getDef(attribName); const { get } = this.getAttribAccessor(attribName); for (let idx = 0; idx < this.count; idx++) { for (let dim = 0; dim < dimension; dim++) { values.push(get(idx, dim)); } } return values; } /** * Set the data for one attribute. * * If you try to set more element that the current buffer * can hold, the buffer will be expanded. * And the property `count` will change accordingly. * * @param attribName If the attribute does not exist, * you will get an exception. * @param value The ArrayBuffer holding the data you * want to set to this attribute * @param param2 */ set(attribName, value, { byteOffset = 0, byteStride, first = 0, count = Number.POSITIVE_INFINITY, targetFirst = 0, } = {}) { const { bytesPerElement, dimension, byteOffset: attribByteOffset } = this.getDef(attribName); const buffer = value instanceof ArrayBuffer ? value : value.buffer; const chunkLength = bytesPerElement * dimension; const sourceStride = byteStride ?? chunkLength; let sourceOffset = byteOffset + sourceStride * first; const dstStride = this.stride; let dstOffset = targetFirst * dstStride + attribByteOffset; this.count = Math.max(this.count, Math.min(count, Math.floor((buffer.byteLength - sourceOffset) / sourceStride))); const sourceStop = buffer.byteLength - sourceStride + 1; const dstStop = this._data.byteLength + attribByteOffset - dstStride + 1; const sourceBuffer = new Uint8Array(buffer); const dstBuffer = new Uint8Array(this._data); let index = 0; while (index < count && sourceOffset < sourceStop && dstOffset < dstStop) { dstBuffer.set(sourceBuffer.subarray(sourceOffset, sourceOffset + chunkLength), dstOffset); index++; sourceOffset += sourceStride; dstOffset += dstStride; } } getDef(attribName) { const definition = this.definitions[attribName]; if (!definition) throw new Error(`[TgdDataset] Attribute "${String(attribName)}" not found in this DataSet!\nAvailable names are: ${Object.keys(this.definitions) .sort() .map((name) => JSON.stringify(name)) .join(", ")}.`); return definition; } /** * Enable the vertex attrib array, and set * the vertex attrib pointer for every declared * attribute. */ defineAttributes(gl, prg) { let offsetDestination = 0; const { definitions } = this; for (const name of Object.keys(definitions)) { const definition = definitions[name]; if (prg.hasAttribute(name)) { const att = prg.getAttribLocation(name); gl.enableVertexAttribArray(att); gl.vertexAttribPointer(att, definition.dimension, gl.FLOAT, false, this.stride, offsetDestination); gl.vertexAttribDivisor(att, definition.divisor); } const bytes = definition.dimension * definition.bytesPerElement; offsetDestination += bytes; } } toCode({ indent = "" } = {}) { const lines = []; let offsetDestination = 0; const { definitions } = this; for (const name of Object.keys(definitions)) { const definition = definitions[name]; const att = `$${name}`; lines.push(`const ${att} = gl.getAttribLocation(prg, "${name}")`, `gl.enableVertexAttribArray(${att})`, "gl.vertexAttribPointer(", ` ${att},`, ` ${definition.dimension}, // Dimension`, " gl.FLOAT,", " false,", ` ${this.stride}, // Stride`, ` ${offsetDestination} // Offset`, ")", `gl.vertexAttribDivisor(${att}, ${definition.divisor})`); const bytes = definition.dimension * definition.bytesPerElement; offsetDestination += bytes; } return lines.map((line) => `${indent}${line}`).join("\n"); } debug(caption = "Dataset") { console.debug(caption, " count:", this.count, " target:", this.target, " usage:", this.usage); const rows = [["Name", "type", "offset"]]; for (const attName of Object.keys(this.definitions)) { const definition = this.definitions[attName]; rows.push([attName, this.attributesDefinition[attName], `${definition.byteOffset}`]); } const sizes = [0, 1, 2].map((index) => rows.reduce((previous, current) => Math.max(previous, current[index].length), 0)); for (const [name, type, offset] of rows) console.debug(`%c${name.padEnd(sizes[0] + 2)}${type.padStart(sizes[1] + 2)}${offset.padStart(sizes[2] + 2)}`, "font-family:monospace"); for (const attName of Object.keys(this.definitions)) { const definition = this.definitions[attName]; if (!definition) continue; const { get } = this.getAttribAccessor(attName); const data = []; for (let index = 0; index < this.count; index++) { const items = []; for (let dim = 0; dim < definition.dimension; dim++) { items.push(get(index, dim)); } data.push(items); } console.debug(`Attribute "${attName}":`, data); } } } TgdDataset.id = 1; const DIMS = { float: 1, vec2: 2, vec3: 3, vec4: 4, }; function resizeFast(buff, newSize) { if (buff.byteLength === (newSize ?? 0)) return buff; return buff.transfer(newSize); } function resizeSlow(inBuff, newSize) { if (inBuff.byteLength === (newSize ?? 0)) return inBuff; const outBuff = new ArrayBuffer(newSize ?? inBuff.byteLength); new Uint8Array(outBuff).set(new Uint8Array(inBuff)); return outBuff; } const resize = typeof ArrayBuffer.prototype.transfer === "function" ? resizeFast : resizeSlow; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YXNldC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYXRhc2V0L2RhdGFzZXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBc0JBLE1BQU0sT0FBTyxVQUFVO0lBY25CLFlBQ3FCLG9CQUEwQyxFQUMxQyxVQUFzQyxFQUFFO1FBRHhDLHlCQUFvQixHQUFwQixvQkFBb0IsQ0FBc0I7UUFDMUMsWUFBTyxHQUFQLE9BQU8sQ0FBaUM7UUFUckQsV0FBTSxHQUFHLENBQUMsQ0FBQTtRQUNWLGdCQUFXLEdBQW9ELEVBQUUsQ0FBQTtRQUVqRSxXQUFNLEdBQUcsQ0FBQyxDQUFBO1FBUWQsSUFBSSxDQUFDLElBQUksR0FBRyxPQUFPLENBQUMsSUFBSSxJQUFJLGNBQWMsVUFBVSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUE7UUFDM0QsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsT0FBTyxJQUFJLENBQUMsQ0FBQTtRQUNuQyxJQUFJLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUE7UUFDNUIsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxJQUFJLGNBQWMsQ0FBQTtRQUM5QyxJQUFJLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUFLLElBQUksYUFBYSxDQUFBO1FBQzNDLElBQUksQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDLElBQUksSUFBSSxJQUFJLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUMvQyxJQUFJLENBQUMsVUFBVSxDQUFDLG9CQUFvQixFQUFFLE9BQU8sQ0FBQyxDQUFBO0lBQ2xELENBQUM7SUFFRCxPQUFPLENBQUMsVUFBa0I7UUFDdEIsTUFBTSxFQUFFLG9CQUFvQixFQUFFLEdBQUcsSUFBSSxDQUFBO1FBQ3JDLE1BQU0sSUFBSSxHQUFHLG9CQUFvQixDQUFDLFVBQVUsQ0FBQyxDQUFBO1FBQzdDLElBQUksQ0FBQyxJQUFJO1lBQ0wsTUFBTSxJQUFJLEtBQUssQ0FD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