@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
167 lines • 15.4 kB
JavaScript
import { TgdDataset } from "./../dataset/index.js";
import { isTgdTypeArrayForElements } from "./../types/index.js";
import { TgdVec3 } from "./../math/index.js";
import { webglElementTypeFromTypedArray, webglLookup } from "./../utils/index.js";
import { TgdBoundingBox, tgdGeometryJoin } from "../index.js";
/**
* Geometry is used to define a mesh.
* It must hold at least one vec3 attributes
* for the vertices.
*/
export class TgdGeometry {
static make(options) {
const definition = {};
const { count, drawMode, elements, attPosition, attNormal, attUV, computeNormalsIfMissing } = options;
definition[attPosition.name] = attPosition.type ?? "vec3";
if (attNormal)
definition[attNormal.name] = attNormal.type ?? "vec3";
if (attUV)
definition[attUV.name] = attUV.type ?? "vec2";
const dataset = new TgdDataset(definition);
dataset.set(attPosition.name, attPosition.data);
if (attNormal)
dataset.set(attNormal.name, attNormal.data);
if (attUV)
dataset.set(attUV.name, attUV.data);
return new TgdGeometry({
dataset,
count,
drawMode,
elements,
computeNormalsIfMissing,
});
}
static fitElementsInTypeArray(elements) {
if (isTgdTypeArrayForElements(elements))
return elements;
const max = elements.reduce((prv, cur) => Math.max(prv, cur), 0);
if (max <= 0xff)
return new Uint8Array(elements);
if (max <= 0xffff)
return new Uint16Array(elements);
return new Uint32Array(elements);
}
static join(geometries) {
return tgdGeometryJoin(geometries);
}
constructor(options) {
const { dataset, drawMode = "TRIANGLES", attPosition = "POSITION", attNormal = "NORMAL", attUV = "TEXCOORD_0", name = `TgdGeometry#${TgdGeometry.counter++}`, } = options;
this.name = name;
this._dataset = dataset;
this.drawMode = typeof drawMode === "number" ? drawMode : WebGL2RenderingContext[drawMode];
const { elements } = options;
this.elements = elements;
this._elementsType = elements ? webglElementTypeFromTypedArray(elements) : 0;
this.attPosition = attPosition;
this.attNormal = attNormal;
this.attUV = attUV;
this.count = elements?.length ?? dataset.count;
if (options.computeNormalsIfMissing)
this.computeNormals();
}
debug(caption) {
const label = `[${caption ?? this.name}]`;
this.dataset.debug(`${label} Dataset`);
console.debug(`${label} Count:`, this.count);
console.debug(`${label} DrawMode:`, webglLookup(this.drawMode));
console.debug(this.computeBoundingBox());
}
get dataset() {
return this._dataset;
}
get elementsType() {
return this._elementsType;
}
/**
* Return the index of a vertex.
* If no elements array has been defined, we return `index` verbatim.
* Otherwise, we use this elements array.
*/
getElement(index) {
return this.elements?.[index] ?? index;
}
computeNormals() {
let normals = [];
if (this.drawMode === WebGL2RenderingContext.TRIANGLES) {
normals = this.computeNormalsForTrianglesDrawMode();
}
else {
console.error("We don't know how to compute normals for this draw mode:", this.drawMode);
return this;
}
const attNormalName = this.attNormal;
this.dataset.addAttributes({
[attNormalName]: "vec3",
});
const values = [];
for (const [nx, ny, nz] of normals) {
values.push(nx, ny, nz);
}
this.dataset.set(attNormalName, new Float32Array(values));
return this;
}
computeBoundingBox() {
const bbox = new TgdBoundingBox();
const { get } = this.dataset.getAttribAccessor(this.attPosition);
for (let index = 0; index < this.count; index++) {
const x = get(index, 0);
const y = get(index, 1);
const z = get(index, 2);
bbox.addPoint(x, y, z);
}
return bbox;
}
computeNormalsForTrianglesDrawMode() {
const ds = this.dataset;
const normalsAccumulator = new Map();
const addNormal = (index, A, B, C) => {
const norm = computeNormal(A, B, C);
const item = normalsAccumulator.get(index);
if (item) {
item.add(norm);
}
else {
normalsAccumulator.set(index, new TgdVec3(norm.x, norm.y, norm.z));
}
};
const { get } = ds.getAttribAccessor(this.attPosition);
const indexes = new Set();
let indexMax = 0;
for (let element = 0; element < this.count; element += 3) {
const index0 = this.getElement(element + 0);
indexes.add(index0);
indexMax = Math.max(indexMax, index0);
const index1 = this.getElement(element + 1);
indexes.add(index1);
indexMax = Math.max(indexMax, index1);
const index2 = this.getElement(element + 2);
indexes.add(index2);
indexMax = Math.max(indexMax, index2);
const A = new TgdVec3(get(index0, 0), get(index0, 1), get(index0, 2));
const B = new TgdVec3(get(index1, 0), get(index1, 1), get(index1, 2));
const C = new TgdVec3(get(index2, 0), get(index2, 1), get(index2, 2));
addNormal(index0, A, B, C);
addNormal(index1, B, C, A);
addNormal(index2, C, A, B);
}
const normals = [];
for (let index = 0; index <= indexMax; index++) {
const item = normalsAccumulator.get(index);
if (item) {
item.normalize();
normals.push(item);
}
else {
normals.push(new TgdVec3());
}
}
return normals;
}
}
TgdGeometry.counter = 1;
function computeNormal(A, B, C) {
const AB = new TgdVec3(B).subtract(A);
const AC = new TgdVec3(C).subtract(A);
return AB.cross(AC).normalize();
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VvbWV0cnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZ2VvbWV0cnkvZ2VvbWV0cnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBd0MsTUFBTSxjQUFjLENBQUE7QUFDL0UsT0FBTyxFQUFFLHlCQUF5QixFQUEwQyxNQUFNLFlBQVksQ0FBQTtBQUM5RixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFBO0FBQ25DLE9BQU8sRUFBRSw4QkFBOEIsRUFBRSxXQUFXLEVBQUUsTUFBTSxZQUFZLENBQUE7QUFDeEUsT0FBTyxFQUFFLGNBQWMsRUFBRSxlQUFlLEVBQUUsTUFBTSxJQUFJLENBQUE7QUF3Q3BEOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sV0FBVztJQWlCYixNQUFNLENBQUMsSUFBSSxDQUFDLE9BQTRCO1FBQzNDLE1BQU0sVUFBVSxHQUF5QixFQUFFLENBQUE7UUFDM0MsTUFBTSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLHVCQUF1QixFQUFFLEdBQUcsT0FBTyxDQUFBO1FBQ3JHLFVBQVUsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEdBQUcsV0FBVyxDQUFDLElBQUksSUFBSSxNQUFNLENBQUE7UUFDekQsSUFBSSxTQUFTO1lBQUUsVUFBVSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsR0FBRyxTQUFTLENBQUMsSUFBSSxJQUFJLE1BQU0sQ0FBQTtRQUNwRSxJQUFJLEtBQUs7WUFBRSxVQUFVLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQyxJQUFJLElBQUksTUFBTSxDQUFBO1FBQ3hELE1BQU0sT0FBTyxHQUFHLElBQUksVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFBO1FBQzFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxXQUFXLENBQUMs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