@babylonjs/loaders 9.25.0 → 9.26.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.
Files changed (106) hide show
  1. package/FBX/fbxConstraintBehavior.d.ts +188 -0
  2. package/FBX/fbxConstraintBehavior.js +532 -0
  3. package/FBX/fbxConstraintBehavior.js.map +1 -0
  4. package/FBX/fbxFileLoader.pure.d.ts +175 -6
  5. package/FBX/fbxFileLoader.pure.js +1521 -286
  6. package/FBX/fbxFileLoader.pure.js.map +1 -1
  7. package/FBX/index.d.ts +4 -1
  8. package/FBX/index.js +1 -0
  9. package/FBX/index.js.map +1 -1
  10. package/FBX/interpreter/animation.d.ts +73 -33
  11. package/FBX/interpreter/animation.js +620 -223
  12. package/FBX/interpreter/animation.js.map +1 -1
  13. package/FBX/interpreter/animationCurve.d.ts +91 -0
  14. package/FBX/interpreter/animationCurve.js +623 -0
  15. package/FBX/interpreter/animationCurve.js.map +1 -0
  16. package/FBX/interpreter/blendShapes.js +9 -18
  17. package/FBX/interpreter/blendShapes.js.map +1 -1
  18. package/FBX/interpreter/connections.d.ts +1 -1
  19. package/FBX/interpreter/connections.js +173 -34
  20. package/FBX/interpreter/connections.js.map +1 -1
  21. package/FBX/interpreter/constraints.d.ts +68 -0
  22. package/FBX/interpreter/constraints.js +143 -0
  23. package/FBX/interpreter/constraints.js.map +1 -0
  24. package/FBX/interpreter/fbxInterpreter.d.ts +89 -4
  25. package/FBX/interpreter/fbxInterpreter.js +474 -122
  26. package/FBX/interpreter/fbxInterpreter.js.map +1 -1
  27. package/FBX/interpreter/geometry.d.ts +1 -1
  28. package/FBX/interpreter/geometry.js +150 -92
  29. package/FBX/interpreter/geometry.js.map +1 -1
  30. package/FBX/interpreter/legacyDocument.d.ts +11 -0
  31. package/FBX/interpreter/legacyDocument.js +425 -0
  32. package/FBX/interpreter/legacyDocument.js.map +1 -0
  33. package/FBX/interpreter/materialModel.d.ts +71 -0
  34. package/FBX/interpreter/materialModel.js +622 -0
  35. package/FBX/interpreter/materialModel.js.map +1 -0
  36. package/FBX/interpreter/materials.d.ts +13 -1
  37. package/FBX/interpreter/materials.js +88 -5
  38. package/FBX/interpreter/materials.js.map +1 -1
  39. package/FBX/interpreter/nodeTransform.d.ts +32 -0
  40. package/FBX/interpreter/nodeTransform.js +54 -0
  41. package/FBX/interpreter/nodeTransform.js.map +1 -0
  42. package/FBX/interpreter/nurbs.d.ts +99 -0
  43. package/FBX/interpreter/nurbs.js +627 -0
  44. package/FBX/interpreter/nurbs.js.map +1 -0
  45. package/FBX/interpreter/propertyTemplates.d.ts +23 -0
  46. package/FBX/interpreter/propertyTemplates.js +109 -2
  47. package/FBX/interpreter/propertyTemplates.js.map +1 -1
  48. package/FBX/interpreter/rig.js +16 -0
  49. package/FBX/interpreter/rig.js.map +1 -1
  50. package/FBX/interpreter/sceneDiagnostics.js +28 -3
  51. package/FBX/interpreter/sceneDiagnostics.js.map +1 -1
  52. package/FBX/interpreter/skeleton.d.ts +4 -18
  53. package/FBX/interpreter/skeleton.js +16 -94
  54. package/FBX/interpreter/skeleton.js.map +1 -1
  55. package/FBX/parsers/fbxAsciiParser.js +119 -9
  56. package/FBX/parsers/fbxAsciiParser.js.map +1 -1
  57. package/FBX/parsers/fbxBinaryParser.js +74 -22
  58. package/FBX/parsers/fbxBinaryParser.js.map +1 -1
  59. package/FBX/pure.d.ts +1 -0
  60. package/FBX/pure.js +1 -0
  61. package/FBX/pure.js.map +1 -1
  62. package/FBX/types/fbxTypes.d.ts +18 -2
  63. package/FBX/types/fbxTypes.js +40 -12
  64. package/FBX/types/fbxTypes.js.map +1 -1
  65. package/SPLAT/gaussianSplattingStream.d.ts +31 -0
  66. package/SPLAT/gaussianSplattingStream.js +49 -0
  67. package/SPLAT/gaussianSplattingStream.js.map +1 -1
  68. package/USD/index.d.ts +2 -0
  69. package/USD/index.js +4 -0
  70. package/USD/index.js.map +1 -0
  71. package/USD/pure.d.ts +3 -0
  72. package/USD/pure.js +5 -0
  73. package/USD/pure.js.map +1 -0
  74. package/USD/usdCommandProtocol.d.ts +83 -0
  75. package/USD/usdCommandProtocol.js +173 -0
  76. package/USD/usdCommandProtocol.js.map +1 -0
  77. package/USD/usdFileLoader.d.ts +6 -0
  78. package/USD/usdFileLoader.js +9 -0
  79. package/USD/usdFileLoader.js.map +1 -0
  80. package/USD/usdFileLoader.metadata.d.ts +20 -0
  81. package/USD/usdFileLoader.metadata.js +18 -0
  82. package/USD/usdFileLoader.metadata.js.map +1 -0
  83. package/USD/usdFileLoader.pure.d.ts +102 -0
  84. package/USD/usdFileLoader.pure.js +341 -0
  85. package/USD/usdFileLoader.pure.js.map +1 -0
  86. package/USD/usdFileLoader.types.d.ts +11 -0
  87. package/USD/usdFileLoader.types.js +2 -0
  88. package/USD/usdFileLoader.types.js.map +1 -0
  89. package/USD/usdLoadingOptions.d.ts +123 -0
  90. package/USD/usdLoadingOptions.js +3 -0
  91. package/USD/usdLoadingOptions.js.map +1 -0
  92. package/USD/usdSceneMaterializer.d.ts +9 -0
  93. package/USD/usdSceneMaterializer.js +982 -0
  94. package/USD/usdSceneMaterializer.js.map +1 -0
  95. package/USD/usdWorkerMessages.d.ts +57 -0
  96. package/USD/usdWorkerMessages.js +3 -0
  97. package/USD/usdWorkerMessages.js.map +1 -0
  98. package/dynamic.js +10 -0
  99. package/dynamic.js.map +1 -1
  100. package/index.d.ts +1 -0
  101. package/index.js +1 -0
  102. package/index.js.map +1 -1
  103. package/package.json +4 -3
  104. package/pure.d.ts +1 -0
  105. package/pure.js +1 -0
  106. package/pure.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"fbxTypes.js","sourceRoot":"","sources":["../../../../../dev/loaders/src/FBX/types/fbxTypes.ts"],"names":[],"mappings":"AAAA,qGAAqG;AACrG;;;GAGG;AA+CH,0CAA0C;AAC1C,MAAM,UAAU,eAAe,CAAC,IAAa,EAAE,IAAY;IACvD,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AACtD,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,kBAAkB,CAAC,IAAa,EAAE,IAAY;IAC1D,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AACxD,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,gBAAgB,CAAC,GAAgB,EAAE,IAAY;IAC3D,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AAClD,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,gBAAgB,CAA6B,IAAa,EAAE,KAAa;IACrF,IAAI,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,KAAU,CAAC;IAC7C,CAAC;IACD,OAAO,SAAS,CAAC;AACrB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC7C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,wBAAwB,KAAK,CAAC,QAAQ,EAAE,qCAAqC,CAAC,CAAC;IACnG,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,SAAS,CAAC,IAAa;IACnC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAChC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,CAAC;QAC3D,OAAO,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,SAAS,CAAC;AACrB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe;IACxC,0DAA0D;IAC1D,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;QACf,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;IAED,yCAAyC;IACzC,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;QAChB,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,OAAO,CAAC;AACnB,CAAC","sourcesContent":["/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\r\n/**\r\n * Intermediate representation for parsed FBX data.\r\n * Both binary and ASCII parsers produce this same structure.\r\n */\r\n\r\n/** Individual property value within an FBX node */\r\nexport type FBXPropertyValue = boolean | number | string | Float32Array | Float64Array | Int32Array | Uint8Array;\r\n\r\n/** Parsed FBX property type identifier. */\r\nexport type FBXPropertyType =\r\n | \"boolean\" // 'C'\r\n | \"int16\" // 'Y'\r\n | \"int32\" // 'I'\r\n | \"int64\" // 'L'\r\n | \"float32\" // 'F'\r\n | \"float64\" // 'D'\r\n | \"string\" // 'S'\r\n | \"raw\" // 'R'\r\n | \"float32[]\" // 'f'\r\n | \"float64[]\" // 'd'\r\n | \"int32[]\" // 'i'\r\n | \"int64[]\" // 'l'\r\n | \"boolean[]\"; // 'b' (stored as Uint8Array where 0=false, 1=true)\r\n\r\n/** Individual property within an FBX node. */\r\nexport interface FBXProperty {\r\n /** Parsed property type. */\r\n type: FBXPropertyType;\r\n /** Parsed property value. */\r\n value: FBXPropertyValue;\r\n}\r\n\r\n/** A node in the FBX document tree */\r\nexport interface FBXNode {\r\n /** Node name. */\r\n name: string;\r\n /** Node properties. */\r\n properties: FBXProperty[];\r\n /** Child nodes. */\r\n children: FBXNode[];\r\n}\r\n\r\n/** Top-level parsed FBX document */\r\nexport interface FBXDocument {\r\n /** FBX file version. */\r\n version: number;\r\n /** Top-level document nodes. */\r\n nodes: FBXNode[];\r\n}\r\n\r\n/** Helper to find a child node by name */\r\nexport function findChildByName(node: FBXNode, name: string): FBXNode | undefined {\r\n return node.children.find((c) => c.name === name);\r\n}\r\n\r\n/** Helper to find all children with a given name */\r\nexport function findChildrenByName(node: FBXNode, name: string): FBXNode[] {\r\n return node.children.filter((c) => c.name === name);\r\n}\r\n\r\n/** Helper to find a top-level node in a document */\r\nexport function findDocumentNode(doc: FBXDocument, name: string): FBXNode | undefined {\r\n return doc.nodes.find((n) => n.name === name);\r\n}\r\n\r\n/** Extract a property value by index, with type narrowing */\r\nexport function getPropertyValue<T extends FBXPropertyValue>(node: FBXNode, index: number): T | undefined {\r\n if (index < node.properties.length) {\r\n return node.properties[index].value as T;\r\n }\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Converts an FBX object ID value to a safe JavaScript number.\r\n * @param value - Parsed FBX object ID value\r\n * @returns The object ID, or undefined when the value is not numeric\r\n */\r\nexport function getSafeFBXObjectId(value: unknown): number | undefined {\r\n if (typeof value !== \"number\") {\r\n return undefined;\r\n }\r\n if (!Number.isSafeInteger(value)) {\r\n throw new Error(`Unsafe FBX object ID ${value.toString()}: object IDs must be safe integers.`);\r\n }\r\n return value;\r\n}\r\n\r\n/** Get the numeric ID from a node (first property is typically the int64 UID) */\r\nexport function getNodeId(node: FBXNode): number | undefined {\r\n const prop = node.properties[0];\r\n if (prop && (prop.type === \"int64\" || prop.type === \"int32\")) {\r\n return getSafeFBXObjectId(prop.value);\r\n }\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Clean FBX object names.\r\n * FBX names may contain:\r\n * - A \"Class::\" prefix (e.g. \"Model::valkyrie_mesh\") — strip it\r\n * - A binary null/control-character class suffix — strip it\r\n */\r\nexport function cleanFBXName(fbxName: string): string {\r\n // Strip \\x00\\x01 suffix (binary FBX name/class separator)\r\n const nullIdx = fbxName.indexOf(\"\\0\");\r\n if (nullIdx >= 0) {\r\n fbxName = fbxName.substring(0, nullIdx);\r\n }\r\n\r\n // Strip \"ClassName::\" prefix (ASCII FBX)\r\n const colonIdx = fbxName.indexOf(\"::\");\r\n if (colonIdx >= 0) {\r\n fbxName = fbxName.substring(colonIdx + 2);\r\n }\r\n\r\n return fbxName;\r\n}\r\n"]}
