UNPKG

@babylonjs/loaders

Version:

For usage documentation please visit https://doc.babylonjs.com/features/featuresDeepDive/importers/loadingFileTypes/.

101 lines 4.01 kB
/** * Adding an exception here will break traversing through the glTF object tree. * This is used for properties that might not be in the glTF object model, but are optional and have a default value. * For example, the path /nodes/\{\}/extensions/KHR_node_visibility/visible is optional - the object can be deferred without the object fully existing. */ export const OptionalPathExceptionsList = [ { // get the node as object when reading an extension regex: new RegExp(`^/nodes/\\d+/extensions/`), }, ]; /** * A converter that takes a glTF Object Model JSON Pointer * and transforms it into an ObjectAccessorContainer, allowing * objects referenced in the glTF to be associated with their * respective Babylon.js objects. */ export class GLTFPathToObjectConverter { constructor(_gltf, _infoTree) { this._gltf = _gltf; this._infoTree = _infoTree; } /** * The pointer string is represented by a [JSON pointer](https://datatracker.ietf.org/doc/html/rfc6901). * See also https://github.com/KhronosGroup/glTF/blob/main/specification/2.0/ObjectModel.adoc#core-pointers * <animationPointer> := /<rootNode>/<assetIndex>/<propertyPath> * <rootNode> := "nodes" | "materials" | "meshes" | "cameras" | "extensions" * <assetIndex> := <digit> | <name> * <propertyPath> := <extensionPath> | <standardPath> * <extensionPath> := "extensions"/<name>/<standardPath> * <standardPath> := <name> | <name>/<standardPath> * <name> := W+ * <digit> := D+ * * Examples: * - "/nodes/0/rotation" * - "/nodes.length" * - "/materials/2/emissiveFactor" * - "/materials/2/pbrMetallicRoughness/baseColorFactor" * - "/materials/2/extensions/KHR_materials_emissive_strength/emissiveStrength" * * @param path The path to convert * @returns The object and info associated with the path */ convert(path) { let objectTree = this._gltf; let infoTree = this._infoTree; let target = undefined; if (!path.startsWith("/")) { throw new Error("Path must start with a /"); } const parts = path.split("/"); parts.shift(); //if the last part has ".length" in it, separate that as an extra part if (parts[parts.length - 1].includes(".length")) { const lastPart = parts[parts.length - 1]; const split = lastPart.split("."); parts.pop(); parts.push(...split); } let ignoreObjectTree = false; for (const part of parts) { const isLength = part === "length"; if (isLength && !infoTree.__array__) { throw new Error(`Path ${path} is invalid`); } if (infoTree.__ignoreObjectTree__) { ignoreObjectTree = true; } if (infoTree.__array__ && !isLength) { infoTree = infoTree.__array__; } else { infoTree = infoTree[part]; if (!infoTree) { throw new Error(`Path ${path} is invalid`); } } if (!ignoreObjectTree) { if (objectTree === undefined) { // check if the path is in the exception list. If it is, break and return the last object that was found const exception = OptionalPathExceptionsList.find((e) => e.regex.test(path)); if (!exception) { throw new Error(`Path ${path} is invalid`); } } else if (!isLength) { objectTree = objectTree?.[part]; } } if (infoTree.__target__ || isLength) { target = objectTree; } } return { object: target, info: infoTree, }; } } //# sourceMappingURL=gltfPathToObjectConverter.js.map