@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
354 lines • 34.3 kB
JavaScript
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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