@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
432 lines • 40.1 kB
JavaScript
/**
* GLTF specs can be found here:
* https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html
*/
import { load } from "@loaders.gl/core";
import { DracoLoader } from "@loaders.gl/draco";
import { GLTFLoader } from "@loaders.gl/gltf";
import { TgdCameraPerspective } from "./../../camera/index.js";
import { TgdDataset } from "./../../dataset/index.js";
import { TgdGeometry } from "./../../geometry/index.js";
import { tgdLoadImage, tgdLoadImageFromArrayBuffer } from "./../../loader/index.js";
import { TgdQuat, TgdTransfo, TgdVec3 } from "./../../math/index.js";
import { TgdTexture2D } from "./../../texture/index.js";
import { assertTgdFormatGltf, assertTgdTypeArrayForElements, } from "./../../types/index.js";
import { isNumber } from "./../../types/guards.js";
const EMPTY_IMAGE = new Image();
export class TgdDataGlb {
static async parse(content) {
const blob = new Blob([content]);
const url = URL.createObjectURL(blob);
const gltfWithBuffers = await load(url, GLTFLoader, {
DracoLoader,
decompress: true,
decompressMeshes: true,
loadBuffers: true,
loadImages: true,
});
URL.revokeObjectURL(url);
const gltf = gltfWithBuffers.json;
const chunks = [];
for (const buffer of gltfWithBuffers.buffers) {
chunks.push(buffer.arrayBuffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength));
}
const images = [];
for (let imageIndex = 0; imageIndex < (gltf.images ?? []).length; imageIndex++) {
const image = gltf.images?.[imageIndex];
if (!image) {
images.push(EMPTY_IMAGE);
continue;
}
if (image.uri) {
images.push((await tgdLoadImage(image.uri)) ?? EMPTY_IMAGE);
continue;
}
if (typeof image.bufferView !== "number") {
images.push(EMPTY_IMAGE);
continue;
}
// const buffer = this.getBufferViewData(image.bufferView, "Uint8")
const bufferView = gltf.bufferViews?.[image.bufferView];
if (!bufferView)
throw new Error(`No bufferView with index #${image.bufferView}!`);
images.push((await tgdLoadImageFromArrayBuffer(chunks[bufferView.buffer].slice(bufferView.byteOffset ?? 0, (bufferView.byteOffset ?? 0) + bufferView.byteLength))) ?? EMPTY_IMAGE);
}
return new TgdDataGlb(gltf, chunks, images, content.byteLength);
}
/**
* @param content The binary content of a GLB file.
*/
constructor(json, chunks, images, fileSize) {
this.chunks = chunks;
this.images = images;
this.fileSize = fileSize;
this.cacheBufferViewDatas = new Map();
try {
// const data = parseGLB(content)
assertTgdFormatGltf(json);
this.json = json;
// this.chunks = data.chunks
// this.chunkDetails = data.chunkTypes
}
catch (error) {
const message = error instanceof Error ? error.message : JSON.stringify(error);
console.error("[TgdParserGLTransfertFormatBinary::new] json:", json);
throw new Error(`[TgdParserGLTransfertFormatBinary] ${message}`);
}
}
getJson() {
return structuredClone(this.json);
}
createTransfoFromNode(node) {
const transfo = {};
if (node.rotation) {
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;
}
throw new Error("Sorry, but for now, we do not support Orthographic cameras...");
}
console.error(node);
throw new Error(`Node "${name}" is not of type Camera!`);
}
getBufferViews() {
return this.json.bufferViews ?? [];
}
getBufferView(bufferViewIndex) {
return this.json.bufferViews?.[bufferViewIndex];
}
getCamera(cameraIndex) {
const camera = this.json.cameras?.[cameraIndex];
if (!camera) {
throw new Error(`Asset has no camera with index #${cameraIndex}!`);
}
return camera;
}
getImages() {
return this.json.images ?? [];
}
getImage(imageIndexOrName) {
const { images } = this.json;
if (!images)
return;
if (typeof imageIndexOrName === "number")
return images?.[imageIndexOrName];
return images.find((img) => img.name === imageIndexOrName);
}
getImageAsHTMLElement(imageIndexOrName) {
const { images } = this.json;
if (!images)
return;
if (typeof imageIndexOrName === "number") {
return this.images[imageIndexOrName] ?? EMPTY_IMAGE;
}
for (let i = 0; i < images.length; i++) {
if (images[i].name === imageIndexOrName)
return this.images[i];
}
throw new Error(`There is no image with name "${imageIndexOrName}" in this GLB file!\nPossible names are: ${images.map((img) => img.name).join(", ")}.`);
}
getScenes() {
return this.json.scenes ?? [];
}
getScene(sceneIndex) {
const scene = this.json.scenes?.[sceneIndex];
if (!scene) {
throw new Error(`Asset has no scene with index #${sceneIndex}!`);
}
return scene;
}
getNodes() {
return this.json.nodes ?? [];
}
getNode(nodeIndex) {
const node = this.json.nodes?.[nodeIndex];
if (!node) {
throw new Error(`Asset has no node with index #${nodeIndex}!`);
}
return node;
}
getNodeByName(nodeName) {
const nodes = this.json.nodes;
if (!nodes)
return;
for (const node of nodes) {
if (node.name === nodeName)
return node;
}
}
getNodeByNameOrThrow(nodeName) {
const node = this.getNodeByName(nodeName);
if (node)
return node;
throw new Error(`Unknown node "${nodeName}"!\nAvailable names:${(this.json.nodes ?? [])
.map((node, index) => `\n - ${typeof node.name === "string" ? JSON.stringify(node.name) : `#${index}`}`)
.join("")}`);
}
getAccessor(accessorIndex = 0) {
const accessor = this.json.accessors?.[accessorIndex];
if (!accessor) {
throw new Error(`Asset has no accessor with index #${accessorIndex}!`);
}
return accessor;
}
getMaterial(materialIndex) {
const material = this.json.materials?.[materialIndex];
if (!material) {
throw new Error(`Asset has no material with index #${materialIndex}!`);
}
return material;
}
getMesh(meshIndexOrName = 0) {
if (typeof meshIndexOrName !== "number" && typeof meshIndexOrName !== "string")
return meshIndexOrName;
const mesh = typeof meshIndexOrName === "number"
? this.json.meshes?.[meshIndexOrName]
: (this.json.meshes ?? []).find((item) => item.name === meshIndexOrName);
if (!mesh)
return undefined;
return mesh;
}
getMeshOrThrow(meshIndexOrName = 0) {
if (typeof meshIndexOrName !== "number" && typeof meshIndexOrName !== "string")
return meshIndexOrName;
const mesh = typeof meshIndexOrName === "number"
? this.json.meshes?.[meshIndexOrName]
: (this.json.meshes ?? []).find((item) => item.name === meshIndexOrName);
if (!mesh) {
throw new Error(`Asset has no mesh with index/name ${JSON.stringify(meshIndexOrName)}!\nAvailable names are: ${(this.json.meshes ?? [])
.sort()
.map((mesh) => mesh.name)
.join(", ")}.`);
}
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)}!\nAvailable names are: ${(this.json.meshes ?? []).map((mesh) => mesh.name).join(", ")}.`);
}
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) {
const primitive = this.getMeshPrimitive(meshIndexOrName, primitiveIndex);
const { indices } = primitive;
if (isNumber(indices)) {
const accessor = this.getAccessor(indices);
const elements = this.getBufferViewData(accessor.bufferView ?? 0, accessor.componentType);
assertTgdTypeArrayForElements(elements);
return elements;
}
if (indices) {
const elements = indices.value;
assertTgdTypeArrayForElements(elements);
return elements;
}
return new Uint8Array();
}
getAccessorByAttributeName(primitive, attribName) {
const { attributes } = primitive;
if (!attributes || Object.keys(attributes).length === 0) {
throw new Error("No attributes found!");
}
const attribute = attributes[attribName];
if (attribute === undefined) {
throw new TypeError(`No attribute with name "${attribName}"!\nAvailable names are: ${Object.keys(attributes)
.map((name) => JSON.stringify(name))
.join(", ")}.`);
}
if (isNumber(attribute)) {
try {
return this.getAccessor(attribute);
}
catch (error) {
const message = error instanceof Error ? error.message : JSON.stringify(error);
throw new Error(`Attribute "${attribName}" pointed to an inexisting accessor!\n${message}`);
}
}
else {
return attribute;
}
}
createTexture2D(context, textureIndex, color = [0, 0, 0, 1]) {
const gltfTex = this.json.textures?.[textureIndex];
if (!gltfTex) {
throw new Error(`Asset has no texture with index #${textureIndex}!`);
}
const source = gltfTex.source ?? gltfTex.extensions?.EXT_texture_webp?.source ?? 0;
const texture = new TgdTexture2D(context, { color }).loadBitmap(this.images[source]);
return texture;
}
getBufferViewData(accessor, type = "Float32") {
if (typeof accessor !== "number") {
return this.getBufferViewData(accessor.bufferView ?? 0, accessor.componentType);
}
const bufferViewIndex = accessor;
const fromCache = this.cacheBufferViewDatas.get(bufferViewIndex);
if (fromCache)
return fromCache;
const { json: gltf } = this;
const bufferView = gltf.bufferViews?.[bufferViewIndex];
if (!bufferView)
throw new Error(`No bufferView with index #${bufferViewIndex}!`);
const buffer = this.chunks[bufferView.buffer];
const byteOffset = bufferView.byteOffset ?? 0;
const data = buffer.slice(byteOffset, byteOffset + bufferView.byteLength);
const view = figureOutView(data, convertTypeToNumber(type ?? this.findAccessorForBufferView(bufferViewIndex)?.componentType ?? "Float32"));
this.cacheBufferViewDatas.set(bufferViewIndex, view);
return view;
}
findAccessorForBufferView(bufferViewIndex) {
return (this.json.accessors ?? []).find((accessor) => accessor.bufferView === bufferViewIndex);
}
setAttrib(dataset, attribName, meshIndexOrName = 0, primitiveIndex = 0, primitiveAttribName) {
const { json: gltf } = this;
const attribute = this.getMeshOrThrow(meshIndexOrName).primitives[primitiveIndex].attributes[primitiveAttribName ?? attribName] ?? -1;
if (!isNumber(attribute)) {
dataset.set(attribName, attribute.value, {
byteStride: attribute.size * 4,
byteOffset: attribute.byteOffset,
count: attribute.count,
});
return;
}
const accessor = gltf.accessors?.[attribute];
if (!accessor) {
throw new Error(`No attribute "${primitiveAttribName ?? attribName}" for primitive #${primitiveIndex} of mesh #${meshIndexOrName}!`);
}
const bufferViewIndex = accessor.bufferView ?? 0;
const bufferView = gltf.bufferViews?.[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(options = {}) {
const { computeNormals, meshIndex = 0, primitiveIndex = 0, attPositionName = "POSITION", attNormalName = "NORMAL", attTextureCoordsName = "TEXCOORD_0", } = options;
try {
const dataset = this.makeDataset(options);
const elements = this.getMeshPrimitiveIndices(meshIndex, primitiveIndex);
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}`);
}
}
makeDataset({ 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 definition = {
[attPositionName]: "vec3",
};
if (attributes[attNormalName] !== undefined) {
definition[attNormalName] = "vec3";
}
if (attributes[attTextureCoordsName] !== undefined) {
definition[attTextureCoordsName] = "vec2";
}
const dataset = new TgdDataset(definition);
if (isNumber(attributes[attPositionName])) {
dataset.set(attPositionName, returnFloat32Array(this.getBufferViewData(this.getAccessorByAttributeName(primitive, attPositionName))));
}
else {
dataset.set(attPositionName, attributes[attPositionName].value);
}
if (typeof definition[attNormalName] === "string") {
dataset.set(attNormalName, isNumber(attributes[attNormalName])
? returnFloat32Array(this.getBufferViewData(this.getAccessorByAttributeName(primitive, attNormalName)))
: attributes[attNormalName].value);
}
if (typeof definition[attTextureCoordsName] === "string") {
dataset.set(attTextureCoordsName, isNumber(attributes[attTextureCoordsName])
? returnFloat32Array(this.getBufferViewData(this.getAccessorByAttributeName(primitive, attTextureCoordsName)))
: attributes[attTextureCoordsName].value);
}
return dataset;
}
catch (error) {
const message = error instanceof Error ? error.message : JSON.stringify(error);
throw new Error(`Error in primitive #${primitiveIndex} of mesh ${typeof meshIndex === "number" ? `#${meshIndex}` : JSON.stringify(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;
}
}
function returnFloat32Array(data) {
if (data instanceof Float32Array)
return data;
throw new Error("We were expecting a Float32Array!");
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2x0Zi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wYXJzZXIvZ2x0Zi9nbHRmLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUNILE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQTtBQUN2QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFDL0MsT0FBTyxFQUFhLFVBQVUsRUFBd0IsTUFBTSxrQkFBa0IsQ0FBQTtBQUM5RSxPQUFPLEVBQWtCLG9CQUFvQixFQUFFLE1BQU0sYUFBYSxDQUFBO0FBR2xFLE9BQU8sRUFBRSxVQUFVLEVBQTZCLE1BQU0sY0FBYyxDQUFBO0FBQ3BFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxlQUFlLENBQUE7QUFDM0MsT0FBTyxFQUFFLFlBQVksRUFBRSwyQkFBMkIsRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUN2RSxPQUFPLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBMEIsT0FBTyxFQUFXLE1BQU0sV0FBVyxDQUFBO0FBQ3pGLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxjQUFjLENBQUE7QUFDM0MsT0FBTyxFQUVILG1CQUFtQixFQUNuQiw2QkFBNkIsR0FFaEMsTUFBTSxZQUFZLENBQUE7QUFlbkIsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBRTVDLE1BQU0sV0FBVyxHQUFHLElBQUksS0FBSyxFQUFFLENBQUE7QUFFL0IsTUFBTSxPQUFPLFVBQVU7SUFDWixNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxPQUFvQjtRQUMxQyxNQUFNLElBQUksR0FBRyxJQUFJLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUE7UUFDaEMsTUFBTSxHQUFHLEdBQUcsR0FBRyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUNyQyxNQUFNLGVBQWUsR0FBb0IsTUFBTSxJQUFJLENBQUMsR0FB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