import { type ISceneLoaderPluginAsync, type ISceneLoaderPluginFactory, type ISceneLoaderAsyncResult, type ISceneLoaderProgressEvent, type SceneLoaderPluginOptions } from "@babylonjs/core/Loading/sceneLoader.js"; import { type Scene } from "@babylonjs/core/scene.js"; import { AssetContainer } from "@babylonjs/core/assetContainer.js"; /** * Source convention for tangent-space normal maps loaded from FBX normal-map slots. */ export type FBXNormalMapCoordinateSystem = "y-up" | "y-down"; /** * Defines options for the FBX loader. */ export interface FBXFileLoaderOptions { /** * Bundle of defaults for the options that change what the loaded scene looks like. * - "compatible" (default): the behaviour of the loader as first shipped: StandardMaterial for every material, * one Babylon geometry per model, curve geometry skipped, constraints recorded as metadata only, clips rebased * to start at frame 0, cameras and lights placed in world space. * - "full": everything the loader can do: PBRMaterial for physically based shaders, geometry shared between * instances, curves as lines meshes, constraints solved at runtime, authored clip times, cameras and lights * parented to their nodes so they animate. * An option set explicitly always wins over the preset. */ preset?: "compatible" | "full"; /** * Source convention for tangent-space normal maps connected through FBX normal-map slots. * FBX does not standardize this convention, so the loader defaults to the glTF/USD-style Y-up convention. * Set to "y-down" for assets authored with inverted green/Y normal maps. */ normalMapCoordinateSystem?: FBXNormalMapCoordinateSystem; /** * Which Babylon material to build. * - "standard" (default, "full" preset: "auto"): always StandardMaterial (PBR parameters are approximated). * - "auto": PBRMaterial for physically based FBX materials (Standard Surface, Arnold, 3ds Max Physical, * 3ds Max PBR, glTF, OpenPBR, Stingray PBS) and StandardMaterial for classic Lambert/Phong materials. * - "pbr": always PBRMaterial (Lambert/Phong parameters are converted). */ materials?: "auto" | "standard" | "pbr"; /** * Unit conversion applied at the root of the loaded hierarchy. * - "preserve" (default): keep the file's units (1 Babylon unit = 1 FBX unit). * - "meters": scale so that 1 Babylon unit is 1 meter, using the file's UnitScaleFactor. * - a number: centimeters per Babylon unit (100 = meters, 1 = centimeters, 2.54 = inches). */ unitScale?: "preserve" | "meters" | number; /** * Share vertex data between models that reference the same FBX geometry (default false, "full" preset: true). * Skinned meshes are never shared. */ shareGeometry?: boolean; /** * Called for every recoverable issue found while loading (unsupported features, malformed data that was * skipped, approximations). The same list is stored on the root node's metadata as `fbxDiagnostics`. */ onWarning?: (warning: FBXLoaderWarning) => void; /** * Segments per knot span when tessellating NURBS surfaces. Zero or undefined uses the subdivision stored in * the file (usually 4), capped at 16. */ nurbsSubdivision?: number; /** How curve geometry (Line, NurbsCurve) is imported: skipped (default) or as lines meshes ("full" preset). */ curves?: "lines" | "skip"; /** * Constraints (aim, parent, position, rotation, scale): "metadata" (default) only records them on the nodes, * "apply" ("full" preset) attaches an `FBXConstraintBehavior` to each constrained node so it is solved before * every render. IK chains are always metadata only. */ constraints?: "apply" | "metadata"; /** * Shift every clip so its first keyframe sits at frame 0 (default true). With false ("full" preset) keys keep * the times authored in the file, so clips of one file stay aligned with each other and with their declared * ranges. */ rebaseAnimations?: boolean; /** * Parent cameras and lights to their FBX node so they follow its animation (default false, "full" preset: * true). Otherwise they are created at the node's world position and orientation, unparented. */ attachCamerasAndLights?: boolean; } /** A recoverable issue reported while loading an FBX file. */ export interface FBXLoaderWarning { /** Which part of the loader reported the issue */ source: "scene" | "model" | "geometry" | "skin" | "rig" | "animation" | "blendShape" | "camera" | "light"; /** Human readable description */ message: string; /** Name of the affected object, when known */ objectName?: string; /** Structured details from the interpreter, when any */ details?: unknown; } /** * FBX file loader plugin for Babylon.js. * Pure TypeScript implementation — no Autodesk FBX SDK dependency. */ export declare class FBXFileLoader implements ISceneLoaderPluginAsync, ISceneLoaderPluginFactory { /** * Defines the name of the plugin. */ readonly name: "fbx"; /** * Defines the extension the plugin is able to load. */ readonly extensions: { readonly ".fbx": { readonly isBinary: true; }; }; private readonly _options; private readonly _bindRestBones; private readonly _sourceBonesBySkeleton; private readonly _scaleCompensationHelpersBySkeleton; /** Frame rate of the file being loaded (GlobalSettings TimeMode); animation is baked at this rate. */ private _frameRate; /** Layers of the animation stack currently being converted; used by the transform samplers. */ private _activeLayers; /** Parent model per model id, for inherit-mode aware sampling. */ private _parentModelById; /** Curve nodes per model id for the stack currently being converted. */ private _curveNodesByModelId; /** Helper nodes inserted above models whose InheritType is not RSrs. */ private _inheritScaleHelpers; /** First mesh built per (geometry, geometric transform), for geometry sharing between instances. */ private _meshByGeometryKey; /** Instance mesh -> source mesh whose geometry it shares. */ private _instanceSource; /** Property curve nodes that were mapped onto Babylon animations; their "not evaluated" diagnostics are dropped. */ private _evaluatedCurveNodeIds; /** * Creates a new FBX loader. * @param options - Options controlling FBX loading behavior */ constructor(options?: FBXFileLoaderOptions); /** * Creates an FBX loader plugin instance with options from SceneLoader. * @param options - Scene loader plugin options * @returns The configured FBX loader */ createPlugin(options: SceneLoaderPluginOptions): ISceneLoaderPluginAsync; /** * Imports meshes from an FBX file and adds them to the scene. * @param meshesNames - A string or array of mesh names to import, or null/undefined to import all meshes * @param scene - The scene to add imported meshes to * @param data - The FBX data to load * @param rootUrl - Root URL used to resolve external resources * @param _onProgress - Callback called while the file is loading * @param _fileName - Name of the file being loaded * @returns A promise containing the loaded meshes, particle systems, skeletons, animation groups, transform nodes, geometries, and lights */ importMeshAsync(meshesNames: string | readonly string[] | null | undefined, scene: Scene, data: unknown, rootUrl: string, _onProgress?: (event: ISceneLoaderProgressEvent) => void, _fileName?: string): Promise; /** * Loads all FBX content into the scene. * @param scene - The scene to load the FBX content into * @param data - The FBX data to load * @param rootUrl - Root URL used to resolve external resources * @param _onProgress - Callback called while the file is loading * @param _fileName - Name of the file being loaded * @returns A promise that resolves when loading is complete */ loadAsync(scene: Scene, data: unknown, rootUrl: string, _onProgress?: (event: ISceneLoaderProgressEvent) => void, _fileName?: string): Promise; /** * Loads all FBX content into an asset container. * @param scene - The scene used to create the asset container * @param data - The FBX data to load * @param rootUrl - Root URL used to resolve external resources * @param _onProgress - Callback called while the file is loading * @param _fileName - Name of the file being loaded * @returns A promise containing the loaded asset container */ loadAssetContainerAsync(scene: Scene, data: unknown, rootUrl: string, _onProgress?: (event: ISceneLoaderProgressEvent) => void, _fileName?: string): Promise; /** * Parses and interprets the file. Parsing is synchronous, so no progress events are emitted: the scene loader's * progress callback reports download bytes and must not be fed synthetic counts. */ private _parseAndInterpret; private _parse; private _parseFromArrayBuffer; private _buildScene; private _addMaterialToContainer; private _addTextureToContainer; private _setAssetContainer; private static _computeFBXAxisConversionMatrix; private _buildModel; private _linkSkeletonsToTransformNodes; private static _modelSubtreeMatchesNameFilter; private static _applyModelMetadata; /** * Wires a LodGroup's children as Babylon LOD levels: the first child holds the highest detail; every further * child replaces it beyond the group's threshold distance (or screen coverage when thresholds are percentages). * Each child's display mode is honoured first: level 1 (show) stays visible outside the LOD chain, level 2 * (hide) is disabled, and only level 0 (use LOD) children take part in the distance switching. */ private static _applyLodGroup; /** Builds a lines mesh from Line or tessellated NurbsCurve geometry, applying the model's geometric transform. */ private _createLinesMesh; private _createMesh; /** * Apply multi-material to a mesh by creating sub-meshes grouped by material index. * Reorders the index buffer so that triangles sharing the same material are contiguous. */ private _applyMultiMaterial; private static _collectCullingConflictMaterialIds; private static _getModelMaterial; private _applyMaterialUVSetCoordinates; private _applyStandardMaterialUVSetCoordinates; /** * Babylon multiplies vertex colors by material diffuse color. Use per-mesh * material clones so vertex-colored geometry can render unmodulated without * changing shared materials used by non-vertex-colored meshes. */ private _useUnmodulatedVertexColorMaterials; /** * Build per-polygon-vertex bone indices and weights from the control-point-based skin data. * The geometry expands control points to per-polygon-vertex, so we need to look up * each polygon-vertex's control point index. */ private _buildSkinningData; private _createMaterial; private _createPbrMaterial; /** Alpha of a classic Lambert/Phong material: Opacity when present, otherwise 1 - TransparentColor * TransparencyFactor. */ private static _alphaFromClassicTransparency; private static _applyTextureSettings; private _createStandardMaterial; private _configureNormalTexture; private _getNormalMapTangentHandednessScale; private static _isSupportedMaterialTextureSlot; private static _isNormalMapTextureSlot; private static _createTexture; private static _createExternalTexture; private static _buildTextureFallbackUrls; private static _getTextureCreationOptions; private static _getExternalTextureUrls; private static _getTextureSourceName; private static _getTextureSourceNameFromPath; private static _isSafeRelativeTexturePath; private static _getForcedExtension; private static _getMimeType; /** * Apply blend shape (morph target) deformers to meshes. * FBX Shape vertices are stored as absolute positions for sparse control points. * We compute deltas relative to the base mesh positions. */ private _applyBlendShapes; private _createCamera; private _createLight; private _createSkeleton; private _rigBoneModelIds; private _isRigBone; private _getSourceBone; private _getScaleCompensationHelper; private static _computeFBXAbsoluteMatrices; /** * Effective ("inherit") scale of every bone, following the FBX SDK: the local scale for RSrs bones, and for * RrSs / Rrs bones the local scale multiplied by the scale of the bone's inherit-scale node (the parent for RrSs, * the parent's inherit-scale node for Rrs). Bones are ordered parents first. */ private static _computeBoneInheritScales; private static _getBoneInheritScaleNode; /** Scale a bone inherits into its own scale (RrSs chains), or unit scale. */ private static _getBoneInheritedScale; private static _computeFBXRuntimeLocalMatrix; private static _applyParentScaleCompensation; /** * Splits a bone's FBX local matrix into a helper (which cancels the parent scale and carries the translation, * so the translation still follows the parent scale as the SDK does) and the bone's own rotation/scale. For RrSs * bones the inherited scale is folded into the bone scale. */ private static _splitParentScaleCompensatedLocalMatrix; private static _safeInverseScale; private static _getInverseScaleVector; private static _shouldUseBindMatricesAsRest; private static _getMaxScaleRatio; private static _getScaleRatio; private static _computeFBXGeometricMatrix; private static _computeFBXGeometricDeltaMatrix; private static _computeFBXGeometricNormalMatrix; /** * Compute the full FBX local transform matrix: * M = T * Roff * Rp * Rpre * R * Rpost^-1 * Rp^-1 * Soff * Sp * S * Sp^-1 * * In row-vector convention: v' = v * M */ private static _computeFBXLocalMatrix; private _applyRestTRS; private static _computeFBXModelLocalMatrix; private static _applyMatrixToTransform; private _createAnimationGroup; private _buildInheritedRigBoneAnimations; private static _pushMatrixKeys; /** * Build animations for a non-bone node, correctly handling pivots. * Computes the full FBX transform matrix at each keyframe and decomposes into TRS. */ private _buildNodeAnimations; /** * Baked keys are interpolated linearly by Babylon. Between two frames an FBX cubic segment can deviate from that * line, so sample times are refined (midpoints inserted, up to two levels) wherever the interpolated transform * differs noticeably from the curve. Flat and linear segments stay at frame resolution. */ private static _refineSampleTimes; /** * Keys of a scalar property animated by one or more layers: the authored keys when a single layer drives it, * otherwise the frame grid evaluated through the layer stack. * @param sources - Per-layer curves of the property (each with at least one curve) * @param animStack - Stack being converted * @param mapValue - Conversion from the FBX value to the Babylon property value * @returns Animation keys */ private _layeredScalarKeys; /** * Maps an animated FBX property (anything other than node transforms and blend shape weights) onto the Babylon * property that carries it: mesh visibility, camera field of view and clip planes, light intensity, colour and * cone angles, and material colours, alpha, roughness and metalness. `group` holds the curve nodes of every * layer animating that property, in layer order; several layers are evaluated through the layer stack. */ private _buildPropertyAnimations; /** Records constraints on their nodes and, unless disabled, attaches the runtime behavior that solves them. */ private _applyConstraints; /** Collects every recoverable issue the interpreter recorded, stores it on the root node and notifies the caller. */ private _reportDiagnostics; /** Curve nodes affecting the inherit scale of a model: its own scale curves and those of its inherit-scale chain. */ private _collectInheritScaleCurves; private _isVector3KeysConstant; /** Samples the animated Lcl Translation / Rotation / Scaling of a model, blending all layers of the active stack. */ private _sampleModelTRS; /** * Local position/rotation/scale of a model from FBX Lcl values. Without pivots and offsets the components map * directly (rotation = pre * lcl * post⁻¹), which keeps zero and negative scales exact. With pivots the full * matrix is built and decomposed. */ private static _computeLocalTRS; /** Applies inherit-mode adjustments to a local TRS (see _computeInheritAwareLocalMatrix). */ private _adjustTRSForInheritMode; private _sampleModelLocalMatrix; private _sampleModelScale; /** * Effective scale of a model for inherit-mode math (`inherit_scale` in ufbx terms): its own local scale, multiplied * componentwise by the inherited scale when the model uses RrSs inheritance. `time` samples animation; undefined * uses the rest pose. */ private _getInheritScale; /** RrSs nodes inherit scale from their parent; Rrs nodes skip their immediate parent (chaining through Rrs parents). */ private _getInheritScaleNode; /** * Local matrix of a model relative to its Babylon parent frame, accounting for inherit modes. For RSrs (the * default) this is the FBX local matrix. For RrSs / Rrs the node sits under a helper that removes the parent's * scale, so translation is pre-scaled by the parent scale and (for RrSs) scale accumulates componentwise. */ private _computeInheritAwareLocalMatrix; /** * Build matrix-baked bone animation from full FBX local transforms. * The bind matrix carries the skinning offset, so animation curves drive * the same FBX local transform chain as the source skeleton. */ private _buildBoneAnimations; private _buildNameFilter; } /** * Registers the FBXFileLoader scene loader plugin. * Safe to call multiple times; only the first call has an effect. */ export declare function RegisterFBXFileLoader(): void;