1
+ {"version":3,"file":"fbxTypes.js","sourceRoot":"","sources":["../../../../../dev/loaders/src/FBX/types/fbxTypes.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\n/**\n * Intermediate representation for parsed FBX data.\n * Both binary and ASCII parsers produce this same structure.\n */\n\n/** Individual property value within an FBX node */\nexport type FBXPropertyValue = boolean | number | string | Float32Array | Float64Array | Int32Array | Uint8Array;\n\n/** Parsed FBX property type identifier. */\nexport type FBXPropertyType =\n | \"boolean\" // 'C'\n | \"int16\" // 'Y'\n | \"int32\" // 'I'\n | \"int64\" // 'L'\n | \"float32\" // 'F'\n | \"float64\" // 'D'\n | \"string\" // 'S'\n | \"raw\" // 'R'\n | \"float32[]\" // 'f'\n | \"float64[]\" // 'd'\n | \"int32[]\" // 'i'\n | \"int64[]\" // 'l'\n | \"boolean[]\"; // 'b' (stored as Uint8Array where 0=false, 1=true)\n\n/** Individual property within an FBX node. */\nexport interface FBXProperty {\n /** Parsed property type. */\n type: FBXPropertyType;\n /** Parsed property value. */\n value: FBXPropertyValue;\n /**\n * Exact decimal text of an int64 whose magnitude exceeds 2^53; `value` then holds the rounded double. Object\n * ids are the only int64 values where the last bits matter, and `resolveConnections` keys them by this text.\n */\n raw?: string;\n}\n\n/** A node in the FBX document tree */\nexport interface FBXNode {\n /** Node name. */\n name: string;\n /** Node properties. */\n properties: FBXProperty[];\n /** Child nodes. */\n children: FBXNode[];\n}\n\n/** Top-level parsed FBX document */\nexport interface FBXDocument {\n /** FBX file version. */\n version: number;\n /** Top-level document nodes. */\n nodes: FBXNode[];\n}\n\n/** Helper to find a child node by name */\nexport function findChildByName(node: FBXNode, name: string): FBXNode | undefined {\n return node.children.find((c) => c.name === name);\n}\n\n/** Helper to find all children with a given name */\nexport function findChildrenByName(node: FBXNode, name: string): FBXNode[] {\n return node.children.filter((c) => c.name === name);\n}\n\n/** Helper to find a top-level node in a document */\nexport function findDocumentNode(doc: FBXDocument, name: string): FBXNode | undefined {\n return doc.nodes.find((n) => n.name === name);\n}\n\n/** Extract a property value by index, with type narrowing */\nexport function getPropertyValue<T extends FBXPropertyValue>(node: FBXNode, index: number): T | undefined {\n if (index < node.properties.length) {\n return node.properties[index].value as T;\n }\n return undefined;\n}\n\n/**\n * Validates an FBX object ID value: IDs are 64-bit integers, so anything non-numeric, non-finite or fractional is\n * rejected. IDs beyond 2^53 are carried losslessly through the property's `raw` text by `resolveConnections`.\n * @param value - Parsed FBX object ID value\n * @returns The object ID, or undefined when the value cannot be an ID\n */\nexport function getSafeFBXObjectId(value: unknown): number | undefined {\n if (typeof value !== \"number\" || !Number.isFinite(value) || !Number.isInteger(value)) {\n return undefined;\n }\n return value;\n}\n\n/** Typed array payload types produced by the parsers. */\nexport type FBXArrayValue = Float32Array | Float64Array | Int32Array | Uint8Array;\n\n/**\n * Returns the array payload of a node.\n * FBX 7.x stores arrays as a single array property. FBX 6.x (and some 7.x ASCII exporters) store them as a run of\n * scalar properties, and a one-element array degenerates to a single scalar. All of these are coalesced here.\n * @param node - Node whose properties hold the array\n * @returns The array, or null when the node has no numeric payload\n */\nexport function getNodeArray(node: FBXNode | undefined | null): FBXArrayValue | null {\n if (!node || node.properties.length === 0) {\n return null;\n }\n const first = node.properties[0].value;\n if (node.properties.length === 1 && (first instanceof Float32Array || first instanceof Float64Array || first instanceof Int32Array || first instanceof Uint8Array)) {\n return first;\n }\n const out = new Float64Array(node.properties.length);\n for (let i = 0; i < node.properties.length; i++) {\n const v = node.properties[i].value;\n if (typeof v === \"number\") {\n out[i] = v;\n } else if (typeof v === \"boolean\") {\n out[i] = v ? 1 : 0;\n } else {\n return null;\n }\n }\n return out;\n}\n\n/** Get the numeric ID from a node (first property is typically the int64 UID) */\nexport function getNodeId(node: FBXNode): number | undefined {\n const prop = node.properties[0];\n if (prop && (prop.type === \"int64\" || prop.type === \"int32\")) {\n return getSafeFBXObjectId(prop.value);\n }\n return undefined;\n}\n\n/**\n * Clean FBX object names.\n * FBX names may contain:\n * - A \"Class::\" prefix (e.g. \"Model::valkyrie_mesh\") — strip it\n * - A binary null/control-character class suffix — strip it\n */\nexport function cleanFBXName(fbxName: string): string {\n // Binary FBX: \"Name\\x00\\x01Class\" — the name is everything before the separator and may itself contain \"::\".\n const sepIdx = fbxName.indexOf(\"\\0\\x01\");\n if (sepIdx >= 0) {\n return fbxName.substring(0, sepIdx);\n }\n\n // ASCII FBX: \"Class::Name\" — strip only the leading class prefix (\"Model::Cube::Model\" -> \"Cube::Model\").\n const colonIdx = fbxName.indexOf(\"::\");\n if (colonIdx >= 0) {\n return fbxName.substring(colonIdx + 2);\n }\n\n return fbxName;\n}\n"]}
@@ -71,6 +71,18 @@ export interface ISOGLODMetadata {
71
71
  * Selects which LOD value drives the {@link GaussianSplattingStream} debug wireframe colors.
72
72
  */
73
73
  export type GaussianSplattingStreamDebugLodSource = "optimal" | "current";
74
+ /**
75
+ * Immutable metadata-resolution state for a stream's total number of finest-LOD splats.
76
+ * @experimental
77
+ */
78
+ export type GaussianSplattingStreamLod0SplatCount = Readonly<{
79
+ status: "pending";
80
+ }> | Readonly<{
81
+ status: "available";
82
+ count: number;
83
+ }> | Readonly<{
84
+ status: "unavailable";
85
+ }>;
74
86
  /**
75
87
  * Options for {@link GaussianSplattingStream}.
76
88
  */
@@ -190,6 +202,7 @@ export declare class GaussianSplattingStream extends GaussianSplattingMesh imple
190
202
  private readonly _rootUrl;
191
203
  private readonly _streamOptions;
192
204
  private readonly _leafNodes;
205
+ private _lod0SplatCount;
193
206
  private _lodBaseDistance;
194
207
  private _lodMultiplier;
195
208
  private _lodBehindPenalty;
@@ -354,6 +367,19 @@ export declare class GaussianSplattingStream extends GaussianSplattingMesh imple
354
367
  * @experimental
355
368
  */
356
369
  get effectiveSplatBudget(): number;
370
+ /**
371
+ * The resolved maximum number of splats kept resident in the work buffer. This combines
372
+ * {@link IGaussianSplattingStreamOptions.maxResidentSplats} and {@link IGaussianSplattingStreamOptions.memoryBudgetMb},
373
+ * taking the smaller limit when both are configured. `0` means the resident budget is disabled.
374
+ * @experimental
375
+ */
376
+ get residentSplatBudget(): number;
377
+ /**
378
+ * The total number of splats represented by valid level-0 leaf entries. This remains pending while source
379
+ * metadata is loading and is unavailable when no applicable level-0 entries exist or required metadata fails.
380
+ * @experimental
381
+ */
382
+ get lod0SplatCount(): GaussianSplattingStreamLod0SplatCount;
357
383
  /**
358
384
  * Resolves the raw {@link splatBudget} option to a concrete cap: `undefined` ⇒ 0 (disabled), `"auto"` ⇒ a
359
385
  * device-tiered default, a positive number ⇒ itself (floored).
@@ -523,6 +549,11 @@ export declare class GaussianSplattingStream extends GaussianSplattingMesh imple
523
549
  * @returns sorted unique file indices
524
550
  */
525
551
  private _collectAllFileIds;
552
+ /**
553
+ * Settles the level-0 diagnostic from normalized renderable leaf entries after their source metadata resolves.
554
+ * A file may back several leaf ranges, so its source count is deliberately not used in the total.
555
+ */
556
+ private _resolveLod0SplatCount;
526
557
  /**
527
558
  * Fetches the environment bundle and every referenced file's metadata to learn splat counts, caching
528
559
  * each file's parsed metadata for the later on-demand decode. Metadata fetches run in parallel.
@@ -97,6 +97,7 @@ export class GaussianSplattingStream extends GaussianSplattingMesh {
97
97
  super(name, null, scene, false);
98
98
  // Flat list of leaf nodes that carry renderable LOD entries (used by the LOD heuristic and debug).
99
99
  this._leafNodes = [];
100
+ this._lod0SplatCount = Object.freeze({ status: "pending" });
100
101
  // LOD heuristic parameters (PlayCanvas-aligned defaults).
101
102
  this._lodBaseDistance = 5;
102
103
  this._lodMultiplier = 3;
@@ -344,6 +345,7 @@ export class GaussianSplattingStream extends GaussianSplattingMesh {
344
345
  this._disposeAndReclaim();
345
346
  }
346
347
  }, (e) => {
348
+ this._lod0SplatCount = Object.freeze({ status: "unavailable" });
347
349
  Logger.Error("GaussianSplattingStream: streaming failed: " + (e?.message ?? e));
348
350
  this._rejectPartReady("GaussianSplattingStream: streaming failed: " + (e?.message ?? e));
349
351
  if (this._hostCompound && !this._disposed) {
@@ -533,6 +535,23 @@ export class GaussianSplattingStream extends GaussianSplattingMesh {
533
535
  get effectiveSplatBudget() {
534
536
  return this._effectiveSplatBudget();
535
537
  }
538
+ /**
539
+ * The resolved maximum number of splats kept resident in the work buffer. This combines
540
+ * {@link IGaussianSplattingStreamOptions.maxResidentSplats} and {@link IGaussianSplattingStreamOptions.memoryBudgetMb},
541
+ * taking the smaller limit when both are configured. `0` means the resident budget is disabled.
542
+ * @experimental
543
+ */
544
+ get residentSplatBudget() {
545
+ return this._residentBudget;
546
+ }
547
+ /**
548
+ * The total number of splats represented by valid level-0 leaf entries. This remains pending while source
549
+ * metadata is loading and is unavailable when no applicable level-0 entries exist or required metadata fails.
550
+ * @experimental
551
+ */
552
+ get lod0SplatCount() {
553
+ return this._lod0SplatCount;
554
+ }
536
555
  /**
537
556
  * Resolves the raw {@link splatBudget} option to a concrete cap: `undefined` ⇒ 0 (disabled), `"auto"` ⇒ a
538
557
  * device-tiered default, a positive number ⇒ itself (floored).
@@ -1113,6 +1132,7 @@ export class GaussianSplattingStream extends GaussianSplattingMesh {
1113
1132
  // resolves the max SH degree, so the resident-splat budget can now be sized with the SH/rotation byte cost.
1114
1133
  const fileIds = this._collectAllFileIds();
1115
1134
  const envCount = await this._gatherCountsAsync(fileIds);
1135
+ this._resolveLod0SplatCount();
1116
1136
  if (this._disposed) {
1117
1137
  return;
1118
1138
  }
@@ -1335,6 +1355,35 @@ export class GaussianSplattingStream extends GaussianSplattingMesh {
1335
1355
  }
1336
1356
  return Array.from(ids).sort((a, b) => a - b);
1337
1357
  }
1358
+ /**
1359
+ * Settles the level-0 diagnostic from normalized renderable leaf entries after their source metadata resolves.
1360
+ * A file may back several leaf ranges, so its source count is deliberately not used in the total.
1361
+ */
1362
+ _resolveLod0SplatCount() {
1363
+ let total = 0;
1364
+ let hasLod0Entry = false;
1365
+ for (const node of this._leafNodes) {
1366
+ if (node.availableLevels?.[0] !== 0) {
1367
+ continue;
1368
+ }
1369
+ const entry = node.lods?.["0"];
1370
+ if (!entry) {
1371
+ this._lod0SplatCount = Object.freeze({ status: "unavailable" });
1372
+ return;
1373
+ }
1374
+ hasLod0Entry = true;
1375
+ if (!this._fileCounts.has(entry.file) || !this._fileMeta.has(entry.file)) {
1376
+ this._lod0SplatCount = Object.freeze({ status: "unavailable" });
1377
+ return;
1378
+ }
1379
+ total += entry.count;
1380
+ if (!Number.isSafeInteger(total)) {
1381
+ this._lod0SplatCount = Object.freeze({ status: "unavailable" });
1382
+ return;
1383
+ }
1384
+ }
1385
+ this._lod0SplatCount = hasLod0Entry ? Object.freeze({ status: "available", count: total }) : Object.freeze({ status: "unavailable" });
1386
+ }
1338
1387
  /**
1339
1388
  * Fetches the environment bundle and every referenced file's metadata to learn splat counts, caching
1340
1389
  * each file's parsed metadata for the later on-demand decode. Metadata fetches run in parallel.