UNPKG

@tolokoban/tgd

Version:

ToloGameDev library for WebGL2

394 lines 35.3 kB
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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