@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
394 lines • 35.3 kB
JavaScript
import { __awaiter } from "tslib";
/**
* GLTF specs can be found here:
* https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html
*/
import { TgdDataset } from "./../../dataset/index.js";
import { parseGLB } from "./parser.js";
import { assertTgdTypeArrayForElements, } from "./../../types/index.js";
import { TgdGeometry } from "./../../geometry/index.js";
import { TgdTexture2D } from "./../../texture/index.js";
import { TgdCameraPerspective } from "./../../camera/index.js";
import { TgdQuat, TgdTransfo, TgdVec3 } from "./../../math/index.js";
export class TgdDataGlb {
/**
* @param content The binary content of a GLB file.
*/
constructor(content) {
this.chunkDetails = [];
this.cacheImages = new Map();
this.cacheImageURLs = new Map();
this.cacheBufferViewDatas = new Map();
try {
const data = parseGLB(content);
this.gltf = data.gltf;
this.chunks = data.chunks;
this.chunkDetails = data.chunkTypes;
}
catch (error) {
const message = error instanceof Error ? error.message : JSON.stringify(error);
console.error("[TgdParserGLTransfertFormatBinary::new] content:", content);
throw new Error(`[TgdParserGLTransfertFormatBinary] ${message}`);
}
}
createTransfoFromNode(node) {
const transfo = {};
if (node.rotation) {
console.log("🚀 [gltf] node.rotation =", node.rotation); // @FIXME: Remove this line written on 2025-04-17 at 21:07
transfo.orientation = new TgdQuat(node.rotation);
}
if (node.translation)
transfo.position = new TgdVec3(node.translation);
if (node.scale)
transfo.scale = new TgdVec3(node.scale);
return new TgdTransfo(transfo);
}
createCameraByName(name) {
const node = this.getNodeByNameOrThrow(name);
if (typeof node.camera === "number") {
const camera = this.getCamera(node.camera);
if (camera.type === "perspective") {
const perspective = new TgdCameraPerspective({
name,
near: camera.perspective.znear,
far: camera.perspective.zfar,
fovy: camera.perspective.yfov,
transfo: this.createTransfoFromNode(node),
});
return perspective;
}
else {
throw new Error("Sorry, but for now, we do not support Orthographic cameras...");
}
}
else {
console.error(node);
throw new Error(`Node "${name}" is not of type Camera!`);
}
}
getCamera(cameraIndex) {
var _a;
const camera = (_a = this.gltf.cameras) === null || _a === void 0 ? void 0 : _a[cameraIndex];
if (!camera) {
throw new Error(`Asset has no camera with index #${cameraIndex}!`);
}
return camera;
}
getChunkDetails() {
return structuredClone(this.chunkDetails);
}
get fileSize() {
return (12 + this.chunks.reduce((size, chunk) => size + chunk.byteLength, 0));
}
getScenes() {
var _a;
return (_a = this.gltf.scenes) !== null && _a !== void 0 ? _a : [];
}
getScene(sceneIndex) {
var _a;
const scene = (_a = this.gltf.scenes) === null || _a === void 0 ? void 0 : _a[sceneIndex];
if (!scene) {
throw new Error(`Asset has no scene with index #${sceneIndex}!`);
}
return scene;
}
getNode(nodeIndex) {
var _a;
const node = (_a = this.gltf.nodes) === null || _a === void 0 ? void 0 : _a[nodeIndex];
if (!node) {
throw new Error(`Asset has no node with index #${nodeIndex}!`);
}
return node;
}
getNodeByName(nodeName) {
const nodes = this.gltf.nodes;
if (!nodes)
return;
for (const node of nodes) {
if (node.name === nodeName)
return node;
}
}
getNodeByNameOrThrow(nodeName) {
var _a;
const node = this.getNodeByName(nodeName);
if (node)
return node;
throw new Error(`Unknown node "${nodeName}"!\nAvailable names:${((_a = this.gltf.nodes) !== null && _a !== void 0 ? _a : [])
.map((node, index) => `\n - ${typeof node.name === "string"
? JSON.stringify(node.name)
: `#${index}`}`)
.join("")}`);
}
getAccessor(accessorIndex = 0) {
var _a;
const accessor = (_a = this.gltf.accessors) === null || _a === void 0 ? void 0 : _a[accessorIndex];
if (!accessor) {
throw new Error(`Asset has no accessor with index #${accessorIndex}!`);
}
return accessor;
}
getMaterial(materialIndex) {
var _a;
const material = (_a = this.gltf.materials) === null || _a === void 0 ? void 0 : _a[materialIndex];
if (!material) {
throw new Error(`Asset has no material with index #${materialIndex}!`);
}
return material;
}
getMesh(meshIndexOrName = 0) {
var _a, _b;
if (typeof meshIndexOrName !== "number" &&
typeof meshIndexOrName !== "string")
return meshIndexOrName;
const mesh = typeof meshIndexOrName === "number"
? (_a = this.gltf.meshes) === null || _a === void 0 ? void 0 : _a[meshIndexOrName]
: ((_b = this.gltf.meshes) !== null && _b !== void 0 ? _b : []).find(item => item.name === meshIndexOrName);
if (!mesh) {
throw new Error(`Asset has no mesh with index/name ${JSON.stringify(meshIndexOrName)}!`);
}
return mesh;
}
getMeshPrimitive(meshIndexOrName = 0, primitiveIndex = 0) {
const mesh = typeof meshIndexOrName === "number" ||
typeof meshIndexOrName === "string"
? this.getMesh(meshIndexOrName)
: meshIndexOrName;
if (!mesh) {
throw new Error(`Asset has no mesh with index/name ${JSON.stringify(meshIndexOrName)}!`);
}
const primitive = mesh.primitives[primitiveIndex];
if (!primitive) {
throw new Error(`Asset has no primitive #${primitiveIndex} in mesh ${JSON.stringify(meshIndexOrName)}!`);
}
return primitive;
}
getMeshPrimitiveIndices(meshIndexOrName = 0, primitiveIndex = 0) {
var _a, _b;
const primitive = this.getMeshPrimitive(meshIndexOrName, primitiveIndex);
const accessor = this.getAccessor((_a = primitive.indices) !== null && _a !== void 0 ? _a : 0);
const elements = this.getBufferViewData((_b = accessor.bufferView) !== null && _b !== void 0 ? _b : 0, accessor.componentType);
assertTgdTypeArrayForElements(elements);
return elements;
}
getAccessorByAttributeName(primitive, attribName) {
const { attributes } = primitive;
if (!attributes || Object.keys(attributes).length === 0)
throw new Error("No attributes found!");
const accessorIndex = attributes[attribName];
if (typeof accessorIndex !== "number") {
throw new TypeError(`No attribute with name "${attribName}"!\nAvailable names are: ${Object.keys(attributes)
.map(name => JSON.stringify(name))
.join(", ")}.`);
}
try {
return this.getAccessor(accessorIndex);
}
catch (error) {
const message = error instanceof Error ? error.message : JSON.stringify(error);
throw new Error(`Attribute "${attribName}" pointed to an inexisting accessor!\n${message}`);
}
}
createTexture2D(context, textureIndex) {
var _a, _b, _c, _d, _e;
const gltfTex = (_a = this.gltf.textures) === null || _a === void 0 ? void 0 : _a[textureIndex];
if (!gltfTex) {
throw new Error(`Asset has no texture with index #${textureIndex}!`);
}
const source = (_e = (_b = gltfTex.source) !== null && _b !== void 0 ? _b : (_d = (_c = gltfTex.extensions) === null || _c === void 0 ? void 0 : _c.EXT_texture_webp) === null || _d === void 0 ? void 0 : _d.source) !== null && _e !== void 0 ? _e : 0;
const url = this.getImageURL(source);
const texture = new TgdTexture2D(context);
if (url) {
loadImage(url)
.then(bmp => {
if (bmp)
texture.loadBitmap(bmp);
else
console.error("Unable to load this file:", url);
})
.catch(console.error);
}
else {
console.error(`[GLTF] texture index #${textureIndex} is empty!`);
}
return texture;
}
loadImage(imageIndex) {
return __awaiter(this, void 0, void 0, function* () {
const fromCache = this.cacheImages.get(imageIndex);
if (fromCache)
return fromCache;
const url = this.getImageURL(imageIndex);
if (!url)
return;
const promise = new Promise((resolve, reject) => {
const img = new Image();
img.src = url;
img.addEventListener("load", () => {
resolve(img);
});
img.addEventListener("error", () => {
var _a;
console.error(`Unable to load image #${imageIndex}!`, (_a = this.gltf.images) === null || _a === void 0 ? void 0 : _a[imageIndex]);
reject();
});
});
this.cacheImages.set(imageIndex, promise);
return promise;
});
}
getImageURL(imageIndex) {
var _a;
const fromCache = this.cacheImageURLs.get(imageIndex);
if (fromCache)
return fromCache;
const { gltf } = this;
const image = (_a = gltf.images) === null || _a === void 0 ? void 0 : _a[imageIndex];
if (!image)
return;
if (image.uri)
return image.uri;
if (typeof image.bufferView !== "number")
return;
const buffer = this.getBufferViewData(image.bufferView, "Uint8");
if (!buffer)
return;
const blob = new Blob([buffer], {
type: image.mimeType,
});
const url = URL.createObjectURL(blob);
this.cacheImageURLs.set(imageIndex, url);
return url;
}
getBufferViewData(accessor, type = "Float32") {
var _a, _b, _c, _d, _e;
if (typeof accessor !== "number") {
return this.getBufferViewData((_a = accessor.bufferView) !== null && _a !== void 0 ? _a : 0, accessor.componentType);
}
const bufferViewIndex = accessor;
const fromCache = this.cacheBufferViewDatas.get(bufferViewIndex);
if (fromCache)
return fromCache;
const { gltf } = this;
const bufferView = (_b = gltf.bufferViews) === null || _b === void 0 ? void 0 : _b[bufferViewIndex];
if (!bufferView)
throw new Error(`No bufferView with index #${bufferViewIndex}!`);
const buffer = this.chunks[bufferView.buffer];
const byteOffset = (_c = bufferView.byteOffset) !== null && _c !== void 0 ? _c : 0;
const data = buffer.slice(byteOffset, byteOffset + bufferView.byteLength);
const view = figureOutView(data, convertTypeToNumber((_e = type !== null && type !== void 0 ? type : (_d = this.findAccessorForBufferView(bufferViewIndex)) === null || _d === void 0 ? void 0 : _d.componentType) !== null && _e !== void 0 ? _e : "Float32"));
this.cacheBufferViewDatas.set(bufferViewIndex, view);
return view;
}
findAccessorForBufferView(bufferViewIndex) {
var _a;
return ((_a = this.gltf.accessors) !== null && _a !== void 0 ? _a : []).find(accessor => accessor.bufferView === bufferViewIndex);
}
setAttrib(dataset, attribName, meshIndexOrName = 0, primitiveIndex = 0, primitiveAttribName) {
var _a, _b, _c, _d;
const { gltf } = this;
const accessorIndex = (_a = this.getMesh(meshIndexOrName).primitives[primitiveIndex].attributes[primitiveAttribName !== null && primitiveAttribName !== void 0 ? primitiveAttribName : attribName]) !== null && _a !== void 0 ? _a : -1;
const accessor = (_b = gltf.accessors) === null || _b === void 0 ? void 0 : _b[accessorIndex];
if (!accessor) {
throw new Error(`No attribute "${primitiveAttribName !== null && primitiveAttribName !== void 0 ? primitiveAttribName : attribName}" for primitive #${primitiveIndex} of mesh #${meshIndexOrName}!`);
}
const bufferViewIndex = (_c = accessor.bufferView) !== null && _c !== void 0 ? _c : 0;
const bufferView = (_d = gltf.bufferViews) === null || _d === void 0 ? void 0 : _d[bufferViewIndex];
if (!bufferView) {
throw new Error(`No bufferView with index #${bufferViewIndex}!`);
}
const view = this.getBufferViewData(bufferViewIndex, accessor.componentType);
dataset.set(attribName, view, {
byteStride: bufferView.byteStride,
byteOffset: accessor.byteOffset,
count: accessor.count,
});
}
makeGeometry({ computeNormals, meshIndex = 0, primitiveIndex = 0, attPositionName = "POSITION", attNormalName = "NORMAL", attTextureCoordsName = "TEXCOORD_0", } = {}) {
const primitive = this.getMeshPrimitive(meshIndex, primitiveIndex);
try {
const { attributes } = primitive;
if (!attributes)
throw new Error("No attributes found!");
const elements = this.getMeshPrimitiveIndices(meshIndex, primitiveIndex);
const definition = {
[attPositionName]: "vec3",
};
if (typeof attributes[attNormalName] === "string") {
definition[attNormalName] = "vec3";
}
if (typeof attributes[attTextureCoordsName] === "string") {
definition[attTextureCoordsName] = "vec2";
}
const dataset = new TgdDataset(definition);
dataset.set(attPositionName, returnFloat32Array(this.getBufferViewData(this.getAccessorByAttributeName(primitive, attPositionName))));
if (typeof attributes[attNormalName] === "string") {
dataset.set(attNormalName, returnFloat32Array(this.getBufferViewData(this.getAccessorByAttributeName(primitive, attNormalName))));
}
if (typeof attributes[attTextureCoordsName] === "string") {
dataset.set(attTextureCoordsName, returnFloat32Array(this.getBufferViewData(this.getAccessorByAttributeName(primitive, attTextureCoordsName))));
}
return new TgdGeometry({
computeNormalsIfMissing: computeNormals,
dataset,
elements,
attPosition: attPositionName,
attNormal: attNormalName,
attUV: attTextureCoordsName,
});
}
catch (error) {
const message = error instanceof Error ? error.message : JSON.stringify(error);
throw new Error(`Error in primitive #${primitiveIndex} of mesh #${meshIndex}:\n${message}`);
}
}
}
function figureOutView(data, componentType) {
switch (componentType) {
case 5120:
return new Int8Array(data);
case 5121:
return new Uint8Array(data);
case 5122:
return new Int16Array(data);
case 5123:
return new Uint16Array(data);
case 5125:
return new Uint32Array(data);
default:
return new Float32Array(data);
}
}
function convertTypeToNumber(type) {
if (typeof type === "number")
return type;
switch (type) {
case "Int8":
return 5120;
case "Uint8":
return 5121;
case "Int16":
return 5122;
case "Uint16":
return 5123;
case "Uint32":
return 5125;
default:
return WebGL2RenderingContext.FLOAT;
}
throw new Error("Function not implemented.");
}
function returnFloat32Array(data) {
if (data instanceof Float32Array)
return data;
throw new Error("We were expecting a Float32Array!");
}
function loadImage(url) {
return new Promise(resolve => {
const img = new Image();
img.src = url;
img.addEventListener("load", () => resolve(img));
img.addEventListener("error", () => resolve(null));
});
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2x0Zi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wYXJzZXIvZ2x0Zi9nbHRmLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O0dBR0c7QUFDSCxPQUFPLEVBQUUsVUFBVSxFQUF3QixNQUFNLGNBQWMsQ0FBQTtBQUMvRCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sVUFBVSxDQUFBO0FBV25DLE9BQU8sRUFDSCw2QkFBNkIsR0FFaEMsTUFBTSxZQUFZLENBQUE7QUFDbkIsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUMzQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sY0FBYyxDQUFBO0FBQzNDLE9BQU8sRUFBYSxvQkFBb0IsRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUM3RCxPQUFPLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBcUIsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFBO0FBRTNFLE1BQU0sT0FBTyxVQUFVO0lBdUJuQjs7T0FFRztJQUNILFlBQVksT0FBb0I7UUF0QmYsaUJBQVksR0FHeEIsRUFBRSxDQUFBO1FBQ1UsZ0JBQVcsR0FBRyxJQUFJLEdBQUcsRUFHbkMsQ0FBQTtRQUNjLG1CQUFjLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUE7UUFDMUMseUJBQW9CLEdBQUcsSUFBSSxHQUFHLEVBUTVDLENBQUE7UUFNQyxJQUFJLENBQUM7WUFDRCxNQUFNLElBQUksR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUE7WUFDOUIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFBO1lBQ3JCLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQTtZQUN6QixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUE7UUFDdkMsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDYixNQUFNLE9BQU8sR0FDVCxLQUFLLFlBQVksS0FB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