@spearwolf/twopoint5d
Version:
Create 2.5D realtime graphics and pixelart with WebGL and three.js
111 lines • 5.02 kB
JavaScript
import { voBuffer, voIndex } from './constants.js';
import { createTypedArray } from './createTypedArray.js';
const makeAttributeGetter = (bufferName, instanceOffset, attrOffset) => {
return function getAttribute() {
const idx = this[voIndex] * instanceOffset + attrOffset;
const buf = this[voBuffer].buffers.get(bufferName);
return buf.typedArray[idx];
};
};
const makeAttributeSetter = (bufferName, instanceOffset, attrOffset) => {
return function setAttribute(value) {
const idx = this[voIndex] * instanceOffset + attrOffset;
const buf = this[voBuffer].buffers.get(bufferName);
buf.typedArray[idx] = value;
};
};
const makeAttributeValuesGetter = (bufferName, bufferItemSize, vertexCount, attrOffset, attrSize) => {
return function getAttributeValues() {
const idx = this[voIndex] * vertexCount * bufferItemSize + attrOffset;
const buf = this[voBuffer].buffers.get(bufferName);
const source = buf.typedArray;
const target = createTypedArray(buf.dataType, vertexCount * attrSize);
for (let i = 0; i < vertexCount; i++) {
if (attrSize === 1) {
target[i] = source[idx + i * bufferItemSize];
}
else {
target.set(source.subarray(idx + i * bufferItemSize, idx + i * bufferItemSize + attrSize), i * attrSize);
}
}
return target;
};
};
const makeAttributeValueSetter = (bufferName, bufferItemSize, vertexCount, attrOffset, attrSize) => {
return function setAttributeValues(...values) {
const source = values.length === 1 && Array.isArray(values[0]) ? values[0] : values;
const idx = this[voIndex] * vertexCount * bufferItemSize + attrOffset;
const target = this[voBuffer].buffers.get(bufferName).typedArray;
for (let i = 0; i < vertexCount; i++) {
if (attrSize === 1) {
target[idx + i * bufferItemSize] = source[i];
}
else {
target.set(Array.prototype.slice.call(source, i * attrSize, i * attrSize + attrSize), idx + i * bufferItemSize);
}
}
};
};
export function createVertexObjectPrototype(voBuffer) {
const { descriptor } = voBuffer;
const { methods } = descriptor;
const entries = descriptor.attributeNames.flatMap((attrName) => {
const attr = descriptor.getAttribute(attrName);
const bufAttr = voBuffer.bufferAttributes.get(attrName);
const buf = voBuffer.buffers.get(bufAttr.bufferName);
const methods = [];
if (descriptor.vertexCount === 1 && attr.size === 1) {
methods.push([
attrName,
{
enumerable: true,
get: makeAttributeGetter(bufAttr.bufferName, buf.itemSize, bufAttr.offset),
set: makeAttributeSetter(bufAttr.bufferName, buf.itemSize, bufAttr.offset),
},
]);
}
else {
methods.push([
attr.getterName,
{
enumerable: true,
value: makeAttributeValuesGetter(bufAttr.bufferName, buf.itemSize, descriptor.vertexCount, bufAttr.offset, attr.size),
},
]);
methods.push([
attr.setterName,
{
enumerable: true,
value: makeAttributeValueSetter(bufAttr.bufferName, buf.itemSize, descriptor.vertexCount, bufAttr.offset, attr.size),
},
]);
}
if (attr.hasComponents) {
attr.components.forEach((component, componentIndex) => {
for (let vertexIndex = 0; vertexIndex < descriptor.vertexCount; vertexIndex++) {
const instanceOffset = descriptor.vertexCount * buf.itemSize;
const attrOffset = vertexIndex * buf.itemSize + bufAttr.offset + componentIndex;
if (descriptor.vertexCount > 1 || component !== attr.name) {
methods.push([
`${component}${descriptor.vertexCount === 1 ? '' : vertexIndex}`,
{
enumerable: true,
get: makeAttributeGetter(bufAttr.bufferName, instanceOffset, attrOffset),
set: makeAttributeSetter(bufAttr.bufferName, instanceOffset, attrOffset),
},
]);
}
}
});
}
return methods;
});
if (methods) {
entries.push(...Object.entries(methods)
.filter(([, val]) => typeof val === 'function')
.map(([key, value]) => [key, { value }]));
}
const props = Object.fromEntries(entries);
return Object.create(descriptor.basePrototype ?? Object.prototype, props);
}
//# sourceMappingURL=createVertexObjectPrototype.js.map