babylonjs-loaders 9.12.0 → 9.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/babylonjs.loaders.d.ts +1391 -0
- package/babylonjs.loaders.js +1 -1
- package/babylonjs.loaders.js.map +1 -1
- package/babylonjs.loaders.min.js +1 -1
- package/babylonjs.loaders.min.js.map +1 -1
- package/babylonjs.loaders.module.d.ts +2846 -0
- package/package.json +3 -3
package/babylonjs.loaders.d.ts
CHANGED
|
@@ -7215,6 +7215,14 @@ declare namespace BABYLON {
|
|
|
7215
7215
|
* @returns a promise containing the loaded meshes, particles, skeletons and animations
|
|
7216
7216
|
*/
|
|
7217
7217
|
importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, _onProgress?: (event: ISceneLoaderProgressEvent) => void, _fileName?: string): Promise<ISceneLoaderAsyncResult>;
|
|
7218
|
+
/**
|
|
7219
|
+
* Detects a PlayCanvas-style `lod-meta.json` payload and, if found, creates a streaming mesh for it.
|
|
7220
|
+
* @param scene hosting scene
|
|
7221
|
+
* @param data loaded file data
|
|
7222
|
+
* @param rootUrl root url the metadata's relative paths resolve against
|
|
7223
|
+
* @returns the streaming mesh, or null when the data is not SOG LOD metadata
|
|
7224
|
+
*/
|
|
7225
|
+
private _tryCreateLODStream;
|
|
7218
7226
|
private static _BuildPointCloud;
|
|
7219
7227
|
private static _BuildMesh;
|
|
7220
7228
|
private _unzipWithFFlateAsync;
|
|
@@ -7417,6 +7425,421 @@ declare namespace BABYLON {
|
|
|
7417
7425
|
|
|
7418
7426
|
|
|
7419
7427
|
|
|
7428
|
+
/** This file must only contain pure code and pure imports */
|
|
7429
|
+
/**
|
|
7430
|
+
* Shared shader names for the SOG -> decoded work-buffer copy pass.
|
|
7431
|
+
*/
|
|
7432
|
+
export const GaussianSplattingWorkBufferShaderName = "gsSogDecodeToWorkBuffer";
|
|
7433
|
+
/**
|
|
7434
|
+
* Pass-through vertex shader (GLSL): the geometry is a fullscreen triangle already in NDC.
|
|
7435
|
+
*/
|
|
7436
|
+
export const GaussianSplattingWorkBufferVertexShaderGLSL = "precision highp float;\nattribute vec3 position;\nvoid main() {\n gl_Position = vec4(position.xy, 0.0, 1.0);\n}\n";
|
|
7437
|
+
/**
|
|
7438
|
+
* Fragment shader (GLSL/WebGL2): decodes one SOG source file into the decoded GS work-buffer layout,
|
|
7439
|
+
* writing each splat into its allocated pixel. Mirrors the USE_SOG decode in ShadersInclude/gaussianSplatting.fx
|
|
7440
|
+
* but outputs the decoded MRT (center, covA, covB, color) consumed by the standard (non-SOG) draw path.
|
|
7441
|
+
*
|
|
7442
|
+
* MRT layout: 0 = center (x,y,z,1), 1 = covA (Sigma00,01,02,11), 2 = covB (Sigma12,22,0,0), 3 = color (rgba).
|
|
7443
|
+
*/
|
|
7444
|
+
export const GaussianSplattingWorkBufferFragmentShaderGLSL = "precision highp float;\nprecision highp int;\n\nuniform sampler2D sogMeansLTex;\nuniform sampler2D sogMeansUTex;\nuniform sampler2D sogScalesTex;\nuniform sampler2D sogQuatsTex;\nuniform sampler2D sogSh0Tex;\nuniform sampler2D sogCodebookTex;\n\nuniform vec3 sogMeansMin;\nuniform vec3 sogMeansMax;\nuniform vec3 sogScalesMin;\nuniform vec3 sogScalesMax;\nuniform vec4 sogSh0Min;\nuniform vec4 sogSh0Max;\nuniform int uVersion;\nuniform int uOffset;\nuniform int uCount;\nuniform int uDestWidth;\nuniform int uSrcWidth;\n\nlayout(location = 0) out vec4 glFragData[4];\n\nmat3 transposeM(mat3 m) {\n return mat3(m[0][0], m[1][0], m[2][0], m[0][1], m[1][1], m[2][1], m[0][2], m[1][2], m[2][2]);\n}\n\nvoid main() {\n ivec2 p = ivec2(gl_FragCoord.xy);\n int global = p.y * uDestWidth + p.x;\n if (global < uOffset || global >= uOffset + uCount) {\n discard;\n }\n int k = global - uOffset;\n ivec2 src = ivec2(k - (k / uSrcWidth) * uSrcWidth, k / uSrcWidth);\n\n vec3 mL = texelFetch(sogMeansLTex, src, 0).xyz;\n vec3 mU = texelFetch(sogMeansUTex, src, 0).xyz;\n vec3 sRaw = texelFetch(sogScalesTex, src, 0).xyz;\n vec4 qRaw = texelFetch(sogQuatsTex, src, 0);\n vec4 c0 = texelFetch(sogSh0Tex, src, 0);\n\n // Position: q16 = (u<<8)|l normalized; n = lerp(min,max,q16); pos = sign(n)*(exp(|n|)-1)\n vec3 q16 = (mU * 256.0 + mL) * (255.0 / 65535.0);\n vec3 nPos = mix(sogMeansMin, sogMeansMax, q16);\n vec3 center = sign(nPos) * (exp(abs(nPos)) - vec3(1.0));\n\n // Scale (v1: lerp+exp ; v2: codebook lookup)\n vec3 splatScale;\n if (uVersion == 2) {\n vec3 sIdx = floor(sRaw * 255.0 + 0.5);\n splatScale.x = exp(texelFetch(sogCodebookTex, ivec2(int(sIdx.x), 0), 0).r);\n splatScale.y = exp(texelFetch(sogCodebookTex, ivec2(int(sIdx.y), 0), 0).r);\n splatScale.z = exp(texelFetch(sogCodebookTex, ivec2(int(sIdx.z), 0), 0).r);\n } else {\n splatScale = exp(mix(sogScalesMin, sogScalesMax, sRaw));\n }\n\n // Quaternion (largest-omitted, mode in alpha as 252 + omitted-index)\n const float invSqrt2 = 0.70710678118;\n vec3 qabc = (qRaw.xyz - vec3(0.5)) * 2.0 * invSqrt2;\n int qMode = int(qRaw.w * 255.0 + 0.5) - 252;\n float qd = sqrt(max(0.0, 1.0 - dot(qabc, qabc)));\n vec4 quat;\n if (qMode == 0) {\n quat = vec4(qd, qabc.x, qabc.y, qabc.z);\n } else if (qMode == 1) {\n quat = vec4(qabc.x, qd, qabc.y, qabc.z);\n } else if (qMode == 2) {\n quat = vec4(qabc.x, qabc.y, qd, qabc.z);\n } else {\n quat = vec4(qabc.x, qabc.y, qabc.z, qd);\n }\n\n float qw = quat.x, qx = quat.y, qy = quat.z, qz = quat.w;\n mat3 R = mat3(\n 1.0 - 2.0 * (qy * qy + qz * qz), 2.0 * (qx * qy + qw * qz), 2.0 * (qx * qz - qw * qy),\n 2.0 * (qx * qy - qw * qz), 1.0 - 2.0 * (qx * qx + qz * qz), 2.0 * (qy * qz + qw * qx),\n 2.0 * (qx * qz + qw * qy), 2.0 * (qy * qz - qw * qx), 1.0 - 2.0 * (qx * qx + qy * qy)\n );\n mat3 S2 = mat3(\n 4.0 * splatScale.x * splatScale.x, 0.0, 0.0,\n 0.0, 4.0 * splatScale.y * splatScale.y, 0.0,\n 0.0, 0.0, 4.0 * splatScale.z * splatScale.z\n );\n mat3 Sigma = R * S2 * transposeM(R);\n\n // Color (sh0)\n const float SH_C0 = 0.28209479177387814;\n vec3 colRgb;\n float colA;\n if (uVersion == 2) {\n vec3 c3;\n c3.x = texelFetch(sogCodebookTex, ivec2(256 + int(c0.x * 255.0 + 0.5), 0), 0).r;\n c3.y = texelFetch(sogCodebookTex, ivec2(256 + int(c0.y * 255.0 + 0.5), 0), 0).r;\n c3.z = texelFetch(sogCodebookTex, ivec2(256 + int(c0.z * 255.0 + 0.5), 0), 0).r;\n colRgb = vec3(0.5) + c3 * SH_C0;\n colA = c0.w;\n } else {\n vec4 cLerp = mix(sogSh0Min, sogSh0Max, c0);\n colRgb = vec3(0.5) + cLerp.xyz * SH_C0;\n colA = 1.0 / (1.0 + exp(-cLerp.w));\n }\n\n glFragData[0] = vec4(center, 1.0);\n glFragData[1] = vec4(Sigma[0][0], Sigma[0][1], Sigma[0][2], Sigma[1][1]);\n glFragData[2] = vec4(Sigma[1][2], Sigma[2][2], 0.0, 0.0);\n glFragData[3] = vec4(colRgb, colA);\n}\n";
|
|
7445
|
+
/**
|
|
7446
|
+
* Pass-through vertex shader (WGSL).
|
|
7447
|
+
*/
|
|
7448
|
+
export const GaussianSplattingWorkBufferVertexShaderWGSL = "\nattribute position : vec3<f32>;\n@vertex\nfn main(input : VertexInputs) -> FragmentInputs {\n vertexOutputs.position = vec4<f32>(input.position.xy, 0.0, 1.0);\n}\n";
|
|
7449
|
+
/**
|
|
7450
|
+
* Fragment shader (WGSL/WebGPU) — same decode as the GLSL variant, writing 4 MRT attachments.
|
|
7451
|
+
*/
|
|
7452
|
+
export const GaussianSplattingWorkBufferFragmentShaderWGSL = "\nvar sogMeansLTexSampler : sampler;\nvar sogMeansLTex : texture_2d<f32>;\nvar sogMeansUTexSampler : sampler;\nvar sogMeansUTex : texture_2d<f32>;\nvar sogScalesTexSampler : sampler;\nvar sogScalesTex : texture_2d<f32>;\nvar sogQuatsTexSampler : sampler;\nvar sogQuatsTex : texture_2d<f32>;\nvar sogSh0TexSampler : sampler;\nvar sogSh0Tex : texture_2d<f32>;\nvar sogCodebookTexSampler : sampler;\nvar sogCodebookTex : texture_2d<f32>;\n\nuniform sogMeansMin : vec3<f32>;\nuniform sogMeansMax : vec3<f32>;\nuniform sogScalesMin : vec3<f32>;\nuniform sogScalesMax : vec3<f32>;\nuniform sogSh0Min : vec4<f32>;\nuniform sogSh0Max : vec4<f32>;\nuniform uVersion : i32;\nuniform uOffset : i32;\nuniform uCount : i32;\nuniform uDestWidth : i32;\nuniform uSrcWidth : i32;\n\n@fragment\nfn main(input : FragmentInputs) -> FragmentOutputs {\n let p : vec2<i32> = vec2<i32>(i32(fragmentInputs.position.x), i32(fragmentInputs.position.y));\n let global : i32 = p.y * uniforms.uDestWidth + p.x;\n if (global < uniforms.uOffset || global >= uniforms.uOffset + uniforms.uCount) {\n discard;\n }\n let k : i32 = global - uniforms.uOffset;\n let src : vec2<i32> = vec2<i32>(k - (k / uniforms.uSrcWidth) * uniforms.uSrcWidth, k / uniforms.uSrcWidth);\n\n let mL : vec3<f32> = textureLoad(sogMeansLTex, src, 0).xyz;\n let mU : vec3<f32> = textureLoad(sogMeansUTex, src, 0).xyz;\n let sRaw : vec3<f32> = textureLoad(sogScalesTex, src, 0).xyz;\n let qRaw : vec4<f32> = textureLoad(sogQuatsTex, src, 0);\n let c0 : vec4<f32> = textureLoad(sogSh0Tex, src, 0);\n\n let q16 : vec3<f32> = (mU * 256.0 + mL) * (255.0 / 65535.0);\n let nPos : vec3<f32> = mix(uniforms.sogMeansMin, uniforms.sogMeansMax, q16);\n let center : vec3<f32> = sign(nPos) * (exp(abs(nPos)) - vec3<f32>(1.0));\n\n var splatScale : vec3<f32>;\n if (uniforms.uVersion == 2) {\n let sIdx : vec3<f32> = floor(sRaw * 255.0 + 0.5);\n splatScale.x = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.x), 0), 0).r);\n splatScale.y = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.y), 0), 0).r);\n splatScale.z = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.z), 0), 0).r);\n } else {\n splatScale = exp(mix(uniforms.sogScalesMin, uniforms.sogScalesMax, sRaw));\n }\n\n let invSqrt2 : f32 = 0.70710678118;\n let qabc : vec3<f32> = (qRaw.xyz - vec3<f32>(0.5)) * 2.0 * invSqrt2;\n let qMode : i32 = i32(qRaw.w * 255.0 + 0.5) - 252;\n let qd : f32 = sqrt(max(0.0, 1.0 - dot(qabc, qabc)));\n var quat : vec4<f32>;\n if (qMode == 0) {\n quat = vec4<f32>(qd, qabc.x, qabc.y, qabc.z);\n } else if (qMode == 1) {\n quat = vec4<f32>(qabc.x, qd, qabc.y, qabc.z);\n } else if (qMode == 2) {\n quat = vec4<f32>(qabc.x, qabc.y, qd, qabc.z);\n } else {\n quat = vec4<f32>(qabc.x, qabc.y, qabc.z, qd);\n }\n\n let qw : f32 = quat.x;\n let qx : f32 = quat.y;\n let qy : f32 = quat.z;\n let qz : f32 = quat.w;\n let R : mat3x3<f32> = mat3x3<f32>(\n 1.0 - 2.0 * (qy * qy + qz * qz), 2.0 * (qx * qy + qw * qz), 2.0 * (qx * qz - qw * qy),\n 2.0 * (qx * qy - qw * qz), 1.0 - 2.0 * (qx * qx + qz * qz), 2.0 * (qy * qz + qw * qx),\n 2.0 * (qx * qz + qw * qy), 2.0 * (qy * qz - qw * qx), 1.0 - 2.0 * (qx * qx + qy * qy)\n );\n let S2 : mat3x3<f32> = mat3x3<f32>(\n 4.0 * splatScale.x * splatScale.x, 0.0, 0.0,\n 0.0, 4.0 * splatScale.y * splatScale.y, 0.0,\n 0.0, 0.0, 4.0 * splatScale.z * splatScale.z\n );\n let Sigma : mat3x3<f32> = R * S2 * transpose(R);\n\n let SH_C0 : f32 = 0.28209479177387814;\n var colRgb : vec3<f32>;\n var colA : f32;\n if (uniforms.uVersion == 2) {\n var c3 : vec3<f32>;\n c3.x = textureLoad(sogCodebookTex, vec2<i32>(256 + i32(c0.x * 255.0 + 0.5), 0), 0).r;\n c3.y = textureLoad(sogCodebookTex, vec2<i32>(256 + i32(c0.y * 255.0 + 0.5), 0), 0).r;\n c3.z = textureLoad(sogCodebookTex, vec2<i32>(256 + i32(c0.z * 255.0 + 0.5), 0), 0).r;\n colRgb = vec3<f32>(0.5) + c3 * SH_C0;\n colA = c0.w;\n } else {\n let cLerp : vec4<f32> = mix(uniforms.sogSh0Min, uniforms.sogSh0Max, c0);\n colRgb = vec3<f32>(0.5) + cLerp.xyz * SH_C0;\n colA = 1.0 / (1.0 + exp(-cLerp.w));\n }\n\n fragmentOutputs.fragData0 = vec4<f32>(center, 1.0);\n fragmentOutputs.fragData1 = vec4<f32>(Sigma[0][0], Sigma[0][1], Sigma[0][2], Sigma[1][1]);\n fragmentOutputs.fragData2 = vec4<f32>(Sigma[1][2], Sigma[2][2], 0.0, 0.0);\n fragmentOutputs.fragData3 = vec4<f32>(colRgb, colA);\n}\n";
|
|
7453
|
+
|
|
7454
|
+
|
|
7455
|
+
/**
|
|
7456
|
+
* A unified, GPU-decoded Gaussian Splatting work buffer.
|
|
7457
|
+
*
|
|
7458
|
+
* Holds a square MRT texture set (centers / covA / covB / colors) sized to a fixed splat capacity
|
|
7459
|
+
* (PlayCanvas-style: `ceil(sqrt(capacity))`). Each streamed SOG file is decoded directly on the GPU
|
|
7460
|
+
* (no CPU readback) into its allocated pixel range. The decoded textures are consumed unchanged by the
|
|
7461
|
+
* standard (non-SOG) Gaussian Splatting draw path.
|
|
7462
|
+
*
|
|
7463
|
+
* @experimental
|
|
7464
|
+
*/
|
|
7465
|
+
export class GaussianSplattingWorkBuffer {
|
|
7466
|
+
private readonly _scene;
|
|
7467
|
+
private readonly _mrt;
|
|
7468
|
+
private readonly _textureSize;
|
|
7469
|
+
private readonly _shaderLanguage;
|
|
7470
|
+
private readonly _material;
|
|
7471
|
+
private readonly _quad;
|
|
7472
|
+
private _disposed;
|
|
7473
|
+
/**
|
|
7474
|
+
* Square edge length (in pixels) of the work-buffer textures.
|
|
7475
|
+
*/
|
|
7476
|
+
get textureSize(): number;
|
|
7477
|
+
/**
|
|
7478
|
+
* The decoded work-buffer textures: [centers, covA, covB, colors].
|
|
7479
|
+
*/
|
|
7480
|
+
get textures(): Texture[];
|
|
7481
|
+
/**
|
|
7482
|
+
* Creates a work buffer sized to hold `capacity` splats.
|
|
7483
|
+
* @param scene hosting scene
|
|
7484
|
+
* @param capacity total number of splats the work buffer must address
|
|
7485
|
+
*/
|
|
7486
|
+
constructor(scene: Scene, capacity: number);
|
|
7487
|
+
/**
|
|
7488
|
+
* Decodes one SOG file into the work buffer at the given splat offset (accumulating; previously
|
|
7489
|
+
* decoded files are preserved). Resolves once the GPU decode has been issued. The caller may
|
|
7490
|
+
* dispose the source pack textures after this resolves.
|
|
7491
|
+
* @param pack the SOG texture pack (GPU source textures + per-file decode parameters)
|
|
7492
|
+
* @param offset first splat index (pixel offset) for this file in the work buffer
|
|
7493
|
+
*/
|
|
7494
|
+
decodeAsync(pack: ISogTexturePack, offset: number): Promise<void>;
|
|
7495
|
+
/**
|
|
7496
|
+
* Disposes the work buffer and its decode resources.
|
|
7497
|
+
*/
|
|
7498
|
+
dispose(): void;
|
|
7499
|
+
private _createQuad;
|
|
7500
|
+
private _createMaterial;
|
|
7501
|
+
private _applyPack;
|
|
7502
|
+
}
|
|
7503
|
+
|
|
7504
|
+
|
|
7505
|
+
/**
|
|
7506
|
+
* A single LOD variant of a tree node: a contiguous splat range inside one streamed SOG file.
|
|
7507
|
+
*/
|
|
7508
|
+
interface ISOGLODEntry {
|
|
7509
|
+
/** Index into {@link ISOGLODMetadata.filenames}. */
|
|
7510
|
+
file: number;
|
|
7511
|
+
/** First splat index inside that file. */
|
|
7512
|
+
offset: number;
|
|
7513
|
+
/** Number of splats. */
|
|
7514
|
+
count: number;
|
|
7515
|
+
}
|
|
7516
|
+
/**
|
|
7517
|
+
* A node of the PlayCanvas-style SOG LOD octree. Internal nodes have `children`; leaves have `lods`.
|
|
7518
|
+
*/
|
|
7519
|
+
interface ISOGLODNode {
|
|
7520
|
+
bound: {
|
|
7521
|
+
min: number[];
|
|
7522
|
+
max: number[];
|
|
7523
|
+
};
|
|
7524
|
+
children?: ISOGLODNode[];
|
|
7525
|
+
lods?: {
|
|
7526
|
+
[level: string]: ISOGLODEntry;
|
|
7527
|
+
};
|
|
7528
|
+
/** LOD level currently streamed/rendered for this node, or undefined until its base LOD is ready. */
|
|
7529
|
+
activeLod?: number;
|
|
7530
|
+
/** Distance-based ideal LOD level for this node, recomputed per frame. */
|
|
7531
|
+
optimalLod?: number;
|
|
7532
|
+
/** Available LOD levels for this leaf, sorted ascending (0 = finest). Set during the tree walk. */
|
|
7533
|
+
availableLevels?: number[];
|
|
7534
|
+
/** Coarsest available level (= max key), always streamed as the permanent base layer. */
|
|
7535
|
+
baseLod?: number;
|
|
7536
|
+
/** Final LOD level the node should stream/render (distance optimal, capped by maxDetailLod). */
|
|
7537
|
+
targetLevel?: number;
|
|
7538
|
+
/** Frames remaining before this node may switch LOD again (oscillation damping). */
|
|
7539
|
+
lodCooldown?: number;
|
|
7540
|
+
}
|
|
7541
|
+
/**
|
|
7542
|
+
* Parsed contents of a PlayCanvas-style `lod-meta.json` file.
|
|
7543
|
+
*/
|
|
7544
|
+
export interface ISOGLODMetadata {
|
|
7545
|
+
/** Number of LOD levels (0 = highest detail). */
|
|
7546
|
+
lodLevels: number;
|
|
7547
|
+
/** SOG `meta.json` paths, relative to the metadata file, indexed by `ISOGLODEntry.file`. */
|
|
7548
|
+
filenames: string[];
|
|
7549
|
+
/** Optional always-on environment `.sog` bundle, relative to the metadata file. */
|
|
7550
|
+
environment?: string;
|
|
7551
|
+
/** Root of the LOD octree. */
|
|
7552
|
+
tree: ISOGLODNode;
|
|
7553
|
+
}
|
|
7554
|
+
/**
|
|
7555
|
+
* Selects which LOD value drives the {@link GaussianSplattingStream} debug wireframe colors.
|
|
7556
|
+
*/
|
|
7557
|
+
export type GaussianSplattingStreamDebugLodSource = "optimal" | "current";
|
|
7558
|
+
/**
|
|
7559
|
+
* Options for {@link GaussianSplattingStream}.
|
|
7560
|
+
*/
|
|
7561
|
+
export interface IGaussianSplattingStreamOptions {
|
|
7562
|
+
/** URL of the fflate UMD module used to unzip `.sog` environment bundles. */
|
|
7563
|
+
deflateURL?: string;
|
|
7564
|
+
/** Pre-loaded fflate module. */
|
|
7565
|
+
fflate?: any;
|
|
7566
|
+
/** When true, renders a wireframe box per LOD node, colored by the node's LOD level. */
|
|
7567
|
+
debugDisplay?: boolean;
|
|
7568
|
+
/** Which LOD value drives the debug wireframe colors. Defaults to `"optimal"`. */
|
|
7569
|
+
debugLodSource?: GaussianSplattingStreamDebugLodSource;
|
|
7570
|
+
/** Distance (in local units) of the first LOD transition. PlayCanvas default `5`. */
|
|
7571
|
+
lodBaseDistance?: number;
|
|
7572
|
+
/** Geometric ratio between successive LOD transition distances. PlayCanvas default `3`. */
|
|
7573
|
+
lodMultiplier?: number;
|
|
7574
|
+
/** Distance multiplier applied to nodes behind the camera (`1` = no penalty). PlayCanvas default `1`. */
|
|
7575
|
+
lodBehindPenalty?: number;
|
|
7576
|
+
/** Lowest LOD index the optimal-LOD heuristic may select. Defaults to `0`. */
|
|
7577
|
+
lodRangeMin?: number;
|
|
7578
|
+
/** Highest LOD index the optimal-LOD heuristic may select. Defaults to `lodLevels - 1`. */
|
|
7579
|
+
lodRangeMax?: number;
|
|
7580
|
+
/** Maximum number of LOD source files to GPU-decode per frame (spreads work to avoid hitches). Defaults to `1`. */
|
|
7581
|
+
maxDecodesPerFrame?: number;
|
|
7582
|
+
/** Frames a node must wait after switching LOD before it may switch again (oscillation damping). Defaults to `10`. */
|
|
7583
|
+
lodCooldownFrames?: number;
|
|
7584
|
+
/** Minimum number of frames between LOD re-evaluations (throttles per-frame work during motion). Defaults to `4`. */
|
|
7585
|
+
lodUpdateInterval?: number;
|
|
7586
|
+
/** Minimum camera movement (world units) required to re-evaluate LODs. Defaults to `0.5`. */
|
|
7587
|
+
lodUpdateDistance?: number;
|
|
7588
|
+
/**
|
|
7589
|
+
* Finest (most detailed) LOD level any node is allowed to render. `0` allows full detail (level 0);
|
|
7590
|
+
* `1` caps detail at the next-coarser level, and so on. Higher values force a coarser maximum detail.
|
|
7591
|
+
*/
|
|
7592
|
+
maxDetailLod?: number;
|
|
7593
|
+
}
|
|
7594
|
+
/**
|
|
7595
|
+
* Streams a PlayCanvas-style SOG LOD scene (`lod-meta.json`) into a single Gaussian Splatting mesh.
|
|
7596
|
+
*
|
|
7597
|
+
* Each selected SOG file (plus the environment) is loaded directly as GPU textures and decoded on the
|
|
7598
|
+
* GPU into one unified, PlayCanvas-style square work buffer (no CPU splat decode or `updateData`). Only
|
|
7599
|
+
* the splats of each node's currently-selected LOD are rendered/sorted via the mesh's interval filter.
|
|
7600
|
+
*
|
|
7601
|
+
* The coarsest (least-detail) LOD of every node is streamed first as a permanent base layer so the whole
|
|
7602
|
+
* scene is visible quickly with no holes. A distance-based "optimal" LOD is then computed per node (see
|
|
7603
|
+
* {@link evaluateOptimalLods}); finer LOD source files are streamed on demand and a node only switches to
|
|
7604
|
+
* a finer LOD once that file is decoded, so transitions never flash or leave gaps.
|
|
7605
|
+
*
|
|
7606
|
+
* @experimental
|
|
7607
|
+
*/
|
|
7608
|
+
export class GaussianSplattingStream extends GaussianSplattingMesh {
|
|
7609
|
+
private readonly _metadata;
|
|
7610
|
+
private readonly _rootUrl;
|
|
7611
|
+
private readonly _streamOptions;
|
|
7612
|
+
private readonly _leafNodes;
|
|
7613
|
+
private _lodBaseDistance;
|
|
7614
|
+
private _lodMultiplier;
|
|
7615
|
+
private _lodBehindPenalty;
|
|
7616
|
+
private _lodRangeMin;
|
|
7617
|
+
private _lodRangeMax;
|
|
7618
|
+
private _maxDecodesPerFrame;
|
|
7619
|
+
private _lodCooldownFrames;
|
|
7620
|
+
private _lodUpdateInterval;
|
|
7621
|
+
private _lodUpdateDistance;
|
|
7622
|
+
private _maxDetailLod;
|
|
7623
|
+
private _workBuffer;
|
|
7624
|
+
private readonly _fileBaseSplat;
|
|
7625
|
+
private readonly _fileCounts;
|
|
7626
|
+
private readonly _fileMeta;
|
|
7627
|
+
private readonly _decodedFiles;
|
|
7628
|
+
private readonly _loadingFiles;
|
|
7629
|
+
private readonly _decodeQueue;
|
|
7630
|
+
private _environmentRange;
|
|
7631
|
+
private _environmentFiles;
|
|
7632
|
+
private _lodObserver;
|
|
7633
|
+
private _baseLayerReady;
|
|
7634
|
+
private _framesSinceLodUpdate;
|
|
7635
|
+
private readonly _lastLodCamPos;
|
|
7636
|
+
private _forceLodUpdate;
|
|
7637
|
+
private readonly _boundsMin;
|
|
7638
|
+
private readonly _boundsMax;
|
|
7639
|
+
private _debugDisplay;
|
|
7640
|
+
private _debugLodSource;
|
|
7641
|
+
private _debugMesh;
|
|
7642
|
+
private _debugObserver;
|
|
7643
|
+
private _debugColorData;
|
|
7644
|
+
private _debugSignature;
|
|
7645
|
+
private _disposed;
|
|
7646
|
+
/**
|
|
7647
|
+
* Returns true when the parsed JSON looks like a PlayCanvas-style `lod-meta.json` payload.
|
|
7648
|
+
* @param data parsed JSON
|
|
7649
|
+
* @returns whether the data is SOG LOD metadata
|
|
7650
|
+
*/
|
|
7651
|
+
static IsLODMetadata(data: unknown): data is ISOGLODMetadata;
|
|
7652
|
+
/**
|
|
7653
|
+
* Creates a new SOG LOD streaming mesh and immediately starts streaming (non-blocking).
|
|
7654
|
+
* @param name mesh name
|
|
7655
|
+
* @param metadata parsed `lod-meta.json`
|
|
7656
|
+
* @param rootUrl base URL the metadata's relative paths resolve against
|
|
7657
|
+
* @param scene hosting scene
|
|
7658
|
+
* @param options streaming options
|
|
7659
|
+
*/
|
|
7660
|
+
constructor(name: string, metadata: ISOGLODMetadata, rootUrl: string, scene: Scene, options?: IGaussianSplattingStreamOptions);
|
|
7661
|
+
getClassName(): string;
|
|
7662
|
+
/**
|
|
7663
|
+
* Finest (most detailed) LOD level any node is allowed to render. `0` allows full detail (level 0);
|
|
7664
|
+
* `1` caps detail at the next-coarser level, and so on. Nodes already coarser than this cap (by
|
|
7665
|
+
* distance) are unaffected. Changes take effect in real time.
|
|
7666
|
+
*/
|
|
7667
|
+
get maxDetailLod(): number;
|
|
7668
|
+
set maxDetailLod(value: number);
|
|
7669
|
+
/**
|
|
7670
|
+
* Coarsest LOD level index in the scene (number of LOD levels minus one). Useful as the upper bound
|
|
7671
|
+
* for {@link maxDetailLod}.
|
|
7672
|
+
*/
|
|
7673
|
+
get maxLodLevel(): number;
|
|
7674
|
+
/**
|
|
7675
|
+
* When true, renders a wireframe box per LOD node, colored by the LOD level selected by {@link debugLodSource}.
|
|
7676
|
+
*/
|
|
7677
|
+
get debugDisplay(): boolean;
|
|
7678
|
+
set debugDisplay(value: boolean);
|
|
7679
|
+
/**
|
|
7680
|
+
* Selects which LOD value drives the debug wireframe colors: the distance-based `"optimal"` LOD
|
|
7681
|
+
* (default, recomputed as the camera moves) or the `"current"` streamed/rendered LOD.
|
|
7682
|
+
*/
|
|
7683
|
+
get debugLodSource(): GaussianSplattingStreamDebugLodSource;
|
|
7684
|
+
set debugLodSource(value: GaussianSplattingStreamDebugLodSource);
|
|
7685
|
+
dispose(doNotRecurse?: boolean): void;
|
|
7686
|
+
/**
|
|
7687
|
+
* Re-evaluates the optimal LOD for every node based on the camera position. The result is stored in
|
|
7688
|
+
* each node's `optimalLod`. Rendering is unaffected; this currently drives only diagnostics and the
|
|
7689
|
+
* debug wireframe display.
|
|
7690
|
+
* @param camera camera to evaluate against (defaults to the scene's active camera)
|
|
7691
|
+
*/
|
|
7692
|
+
evaluateOptimalLods(camera?: Nullable<Camera>): void;
|
|
7693
|
+
/**
|
|
7694
|
+
* The LOD level used to color a node's debug box, per {@link debugLodSource}.
|
|
7695
|
+
* @param node leaf node
|
|
7696
|
+
* @returns the displayed LOD level
|
|
7697
|
+
*/
|
|
7698
|
+
private _displayedLodLevel;
|
|
7699
|
+
/**
|
|
7700
|
+
* Rebuilds the debug wireframe (evaluating the optimal LOD first when needed) and wires up the per-frame
|
|
7701
|
+
* recolor observer. The observer runs for both LOD sources: "optimal" colors track the camera, and
|
|
7702
|
+
* "current" colors track LOD levels as they stream in/out.
|
|
7703
|
+
*/
|
|
7704
|
+
private _refreshDebugDisplay;
|
|
7705
|
+
/**
|
|
7706
|
+
* Per-frame debug update: recolors the existing wireframe in place whenever the displayed LOD levels
|
|
7707
|
+
* change. For the "optimal" source the optimal LOD is recomputed first (it tracks the camera); for the
|
|
7708
|
+
* "current" source the levels are driven by the streaming loop, so no recomputation is needed here. The
|
|
7709
|
+
* geometry is never rebuilt, which avoids the dispose/recreate flicker while the camera moves.
|
|
7710
|
+
*/
|
|
7711
|
+
private _onDebugFrame;
|
|
7712
|
+
/**
|
|
7713
|
+
* Builds the LOD-node wireframe boxes once (one box per leaf node), colored by the displayed LOD level.
|
|
7714
|
+
* The color vertex buffer is created updatable so subsequent recolors can happen in place.
|
|
7715
|
+
*/
|
|
7716
|
+
private _buildDebugMesh;
|
|
7717
|
+
/**
|
|
7718
|
+
* Recolors the existing wireframe in place from the current displayed LOD levels, without rebuilding geometry.
|
|
7719
|
+
*/
|
|
7720
|
+
private _updateDebugColors;
|
|
7721
|
+
/**
|
|
7722
|
+
* Computes a cheap 32-bit rolling hash of every leaf's displayed LOD level, used to detect when the
|
|
7723
|
+
* debug wireframe needs recoloring. Avoids per-frame string allocation in the render loop.
|
|
7724
|
+
* @returns a numeric signature of the current displayed LOD levels
|
|
7725
|
+
*/
|
|
7726
|
+
private _computeDebugSignature;
|
|
7727
|
+
/**
|
|
7728
|
+
* Disposes the LOD-node wireframe boxes and stops live debug updates.
|
|
7729
|
+
*/
|
|
7730
|
+
private _clearDebugDisplay;
|
|
7731
|
+
/**
|
|
7732
|
+
* Walks the LOD tree and records every leaf that carries renderable LOD entries, capturing the set of
|
|
7733
|
+
* available levels and the coarsest (base) level for each.
|
|
7734
|
+
* @param node current tree node
|
|
7735
|
+
*/
|
|
7736
|
+
private _collectLodEntries;
|
|
7737
|
+
/**
|
|
7738
|
+
* Streams the scene: learns every source file's splat count, allocates one unified GPU work buffer
|
|
7739
|
+
* sized for all LOD files, decodes the environment and the coarsest LOD of every node as a permanent
|
|
7740
|
+
* base layer, then installs the per-frame loop that streams finer LODs on demand.
|
|
7741
|
+
*/
|
|
7742
|
+
private _streamAllAsync;
|
|
7743
|
+
/**
|
|
7744
|
+
* Collects the unique set of source file indices referenced by any LOD of any leaf, sorted ascending.
|
|
7745
|
+
* @returns sorted unique file indices
|
|
7746
|
+
*/
|
|
7747
|
+
private _collectAllFileIds;
|
|
7748
|
+
/**
|
|
7749
|
+
* Fetches the environment bundle and every referenced file's metadata to learn splat counts, caching
|
|
7750
|
+
* each file's parsed metadata for the later on-demand decode. Metadata fetches run in parallel.
|
|
7751
|
+
* @param fileIds file indices to fetch metadata for
|
|
7752
|
+
* @returns the environment splat count (0 when there is no environment)
|
|
7753
|
+
*/
|
|
7754
|
+
private _gatherCountsAsync;
|
|
7755
|
+
/**
|
|
7756
|
+
* Queues a file for on-demand decode if it isn't already decoded, in flight, or already queued.
|
|
7757
|
+
* @param fileId file index to decode
|
|
7758
|
+
*/
|
|
7759
|
+
private _enqueueDecode;
|
|
7760
|
+
/**
|
|
7761
|
+
* Starts up to {@link _maxDecodesPerFrame} queued decodes for this frame. Decodes run asynchronously
|
|
7762
|
+
* and promote any waiting nodes once they complete.
|
|
7763
|
+
*/
|
|
7764
|
+
private _pumpDecodeQueue;
|
|
7765
|
+
/**
|
|
7766
|
+
* Decodes the always-on environment bundle into its work-buffer block and activates its range.
|
|
7767
|
+
*/
|
|
7768
|
+
private _decodeEnvironmentAsync;
|
|
7769
|
+
/**
|
|
7770
|
+
* Loads one LOD source file as GPU textures, decodes it into its fixed work-buffer block, records its
|
|
7771
|
+
* CPU centers for sorting, frees the source textures, then promotes any nodes that were waiting for it.
|
|
7772
|
+
* Concurrent or repeat requests for the same file are ignored.
|
|
7773
|
+
* @param fileId file index to decode
|
|
7774
|
+
*/
|
|
7775
|
+
private _decodeFileAsync;
|
|
7776
|
+
/**
|
|
7777
|
+
* Snaps a desired LOD level to the nearest level the node provides, while never selecting a level finer
|
|
7778
|
+
* than {@link maxDetailLod} (i.e. with an index below the cap). Ties prefer the finer allowed level. If
|
|
7779
|
+
* the node has no level at or coarser than the cap, its coarsest available level is used.
|
|
7780
|
+
* @param node leaf node
|
|
7781
|
+
* @param desired desired LOD level
|
|
7782
|
+
* @returns the chosen available level
|
|
7783
|
+
*/
|
|
7784
|
+
private _cappedLevelForNode;
|
|
7785
|
+
/**
|
|
7786
|
+
* Computes each node's {@link ISOGLODNode.targetLevel}: the distance-based optimal level snapped to an
|
|
7787
|
+
* available level, capped so no node renders finer (more detailed) than {@link maxDetailLod}.
|
|
7788
|
+
*/
|
|
7789
|
+
private _computeTargetLevels;
|
|
7790
|
+
/**
|
|
7791
|
+
* Applies each node's {@link ISOGLODNode.targetLevel}: switches a node to its target level when that
|
|
7792
|
+
* level's file is already decoded, otherwise queues the file and leaves the node on its current LOD (so
|
|
7793
|
+
* nothing ever disappears). Nodes within their post-switch cooldown are left untouched to damp oscillation.
|
|
7794
|
+
* @returns true when at least one node changed LOD (callers should refresh the active ranges)
|
|
7795
|
+
*/
|
|
7796
|
+
private _applyDesiredLods;
|
|
7797
|
+
/**
|
|
7798
|
+
* Per-frame LOD streaming loop. Ticks cooldowns and pumps the decode queue every frame, but throttles
|
|
7799
|
+
* the expensive LOD re-evaluation (optimal-LOD computation, budget balancing, desired-LOD application
|
|
7800
|
+
* and interval rebuild) to run at most every {@link _lodUpdateInterval} frames and only after the camera
|
|
7801
|
+
* has moved far enough, so continuous camera motion no longer rebuilds the interval set every frame. A
|
|
7802
|
+
* budget change forces a single immediate update regardless of the throttle.
|
|
7803
|
+
*/
|
|
7804
|
+
private _onLodFrame;
|
|
7805
|
+
/**
|
|
7806
|
+
* Reads the splat count from SOG metadata.
|
|
7807
|
+
* @param data SOG metadata
|
|
7808
|
+
* @returns the splat count
|
|
7809
|
+
*/
|
|
7810
|
+
private static _GetSplatCount;
|
|
7811
|
+
/**
|
|
7812
|
+
* Disposes all GPU source textures of a SOG pack (they are only needed for the one decode pass).
|
|
7813
|
+
* @param pack the SOG texture pack
|
|
7814
|
+
*/
|
|
7815
|
+
private static _DisposePack;
|
|
7816
|
+
/**
|
|
7817
|
+
* Expands the running splat-center bounds with a newly decoded file's centers and updates the
|
|
7818
|
+
* mesh bounding info so the GS is correctly frustum-culled and pickable.
|
|
7819
|
+
* @param positions stride-4 splat centers for the new file
|
|
7820
|
+
* @param count number of splats
|
|
7821
|
+
*/
|
|
7822
|
+
private _updateBounds;
|
|
7823
|
+
/**
|
|
7824
|
+
* Rebuilds the active interval set from the environment plus each node's currently-selected LOD entry,
|
|
7825
|
+
* coalesces adjacent ranges, and pushes the result to the sort worker.
|
|
7826
|
+
*/
|
|
7827
|
+
private _refreshActiveRanges;
|
|
7828
|
+
/**
|
|
7829
|
+
* Sorts and merges adjacent/overlapping ranges to keep the interval list compact.
|
|
7830
|
+
* @param ranges raw ranges
|
|
7831
|
+
* @returns coalesced ranges
|
|
7832
|
+
*/
|
|
7833
|
+
private static _CoalesceRanges;
|
|
7834
|
+
/**
|
|
7835
|
+
* Unzips a `.sog` bundle into a name -> bytes map, loading fflate on demand.
|
|
7836
|
+
* @param data zipped bytes
|
|
7837
|
+
* @returns map of entry name to bytes
|
|
7838
|
+
*/
|
|
7839
|
+
private _unzipAsync;
|
|
7840
|
+
}
|
|
7841
|
+
|
|
7842
|
+
|
|
7420
7843
|
/**
|
|
7421
7844
|
* Class used to load mesh data from OBJ content
|
|
7422
7845
|
*/
|
|
@@ -7816,6 +8239,974 @@ declare namespace BABYLON {
|
|
|
7816
8239
|
|
|
7817
8240
|
|
|
7818
8241
|
|
|
8242
|
+
/**
|
|
8243
|
+
* Defines the FBX loader plugin metadata.
|
|
8244
|
+
*/
|
|
8245
|
+
export var FBXFileLoaderMetadata: {
|
|
8246
|
+
readonly name: "fbx";
|
|
8247
|
+
readonly extensions: {
|
|
8248
|
+
readonly ".fbx": {
|
|
8249
|
+
readonly isBinary: true;
|
|
8250
|
+
};
|
|
8251
|
+
};
|
|
8252
|
+
};
|
|
8253
|
+
|
|
8254
|
+
|
|
8255
|
+
/**
|
|
8256
|
+
* Source convention for tangent-space normal maps loaded from FBX normal-map slots.
|
|
8257
|
+
*/
|
|
8258
|
+
export type FBXNormalMapCoordinateSystem = "y-up" | "y-down";
|
|
8259
|
+
/**
|
|
8260
|
+
* Defines options for the FBX loader.
|
|
8261
|
+
*/
|
|
8262
|
+
export interface FBXFileLoaderOptions {
|
|
8263
|
+
/**
|
|
8264
|
+
* Source convention for tangent-space normal maps connected through FBX normal-map slots.
|
|
8265
|
+
* FBX does not standardize this convention, so the loader defaults to the glTF/USD-style Y-up convention.
|
|
8266
|
+
* Set to "y-down" for assets authored with inverted green/Y normal maps.
|
|
8267
|
+
*/
|
|
8268
|
+
normalMapCoordinateSystem?: FBXNormalMapCoordinateSystem;
|
|
8269
|
+
}
|
|
8270
|
+
interface SceneLoaderPluginOptions {
|
|
8271
|
+
/**
|
|
8272
|
+
* Defines options for the FBX loader.
|
|
8273
|
+
*/
|
|
8274
|
+
[FBXFileLoaderMetadata.name]: FBXFileLoaderOptions;
|
|
8275
|
+
}
|
|
8276
|
+
/**
|
|
8277
|
+
* FBX file loader plugin for Babylon.js.
|
|
8278
|
+
* Pure TypeScript implementation — no Autodesk FBX SDK dependency.
|
|
8279
|
+
*/
|
|
8280
|
+
export class FBXFileLoader implements ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {
|
|
8281
|
+
/**
|
|
8282
|
+
* Defines the name of the plugin.
|
|
8283
|
+
*/
|
|
8284
|
+
readonly name: "fbx";
|
|
8285
|
+
/**
|
|
8286
|
+
* Defines the extension the plugin is able to load.
|
|
8287
|
+
*/
|
|
8288
|
+
readonly extensions: {
|
|
8289
|
+
readonly ".fbx": {
|
|
8290
|
+
readonly isBinary: true;
|
|
8291
|
+
};
|
|
8292
|
+
};
|
|
8293
|
+
private readonly _options;
|
|
8294
|
+
private readonly _bindRestBones;
|
|
8295
|
+
private readonly _sourceBonesBySkeleton;
|
|
8296
|
+
private readonly _scaleCompensationHelpersBySkeleton;
|
|
8297
|
+
/**
|
|
8298
|
+
* Creates a new FBX loader.
|
|
8299
|
+
* @param options - Options controlling FBX loading behavior
|
|
8300
|
+
*/
|
|
8301
|
+
constructor(options?: FBXFileLoaderOptions);
|
|
8302
|
+
/**
|
|
8303
|
+
* Creates an FBX loader plugin instance with options from SceneLoader.
|
|
8304
|
+
* @param options - Scene loader plugin options
|
|
8305
|
+
* @returns The configured FBX loader
|
|
8306
|
+
*/
|
|
8307
|
+
createPlugin(options: SceneLoaderPluginOptions): ISceneLoaderPluginAsync;
|
|
8308
|
+
/**
|
|
8309
|
+
* Imports meshes from an FBX file and adds them to the scene.
|
|
8310
|
+
* @param meshesNames - A string or array of mesh names to import, or null/undefined to import all meshes
|
|
8311
|
+
* @param scene - The scene to add imported meshes to
|
|
8312
|
+
* @param data - The FBX data to load
|
|
8313
|
+
* @param rootUrl - Root URL used to resolve external resources
|
|
8314
|
+
* @param _onProgress - Callback called while the file is loading
|
|
8315
|
+
* @param _fileName - Name of the file being loaded
|
|
8316
|
+
* @returns A promise containing the loaded meshes, particle systems, skeletons, animation groups, transform nodes, geometries, and lights
|
|
8317
|
+
*/
|
|
8318
|
+
importMeshAsync(meshesNames: string | readonly string[] | null | undefined, scene: Scene, data: unknown, rootUrl: string, _onProgress?: (event: ISceneLoaderProgressEvent) => void, _fileName?: string): Promise<ISceneLoaderAsyncResult>;
|
|
8319
|
+
/**
|
|
8320
|
+
* Loads all FBX content into the scene.
|
|
8321
|
+
* @param scene - The scene to load the FBX content into
|
|
8322
|
+
* @param data - The FBX data to load
|
|
8323
|
+
* @param rootUrl - Root URL used to resolve external resources
|
|
8324
|
+
* @param _onProgress - Callback called while the file is loading
|
|
8325
|
+
* @param _fileName - Name of the file being loaded
|
|
8326
|
+
* @returns A promise that resolves when loading is complete
|
|
8327
|
+
*/
|
|
8328
|
+
loadAsync(scene: Scene, data: unknown, rootUrl: string, _onProgress?: (event: ISceneLoaderProgressEvent) => void, _fileName?: string): Promise<void>;
|
|
8329
|
+
/**
|
|
8330
|
+
* Loads all FBX content into an asset container.
|
|
8331
|
+
* @param scene - The scene used to create the asset container
|
|
8332
|
+
* @param data - The FBX data to load
|
|
8333
|
+
* @param rootUrl - Root URL used to resolve external resources
|
|
8334
|
+
* @param _onProgress - Callback called while the file is loading
|
|
8335
|
+
* @param _fileName - Name of the file being loaded
|
|
8336
|
+
* @returns A promise containing the loaded asset container
|
|
8337
|
+
*/
|
|
8338
|
+
loadAssetContainerAsync(scene: Scene, data: unknown, rootUrl: string, _onProgress?: (event: ISceneLoaderProgressEvent) => void, _fileName?: string): Promise<AssetContainer>;
|
|
8339
|
+
private _parse;
|
|
8340
|
+
private _parseFromArrayBuffer;
|
|
8341
|
+
private _buildScene;
|
|
8342
|
+
private _addMaterialToContainer;
|
|
8343
|
+
private _addTextureToContainer;
|
|
8344
|
+
private _setAssetContainer;
|
|
8345
|
+
private static _computeFBXAxisConversionMatrix;
|
|
8346
|
+
private _buildModel;
|
|
8347
|
+
private static _modelSubtreeMatchesNameFilter;
|
|
8348
|
+
private static _applyModelMetadata;
|
|
8349
|
+
private _createMesh;
|
|
8350
|
+
/**
|
|
8351
|
+
* Apply multi-material to a mesh by creating sub-meshes grouped by material index.
|
|
8352
|
+
* Reorders the index buffer so that triangles sharing the same material are contiguous.
|
|
8353
|
+
*/
|
|
8354
|
+
private _applyMultiMaterial;
|
|
8355
|
+
private static _collectCullingConflictMaterialIds;
|
|
8356
|
+
private static _getModelMaterial;
|
|
8357
|
+
private _applyMaterialUVSetCoordinates;
|
|
8358
|
+
private _applyStandardMaterialUVSetCoordinates;
|
|
8359
|
+
/**
|
|
8360
|
+
* Babylon multiplies vertex colors by material diffuse color. Use per-mesh
|
|
8361
|
+
* material clones so vertex-colored geometry can render unmodulated without
|
|
8362
|
+
* changing shared materials used by non-vertex-colored meshes.
|
|
8363
|
+
*/
|
|
8364
|
+
private _useUnmodulatedVertexColorMaterials;
|
|
8365
|
+
/**
|
|
8366
|
+
* Build per-polygon-vertex bone indices and weights from the control-point-based skin data.
|
|
8367
|
+
* The geometry expands control points to per-polygon-vertex, so we need to look up
|
|
8368
|
+
* each polygon-vertex's control point index.
|
|
8369
|
+
*/
|
|
8370
|
+
private _buildSkinningData;
|
|
8371
|
+
private _createMaterial;
|
|
8372
|
+
private _configureNormalTexture;
|
|
8373
|
+
private _getNormalMapTangentHandednessScale;
|
|
8374
|
+
private static _isSupportedMaterialTextureSlot;
|
|
8375
|
+
private static _isNormalMapTextureSlot;
|
|
8376
|
+
private static _createTexture;
|
|
8377
|
+
private static _createExternalTexture;
|
|
8378
|
+
private static _buildTextureFallbackUrls;
|
|
8379
|
+
private static _getTextureCreationOptions;
|
|
8380
|
+
private static _getExternalTextureUrls;
|
|
8381
|
+
private static _getTextureSourceName;
|
|
8382
|
+
private static _getTextureSourceNameFromPath;
|
|
8383
|
+
private static _isSafeRelativeTexturePath;
|
|
8384
|
+
private static _getForcedExtension;
|
|
8385
|
+
private static _getMimeType;
|
|
8386
|
+
/**
|
|
8387
|
+
* Apply blend shape (morph target) deformers to meshes.
|
|
8388
|
+
* FBX Shape vertices are stored as absolute positions for sparse control points.
|
|
8389
|
+
* We compute deltas relative to the base mesh positions.
|
|
8390
|
+
*/
|
|
8391
|
+
private _applyBlendShapes;
|
|
8392
|
+
private _createCamera;
|
|
8393
|
+
private _createLight;
|
|
8394
|
+
private _createSkeleton;
|
|
8395
|
+
private _getSourceBone;
|
|
8396
|
+
private _getScaleCompensationHelper;
|
|
8397
|
+
private static _computeFBXAbsoluteMatrices;
|
|
8398
|
+
private static _computeFBXRuntimeLocalMatrix;
|
|
8399
|
+
private static _applyParentScaleCompensation;
|
|
8400
|
+
private static _splitParentScaleCompensatedLocalMatrix;
|
|
8401
|
+
private static _safeInverseScale;
|
|
8402
|
+
private static _getInverseScaleVector;
|
|
8403
|
+
private static _shouldUseBindMatricesAsRest;
|
|
8404
|
+
private static _getMaxScaleRatio;
|
|
8405
|
+
private static _getScaleRatio;
|
|
8406
|
+
private static _computeFBXGeometricMatrix;
|
|
8407
|
+
private static _computeFBXGeometricDeltaMatrix;
|
|
8408
|
+
private static _computeFBXGeometricNormalMatrix;
|
|
8409
|
+
/**
|
|
8410
|
+
* Compute the full FBX local transform matrix:
|
|
8411
|
+
* M = T * Roff * Rp * Rpre * R * Rpost^-1 * Rp^-1 * Soff * Sp * S * Sp^-1
|
|
8412
|
+
*
|
|
8413
|
+
* In row-vector convention: v' = v * M
|
|
8414
|
+
*/
|
|
8415
|
+
private static _computeFBXLocalMatrix;
|
|
8416
|
+
/**
|
|
8417
|
+
* Apply the FBX transform chain to a Babylon TransformNode or Mesh.
|
|
8418
|
+
* Decomposes the full local matrix into position/rotation/scale.
|
|
8419
|
+
*/
|
|
8420
|
+
private static _applyFBXTransform;
|
|
8421
|
+
private static _computeFBXModelLocalMatrix;
|
|
8422
|
+
private static _getBoneReferenceWorldMatrix;
|
|
8423
|
+
private static _applyMatrixToTransform;
|
|
8424
|
+
private _createAnimationGroup;
|
|
8425
|
+
private _buildInheritedRigBoneAnimations;
|
|
8426
|
+
private static _pushMatrixKeys;
|
|
8427
|
+
/**
|
|
8428
|
+
* Build animations for a non-bone node, correctly handling pivots.
|
|
8429
|
+
* Computes the full FBX transform matrix at each keyframe and decomposes into TRS.
|
|
8430
|
+
*/
|
|
8431
|
+
private _buildNodeAnimations;
|
|
8432
|
+
private _isVector3KeysConstant;
|
|
8433
|
+
private _sampleModelLocalMatrix;
|
|
8434
|
+
private _sampleModelScale;
|
|
8435
|
+
/**
|
|
8436
|
+
* Build matrix-baked bone animation from full FBX local transforms.
|
|
8437
|
+
* The bind matrix carries the skinning offset, so animation curves drive
|
|
8438
|
+
* the same FBX local transform chain as the source skeleton.
|
|
8439
|
+
*/
|
|
8440
|
+
private _buildBoneAnimations;
|
|
8441
|
+
private _buildNameFilter;
|
|
8442
|
+
}
|
|
8443
|
+
|
|
8444
|
+
|
|
8445
|
+
/**
|
|
8446
|
+
* Intermediate representation for parsed FBX data.
|
|
8447
|
+
* Both binary and ASCII parsers produce this same structure.
|
|
8448
|
+
*/
|
|
8449
|
+
/** Individual property value within an FBX node */
|
|
8450
|
+
export type FBXPropertyValue = boolean | number | string | Float32Array | Float64Array | Int32Array | Uint8Array;
|
|
8451
|
+
/** Parsed FBX property type identifier. */
|
|
8452
|
+
export type FBXPropertyType = "boolean" | "int16" | "int32" | "int64" | "float32" | "float64" | "string" | "raw" | "float32[]" | "float64[]" | "int32[]" | "int64[]" | "boolean[]";
|
|
8453
|
+
/** Individual property within an FBX node. */
|
|
8454
|
+
export interface FBXProperty {
|
|
8455
|
+
/** Parsed property type. */
|
|
8456
|
+
type: FBXPropertyType;
|
|
8457
|
+
/** Parsed property value. */
|
|
8458
|
+
value: FBXPropertyValue;
|
|
8459
|
+
}
|
|
8460
|
+
/** A node in the FBX document tree */
|
|
8461
|
+
export interface FBXNode {
|
|
8462
|
+
/** Node name. */
|
|
8463
|
+
name: string;
|
|
8464
|
+
/** Node properties. */
|
|
8465
|
+
properties: FBXProperty[];
|
|
8466
|
+
/** Child nodes. */
|
|
8467
|
+
children: FBXNode[];
|
|
8468
|
+
}
|
|
8469
|
+
/** Top-level parsed FBX document */
|
|
8470
|
+
export interface FBXDocument {
|
|
8471
|
+
/** FBX file version. */
|
|
8472
|
+
version: number;
|
|
8473
|
+
/** Top-level document nodes. */
|
|
8474
|
+
nodes: FBXNode[];
|
|
8475
|
+
}
|
|
8476
|
+
/** Helper to find a child node by name */
|
|
8477
|
+
export function findChildByName(node: FBXNode, name: string): FBXNode | undefined;
|
|
8478
|
+
/** Helper to find all children with a given name */
|
|
8479
|
+
export function findChildrenByName(node: FBXNode, name: string): FBXNode[];
|
|
8480
|
+
/** Helper to find a top-level node in a document */
|
|
8481
|
+
export function findDocumentNode(doc: FBXDocument, name: string): FBXNode | undefined;
|
|
8482
|
+
/** Extract a property value by index, with type narrowing */
|
|
8483
|
+
export function getPropertyValue<T extends FBXPropertyValue>(node: FBXNode, index: number): T | undefined;
|
|
8484
|
+
/**
|
|
8485
|
+
* Converts an FBX object ID value to a safe JavaScript number.
|
|
8486
|
+
* @param value - Parsed FBX object ID value
|
|
8487
|
+
* @returns The object ID, or undefined when the value is not numeric
|
|
8488
|
+
*/
|
|
8489
|
+
export function getSafeFBXObjectId(value: unknown): number | undefined;
|
|
8490
|
+
/** Get the numeric ID from a node (first property is typically the int64 UID) */
|
|
8491
|
+
export function getNodeId(node: FBXNode): number | undefined;
|
|
8492
|
+
/**
|
|
8493
|
+
* Clean FBX object names.
|
|
8494
|
+
* FBX names may contain:
|
|
8495
|
+
* - A "Class::" prefix (e.g. "Model::valkyrie_mesh") — strip it
|
|
8496
|
+
* - A binary null/control-character class suffix — strip it
|
|
8497
|
+
*/
|
|
8498
|
+
export function cleanFBXName(fbxName: string): string;
|
|
8499
|
+
|
|
8500
|
+
|
|
8501
|
+
/**
|
|
8502
|
+
* Inflate a zlib-wrapped deflate stream.
|
|
8503
|
+
*
|
|
8504
|
+
* This implementation is intentionally scoped to FBX binary array payloads: one-shot,
|
|
8505
|
+
* synchronous zlib streams with the exact uncompressed length known up front.
|
|
8506
|
+
*/
|
|
8507
|
+
export function inflateZlib(input: Uint8Array, expectedLength: number): Uint8Array;
|
|
8508
|
+
|
|
8509
|
+
|
|
8510
|
+
/**
|
|
8511
|
+
* Parse a binary FBX file into an FBXDocument.
|
|
8512
|
+
* Supports FBX versions 7.0–7.7 (v7.5+ uses 64-bit node headers).
|
|
8513
|
+
*/
|
|
8514
|
+
export function parseBinaryFBX(buffer: ArrayBuffer): FBXDocument;
|
|
8515
|
+
|
|
8516
|
+
|
|
8517
|
+
/**
|
|
8518
|
+
* Parse an ASCII FBX file into an FBXDocument.
|
|
8519
|
+
*/
|
|
8520
|
+
export function parseAsciiFBX(text: string): FBXDocument;
|
|
8521
|
+
|
|
8522
|
+
|
|
8523
|
+
export type FBXVector3 = [number, number, number];
|
|
8524
|
+
export interface FBXTransformComponents {
|
|
8525
|
+
translation: FBXVector3;
|
|
8526
|
+
rotation: FBXVector3;
|
|
8527
|
+
scale: FBXVector3;
|
|
8528
|
+
preRotation: FBXVector3;
|
|
8529
|
+
postRotation: FBXVector3;
|
|
8530
|
+
rotationPivot: FBXVector3;
|
|
8531
|
+
scalingPivot: FBXVector3;
|
|
8532
|
+
rotationOffset: FBXVector3;
|
|
8533
|
+
scalingOffset: FBXVector3;
|
|
8534
|
+
rotationOrder: number;
|
|
8535
|
+
inheritType?: number;
|
|
8536
|
+
}
|
|
8537
|
+
export function eulerToMatrixXYZ(rx: number, ry: number, rz: number): Matrix;
|
|
8538
|
+
export function eulerToMatrix(rx: number, ry: number, rz: number, order: number): Matrix;
|
|
8539
|
+
export function computeFBXGeometricMatrix(translation: FBXVector3, rotation: FBXVector3, scale: FBXVector3): Matrix;
|
|
8540
|
+
export function computeFBXGeometricDeltaMatrix(rotation: FBXVector3, scale: FBXVector3): Matrix;
|
|
8541
|
+
export function computeFBXGeometricNormalMatrix(rotation: FBXVector3, scale: FBXVector3): Matrix;
|
|
8542
|
+
export function computeFBXLocalMatrix(components: FBXTransformComponents): Matrix;
|
|
8543
|
+
|
|
8544
|
+
|
|
8545
|
+
export type FBXClusterMode = "Normalize" | "Additive" | "TotalOne" | "Unknown";
|
|
8546
|
+
export interface FBXSkinDiagnostic {
|
|
8547
|
+
type: "cluster-mode-runtime-unsupported" | "missing-cluster-transform" | "missing-cluster-transform-link" | "missing-bind-pose-matrix" | "associate-model-present";
|
|
8548
|
+
message: string;
|
|
8549
|
+
boneModelId?: number;
|
|
8550
|
+
boneName?: string;
|
|
8551
|
+
clusterMode?: FBXClusterMode;
|
|
8552
|
+
}
|
|
8553
|
+
/** Represents a single bone (cluster) in the FBX skeleton */
|
|
8554
|
+
export interface FBXBoneData {
|
|
8555
|
+
/** The Model node ID for this bone */
|
|
8556
|
+
modelId: number;
|
|
8557
|
+
/** Bone name (from the Model node) */
|
|
8558
|
+
name: string;
|
|
8559
|
+
/** Index of this bone in the skeleton */
|
|
8560
|
+
index: number;
|
|
8561
|
+
/** Index of the parent bone (-1 for root) */
|
|
8562
|
+
parentIndex: number;
|
|
8563
|
+
/** Whether this bone corresponds to an FBX Cluster with vertex weights */
|
|
8564
|
+
isCluster: boolean;
|
|
8565
|
+
/** Local translation from parent (Lcl Translation) */
|
|
8566
|
+
translation: [number, number, number];
|
|
8567
|
+
/** Local rotation in degrees (Lcl Rotation) */
|
|
8568
|
+
rotation: [number, number, number];
|
|
8569
|
+
/** Pre-rotation in degrees (applied before Lcl Rotation) */
|
|
8570
|
+
preRotation: [number, number, number];
|
|
8571
|
+
/** Post-rotation in degrees (applied after Lcl Rotation, inverted) */
|
|
8572
|
+
postRotation: [number, number, number];
|
|
8573
|
+
/** Rotation pivot point */
|
|
8574
|
+
rotationPivot: [number, number, number];
|
|
8575
|
+
/** Scaling pivot point */
|
|
8576
|
+
scalingPivot: [number, number, number];
|
|
8577
|
+
/** Rotation offset */
|
|
8578
|
+
rotationOffset: [number, number, number];
|
|
8579
|
+
/** Scaling offset */
|
|
8580
|
+
scalingOffset: [number, number, number];
|
|
8581
|
+
/** Local scale (Lcl Scaling) */
|
|
8582
|
+
scale: [number, number, number];
|
|
8583
|
+
/** Rotation order: 0=XYZ, 1=XZY, 2=YZX, 3=YXZ, 4=ZXY, 5=ZYX */
|
|
8584
|
+
rotationOrder: number;
|
|
8585
|
+
/** FBX transform inheritance mode. 0=RrSs, 1=RSrs, 2=Rrs */
|
|
8586
|
+
inheritType: number;
|
|
8587
|
+
/** Cluster skinning mode */
|
|
8588
|
+
clusterMode: FBXClusterMode;
|
|
8589
|
+
/** Bind pose transform matrix (cluster Transform, 4x4) */
|
|
8590
|
+
bindPoseMatrix: Float64Array | null;
|
|
8591
|
+
/** Bone's world transform at bind time (cluster TransformLink, 4x4) */
|
|
8592
|
+
transformLinkMatrix: Float64Array | null;
|
|
8593
|
+
/** Associate model world transform at bind time (cluster TransformAssociateModel, 4x4) */
|
|
8594
|
+
transformAssociateModelMatrix: Float64Array | null;
|
|
8595
|
+
/** Model's absolute matrix from the FBX BindPose, when present */
|
|
8596
|
+
modelBindPoseMatrix: Float64Array | null;
|
|
8597
|
+
/** Recoverable bind/skinning diagnostics for this bone */
|
|
8598
|
+
diagnostics: FBXSkinDiagnostic[];
|
|
8599
|
+
}
|
|
8600
|
+
/** Represents a skin deformer with its clusters */
|
|
8601
|
+
export interface FBXSkinData {
|
|
8602
|
+
/** Skin deformer ID */
|
|
8603
|
+
id: number;
|
|
8604
|
+
/** Geometry ID this skin is attached to */
|
|
8605
|
+
geometryId: number;
|
|
8606
|
+
/** Mesh model world matrix from the FBX BindPose, when present */
|
|
8607
|
+
meshBindPoseMatrix: Float64Array | null;
|
|
8608
|
+
/** Bones in this skeleton */
|
|
8609
|
+
bones: FBXBoneData[];
|
|
8610
|
+
/** Per-vertex bone indices, sorted by descending weight and capped for Babylon skinning */
|
|
8611
|
+
boneIndices: number[][];
|
|
8612
|
+
/** Per-vertex bone weights, matching boneIndices */
|
|
8613
|
+
boneWeights: number[][];
|
|
8614
|
+
/** Recoverable skinning/bind diagnostics */
|
|
8615
|
+
diagnostics: FBXSkinDiagnostic[];
|
|
8616
|
+
}
|
|
8617
|
+
/**
|
|
8618
|
+
* Extract all skin deformers from the FBX scene.
|
|
8619
|
+
* Returns skin data including bone hierarchy and vertex weights.
|
|
8620
|
+
*/
|
|
8621
|
+
export function extractSkins(objectMap: FBXObjectMap): FBXSkinData[];
|
|
8622
|
+
export function isSkeletonModel(modelNode: FBXNode): boolean;
|
|
8623
|
+
export function extractBoneTransform(modelNode: FBXNode): {
|
|
8624
|
+
translation: [number, number, number];
|
|
8625
|
+
rotation: [number, number, number];
|
|
8626
|
+
preRotation: [number, number, number];
|
|
8627
|
+
postRotation: [number, number, number];
|
|
8628
|
+
rotationPivot: [number, number, number];
|
|
8629
|
+
scalingPivot: [number, number, number];
|
|
8630
|
+
rotationOffset: [number, number, number];
|
|
8631
|
+
scalingOffset: [number, number, number];
|
|
8632
|
+
scale: [number, number, number];
|
|
8633
|
+
rotationOrder: number;
|
|
8634
|
+
inheritType: number;
|
|
8635
|
+
};
|
|
8636
|
+
|
|
8637
|
+
|
|
8638
|
+
export type FBXSceneDiagnosticType = "unsupported-constraint" | "unsupported-helper" | "unsupported-deformer" | "unsupported-node-attribute" | "unsupported-pose" | "unsupported-layered-texture" | "connection-graph";
|
|
8639
|
+
export interface FBXSceneDiagnostic {
|
|
8640
|
+
type: FBXSceneDiagnosticType;
|
|
8641
|
+
message: string;
|
|
8642
|
+
objectId?: number;
|
|
8643
|
+
objectName?: string;
|
|
8644
|
+
nodeName?: string;
|
|
8645
|
+
subType?: string;
|
|
8646
|
+
/** Number of accepted parent graph edges for objectId, when objectId is known. */
|
|
8647
|
+
parentCount?: number;
|
|
8648
|
+
childCount?: number;
|
|
8649
|
+
}
|
|
8650
|
+
export function extractSceneDiagnostics(objectMap: FBXObjectMap): FBXSceneDiagnostic[];
|
|
8651
|
+
|
|
8652
|
+
|
|
8653
|
+
export type FBXRigBoneData = FBXBoneData;
|
|
8654
|
+
export interface FBXSkinBindingData {
|
|
8655
|
+
skinId: number;
|
|
8656
|
+
geometryId: number;
|
|
8657
|
+
rigId: string;
|
|
8658
|
+
skinBoneIndexToRigBoneIndex: number[];
|
|
8659
|
+
clusterModelIds: Set<number>;
|
|
8660
|
+
}
|
|
8661
|
+
export interface FBXRigData {
|
|
8662
|
+
id: string;
|
|
8663
|
+
rootModelIds: number[];
|
|
8664
|
+
bones: FBXRigBoneData[];
|
|
8665
|
+
modelIdToBoneIndex: Map<number, number>;
|
|
8666
|
+
clusterModelIds: Set<number>;
|
|
8667
|
+
skinBindings: FBXSkinBindingData[];
|
|
8668
|
+
warnings: string[];
|
|
8669
|
+
}
|
|
8670
|
+
export function resolveRigs(objectMap: FBXObjectMap, skins: FBXSkinData[]): FBXRigData[];
|
|
8671
|
+
|
|
8672
|
+
|
|
8673
|
+
export interface FBXTemplateProperty {
|
|
8674
|
+
name: string;
|
|
8675
|
+
propertyType: string;
|
|
8676
|
+
label: string;
|
|
8677
|
+
flags: string;
|
|
8678
|
+
values: FBXPropertyValue[];
|
|
8679
|
+
}
|
|
8680
|
+
export interface FBXPropertyTemplate {
|
|
8681
|
+
objectType: string;
|
|
8682
|
+
templateName: string;
|
|
8683
|
+
properties: Map<string, FBXTemplateProperty>;
|
|
8684
|
+
}
|
|
8685
|
+
export type FBXPropertyTemplateMap = Map<string, Map<string, FBXPropertyTemplate>>;
|
|
8686
|
+
export function extractPropertyTemplates(doc: FBXDocument): FBXPropertyTemplateMap;
|
|
8687
|
+
export function getPropertyTemplate(templates: FBXPropertyTemplateMap, objectType: string, templateName?: string): FBXPropertyTemplate | undefined;
|
|
8688
|
+
export function getTemplatePropertyValue<T extends FBXPropertyValue>(template: FBXPropertyTemplate | undefined, propertyName: string, valueIndex?: number): T | undefined;
|
|
8689
|
+
export function resolvePropertyValue<T extends FBXPropertyValue>(node: FBXNode, template: FBXPropertyTemplate | undefined, propertyName: string, valueIndex?: number): T | undefined;
|
|
8690
|
+
export function resolveNumberProperty(node: FBXNode, template: FBXPropertyTemplate | undefined, propertyName: string, fallback: number): number;
|
|
8691
|
+
export function resolveVector2Property(node: FBXNode, template: FBXPropertyTemplate | undefined, propertyName: string, fallback: [number, number]): [number, number];
|
|
8692
|
+
export function resolveVector3Property(node: FBXNode, template: FBXPropertyTemplate | undefined, propertyName: string, fallback: [number, number, number]): [number, number, number];
|
|
8693
|
+
export function resolvePropertyValues(node: FBXNode, template: FBXPropertyTemplate | undefined, propertyName: string): FBXPropertyValue[] | undefined;
|
|
8694
|
+
|
|
8695
|
+
|
|
8696
|
+
/** Parsed material data */
|
|
8697
|
+
export interface FBXMaterialData {
|
|
8698
|
+
id: number;
|
|
8699
|
+
name: string;
|
|
8700
|
+
type: "Lambert" | "Phong";
|
|
8701
|
+
properties: FBXMaterialProperties;
|
|
8702
|
+
textures: FBXTextureRef[];
|
|
8703
|
+
}
|
|
8704
|
+
export interface FBXMaterialProperties {
|
|
8705
|
+
diffuseColor?: [number, number, number];
|
|
8706
|
+
diffuseFactor?: number;
|
|
8707
|
+
ambientColor?: [number, number, number];
|
|
8708
|
+
ambientFactor?: number;
|
|
8709
|
+
specularColor?: [number, number, number];
|
|
8710
|
+
specularFactor?: number;
|
|
8711
|
+
shininess?: number;
|
|
8712
|
+
emissiveColor?: [number, number, number];
|
|
8713
|
+
emissiveFactor?: number;
|
|
8714
|
+
opacity?: number;
|
|
8715
|
+
transparencyFactor?: number;
|
|
8716
|
+
}
|
|
8717
|
+
export interface FBXTextureRef {
|
|
8718
|
+
/** Which material property this texture is connected to */
|
|
8719
|
+
propertyName: string;
|
|
8720
|
+
/** Absolute file path from the FBX */
|
|
8721
|
+
fileName: string;
|
|
8722
|
+
/** Relative file path from the FBX */
|
|
8723
|
+
relativeFileName: string;
|
|
8724
|
+
/** Texture node ID */
|
|
8725
|
+
id: number;
|
|
8726
|
+
/** Embedded texture data (from Video node Content), if available */
|
|
8727
|
+
embeddedData: Uint8Array | null;
|
|
8728
|
+
/** UV translation [u, v] */
|
|
8729
|
+
uvTranslation?: [number, number];
|
|
8730
|
+
/** UV scaling [u, v] */
|
|
8731
|
+
uvScaling?: [number, number];
|
|
8732
|
+
/** UV rotation in degrees */
|
|
8733
|
+
uvRotation?: number;
|
|
8734
|
+
/** Which UV set index this texture uses */
|
|
8735
|
+
uvSetIndex?: number;
|
|
8736
|
+
/** Which named UV set this texture uses */
|
|
8737
|
+
uvSetName?: string;
|
|
8738
|
+
}
|
|
8739
|
+
/**
|
|
8740
|
+
* Extract material data from an FBX Material node.
|
|
8741
|
+
*/
|
|
8742
|
+
export function extractMaterial(materialNode: FBXNode, materialId: number, objectMap: FBXObjectMap, templates?: FBXPropertyTemplateMap): FBXMaterialData;
|
|
8743
|
+
|
|
8744
|
+
|
|
8745
|
+
/** A named UV set */
|
|
8746
|
+
export interface FBXUVSet {
|
|
8747
|
+
/** UV set name (e.g. "UVMap", "lightmap") */
|
|
8748
|
+
name: string;
|
|
8749
|
+
/** Per-vertex UV data [u,v, ...] (expanded to match triangle vertices) */
|
|
8750
|
+
data: Float64Array;
|
|
8751
|
+
}
|
|
8752
|
+
/** Recoverable geometry import issue. */
|
|
8753
|
+
export interface FBXGeometryDiagnostic {
|
|
8754
|
+
/** Diagnostic category. */
|
|
8755
|
+
type: "degenerate-polygon" | "triangulation-fallback" | "layer-index-out-of-bounds" | "layer-data-too-short";
|
|
8756
|
+
/** Human-readable diagnostic message. */
|
|
8757
|
+
message: string;
|
|
8758
|
+
/** Polygon index associated with the diagnostic, if applicable. */
|
|
8759
|
+
polygonIndex?: number;
|
|
8760
|
+
/** Layer element name associated with the diagnostic, if applicable. */
|
|
8761
|
+
layerName?: string;
|
|
8762
|
+
/** Source data index associated with the diagnostic, if applicable. */
|
|
8763
|
+
index?: number;
|
|
8764
|
+
}
|
|
8765
|
+
/** Parsed geometry data ready for Babylon consumption */
|
|
8766
|
+
export interface FBXGeometryData {
|
|
8767
|
+
/** Node ID from the FBX document */
|
|
8768
|
+
id: number;
|
|
8769
|
+
/** Geometry name */
|
|
8770
|
+
name: string;
|
|
8771
|
+
/** Flat array of vertex positions [x,y,z, x,y,z, ...] */
|
|
8772
|
+
positions: Float64Array;
|
|
8773
|
+
/** Triangle indices (already triangulated from n-gons) */
|
|
8774
|
+
indices: Uint32Array;
|
|
8775
|
+
/** Per-vertex normals [x,y,z, ...] (expanded to match triangle vertices) */
|
|
8776
|
+
normals: Float64Array | null;
|
|
8777
|
+
/** Per-vertex UVs [u,v, ...] (expanded to match triangle vertices) — first UV set for convenience */
|
|
8778
|
+
uvs: Float64Array | null;
|
|
8779
|
+
/** All UV sets (including the first) */
|
|
8780
|
+
uvSets: FBXUVSet[];
|
|
8781
|
+
/** Per-vertex colors [r,g,b,a, ...] (expanded to match triangle vertices) */
|
|
8782
|
+
colors: Float32Array | null;
|
|
8783
|
+
/** Per-vertex tangents [x,y,z,w, ...] expanded to match triangle vertices */
|
|
8784
|
+
tangents: Float64Array | null;
|
|
8785
|
+
/** Per-vertex binormals [x,y,z, ...] expanded to match triangle vertices */
|
|
8786
|
+
binormals: Float64Array | null;
|
|
8787
|
+
/** Control point index for each polygon-vertex (for skinning lookup) */
|
|
8788
|
+
controlPointIndices: Uint32Array | null;
|
|
8789
|
+
/** Per-triangle material index (which material each triangle belongs to) */
|
|
8790
|
+
materialIndices: Int32Array | null;
|
|
8791
|
+
/** Recoverable geometry import issues */
|
|
8792
|
+
diagnostics: FBXGeometryDiagnostic[];
|
|
8793
|
+
}
|
|
8794
|
+
/**
|
|
8795
|
+
* Extract geometry data from an FBX Geometry node.
|
|
8796
|
+
* Handles polygon triangulation and layer element expansion.
|
|
8797
|
+
*/
|
|
8798
|
+
export function extractGeometry(geometryNode: FBXNode, nodeId: number): FBXGeometryData;
|
|
8799
|
+
|
|
8800
|
+
|
|
8801
|
+
/** Represents a model (transform node) in the FBX scene */
|
|
8802
|
+
export interface FBXModelData {
|
|
8803
|
+
id: number;
|
|
8804
|
+
name: string;
|
|
8805
|
+
subType: string;
|
|
8806
|
+
/** Geometry attached to this model (if it's a Mesh type) */
|
|
8807
|
+
geometry?: FBXGeometryData;
|
|
8808
|
+
/** Materials assigned to this model */
|
|
8809
|
+
materials: FBXMaterialData[];
|
|
8810
|
+
/** Child models */
|
|
8811
|
+
children: FBXModelData[];
|
|
8812
|
+
/** Transform properties */
|
|
8813
|
+
translation: [number, number, number];
|
|
8814
|
+
rotation: [number, number, number];
|
|
8815
|
+
scale: [number, number, number];
|
|
8816
|
+
/** PreRotation (applied before Lcl Rotation, in degrees) */
|
|
8817
|
+
preRotation: [number, number, number];
|
|
8818
|
+
/** PostRotation (applied after Lcl Rotation, inverted, in degrees) */
|
|
8819
|
+
postRotation: [number, number, number];
|
|
8820
|
+
/** RotationPivot — point around which rotation occurs */
|
|
8821
|
+
rotationPivot: [number, number, number];
|
|
8822
|
+
/** ScalingPivot — point around which scaling occurs */
|
|
8823
|
+
scalingPivot: [number, number, number];
|
|
8824
|
+
/** RotationOffset — translation after rotation pivot */
|
|
8825
|
+
rotationOffset: [number, number, number];
|
|
8826
|
+
/** ScalingOffset — translation after scaling pivot */
|
|
8827
|
+
scalingOffset: [number, number, number];
|
|
8828
|
+
/** Geometric transforms — applied to geometry only, do not affect children */
|
|
8829
|
+
geometricTranslation: [number, number, number];
|
|
8830
|
+
geometricRotation: [number, number, number];
|
|
8831
|
+
geometricScaling: [number, number, number];
|
|
8832
|
+
/** Rotation order: 0=XYZ, 1=XZY, 2=YZX, 3=YXZ, 4=ZXY, 5=ZYX */
|
|
8833
|
+
rotationOrder: number;
|
|
8834
|
+
/** FBX transform inheritance mode. 0=RrSs, 1=RSrs, 2=Rrs */
|
|
8835
|
+
inheritType: number;
|
|
8836
|
+
/** Whether backface culling is disabled ("CullingOff") */
|
|
8837
|
+
cullingOff: boolean;
|
|
8838
|
+
/** User-defined custom properties from Properties70 */
|
|
8839
|
+
customProperties?: Record<string, string | number | boolean>;
|
|
8840
|
+
/** Recoverable model import diagnostics */
|
|
8841
|
+
diagnostics: string[];
|
|
8842
|
+
}
|
|
8843
|
+
/** Camera data extracted from FBX */
|
|
8844
|
+
export interface FBXCameraData {
|
|
8845
|
+
/** Model ID this camera is attached to */
|
|
8846
|
+
modelId: number;
|
|
8847
|
+
/** Camera name */
|
|
8848
|
+
name: string;
|
|
8849
|
+
/** Field of view in degrees */
|
|
8850
|
+
fieldOfView: number;
|
|
8851
|
+
/** Near clip plane */
|
|
8852
|
+
nearPlane: number;
|
|
8853
|
+
/** Far clip plane */
|
|
8854
|
+
farPlane: number;
|
|
8855
|
+
/** Aspect ratio (width/height), 0 = use viewport */
|
|
8856
|
+
aspectRatio: number;
|
|
8857
|
+
/** Projection type */
|
|
8858
|
+
projectionType: "perspective" | "orthographic";
|
|
8859
|
+
/** Focal length in millimeters when present */
|
|
8860
|
+
focalLength?: number;
|
|
8861
|
+
/** Filmback width in inches when present */
|
|
8862
|
+
filmWidth?: number;
|
|
8863
|
+
/** Filmback height in inches when present */
|
|
8864
|
+
filmHeight?: number;
|
|
8865
|
+
/** Orthographic zoom/height when present */
|
|
8866
|
+
orthoZoom?: number;
|
|
8867
|
+
/** Camera roll in degrees when present */
|
|
8868
|
+
roll?: number;
|
|
8869
|
+
/** Known unsupported or unrecognized camera properties */
|
|
8870
|
+
unknownProperties: string[];
|
|
8871
|
+
/** Recoverable camera import diagnostics */
|
|
8872
|
+
diagnostics: string[];
|
|
8873
|
+
}
|
|
8874
|
+
/** Light data extracted from FBX */
|
|
8875
|
+
export interface FBXLightData {
|
|
8876
|
+
/** Model ID this light is attached to */
|
|
8877
|
+
modelId: number;
|
|
8878
|
+
/** Light name */
|
|
8879
|
+
name: string;
|
|
8880
|
+
/** Light type: 0=Point, 1=Directional, 2=Spot */
|
|
8881
|
+
lightType: number;
|
|
8882
|
+
/** Color [r,g,b] 0-1 */
|
|
8883
|
+
color: [number, number, number];
|
|
8884
|
+
/** Intensity multiplier */
|
|
8885
|
+
intensity: number;
|
|
8886
|
+
/** Cone angle in degrees (for spot lights) */
|
|
8887
|
+
coneAngle: number;
|
|
8888
|
+
/** Decay type: 0=None, 1=Linear, 2=Quadratic */
|
|
8889
|
+
decayType: number;
|
|
8890
|
+
/** Inner cone angle in degrees for spot lights */
|
|
8891
|
+
innerAngle?: number;
|
|
8892
|
+
/** Outer cone angle in degrees for spot lights */
|
|
8893
|
+
outerAngle?: number;
|
|
8894
|
+
/** Distance at which FBX attenuation starts; preserved as metadata */
|
|
8895
|
+
decayStart?: number;
|
|
8896
|
+
/** Whether FBX near attenuation is enabled */
|
|
8897
|
+
enableNearAttenuation?: boolean;
|
|
8898
|
+
/** Whether FBX far attenuation is enabled */
|
|
8899
|
+
enableFarAttenuation?: boolean;
|
|
8900
|
+
/** Whether the source light requested shadow casting */
|
|
8901
|
+
castShadows?: boolean;
|
|
8902
|
+
/** Known unsupported or unrecognized light properties */
|
|
8903
|
+
unknownProperties: string[];
|
|
8904
|
+
/** Recoverable light import diagnostics */
|
|
8905
|
+
diagnostics: string[];
|
|
8906
|
+
}
|
|
8907
|
+
/** Result of interpreting an FBX document */
|
|
8908
|
+
export interface FBXSceneData {
|
|
8909
|
+
/** All root-level models */
|
|
8910
|
+
rootModels: FBXModelData[];
|
|
8911
|
+
/** All geometries in the scene */
|
|
8912
|
+
geometries: FBXGeometryData[];
|
|
8913
|
+
/** All materials in the scene */
|
|
8914
|
+
materials: FBXMaterialData[];
|
|
8915
|
+
/** Skin deformers (skeletons + vertex weights) */
|
|
8916
|
+
skins: FBXSkinData[];
|
|
8917
|
+
/** Resolved deformation rigs shared by one or more skins */
|
|
8918
|
+
rigs: FBXRigData[];
|
|
8919
|
+
/** Blend shape deformers (morph targets) */
|
|
8920
|
+
blendShapes: FBXBlendShapeData[];
|
|
8921
|
+
/** Animation stacks (clips) */
|
|
8922
|
+
animations: FBXAnimationStackData[];
|
|
8923
|
+
/** Cameras */
|
|
8924
|
+
cameras: FBXCameraData[];
|
|
8925
|
+
/** Lights */
|
|
8926
|
+
lights: FBXLightData[];
|
|
8927
|
+
/** Scene-level unsupported feature diagnostics */
|
|
8928
|
+
diagnostics: FBXSceneDiagnostic[];
|
|
8929
|
+
/** Global settings */
|
|
8930
|
+
upAxis: number;
|
|
8931
|
+
upAxisSign: number;
|
|
8932
|
+
frontAxis: number;
|
|
8933
|
+
frontAxisSign: number;
|
|
8934
|
+
coordAxis: number;
|
|
8935
|
+
coordAxisSign: number;
|
|
8936
|
+
unitScaleFactor: number;
|
|
8937
|
+
}
|
|
8938
|
+
/**
|
|
8939
|
+
* Interpret a parsed FBX document into scene data.
|
|
8940
|
+
*/
|
|
8941
|
+
export function interpretFBX(doc: FBXDocument): FBXSceneData;
|
|
8942
|
+
|
|
8943
|
+
|
|
8944
|
+
/** Connection type: OO = object-to-object, OP = object-to-property */
|
|
8945
|
+
export type ConnectionType = "OO" | "OP";
|
|
8946
|
+
/** A resolved FBX object connection. */
|
|
8947
|
+
export interface FBXConnection {
|
|
8948
|
+
/** Connection type. */
|
|
8949
|
+
type: ConnectionType;
|
|
8950
|
+
/** Child object ID. */
|
|
8951
|
+
childId: number;
|
|
8952
|
+
/** Parent object ID. */
|
|
8953
|
+
parentId: number;
|
|
8954
|
+
/** For OP connections, the property name on the parent (e.g. "DiffuseColor") */
|
|
8955
|
+
propertyName?: string;
|
|
8956
|
+
}
|
|
8957
|
+
/** Object table entry used by the FBX connection graph. */
|
|
8958
|
+
export interface FBXObjectEntry {
|
|
8959
|
+
/** Object ID. */
|
|
8960
|
+
id: number;
|
|
8961
|
+
/** Object node. */
|
|
8962
|
+
node: FBXNode;
|
|
8963
|
+
/** Source of the object entry. */
|
|
8964
|
+
source: "Objects" | "legacySyntheticGeometry";
|
|
8965
|
+
/** Legacy string object name, when applicable. */
|
|
8966
|
+
legacyName?: string;
|
|
8967
|
+
/** True if the object was synthesized for legacy compatibility. */
|
|
8968
|
+
synthetic: boolean;
|
|
8969
|
+
}
|
|
8970
|
+
/** Raw connection-table entry and import status. */
|
|
8971
|
+
export interface FBXConnectionEntry {
|
|
8972
|
+
/** Source node name. */
|
|
8973
|
+
source: "C" | "Connect";
|
|
8974
|
+
/** Raw connection type. */
|
|
8975
|
+
rawType?: string;
|
|
8976
|
+
/** Child object ID, when resolved. */
|
|
8977
|
+
childId?: number;
|
|
8978
|
+
/** Parent object ID, when resolved. */
|
|
8979
|
+
parentId?: number;
|
|
8980
|
+
/** OP connection property name, when present. */
|
|
8981
|
+
propertyName?: string;
|
|
8982
|
+
/** True if the connection was accepted into the resolved graph. */
|
|
8983
|
+
accepted: boolean;
|
|
8984
|
+
}
|
|
8985
|
+
/** Reason a connection produced a diagnostic. */
|
|
8986
|
+
export type FBXConnectionDiagnosticReason = "unsupported-connection-type" | "missing-connection-endpoint" | "unresolved-legacy-endpoint" | "unresolved-object-reference" | "duplicate-parent" | "self-loop";
|
|
8987
|
+
/** Recoverable connection graph issue. */
|
|
8988
|
+
export interface FBXConnectionDiagnostic {
|
|
8989
|
+
/** Diagnostic reason. */
|
|
8990
|
+
reason: FBXConnectionDiagnosticReason;
|
|
8991
|
+
/** Human-readable diagnostic message. */
|
|
8992
|
+
message: string;
|
|
8993
|
+
/** Connection-table index associated with the diagnostic, if applicable. */
|
|
8994
|
+
connectionIndex?: number;
|
|
8995
|
+
/** Connection type associated with the diagnostic, if applicable. */
|
|
8996
|
+
type?: string;
|
|
8997
|
+
/** Child object ID associated with the diagnostic, if applicable. */
|
|
8998
|
+
childId?: number;
|
|
8999
|
+
/** Parent object ID associated with the diagnostic, if applicable. */
|
|
9000
|
+
parentId?: number;
|
|
9001
|
+
/** OP connection property name associated with the diagnostic, if applicable. */
|
|
9002
|
+
propertyName?: string;
|
|
9003
|
+
}
|
|
9004
|
+
/** Resolved FBX object and connection graph. */
|
|
9005
|
+
export interface FBXObjectMap {
|
|
9006
|
+
/** All objects by their unique ID */
|
|
9007
|
+
objects: Map<number, FBXNode>;
|
|
9008
|
+
/** Object table entries, including synthetic compatibility objects */
|
|
9009
|
+
objectEntries: FBXObjectEntry[];
|
|
9010
|
+
/** Children of each object ID */
|
|
9011
|
+
childrenOf: Map<number, {
|
|
9012
|
+
id: number;
|
|
9013
|
+
propertyName?: string;
|
|
9014
|
+
}[]>;
|
|
9015
|
+
/** Parent of each object ID */
|
|
9016
|
+
parentOf: Map<number, {
|
|
9017
|
+
id: number;
|
|
9018
|
+
propertyName?: string;
|
|
9019
|
+
}>;
|
|
9020
|
+
/** Raw connection list */
|
|
9021
|
+
connections: FBXConnection[];
|
|
9022
|
+
/** Raw connection-table entries and whether they were accepted into the graph */
|
|
9023
|
+
connectionEntries: FBXConnectionEntry[];
|
|
9024
|
+
/** Unsupported or suspicious connection shapes encountered while preserving graph behavior */
|
|
9025
|
+
diagnostics: FBXConnectionDiagnostic[];
|
|
9026
|
+
}
|
|
9027
|
+
/**
|
|
9028
|
+
* Build a connection graph from a parsed FBX document.
|
|
9029
|
+
* Maps object IDs to their FBXNode and resolves parent-child relationships.
|
|
9030
|
+
*/
|
|
9031
|
+
export function resolveConnections(doc: FBXDocument): FBXObjectMap;
|
|
9032
|
+
/** Get all child objects of a given parent ID, optionally filtered by node name */
|
|
9033
|
+
export function getChildren(map: FBXObjectMap, parentId: number, nodeName?: string): {
|
|
9034
|
+
id: number;
|
|
9035
|
+
node: FBXNode;
|
|
9036
|
+
propertyName?: string;
|
|
9037
|
+
}[];
|
|
9038
|
+
|
|
9039
|
+
|
|
9040
|
+
/** A single morph target (shape) within a blend shape channel */
|
|
9041
|
+
export interface FBXShapeData {
|
|
9042
|
+
/** Sparse vertex indices affected by this shape */
|
|
9043
|
+
indices: Uint32Array;
|
|
9044
|
+
/** Absolute vertex positions for affected vertices [x,y,z,...] */
|
|
9045
|
+
vertices: Float64Array;
|
|
9046
|
+
/** Normals for affected vertices [x,y,z,...] (optional) */
|
|
9047
|
+
normals: Float64Array | null;
|
|
9048
|
+
}
|
|
9049
|
+
export interface FBXBlendShapeDiagnostic {
|
|
9050
|
+
type: "full-weights-mismatch" | "missing-full-weights";
|
|
9051
|
+
message: string;
|
|
9052
|
+
channelId: number;
|
|
9053
|
+
channelName: string;
|
|
9054
|
+
}
|
|
9055
|
+
/** A blend shape channel (one animatable morph target) */
|
|
9056
|
+
export interface FBXBlendShapeChannelData {
|
|
9057
|
+
/** Channel name */
|
|
9058
|
+
name: string;
|
|
9059
|
+
/** Channel node ID */
|
|
9060
|
+
id: number;
|
|
9061
|
+
/** Default weight (0-100 in FBX) */
|
|
9062
|
+
deformPercent: number;
|
|
9063
|
+
/** Shape geometry (typically one per channel, but FBX supports in-between shapes) */
|
|
9064
|
+
shapes: FBXShapeData[];
|
|
9065
|
+
/** In-between full weights in FBX DeformPercent units (0-100), one per shape when present */
|
|
9066
|
+
fullWeights: number[] | null;
|
|
9067
|
+
/** Recoverable blend-shape diagnostics */
|
|
9068
|
+
diagnostics: FBXBlendShapeDiagnostic[];
|
|
9069
|
+
}
|
|
9070
|
+
/** A blend shape deformer attached to a geometry */
|
|
9071
|
+
export interface FBXBlendShapeData {
|
|
9072
|
+
/** Deformer ID */
|
|
9073
|
+
id: number;
|
|
9074
|
+
/** Geometry ID this blend shape is attached to */
|
|
9075
|
+
geometryId: number;
|
|
9076
|
+
/** Channels (each is an animatable morph target) */
|
|
9077
|
+
channels: FBXBlendShapeChannelData[];
|
|
9078
|
+
}
|
|
9079
|
+
/**
|
|
9080
|
+
* Extract all blend shape deformers from the FBX scene.
|
|
9081
|
+
*/
|
|
9082
|
+
export function extractBlendShapes(objectMap: FBXObjectMap): FBXBlendShapeData[];
|
|
9083
|
+
|
|
9084
|
+
|
|
9085
|
+
export type FBXInterpolationType = "constant" | "linear" | "cubic";
|
|
9086
|
+
/** A single keyframe */
|
|
9087
|
+
export interface FBXKeyframe {
|
|
9088
|
+
/** Time in seconds */
|
|
9089
|
+
time: number;
|
|
9090
|
+
/** Value at this keyframe */
|
|
9091
|
+
value: number;
|
|
9092
|
+
/** Interpolation used from this key to the next key */
|
|
9093
|
+
interpolation: FBXInterpolationType;
|
|
9094
|
+
/** Constant interpolation variant */
|
|
9095
|
+
constantMode?: "standard" | "next";
|
|
9096
|
+
/** Cubic outgoing slope in value units per second */
|
|
9097
|
+
rightSlope?: number;
|
|
9098
|
+
/** Cubic incoming slope for the next key, in value units per second */
|
|
9099
|
+
nextLeftSlope?: number;
|
|
9100
|
+
}
|
|
9101
|
+
/** An animation curve (one axis of one property) */
|
|
9102
|
+
export interface FBXCurveData {
|
|
9103
|
+
/** Channel: "d|X", "d|Y", "d|Z" */
|
|
9104
|
+
channel: string;
|
|
9105
|
+
/** Keyframes */
|
|
9106
|
+
keys: FBXKeyframe[];
|
|
9107
|
+
/** True for baked sample curves that should be connected as linear samples */
|
|
9108
|
+
isSampled?: boolean;
|
|
9109
|
+
}
|
|
9110
|
+
/** An animation curve node (T/R/S for one bone) */
|
|
9111
|
+
export interface FBXCurveNodeData {
|
|
9112
|
+
/** Property type: "T" (translation), "R" (rotation), "S" (scale) */
|
|
9113
|
+
type: string;
|
|
9114
|
+
/** Target model (bone) ID */
|
|
9115
|
+
targetModelId: number;
|
|
9116
|
+
/** Curves for each axis */
|
|
9117
|
+
curves: FBXCurveData[];
|
|
9118
|
+
}
|
|
9119
|
+
/** Unsupported animation curve node preserved for diagnostics and future support. */
|
|
9120
|
+
export interface FBXUnsupportedCurveNodeData {
|
|
9121
|
+
/** Raw AnimationCurveNode property type/name */
|
|
9122
|
+
type: string;
|
|
9123
|
+
/** CurveNode object ID */
|
|
9124
|
+
id: number;
|
|
9125
|
+
/** Target object ID if the curve node is connected to an object/property */
|
|
9126
|
+
targetId: number | null;
|
|
9127
|
+
/** OP connection property name on the target, e.g. Visibility */
|
|
9128
|
+
propertyName?: string;
|
|
9129
|
+
/** Number of connected animation curves that were ignored */
|
|
9130
|
+
curveCount: number;
|
|
9131
|
+
/** Connected curves preserved for diagnostics and future runtime support */
|
|
9132
|
+
curves: FBXCurveData[];
|
|
9133
|
+
/** Local default values stored on the unsupported curve node */
|
|
9134
|
+
defaultValues: Record<string, number>;
|
|
9135
|
+
}
|
|
9136
|
+
/** Recoverable animation import issue. */
|
|
9137
|
+
export interface FBXAnimationDiagnostic {
|
|
9138
|
+
/** Diagnostic category. */
|
|
9139
|
+
type: "multiple-animation-layers" | "unsupported-layer-blend-mode" | "partial-layer-weight" | "unsupported-curve-node";
|
|
9140
|
+
/** Human-readable diagnostic message. */
|
|
9141
|
+
message: string;
|
|
9142
|
+
/** Animation layer name associated with the diagnostic, if applicable. */
|
|
9143
|
+
layerName?: string;
|
|
9144
|
+
/** AnimationCurveNode object ID associated with the diagnostic, if applicable. */
|
|
9145
|
+
curveNodeId?: number;
|
|
9146
|
+
/** AnimationCurveNode type/name associated with the diagnostic, if applicable. */
|
|
9147
|
+
curveNodeType?: string;
|
|
9148
|
+
/** Target object ID associated with the diagnostic, if applicable. */
|
|
9149
|
+
targetId?: number | null;
|
|
9150
|
+
/** Target property name associated with the diagnostic, if applicable. */
|
|
9151
|
+
propertyName?: string;
|
|
9152
|
+
}
|
|
9153
|
+
/** Animation layer with blend mode info */
|
|
9154
|
+
export interface FBXAnimationLayerData {
|
|
9155
|
+
/** Layer name */
|
|
9156
|
+
name: string;
|
|
9157
|
+
/** Layer weight (0-100, default 100) */
|
|
9158
|
+
weight: number;
|
|
9159
|
+
/** Layer weight normalized to 0-1 */
|
|
9160
|
+
normalizedWeight: number;
|
|
9161
|
+
/** Blend mode: 0=Additive, 1=Override, 2=OverridePassthrough */
|
|
9162
|
+
blendMode: number;
|
|
9163
|
+
/** Curve nodes in this layer */
|
|
9164
|
+
curveNodes: FBXCurveNodeData[];
|
|
9165
|
+
/** Unsupported/non-TRS curve nodes preserved for diagnostics */
|
|
9166
|
+
unsupportedCurveNodes: FBXUnsupportedCurveNodeData[];
|
|
9167
|
+
/** Recoverable layer diagnostics */
|
|
9168
|
+
diagnostics: FBXAnimationDiagnostic[];
|
|
9169
|
+
}
|
|
9170
|
+
/** One animation clip (AnimationStack) */
|
|
9171
|
+
export interface FBXAnimationStackData {
|
|
9172
|
+
/** Animation name */
|
|
9173
|
+
name: string;
|
|
9174
|
+
/** Clip start in seconds after any keyframe rebasing */
|
|
9175
|
+
startTime: number;
|
|
9176
|
+
/** Clip stop in seconds after any keyframe rebasing */
|
|
9177
|
+
stopTime: number;
|
|
9178
|
+
/** Duration in seconds */
|
|
9179
|
+
duration: number;
|
|
9180
|
+
/** Per-bone curve nodes (flattened from all layers for backward compat) */
|
|
9181
|
+
curveNodes: FBXCurveNodeData[];
|
|
9182
|
+
/** Animation layers (preserves blend mode info) */
|
|
9183
|
+
layers: FBXAnimationLayerData[];
|
|
9184
|
+
/** Unsupported/non-TRS curve nodes preserved for diagnostics */
|
|
9185
|
+
unsupportedCurveNodes: FBXUnsupportedCurveNodeData[];
|
|
9186
|
+
/** Recoverable animation diagnostics */
|
|
9187
|
+
diagnostics: FBXAnimationDiagnostic[];
|
|
9188
|
+
}
|
|
9189
|
+
/**
|
|
9190
|
+
* Extract all animation stacks from the FBX scene.
|
|
9191
|
+
*/
|
|
9192
|
+
export function extractAnimations(objectMap: FBXObjectMap): FBXAnimationStackData[];
|
|
9193
|
+
/**
|
|
9194
|
+
* Determines whether a key sequence appears to be a uniformly frame-baked sampled curve.
|
|
9195
|
+
* @param keys - Keyframes to inspect
|
|
9196
|
+
* @returns true if the keys look like sampled frame data rather than authored interpolation
|
|
9197
|
+
*/
|
|
9198
|
+
export function isFrameBakedSampledCurve(keys: readonly FBXKeyframe[]): boolean;
|
|
9199
|
+
/**
|
|
9200
|
+
* Samples an FBX animation curve at a specific time.
|
|
9201
|
+
* @param curveData - Curve data to sample
|
|
9202
|
+
* @param time - Time in seconds
|
|
9203
|
+
* @returns The sampled value, or null when the curve has no keys
|
|
9204
|
+
*/
|
|
9205
|
+
export function sampleFBXCurveAtTime(curveData: FBXCurveData | undefined, time: number): number | null;
|
|
9206
|
+
|
|
9207
|
+
|
|
9208
|
+
|
|
9209
|
+
|
|
7819
9210
|
/**
|
|
7820
9211
|
* Options for loading BVH files
|
|
7821
9212
|
*/
|