@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":"fbxAsciiParser.js","sourceRoot":"","sources":["../../../../../dev/loaders/src/FBX/parsers/fbxAsciiParser.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\r\nimport { type FBXDocument, type FBXNode, type FBXProperty } from \"../types/fbxTypes\";\r\n\r\n/**\r\n * Parse an ASCII FBX file into an FBXDocument.\r\n */\r\nexport function parseAsciiFBX(text: string): FBXDocument {\r\n const tokenizer = new Tokenizer(text);\r\n const version = parseVersion(text);\r\n const nodes: FBXNode[] = [];\r\n\r\n while (!tokenizer.isEOF()) {\r\n tokenizer.skipWhitespaceAndComments();\r\n if (tokenizer.isEOF()) {\r\n break;\r\n }\r\n const node = parseNodeFromTokens(tokenizer);\r\n if (node) {\r\n nodes.push(node);\r\n }\r\n }\r\n\r\n return { version, nodes };\r\n}\r\n\r\n/** Extract FBX version from the header comment (e.g. \"; FBX 7.7.0 project file\") */\r\nfunction parseVersion(text: string): number {\r\n const match = text.match(/;\\s*FBX\\s+(\\d+)\\.(\\d+)\\.(\\d+)/);\r\n if (!match) {\r\n throw new Error(\"Cannot determine FBX version from ASCII header\");\r\n }\r\n return parseInt(match[1]) * 1000 + parseInt(match[2]) * 100 + parseInt(match[3]);\r\n}\r\n\r\n// ── Tokenizer ──────────────────────────────────────────────────────────────────\r\n\r\nconst enum TokenType {\r\n Identifier,\r\n Number,\r\n String,\r\n OpenBrace,\r\n CloseBrace,\r\n Colon,\r\n Comma,\r\n Star,\r\n EOF,\r\n}\r\n\r\ninterface Token {\r\n type: TokenType;\r\n value: string;\r\n pos: number;\r\n}\r\n\r\nclass Tokenizer {\r\n private pos = 0;\r\n private readonly len: number;\r\n\r\n constructor(private readonly text: string) {\r\n this.len = text.length;\r\n }\r\n\r\n isEOF(): boolean {\r\n this.skipWhitespaceAndComments();\r\n return this.pos >= this.len;\r\n }\r\n\r\n peek(): Token {\r\n const saved = this.pos;\r\n const tok = this.next();\r\n this.pos = saved;\r\n return tok;\r\n }\r\n\r\n next(): Token {\r\n this.skipWhitespaceAndComments();\r\n if (this.pos >= this.len) {\r\n return { type: TokenType.EOF, value: \"\", pos: this.pos };\r\n }\r\n\r\n const ch = this.text[this.pos];\r\n const startPos = this.pos;\r\n\r\n switch (ch) {\r\n case \"{\":\r\n this.pos++;\r\n return { type: TokenType.OpenBrace, value: \"{\", pos: startPos };\r\n case \"}\":\r\n this.pos++;\r\n return { type: TokenType.CloseBrace, value: \"}\", pos: startPos };\r\n case \":\":\r\n this.pos++;\r\n return { type: TokenType.Colon, value: \":\", pos: startPos };\r\n case \",\":\r\n this.pos++;\r\n return { type: TokenType.Comma, value: \",\", pos: startPos };\r\n case \"*\":\r\n this.pos++;\r\n return { type: TokenType.Star, value: \"*\", pos: startPos };\r\n case '\"':\r\n return this.readString();\r\n default:\r\n if (this.isNumberStart(ch)) {\r\n return this.readNumber();\r\n }\r\n if (this.isIdentStart(ch)) {\r\n return this.readIdentifier();\r\n }\r\n throw new Error(`Unexpected character '${ch}' at position ${this.pos}`);\r\n }\r\n }\r\n\r\n expect(type: TokenType): Token {\r\n const tok = this.next();\r\n if (tok.type !== type) {\r\n throw new Error(`Expected token type ${type} but got ${tok.type} ('${tok.value}') at pos ${tok.pos}`);\r\n }\r\n return tok;\r\n }\r\n\r\n /** Look ahead to see if the next identifier + colon is a child node start */\r\n isNextNodeStart(): boolean {\r\n const saved = this.pos;\r\n this.skipWhitespaceAndComments();\r\n // Read the identifier\r\n if (this.pos < this.len && this.isIdentStart(this.text[this.pos])) {\r\n while (this.pos < this.len && this.isIdentChar(this.text[this.pos])) {\r\n this.pos++;\r\n }\r\n // Skip whitespace between identifier and potential colon\r\n while (this.pos < this.len && (this.text[this.pos] === \" \" || this.text[this.pos] === \"\\t\")) {\r\n this.pos++;\r\n }\r\n const isNode = this.pos < this.len && this.text[this.pos] === \":\";\r\n this.pos = saved;\r\n return isNode;\r\n }\r\n this.pos = saved;\r\n return false;\r\n }\r\n\r\n skipWhitespaceAndComments(): void {\r\n while (this.pos < this.len) {\r\n const ch = this.text[this.pos];\r\n if (ch === \" \" || ch === \"\\t\" || ch === \"\\r\" || ch === \"\\n\") {\r\n this.pos++;\r\n } else if (ch === \";\") {\r\n // Skip comment to end of line\r\n while (this.pos < this.len && this.text[this.pos] !== \"\\n\") {\r\n this.pos++;\r\n }\r\n } else {\r\n break;\r\n }\r\n }\r\n }\r\n\r\n private readString(): Token {\r\n const startPos = this.pos;\r\n this.pos++; // skip opening quote\r\n let value = \"\";\r\n while (this.pos < this.len && this.text[this.pos] !== '\"') {\r\n if (this.text[this.pos] === \"\\\\\" && this.pos + 1 < this.len) {\r\n this.pos++;\r\n value += this.text[this.pos];\r\n } else {\r\n value += this.text[this.pos];\r\n }\r\n this.pos++;\r\n }\r\n if (this.pos < this.len) {\r\n this.pos++; // skip closing quote\r\n }\r\n return { type: TokenType.String, value, pos: startPos };\r\n }\r\n\r\n private readNumber(): Token {\r\n const startPos = this.pos;\r\n // Handle leading sign\r\n if (this.text[this.pos] === \"-\" || this.text[this.pos] === \"+\") {\r\n this.pos++;\r\n }\r\n while (this.pos < this.len && this.isDigit(this.text[this.pos])) {\r\n this.pos++;\r\n }\r\n if (this.pos < this.len && this.text[this.pos] === \".\") {\r\n this.pos++;\r\n while (this.pos < this.len && this.isDigit(this.text[this.pos])) {\r\n this.pos++;\r\n }\r\n }\r\n // Scientific notation\r\n if (this.pos < this.len && (this.text[this.pos] === \"e\" || this.text[this.pos] === \"E\")) {\r\n this.pos++;\r\n if (this.pos < this.len && (this.text[this.pos] === \"+\" || this.text[this.pos] === \"-\")) {\r\n this.pos++;\r\n }\r\n while (this.pos < this.len && this.isDigit(this.text[this.pos])) {\r\n this.pos++;\r\n }\r\n }\r\n return { type: TokenType.Number, value: this.text.substring(startPos, this.pos), pos: startPos };\r\n }\r\n\r\n private readIdentifier(): Token {\r\n const startPos = this.pos;\r\n while (this.pos < this.len && this.isIdentChar(this.text[this.pos])) {\r\n this.pos++;\r\n }\r\n return { type: TokenType.Identifier, value: this.text.substring(startPos, this.pos), pos: startPos };\r\n }\r\n\r\n private isDigit(ch: string): boolean {\r\n return ch >= \"0\" && ch <= \"9\";\r\n }\r\n\r\n private isNumberStart(ch: string): boolean {\r\n if (this.isDigit(ch)) {\r\n return true;\r\n }\r\n if ((ch === \"-\" || ch === \"+\") && this.pos + 1 < this.len) {\r\n return this.isDigit(this.text[this.pos + 1]) || this.text[this.pos + 1] === \".\";\r\n }\r\n return false;\r\n }\r\n\r\n private isIdentStart(ch: string): boolean {\r\n return (ch >= \"a\" && ch <= \"z\") || (ch >= \"A\" && ch <= \"Z\") || ch === \"_\";\r\n }\r\n\r\n private isIdentChar(ch: string): boolean {\r\n return this.isIdentStart(ch) || this.isDigit(ch) || ch === \"|\";\r\n }\r\n}\r\n\r\n// ── Node Parsing ───────────────────────────────────────────────────────────────\r\n\r\nfunction parseNodeFromTokens(tokenizer: Tokenizer): FBXNode | null {\r\n const nameTok = tokenizer.peek();\r\n if (nameTok.type === TokenType.CloseBrace || nameTok.type === TokenType.EOF) {\r\n return null;\r\n }\r\n\r\n // Node name\r\n const identTok = tokenizer.next();\r\n if (identTok.type !== TokenType.Identifier) {\r\n throw new Error(`Expected identifier for node name, got '${identTok.value}' at pos ${identTok.pos}`);\r\n }\r\n const name = identTok.value;\r\n tokenizer.expect(TokenType.Colon);\r\n\r\n // Parse properties until we hit '{' or end-of-line content\r\n const properties: FBXProperty[] = [];\r\n const children: FBXNode[] = [];\r\n\r\n // Check for array shorthand: *count { a: ... }\r\n let peek = tokenizer.peek();\r\n if (peek.type === TokenType.Star) {\r\n // Array node like \"Vertices: *25959 {\"\r\n tokenizer.next(); // consume *\r\n const countTok = tokenizer.expect(TokenType.Number);\r\n const count = parseInt(countTok.value);\r\n tokenizer.expect(TokenType.OpenBrace);\r\n\r\n // Expect \"a:\" followed by comma-separated values\r\n const aTok = tokenizer.next();\r\n if (aTok.type === TokenType.Identifier && aTok.value === \"a\") {\r\n tokenizer.expect(TokenType.Colon);\r\n const values = parseArrayValues(tokenizer, count);\r\n properties.push({ type: \"float64[]\", value: new Float64Array(values) });\r\n }\r\n\r\n tokenizer.expect(TokenType.CloseBrace);\r\n return { name, properties, children };\r\n }\r\n\r\n // Parse inline properties (comma-separated values on the same logical line)\r\n // Values can be: numbers, strings, or bare identifiers (e.g. \"T\", \"Y\", \"CullingOff\")\r\n peek = tokenizer.peek();\r\n while (peek.type !== TokenType.OpenBrace && peek.type !== TokenType.CloseBrace && peek.type !== TokenType.EOF) {\r\n if (peek.type === TokenType.Number) {\r\n const tok = tokenizer.next();\r\n const numVal = parseNumericValue(tok.value);\r\n if (Number.isInteger(numVal) && !tok.value.includes(\".\") && !tok.value.includes(\"e\") && !tok.value.includes(\"E\")) {\r\n properties.push({ type: isInt32(numVal) ? \"int32\" : \"int64\", value: numVal });\r\n } else {\r\n properties.push({ type: \"float64\", value: numVal });\r\n }\r\n } else if (peek.type === TokenType.String) {\r\n const tok = tokenizer.next();\r\n properties.push({ type: \"string\", value: tok.value });\r\n } else if (peek.type === TokenType.Identifier) {\r\n // Check if this is a property value or the start of a new child node.\r\n // If the next non-whitespace after the identifier is ':', it's a child node name — stop.\r\n if (tokenizer.isNextNodeStart()) {\r\n break;\r\n }\r\n // Bare identifier as a property value (e.g. \"T\", \"Y\", \"CullingOff\")\r\n const tok = tokenizer.next();\r\n properties.push({ type: \"string\", value: tok.value });\r\n } else if (peek.type === TokenType.Comma) {\r\n tokenizer.next(); // consume comma\r\n } else {\r\n break;\r\n }\r\n peek = tokenizer.peek();\r\n }\r\n\r\n // Check for block body { ... }\r\n peek = tokenizer.peek();\r\n if (peek.type === TokenType.OpenBrace) {\r\n tokenizer.next(); // consume '{'\r\n // Parse child nodes\r\n while (true) {\r\n peek = tokenizer.peek();\r\n if (peek.type === TokenType.CloseBrace || peek.type === TokenType.EOF) {\r\n break;\r\n }\r\n const child = parseNodeFromTokens(tokenizer);\r\n if (child) {\r\n children.push(child);\r\n } else {\r\n break;\r\n }\r\n }\r\n tokenizer.expect(TokenType.CloseBrace);\r\n }\r\n\r\n return { name, properties, children };\r\n}\r\n\r\nfunction parseArrayValues(tokenizer: Tokenizer, count: number): number[] {\r\n const values: number[] = [];\r\n while (true) {\r\n const peek = tokenizer.peek();\r\n if (peek.type === TokenType.CloseBrace || peek.type === TokenType.EOF) {\r\n break;\r\n }\r\n if (peek.type === TokenType.Comma) {\r\n tokenizer.next();\r\n continue;\r\n }\r\n if (peek.type === TokenType.Number) {\r\n const tok = tokenizer.next();\r\n values.push(Number(tok.value));\r\n } else {\r\n break;\r\n }\r\n }\r\n if (values.length !== count) {\r\n throw new Error(`ASCII FBX array declared ${count} values but parsed ${values.length}`);\r\n }\r\n return values;\r\n}\r\n\r\nfunction parseNumericValue(str: string): number {\r\n return Number(str);\r\n}\r\n\r\nfunction isInt32(value: number): boolean {\r\n return value >= -2147483648 && value <= 2147483647;\r\n}\r\n"]}
1
+ {"version":3,"file":"fbxAsciiParser.js","sourceRoot":"","sources":["../../../../../dev/loaders/src/FBX/parsers/fbxAsciiParser.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\nimport { type FBXDocument, type FBXNode, type FBXProperty } from \"../types/fbxTypes\";\n\n/**\n * Parse an ASCII FBX file into an FBXDocument.\n */\nexport function parseAsciiFBX(text: string): FBXDocument {\n const tokenizer = new Tokenizer(text);\n const version = parseVersion(text);\n const nodes: FBXNode[] = [];\n\n while (!tokenizer.isEOF()) {\n tokenizer.skipWhitespaceAndComments();\n if (tokenizer.isEOF()) {\n break;\n }\n const node = parseNodeFromTokens(tokenizer);\n if (node) {\n nodes.push(node);\n }\n }\n\n if (version >= 7200) {\n reinterpretKeyAttrDataFloat(nodes);\n }\n return { version, nodes };\n}\n\n/**\n * In ASCII files of version 7.2+, `KeyAttrDataFloat` holds the raw 32-bit float bit patterns written as integers\n * (some elements are genuinely integers). Reinterpret them so tangent data reads like the binary format.\n */\nfunction reinterpretKeyAttrDataFloat(nodes: FBXNode[]): void {\n for (const node of nodes) {\n if (node.name === \"KeyAttrDataFloat\" && node.properties.length === 1 && node.properties[0].value instanceof Float64Array) {\n const raw = node.properties[0].value;\n const bits = new Int32Array(raw.length);\n for (let i = 0; i < raw.length; i++) {\n bits[i] = raw[i] | 0;\n }\n node.properties[0] = { type: \"float32[]\", value: new Float32Array(bits.buffer) };\n }\n if (node.children.length > 0) {\n reinterpretKeyAttrDataFloat(node.children);\n }\n }\n}\n\n/** Extract FBX version from the header comment (e.g. \"; FBX 7.7.0 project file\") */\nfunction parseVersion(text: string): number {\n const match = text.match(/;\\s*FBX\\s+(\\d+)\\.(\\d+)\\.(\\d+)/);\n if (match) {\n return parseInt(match[1]) * 1000 + parseInt(match[2]) * 100 + parseInt(match[3]);\n }\n // Some files lack the header comment. The FBXHeaderExtension block carries the version too.\n const ext = text.match(/FBXVersion:\\s*(\\d+)/);\n if (ext) {\n return parseInt(ext[1]);\n }\n // Fall back to the layout heuristic: Properties70 blocks only exist in 7.x files.\n return text.includes(\"Properties70\") ? 7000 : 6000;\n}\n\n// ── Tokenizer ──────────────────────────────────────────────────────────────────\n\nconst enum TokenType {\n Identifier,\n Number,\n String,\n OpenBrace,\n CloseBrace,\n Colon,\n Comma,\n Star,\n EOF,\n}\n\ninterface Token {\n type: TokenType;\n value: string;\n pos: number;\n}\n\nclass Tokenizer {\n private pos = 0;\n private readonly len: number;\n\n constructor(private readonly text: string) {\n this.len = text.length;\n }\n\n isEOF(): boolean {\n this.skipWhitespaceAndComments();\n return this.pos >= this.len;\n }\n\n peek(): Token {\n const saved = this.pos;\n const tok = this.next();\n this.pos = saved;\n return tok;\n }\n\n next(): Token {\n this.skipWhitespaceAndComments();\n if (this.pos >= this.len) {\n return { type: TokenType.EOF, value: \"\", pos: this.pos };\n }\n\n const ch = this.text[this.pos];\n const startPos = this.pos;\n\n switch (ch) {\n case \"{\":\n this.pos++;\n return { type: TokenType.OpenBrace, value: \"{\", pos: startPos };\n case \"}\":\n this.pos++;\n return { type: TokenType.CloseBrace, value: \"}\", pos: startPos };\n case \":\":\n this.pos++;\n return { type: TokenType.Colon, value: \":\", pos: startPos };\n case \",\":\n this.pos++;\n return { type: TokenType.Comma, value: \",\", pos: startPos };\n case \"*\":\n this.pos++;\n return { type: TokenType.Star, value: \"*\", pos: startPos };\n case '\"':\n return this.readString();\n default:\n if (this.isNumberStart(ch)) {\n return this.readNumber();\n }\n if (this.isIdentStart(ch)) {\n return this.readIdentifier();\n }\n throw new Error(`Unexpected character '${ch}' at position ${this.pos}`);\n }\n }\n\n expect(type: TokenType): Token {\n const tok = this.next();\n if (tok.type !== type) {\n throw new Error(`Expected token type ${type} but got ${tok.type} ('${tok.value}') at pos ${tok.pos}`);\n }\n return tok;\n }\n\n /** Look ahead to see if the next identifier + colon is a child node start */\n isNextNodeStart(): boolean {\n const saved = this.pos;\n this.skipWhitespaceAndComments();\n // Read the identifier\n if (this.pos < this.len && this.isIdentStart(this.text[this.pos])) {\n while (this.pos < this.len && this.isIdentChar(this.text[this.pos])) {\n this.pos++;\n }\n // Skip whitespace between identifier and potential colon\n while (this.pos < this.len && (this.text[this.pos] === \" \" || this.text[this.pos] === \"\\t\")) {\n this.pos++;\n }\n const isNode = this.pos < this.len && this.text[this.pos] === \":\";\n this.pos = saved;\n return isNode;\n }\n this.pos = saved;\n return false;\n }\n\n skipWhitespaceAndComments(): void {\n while (this.pos < this.len) {\n const ch = this.text[this.pos];\n if (ch === \" \" || ch === \"\\t\" || ch === \"\\r\" || ch === \"\\n\") {\n this.pos++;\n } else if (ch === \";\") {\n // Skip comment to end of line\n while (this.pos < this.len && this.text[this.pos] !== \"\\n\") {\n this.pos++;\n }\n } else {\n break;\n }\n }\n }\n\n private readString(): Token {\n const startPos = this.pos;\n this.pos++; // skip opening quote\n let value = \"\";\n while (this.pos < this.len && this.text[this.pos] !== '\"') {\n if (this.text[this.pos] === \"\\\\\" && this.pos + 1 < this.len) {\n this.pos++;\n value += this.text[this.pos];\n } else {\n value += this.text[this.pos];\n }\n this.pos++;\n }\n if (this.pos < this.len) {\n this.pos++; // skip closing quote\n }\n // The SDK writes double quotes inside strings as &quot;\n if (value.includes(\"&quot;\")) {\n value = value.split(\"&quot;\").join('\"');\n }\n return { type: TokenType.String, value, pos: startPos };\n }\n\n private readNumber(): Token {\n const startPos = this.pos;\n // Handle leading sign\n if (this.text[this.pos] === \"-\" || this.text[this.pos] === \"+\") {\n this.pos++;\n }\n // Word-form specials: inf, infinity, nan, ind (any case), optionally signed, optionally with a\n // parenthesised payload such as nan(ind) or nan(12345).\n if (this.pos < this.len && this.isIdentStart(this.text[this.pos])) {\n while (this.pos < this.len && this.isIdentStart(this.text[this.pos])) {\n this.pos++;\n }\n this.skipSpecialNumberSuffix();\n return { type: TokenType.Number, value: this.text.substring(startPos, this.pos), pos: startPos };\n }\n while (this.pos < this.len && this.isDigit(this.text[this.pos])) {\n this.pos++;\n }\n if (this.pos < this.len && this.text[this.pos] === \".\") {\n this.pos++;\n while (this.pos < this.len && this.isDigit(this.text[this.pos])) {\n this.pos++;\n }\n }\n // Scientific notation\n if (this.pos < this.len && (this.text[this.pos] === \"e\" || this.text[this.pos] === \"E\")) {\n this.pos++;\n if (this.pos < this.len && (this.text[this.pos] === \"+\" || this.text[this.pos] === \"-\")) {\n this.pos++;\n }\n while (this.pos < this.len && this.isDigit(this.text[this.pos])) {\n this.pos++;\n }\n }\n // MSVC-style specials: 1.#INF, -1.#IND, 1.#QNAN, 1.#SNAN, 2.#IND12345678\n if (this.pos < this.len && this.text[this.pos] === \"#\") {\n this.pos++;\n while (this.pos < this.len && (this.isIdentStart(this.text[this.pos]) || this.isDigit(this.text[this.pos]))) {\n this.pos++;\n }\n this.skipSpecialNumberSuffix();\n }\n return { type: TokenType.Number, value: this.text.substring(startPos, this.pos), pos: startPos };\n }\n\n private readIdentifier(): Token {\n const startPos = this.pos;\n while (this.pos < this.len && this.isIdentChar(this.text[this.pos])) {\n this.pos++;\n }\n // Malformed special numbers such as \"snan(\" or \"Nan((\" lex as identifiers; swallow their parenthesised tail.\n this.skipSpecialNumberSuffix();\n return { type: TokenType.Identifier, value: this.text.substring(startPos, this.pos), pos: startPos };\n }\n\n /** Consumes a run of parentheses and alphanumerics that some writers append to nan/inf tokens. */\n private skipSpecialNumberSuffix(): void {\n if (this.pos < this.len && this.text[this.pos] === \"(\") {\n while (this.pos < this.len) {\n const ch = this.text[this.pos];\n if (ch === \"(\" || ch === \")\" || this.isIdentChar(ch)) {\n this.pos++;\n } else {\n break;\n }\n }\n }\n }\n\n private isDigit(ch: string): boolean {\n return ch >= \"0\" && ch <= \"9\";\n }\n\n private isNumberStart(ch: string): boolean {\n if (this.isDigit(ch) || ch === \".\") {\n return true;\n }\n if ((ch === \"-\" || ch === \"+\") && this.pos + 1 < this.len) {\n const next = this.text[this.pos + 1];\n return this.isDigit(next) || next === \".\" || isSpecialNumberWord(this.text.substring(this.pos + 1, this.pos + 10));\n }\n if (isSpecialNumberWord(this.text.substring(this.pos, this.pos + 9))) {\n // Bare inf/nan words in value position; identifiers followed by ':' are node names and never match.\n return !this.isFollowedByColon(this.pos);\n }\n return false;\n }\n\n private isFollowedByColon(from: number): boolean {\n let p = from;\n while (p < this.len && this.isIdentChar(this.text[p])) {\n p++;\n }\n while (p < this.len && (this.text[p] === \" \" || this.text[p] === \"\\t\")) {\n p++;\n }\n return p < this.len && this.text[p] === \":\";\n }\n\n private isIdentStart(ch: string): boolean {\n return (ch >= \"a\" && ch <= \"z\") || (ch >= \"A\" && ch <= \"Z\") || ch === \"_\";\n }\n\n private isIdentChar(ch: string): boolean {\n // '-' appears inside node names such as \"Pre-Extrapolation\" / \"Post-Extrapolation\".\n return this.isIdentStart(ch) || this.isDigit(ch) || ch === \"|\" || ch === \"-\";\n }\n}\n\n// ── Node Parsing ───────────────────────────────────────────────────────────────\n\nfunction parseNodeFromTokens(tokenizer: Tokenizer): FBXNode | null {\n const nameTok = tokenizer.peek();\n if (nameTok.type === TokenType.CloseBrace || nameTok.type === TokenType.EOF) {\n return null;\n }\n\n // Node name\n const identTok = tokenizer.next();\n if (identTok.type !== TokenType.Identifier) {\n throw new Error(`Expected identifier for node name, got '${identTok.value}' at pos ${identTok.pos}`);\n }\n const name = identTok.value;\n tokenizer.expect(TokenType.Colon);\n\n // Parse properties until we hit '{' or end-of-line content\n const properties: FBXProperty[] = [];\n const children: FBXNode[] = [];\n\n // Check for array shorthand: *count { a: ... }\n let peek = tokenizer.peek();\n if (peek.type === TokenType.Star) {\n // Array node like \"Vertices: *25959 {\"\n tokenizer.next(); // consume *\n const countTok = tokenizer.expect(TokenType.Number);\n const count = parseInt(countTok.value);\n tokenizer.expect(TokenType.OpenBrace);\n\n // Expect \"a:\" followed by comma-separated values\n const aTok = tokenizer.next();\n if (aTok.type === TokenType.Identifier && aTok.value === \"a\") {\n tokenizer.expect(TokenType.Colon);\n const values = parseArrayValues(tokenizer, count);\n properties.push({ type: \"float64[]\", value: new Float64Array(values) });\n }\n\n tokenizer.expect(TokenType.CloseBrace);\n return { name, properties, children };\n }\n\n // Parse inline properties (comma-separated values on the same logical line)\n // Values can be: numbers, strings, or bare identifiers (e.g. \"T\", \"Y\", \"CullingOff\")\n peek = tokenizer.peek();\n while (peek.type !== TokenType.OpenBrace && peek.type !== TokenType.CloseBrace && peek.type !== TokenType.EOF) {\n if (peek.type === TokenType.Number) {\n const tok = tokenizer.next();\n const numVal = parseNumericValue(tok.value);\n if (Number.isInteger(numVal) && !tok.value.includes(\".\") && !tok.value.includes(\"e\") && !tok.value.includes(\"E\")) {\n const property: FBXProperty = { type: isInt32(numVal) ? \"int32\" : \"int64\", value: numVal };\n if (!Number.isSafeInteger(numVal)) {\n property.raw = canonicalIntegerText(tok.value);\n }\n properties.push(property);\n } else {\n properties.push({ type: \"float64\", value: numVal });\n }\n } else if (peek.type === TokenType.String) {\n const tok = tokenizer.next();\n properties.push({ type: \"string\", value: tok.value });\n } else if (peek.type === TokenType.Identifier) {\n // Check if this is a property value or the start of a new child node.\n // If the next non-whitespace after the identifier is ':', it's a child node name — stop.\n if (tokenizer.isNextNodeStart()) {\n break;\n }\n // Bare identifier as a property value (e.g. \"T\", \"Y\", \"CullingOff\")\n const tok = tokenizer.next();\n properties.push({ type: \"string\", value: tok.value });\n } else if (peek.type === TokenType.Comma) {\n tokenizer.next(); // consume comma\n } else {\n break;\n }\n peek = tokenizer.peek();\n }\n\n // Check for block body { ... }\n peek = tokenizer.peek();\n if (peek.type === TokenType.OpenBrace) {\n tokenizer.next(); // consume '{'\n // Parse child nodes\n while (true) {\n peek = tokenizer.peek();\n if (peek.type === TokenType.CloseBrace || peek.type === TokenType.EOF) {\n break;\n }\n const child = parseNodeFromTokens(tokenizer);\n if (child) {\n children.push(child);\n } else {\n break;\n }\n }\n tokenizer.expect(TokenType.CloseBrace);\n }\n\n return { name, properties, children };\n}\n\nfunction parseArrayValues(tokenizer: Tokenizer, count: number): number[] {\n const values: number[] = [];\n while (true) {\n const peek = tokenizer.peek();\n if (peek.type === TokenType.CloseBrace || peek.type === TokenType.EOF) {\n break;\n }\n if (peek.type === TokenType.Comma) {\n tokenizer.next();\n continue;\n }\n if (peek.type === TokenType.Number) {\n const tok = tokenizer.next();\n values.push(parseNumericValue(tok.value));\n } else if (peek.type === TokenType.Identifier && !tokenizer.isNextNodeStart()) {\n // Unrecognised nan/inf spellings (\"snan\", \"infty\", \"ind\") still count as values.\n const tok = tokenizer.next();\n values.push(parseNumericValue(tok.value));\n } else {\n break;\n }\n }\n if (values.length !== count) {\n throw new Error(`ASCII FBX array declared ${count} values but parsed ${values.length}`);\n }\n return values;\n}\n\n/** Matches a leading inf/infinity/nan/ind word (case-insensitive) at the start of the string. */\nfunction isSpecialNumberWord(str: string): boolean {\n return /^(?:inf(?:inity)?|nan|ind)(?![A-Za-z0-9_|])/i.test(str);\n}\n\nfunction parseNumericValue(str: string): number {\n const n = Number(str);\n if (!Number.isNaN(n)) {\n return n;\n }\n // \"1.#INF\", \"-1.#IND\", \"1.#QNAN\", \"inf\", \"-Infinity\", \"nan\", \"nan(ind)\", \"infty\"\n const sign = str.startsWith(\"-\") ? -1 : 1;\n const body = str.replace(/^[+-]/, \"\").replace(/\\(.*$/, \"\");\n if (/#INF/i.test(body) || /^inf/i.test(body)) {\n return sign * Infinity;\n }\n return NaN;\n}\n\n/** Integer text without sign prefix noise or leading zeros, so equal values produce equal keys. */\nfunction canonicalIntegerText(text: string): string {\n const negative = text.startsWith(\"-\");\n const digits = text.replace(/^[+-]/, \"\").replace(/^0+(?=\\d)/, \"\");\n return negative && digits !== \"0\" ? `-${digits}` : digits;\n}\n\nfunction isInt32(value: number): boolean {\n return value >= -2147483648 && value <= 2147483647;\n}\n"]}
@@ -1,6 +1,9 @@
1
1
  import { inflateZlib } from "./zlibInflate.js";
2
2
  const FBX_MAGIC = "Kaydara FBX Binary \0";
3
- const HEADER_SIZE = 27; // 21 magic + 2 padding + 4 version uint32
3
+ const HEADER_SIZE = 27; // 21 magic + 1 (0x1A) + 1 endianness flag + 4 version uint32
4
+ // Byte order of the file being parsed. Big-endian FBX files exist (e.g. old Maya exports); the flag byte after the
5
+ // magic is non-zero for them. Parsing is synchronous so a module-level flag is safe.
6
+ let littleEndian = true;
4
7
  /**
5
8
  * Parse a binary FBX file into an FBXDocument.
6
9
  * Supports FBX versions 7.0–7.7 (v7.5+ uses 64-bit node headers).
@@ -8,6 +11,7 @@ const HEADER_SIZE = 27; // 21 magic + 2 padding + 4 version uint32
8
11
  export function parseBinaryFBX(buffer) {
9
12
  const view = new DataView(buffer);
10
13
  const bytes = new Uint8Array(buffer);
14
+ littleEndian = bytes.length > 22 ? bytes[22] === 0 : true;
11
15
  // Validate magic
12
16
  const magic = decodeASCII(bytes, 0, 21);
13
17
  if (magic !== FBX_MAGIC) {
@@ -16,7 +20,7 @@ export function parseBinaryFBX(buffer) {
16
20
  if (buffer.byteLength < HEADER_SIZE) {
17
21
  throw new Error("Truncated binary FBX header");
18
22
  }
19
- const version = view.getUint32(23, true);
23
+ const version = view.getUint32(23, littleEndian);
20
24
  // v7.5+ uses 64-bit offsets in node records
21
25
  const is64Bit = version >= 7500;
22
26
  const nodes = [];
@@ -46,9 +50,9 @@ function parseNode(view, bytes, offset, is64Bit, limit) {
46
50
  }
47
51
  else {
48
52
  ensureRange(bytes, offset, 13, limit, "FBX node header");
49
- endOffset = view.getUint32(offset, true);
50
- numProperties = view.getUint32(offset + 4, true);
51
- propertyListLen = view.getUint32(offset + 8, true);
53
+ endOffset = view.getUint32(offset, littleEndian);
54
+ numProperties = view.getUint32(offset + 4, littleEndian);
55
+ propertyListLen = view.getUint32(offset + 8, littleEndian);
52
56
  headerSize = 13; // 4+4+4+1 (nameLen byte)
53
57
  }
54
58
  // Null sentinel: all header fields are zero
@@ -103,45 +107,59 @@ function parseProperty(view, bytes, offset, limit) {
103
107
  offset += 1;
104
108
  switch (typeCode) {
105
109
  case "C": {
106
- // Boolean (1 byte)
110
+ // Boolean (1 byte). Legacy (pre-7000) files also use 'C' for bare characters such as key modes
111
+ // ('U', 's', 'n'); those are surfaced as small integers so consumers can read the character code.
107
112
  ensureRange(bytes, offset, 1, limit, "FBX boolean property");
108
- const value = bytes[offset] !== 0;
109
- return { property: { type: "boolean", value }, nextOffset: offset + 1 };
113
+ const byte = bytes[offset];
114
+ if (byte > 1) {
115
+ return { property: { type: "int32", value: byte }, nextOffset: offset + 1 };
116
+ }
117
+ return { property: { type: "boolean", value: byte !== 0 }, nextOffset: offset + 1 };
118
+ }
119
+ case "Z": {
120
+ // Single byte integer (rare, emitted by some exporters); ufbx reads it as an unsigned byte number.
121
+ ensureRange(bytes, offset, 1, limit, "FBX byte property");
122
+ const value = bytes[offset];
123
+ return { property: { type: "int32", value }, nextOffset: offset + 1 };
110
124
  }
111
125
  case "Y": {
112
126
  // Int16
113
127
  ensureRange(bytes, offset, 2, limit, "FBX int16 property");
114
- const value = view.getInt16(offset, true);
128
+ const value = view.getInt16(offset, littleEndian);
115
129
  return { property: { type: "int16", value }, nextOffset: offset + 2 };
116
130
  }
117
131
  case "I": {
118
132
  // Int32
119
133
  ensureRange(bytes, offset, 4, limit, "FBX int32 property");
120
- const value = view.getInt32(offset, true);
134
+ const value = view.getInt32(offset, littleEndian);
121
135
  return { property: { type: "int32", value }, nextOffset: offset + 4 };
122
136
  }
123
137
  case "F": {
124
138
  // Float32
125
139
  ensureRange(bytes, offset, 4, limit, "FBX float32 property");
126
- const value = view.getFloat32(offset, true);
140
+ const value = view.getFloat32(offset, littleEndian);
127
141
  return { property: { type: "float32", value }, nextOffset: offset + 4 };
128
142
  }
129
143
  case "D": {
130
144
  // Float64
131
145
  ensureRange(bytes, offset, 8, limit, "FBX float64 property");
132
- const value = view.getFloat64(offset, true);
146
+ const value = view.getFloat64(offset, littleEndian);
133
147
  return { property: { type: "float64", value }, nextOffset: offset + 8 };
134
148
  }
135
149
  case "L": {
136
150
  // Int64
137
151
  ensureRange(bytes, offset, 8, limit, "FBX int64 property");
138
152
  const value = readInt64AsNumber(view, offset);
139
- return { property: { type: "int64", value }, nextOffset: offset + 8 };
153
+ const property = { type: "int64", value };
154
+ if (!Number.isSafeInteger(value)) {
155
+ property.raw = int64ToDecimalString(view, offset);
156
+ }
157
+ return { property, nextOffset: offset + 8 };
140
158
  }
141
159
  case "S": {
142
160
  // String (uint32 length + data)
143
161
  ensureRange(bytes, offset, 4, limit, "FBX string property length");
144
- const len = view.getUint32(offset, true);
162
+ const len = view.getUint32(offset, littleEndian);
145
163
  ensureRange(bytes, offset + 4, len, limit, "FBX string property data");
146
164
  const value = decodeUTF8(bytes, offset + 4, len);
147
165
  return { property: { type: "string", value }, nextOffset: offset + 4 + len };
@@ -149,7 +167,7 @@ function parseProperty(view, bytes, offset, limit) {
149
167
  case "R": {
150
168
  // Raw binary data (uint32 length + data)
151
169
  ensureRange(bytes, offset, 4, limit, "FBX raw property length");
152
- const len = view.getUint32(offset, true);
170
+ const len = view.getUint32(offset, littleEndian);
153
171
  ensureRange(bytes, offset + 4, len, limit, "FBX raw property data");
154
172
  const value = bytes.slice(offset + 4, offset + 4 + len);
155
173
  return { property: { type: "raw", value }, nextOffset: offset + 4 + len };
@@ -165,15 +183,18 @@ function parseProperty(view, bytes, offset, limit) {
165
183
  return parseArrayProperty(view, bytes, offset, "int64[]", 8, limit);
166
184
  case "b":
167
185
  return parseArrayProperty(view, bytes, offset, "boolean[]", 1, limit);
186
+ case "c":
187
+ // Byte array (same layout as 'b'); consumers treat it as small integers.
188
+ return parseArrayProperty(view, bytes, offset, "boolean[]", 1, limit);
168
189
  default:
169
190
  throw new Error(`Unknown FBX property type: '${typeCode}' at offset ${offset - 1}`);
170
191
  }
171
192
  }
172
193
  function parseArrayProperty(view, bytes, offset, type, elementSize, limit) {
173
194
  ensureRange(bytes, offset, 12, limit, `FBX array property header for ${type}`);
174
- const arrayLength = view.getUint32(offset, true);
175
- const encoding = view.getUint32(offset + 4, true); // 0=raw, 1=zlib
176
- const compressedLength = view.getUint32(offset + 8, true);
195
+ const arrayLength = view.getUint32(offset, littleEndian);
196
+ const encoding = view.getUint32(offset + 4, littleEndian); // 0=raw, 1=zlib
197
+ const compressedLength = view.getUint32(offset + 8, littleEndian);
177
198
  offset += 12;
178
199
  const expectedByteLength = arrayLength * elementSize;
179
200
  ensureRange(bytes, offset, compressedLength, limit, `FBX array property data for ${type}`);
@@ -192,6 +213,9 @@ function parseArrayProperty(view, bytes, offset, type, elementSize, limit) {
192
213
  }
193
214
  arrayData = bytes.slice(offset, offset + compressedLength);
194
215
  }
216
+ if (!littleEndian && elementSize > 1 && type !== "int64[]") {
217
+ swapBytesInPlace(arrayData, elementSize);
218
+ }
195
219
  const arrayBuffer = arrayData.buffer.slice(arrayData.byteOffset, arrayData.byteOffset + arrayData.byteLength);
196
220
  let value;
197
221
  switch (type) {
@@ -223,16 +247,44 @@ function ensureRange(bytes, offset, byteLength, limit, context) {
223
247
  throw new Error(`${context}: unexpected end of input`);
224
248
  }
225
249
  }
250
+ function swapBytesInPlace(data, elementSize) {
251
+ for (let i = 0; i + elementSize <= data.length; i += elementSize) {
252
+ for (let a = i, b = i + elementSize - 1; a < b; a++, b--) {
253
+ const t = data[a];
254
+ data[a] = data[b];
255
+ data[b] = t;
256
+ }
257
+ }
258
+ }
226
259
  function readUint64AsNumber(view, offset) {
227
- const low = view.getUint32(offset, true);
228
- const high = view.getUint32(offset + 4, true);
260
+ const low = view.getUint32(littleEndian ? offset : offset + 4, littleEndian);
261
+ const high = view.getUint32(littleEndian ? offset + 4 : offset, littleEndian);
229
262
  return high * 0x100000000 + low;
230
263
  }
231
264
  function readInt64AsNumber(view, offset) {
232
- const low = view.getUint32(offset, true);
233
- const high = view.getInt32(offset + 4, true);
265
+ const low = view.getUint32(littleEndian ? offset : offset + 4, littleEndian);
266
+ const high = view.getInt32(littleEndian ? offset + 4 : offset, littleEndian);
234
267
  return high * 0x100000000 + low;
235
268
  }
269
+ /** Exact decimal text of a 64-bit two's complement integer, for values a double cannot represent. */
270
+ function int64ToDecimalString(view, offset) {
271
+ let low = view.getUint32(littleEndian ? offset : offset + 4, littleEndian);
272
+ let high = view.getUint32(littleEndian ? offset + 4 : offset, littleEndian);
273
+ const negative = (high & 0x80000000) !== 0;
274
+ if (negative) {
275
+ low = (~low + 1) >>> 0;
276
+ high = (~high + (low === 0 ? 1 : 0)) >>> 0;
277
+ }
278
+ const digits = [];
279
+ while (high !== 0 || low !== 0) {
280
+ const highQuotient = Math.floor(high / 10);
281
+ const carried = (high % 10) * 4294967296 + low;
282
+ digits.push(carried % 10);
283
+ high = highQuotient;
284
+ low = Math.floor(carried / 10);
285
+ }
286
+ return (negative ? "-" : "") + (digits.length > 0 ? digits.reverse().join("") : "0");
287
+ }
236
288
  function readInt64ArrayData(arrayData) {
237
289
  const view = new DataView(arrayData.buffer, arrayData.byteOffset, arrayData.byteLength);
238
290
  const values = new Float64Array(arrayData.byteLength / 8);
@@ -1 +1 @@
1
- {"version":3,"file":"fbxBinaryParser.js","sourceRoot":"","sources":["../../../../../dev/loaders/src/FBX/parsers/fbxBinaryParser.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\r\nimport { type FBXDocument, type FBXNode, type FBXProperty, type FBXPropertyType } from \"../types/fbxTypes\";\r\nimport { inflateZlib } from \"./zlibInflate\";\r\n\r\nconst FBX_MAGIC = \"Kaydara FBX Binary \\0\";\r\nconst HEADER_SIZE = 27; // 21 magic + 2 padding + 4 version uint32\r\n\r\n/**\r\n * Parse a binary FBX file into an FBXDocument.\r\n * Supports FBX versions 7.0–7.7 (v7.5+ uses 64-bit node headers).\r\n */\r\nexport function parseBinaryFBX(buffer: ArrayBuffer): FBXDocument {\r\n const view = new DataView(buffer);\r\n const bytes = new Uint8Array(buffer);\r\n\r\n // Validate magic\r\n const magic = decodeASCII(bytes, 0, 21);\r\n if (magic !== FBX_MAGIC) {\r\n throw new Error(\"Not a valid binary FBX file\");\r\n }\r\n if (buffer.byteLength < HEADER_SIZE) {\r\n throw new Error(\"Truncated binary FBX header\");\r\n }\r\n\r\n const version = view.getUint32(23, true);\r\n // v7.5+ uses 64-bit offsets in node records\r\n const is64Bit = version >= 7500;\r\n\r\n const nodes: FBXNode[] = [];\r\n let offset = HEADER_SIZE;\r\n\r\n while (offset < buffer.byteLength) {\r\n const result = parseNode(view, bytes, offset, is64Bit, buffer.byteLength);\r\n if (result === null) {\r\n break; // null sentinel node\r\n }\r\n nodes.push(result.node);\r\n offset = result.endOffset;\r\n }\r\n\r\n return { version, nodes };\r\n}\r\n\r\ninterface ParsedNode {\r\n node: FBXNode;\r\n endOffset: number;\r\n}\r\n\r\nfunction parseNode(view: DataView, bytes: Uint8Array, offset: number, is64Bit: boolean, limit: number): ParsedNode | null {\r\n // Read node header\r\n let endOffset: number;\r\n let numProperties: number;\r\n let propertyListLen: number;\r\n let headerSize: number;\r\n\r\n if (is64Bit) {\r\n ensureRange(bytes, offset, 25, limit, \"FBX node header\");\r\n endOffset = readUint64AsNumber(view, offset);\r\n numProperties = readUint64AsNumber(view, offset + 8);\r\n propertyListLen = readUint64AsNumber(view, offset + 16);\r\n headerSize = 25; // 8+8+8+1 (nameLen byte)\r\n } else {\r\n ensureRange(bytes, offset, 13, limit, \"FBX node header\");\r\n endOffset = view.getUint32(offset, true);\r\n numProperties = view.getUint32(offset + 4, true);\r\n propertyListLen = view.getUint32(offset + 8, true);\r\n headerSize = 13; // 4+4+4+1 (nameLen byte)\r\n }\r\n\r\n // Null sentinel: all header fields are zero\r\n if (endOffset === 0) {\r\n return null;\r\n }\r\n if (endOffset <= offset || endOffset > limit) {\r\n throw new Error(`Invalid FBX node end offset ${endOffset} at offset ${offset}`);\r\n }\r\n\r\n const nameLen = bytes[offset + headerSize - 1];\r\n ensureRange(bytes, offset + headerSize, nameLen, endOffset, \"FBX node name\");\r\n const name = decodeASCII(bytes, offset + headerSize, nameLen);\r\n\r\n let cursor = offset + headerSize + nameLen;\r\n const propertiesStart = cursor;\r\n const propertiesEnd = propertiesStart + propertyListLen;\r\n if (propertiesEnd > endOffset) {\r\n throw new Error(`Invalid FBX property list length for node '${name}' at offset ${offset}`);\r\n }\r\n\r\n // Parse properties\r\n const properties: FBXProperty[] = [];\r\n for (let i = 0; i < numProperties; i++) {\r\n const result = parseProperty(view, bytes, cursor, propertiesEnd);\r\n properties.push(result.property);\r\n cursor = result.nextOffset;\r\n }\r\n if (cursor !== propertiesEnd) {\r\n throw new Error(`Invalid FBX property list length for node '${name}' at offset ${offset}`);\r\n }\r\n\r\n // Parse nested child nodes (between end of properties and endOffset)\r\n const children: FBXNode[] = [];\r\n if (cursor < endOffset) {\r\n while (cursor < endOffset) {\r\n const child = parseNode(view, bytes, cursor, is64Bit, endOffset);\r\n if (child === null) {\r\n break;\r\n }\r\n if (child.endOffset <= cursor || child.endOffset > endOffset) {\r\n throw new Error(`Invalid FBX child node end offset ${child.endOffset} at offset ${cursor}`);\r\n }\r\n children.push(child.node);\r\n cursor = child.endOffset;\r\n }\r\n }\r\n\r\n return {\r\n node: { name, properties, children },\r\n endOffset,\r\n };\r\n}\r\n\r\ninterface ParsedProperty {\r\n property: FBXProperty;\r\n nextOffset: number;\r\n}\r\n\r\nfunction parseProperty(view: DataView, bytes: Uint8Array, offset: number, limit: number): ParsedProperty {\r\n ensureRange(bytes, offset, 1, limit, \"FBX property type\");\r\n const typeCode = String.fromCharCode(bytes[offset]);\r\n offset += 1;\r\n\r\n switch (typeCode) {\r\n case \"C\": {\r\n // Boolean (1 byte)\r\n ensureRange(bytes, offset, 1, limit, \"FBX boolean property\");\r\n const value = bytes[offset] !== 0;\r\n return { property: { type: \"boolean\", value }, nextOffset: offset + 1 };\r\n }\r\n case \"Y\": {\r\n // Int16\r\n ensureRange(bytes, offset, 2, limit, \"FBX int16 property\");\r\n const value = view.getInt16(offset, true);\r\n return { property: { type: \"int16\", value }, nextOffset: offset + 2 };\r\n }\r\n case \"I\": {\r\n // Int32\r\n ensureRange(bytes, offset, 4, limit, \"FBX int32 property\");\r\n const value = view.getInt32(offset, true);\r\n return { property: { type: \"int32\", value }, nextOffset: offset + 4 };\r\n }\r\n case \"F\": {\r\n // Float32\r\n ensureRange(bytes, offset, 4, limit, \"FBX float32 property\");\r\n const value = view.getFloat32(offset, true);\r\n return { property: { type: \"float32\", value }, nextOffset: offset + 4 };\r\n }\r\n case \"D\": {\r\n // Float64\r\n ensureRange(bytes, offset, 8, limit, \"FBX float64 property\");\r\n const value = view.getFloat64(offset, true);\r\n return { property: { type: \"float64\", value }, nextOffset: offset + 8 };\r\n }\r\n case \"L\": {\r\n // Int64\r\n ensureRange(bytes, offset, 8, limit, \"FBX int64 property\");\r\n const value = readInt64AsNumber(view, offset);\r\n return { property: { type: \"int64\", value }, nextOffset: offset + 8 };\r\n }\r\n case \"S\": {\r\n // String (uint32 length + data)\r\n ensureRange(bytes, offset, 4, limit, \"FBX string property length\");\r\n const len = view.getUint32(offset, true);\r\n ensureRange(bytes, offset + 4, len, limit, \"FBX string property data\");\r\n const value = decodeUTF8(bytes, offset + 4, len);\r\n return { property: { type: \"string\", value }, nextOffset: offset + 4 + len };\r\n }\r\n case \"R\": {\r\n // Raw binary data (uint32 length + data)\r\n ensureRange(bytes, offset, 4, limit, \"FBX raw property length\");\r\n const len = view.getUint32(offset, true);\r\n ensureRange(bytes, offset + 4, len, limit, \"FBX raw property data\");\r\n const value = bytes.slice(offset + 4, offset + 4 + len);\r\n return { property: { type: \"raw\", value }, nextOffset: offset + 4 + len };\r\n }\r\n // Array types\r\n case \"f\":\r\n return parseArrayProperty(view, bytes, offset, \"float32[]\", 4, limit);\r\n case \"d\":\r\n return parseArrayProperty(view, bytes, offset, \"float64[]\", 8, limit);\r\n case \"i\":\r\n return parseArrayProperty(view, bytes, offset, \"int32[]\", 4, limit);\r\n case \"l\":\r\n return parseArrayProperty(view, bytes, offset, \"int64[]\", 8, limit);\r\n case \"b\":\r\n return parseArrayProperty(view, bytes, offset, \"boolean[]\", 1, limit);\r\n default:\r\n throw new Error(`Unknown FBX property type: '${typeCode}' at offset ${offset - 1}`);\r\n }\r\n}\r\n\r\nfunction parseArrayProperty(view: DataView, bytes: Uint8Array, offset: number, type: FBXPropertyType, elementSize: number, limit: number): ParsedProperty {\r\n ensureRange(bytes, offset, 12, limit, `FBX array property header for ${type}`);\r\n const arrayLength = view.getUint32(offset, true);\r\n const encoding = view.getUint32(offset + 4, true); // 0=raw, 1=zlib\r\n const compressedLength = view.getUint32(offset + 8, true);\r\n offset += 12;\r\n const expectedByteLength = arrayLength * elementSize;\r\n ensureRange(bytes, offset, compressedLength, limit, `FBX array property data for ${type}`);\r\n\r\n let arrayData: Uint8Array;\r\n if (encoding === 1) {\r\n // zlib compressed\r\n const compressed = bytes.subarray(offset, offset + compressedLength);\r\n arrayData = inflateZlib(compressed, expectedByteLength);\r\n } else {\r\n if (encoding !== 0) {\r\n throw new Error(`Unsupported FBX array encoding: ${encoding}`);\r\n }\r\n if (compressedLength !== expectedByteLength) {\r\n throw new Error(`Invalid FBX array byte length for ${type}`);\r\n }\r\n arrayData = bytes.slice(offset, offset + compressedLength);\r\n }\r\n\r\n const arrayBuffer = arrayData.buffer.slice(arrayData.byteOffset, arrayData.byteOffset + arrayData.byteLength);\r\n\r\n let value: Float32Array | Float64Array | Int32Array | Uint8Array;\r\n switch (type) {\r\n case \"float32[]\":\r\n value = new Float32Array(arrayBuffer);\r\n break;\r\n case \"float64[]\":\r\n value = new Float64Array(arrayBuffer);\r\n break;\r\n case \"int32[]\":\r\n value = new Int32Array(arrayBuffer);\r\n break;\r\n case \"boolean[]\":\r\n value = arrayData;\r\n break;\r\n case \"int64[]\":\r\n value = readInt64ArrayData(arrayData);\r\n break;\r\n default:\r\n throw new Error(`Unexpected array type: ${type}`);\r\n }\r\n\r\n return {\r\n property: { type, value },\r\n nextOffset: offset + compressedLength,\r\n };\r\n}\r\n\r\nfunction ensureRange(bytes: Uint8Array, offset: number, byteLength: number, limit: number, context: string): void {\r\n if (offset < 0 || byteLength < 0 || offset + byteLength > limit || offset + byteLength > bytes.byteLength) {\r\n throw new Error(`${context}: unexpected end of input`);\r\n }\r\n}\r\n\r\nfunction readUint64AsNumber(view: DataView, offset: number): number {\r\n const low = view.getUint32(offset, true);\r\n const high = view.getUint32(offset + 4, true);\r\n return high * 0x100000000 + low;\r\n}\r\n\r\nfunction readInt64AsNumber(view: DataView, offset: number): number {\r\n const low = view.getUint32(offset, true);\r\n const high = view.getInt32(offset + 4, true);\r\n return high * 0x100000000 + low;\r\n}\r\n\r\nfunction readInt64ArrayData(arrayData: Uint8Array): Float64Array {\r\n const view = new DataView(arrayData.buffer, arrayData.byteOffset, arrayData.byteLength);\r\n const values = new Float64Array(arrayData.byteLength / 8);\r\n for (let i = 0; i < values.length; i++) {\r\n values[i] = readInt64AsNumber(view, i * 8);\r\n }\r\n return values;\r\n}\r\n\r\nfunction decodeASCII(bytes: Uint8Array, offset: number, length: number): string {\r\n let result = \"\";\r\n for (let i = 0; i < length; i++) {\r\n result += String.fromCharCode(bytes[offset + i]);\r\n }\r\n return result;\r\n}\r\n\r\nfunction decodeUTF8(bytes: Uint8Array, offset: number, length: number): string {\r\n const decoder = new TextDecoder(\"utf-8\");\r\n return decoder.decode(bytes.subarray(offset, offset + length));\r\n}\r\n"]}
1
+ {"version":3,"file":"fbxBinaryParser.js","sourceRoot":"","sources":["../../../../../dev/loaders/src/FBX/parsers/fbxBinaryParser.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\nimport { type FBXDocument, type FBXNode, type FBXProperty, type FBXPropertyType } from \"../types/fbxTypes\";\nimport { inflateZlib } from \"./zlibInflate\";\n\nconst FBX_MAGIC = \"Kaydara FBX Binary \\0\";\nconst HEADER_SIZE = 27; // 21 magic + 1 (0x1A) + 1 endianness flag + 4 version uint32\n\n// Byte order of the file being parsed. Big-endian FBX files exist (e.g. old Maya exports); the flag byte after the\n// magic is non-zero for them. Parsing is synchronous so a module-level flag is safe.\nlet littleEndian = true;\n\n/**\n * Parse a binary FBX file into an FBXDocument.\n * Supports FBX versions 7.0–7.7 (v7.5+ uses 64-bit node headers).\n */\nexport function parseBinaryFBX(buffer: ArrayBuffer): FBXDocument {\n const view = new DataView(buffer);\n const bytes = new Uint8Array(buffer);\n littleEndian = bytes.length > 22 ? bytes[22] === 0 : true;\n\n // Validate magic\n const magic = decodeASCII(bytes, 0, 21);\n if (magic !== FBX_MAGIC) {\n throw new Error(\"Not a valid binary FBX file\");\n }\n if (buffer.byteLength < HEADER_SIZE) {\n throw new Error(\"Truncated binary FBX header\");\n }\n\n const version = view.getUint32(23, littleEndian);\n // v7.5+ uses 64-bit offsets in node records\n const is64Bit = version >= 7500;\n\n const nodes: FBXNode[] = [];\n let offset = HEADER_SIZE;\n\n while (offset < buffer.byteLength) {\n const result = parseNode(view, bytes, offset, is64Bit, buffer.byteLength);\n if (result === null) {\n break; // null sentinel node\n }\n nodes.push(result.node);\n offset = result.endOffset;\n }\n\n return { version, nodes };\n}\n\ninterface ParsedNode {\n node: FBXNode;\n endOffset: number;\n}\n\nfunction parseNode(view: DataView, bytes: Uint8Array, offset: number, is64Bit: boolean, limit: number): ParsedNode | null {\n // Read node header\n let endOffset: number;\n let numProperties: number;\n let propertyListLen: number;\n let headerSize: number;\n\n if (is64Bit) {\n ensureRange(bytes, offset, 25, limit, \"FBX node header\");\n endOffset = readUint64AsNumber(view, offset);\n numProperties = readUint64AsNumber(view, offset + 8);\n propertyListLen = readUint64AsNumber(view, offset + 16);\n headerSize = 25; // 8+8+8+1 (nameLen byte)\n } else {\n ensureRange(bytes, offset, 13, limit, \"FBX node header\");\n endOffset = view.getUint32(offset, littleEndian);\n numProperties = view.getUint32(offset + 4, littleEndian);\n propertyListLen = view.getUint32(offset + 8, littleEndian);\n headerSize = 13; // 4+4+4+1 (nameLen byte)\n }\n\n // Null sentinel: all header fields are zero\n if (endOffset === 0) {\n return null;\n }\n if (endOffset <= offset || endOffset > limit) {\n throw new Error(`Invalid FBX node end offset ${endOffset} at offset ${offset}`);\n }\n\n const nameLen = bytes[offset + headerSize - 1];\n ensureRange(bytes, offset + headerSize, nameLen, endOffset, \"FBX node name\");\n const name = decodeASCII(bytes, offset + headerSize, nameLen);\n\n let cursor = offset + headerSize + nameLen;\n const propertiesStart = cursor;\n const propertiesEnd = propertiesStart + propertyListLen;\n if (propertiesEnd > endOffset) {\n throw new Error(`Invalid FBX property list length for node '${name}' at offset ${offset}`);\n }\n\n // Parse properties\n const properties: FBXProperty[] = [];\n for (let i = 0; i < numProperties; i++) {\n const result = parseProperty(view, bytes, cursor, propertiesEnd);\n properties.push(result.property);\n cursor = result.nextOffset;\n }\n if (cursor !== propertiesEnd) {\n throw new Error(`Invalid FBX property list length for node '${name}' at offset ${offset}`);\n }\n\n // Parse nested child nodes (between end of properties and endOffset)\n const children: FBXNode[] = [];\n if (cursor < endOffset) {\n while (cursor < endOffset) {\n const child = parseNode(view, bytes, cursor, is64Bit, endOffset);\n if (child === null) {\n break;\n }\n if (child.endOffset <= cursor || child.endOffset > endOffset) {\n throw new Error(`Invalid FBX child node end offset ${child.endOffset} at offset ${cursor}`);\n }\n children.push(child.node);\n cursor = child.endOffset;\n }\n }\n\n return {\n node: { name, properties, children },\n endOffset,\n };\n}\n\ninterface ParsedProperty {\n property: FBXProperty;\n nextOffset: number;\n}\n\nfunction parseProperty(view: DataView, bytes: Uint8Array, offset: number, limit: number): ParsedProperty {\n ensureRange(bytes, offset, 1, limit, \"FBX property type\");\n const typeCode = String.fromCharCode(bytes[offset]);\n offset += 1;\n\n switch (typeCode) {\n case \"C\": {\n // Boolean (1 byte). Legacy (pre-7000) files also use 'C' for bare characters such as key modes\n // ('U', 's', 'n'); those are surfaced as small integers so consumers can read the character code.\n ensureRange(bytes, offset, 1, limit, \"FBX boolean property\");\n const byte = bytes[offset];\n if (byte > 1) {\n return { property: { type: \"int32\", value: byte }, nextOffset: offset + 1 };\n }\n return { property: { type: \"boolean\", value: byte !== 0 }, nextOffset: offset + 1 };\n }\n case \"Z\": {\n // Single byte integer (rare, emitted by some exporters); ufbx reads it as an unsigned byte number.\n ensureRange(bytes, offset, 1, limit, \"FBX byte property\");\n const value = bytes[offset];\n return { property: { type: \"int32\", value }, nextOffset: offset + 1 };\n }\n case \"Y\": {\n // Int16\n ensureRange(bytes, offset, 2, limit, \"FBX int16 property\");\n const value = view.getInt16(offset, littleEndian);\n return { property: { type: \"int16\", value }, nextOffset: offset + 2 };\n }\n case \"I\": {\n // Int32\n ensureRange(bytes, offset, 4, limit, \"FBX int32 property\");\n const value = view.getInt32(offset, littleEndian);\n return { property: { type: \"int32\", value }, nextOffset: offset + 4 };\n }\n case \"F\": {\n // Float32\n ensureRange(bytes, offset, 4, limit, \"FBX float32 property\");\n const value = view.getFloat32(offset, littleEndian);\n return { property: { type: \"float32\", value }, nextOffset: offset + 4 };\n }\n case \"D\": {\n // Float64\n ensureRange(bytes, offset, 8, limit, \"FBX float64 property\");\n const value = view.getFloat64(offset, littleEndian);\n return { property: { type: \"float64\", value }, nextOffset: offset + 8 };\n }\n case \"L\": {\n // Int64\n ensureRange(bytes, offset, 8, limit, \"FBX int64 property\");\n const value = readInt64AsNumber(view, offset);\n const property: FBXProperty = { type: \"int64\", value };\n if (!Number.isSafeInteger(value)) {\n property.raw = int64ToDecimalString(view, offset);\n }\n return { property, nextOffset: offset + 8 };\n }\n case \"S\": {\n // String (uint32 length + data)\n ensureRange(bytes, offset, 4, limit, \"FBX string property length\");\n const len = view.getUint32(offset, littleEndian);\n ensureRange(bytes, offset + 4, len, limit, \"FBX string property data\");\n const value = decodeUTF8(bytes, offset + 4, len);\n return { property: { type: \"string\", value }, nextOffset: offset + 4 + len };\n }\n case \"R\": {\n // Raw binary data (uint32 length + data)\n ensureRange(bytes, offset, 4, limit, \"FBX raw property length\");\n const len = view.getUint32(offset, littleEndian);\n ensureRange(bytes, offset + 4, len, limit, \"FBX raw property data\");\n const value = bytes.slice(offset + 4, offset + 4 + len);\n return { property: { type: \"raw\", value }, nextOffset: offset + 4 + len };\n }\n // Array types\n case \"f\":\n return parseArrayProperty(view, bytes, offset, \"float32[]\", 4, limit);\n case \"d\":\n return parseArrayProperty(view, bytes, offset, \"float64[]\", 8, limit);\n case \"i\":\n return parseArrayProperty(view, bytes, offset, \"int32[]\", 4, limit);\n case \"l\":\n return parseArrayProperty(view, bytes, offset, \"int64[]\", 8, limit);\n case \"b\":\n return parseArrayProperty(view, bytes, offset, \"boolean[]\", 1, limit);\n case \"c\":\n // Byte array (same layout as 'b'); consumers treat it as small integers.\n return parseArrayProperty(view, bytes, offset, \"boolean[]\", 1, limit);\n default:\n throw new Error(`Unknown FBX property type: '${typeCode}' at offset ${offset - 1}`);\n }\n}\n\nfunction parseArrayProperty(view: DataView, bytes: Uint8Array, offset: number, type: FBXPropertyType, elementSize: number, limit: number): ParsedProperty {\n ensureRange(bytes, offset, 12, limit, `FBX array property header for ${type}`);\n const arrayLength = view.getUint32(offset, littleEndian);\n const encoding = view.getUint32(offset + 4, littleEndian); // 0=raw, 1=zlib\n const compressedLength = view.getUint32(offset + 8, littleEndian);\n offset += 12;\n const expectedByteLength = arrayLength * elementSize;\n ensureRange(bytes, offset, compressedLength, limit, `FBX array property data for ${type}`);\n\n let arrayData: Uint8Array;\n if (encoding === 1) {\n // zlib compressed\n const compressed = bytes.subarray(offset, offset + compressedLength);\n arrayData = inflateZlib(compressed, expectedByteLength);\n } else {\n if (encoding !== 0) {\n throw new Error(`Unsupported FBX array encoding: ${encoding}`);\n }\n if (compressedLength !== expectedByteLength) {\n throw new Error(`Invalid FBX array byte length for ${type}`);\n }\n arrayData = bytes.slice(offset, offset + compressedLength);\n }\n\n if (!littleEndian && elementSize > 1 && type !== \"int64[]\") {\n swapBytesInPlace(arrayData, elementSize);\n }\n const arrayBuffer = arrayData.buffer.slice(arrayData.byteOffset, arrayData.byteOffset + arrayData.byteLength);\n\n let value: Float32Array | Float64Array | Int32Array | Uint8Array;\n switch (type) {\n case \"float32[]\":\n value = new Float32Array(arrayBuffer);\n break;\n case \"float64[]\":\n value = new Float64Array(arrayBuffer);\n break;\n case \"int32[]\":\n value = new Int32Array(arrayBuffer);\n break;\n case \"boolean[]\":\n value = arrayData;\n break;\n case \"int64[]\":\n value = readInt64ArrayData(arrayData);\n break;\n default:\n throw new Error(`Unexpected array type: ${type}`);\n }\n\n return {\n property: { type, value },\n nextOffset: offset + compressedLength,\n };\n}\n\nfunction ensureRange(bytes: Uint8Array, offset: number, byteLength: number, limit: number, context: string): void {\n if (offset < 0 || byteLength < 0 || offset + byteLength > limit || offset + byteLength > bytes.byteLength) {\n throw new Error(`${context}: unexpected end of input`);\n }\n}\n\nfunction swapBytesInPlace(data: Uint8Array, elementSize: number): void {\n for (let i = 0; i + elementSize <= data.length; i += elementSize) {\n for (let a = i, b = i + elementSize - 1; a < b; a++, b--) {\n const t = data[a];\n data[a] = data[b];\n data[b] = t;\n }\n }\n}\n\nfunction readUint64AsNumber(view: DataView, offset: number): number {\n const low = view.getUint32(littleEndian ? offset : offset + 4, littleEndian);\n const high = view.getUint32(littleEndian ? offset + 4 : offset, littleEndian);\n return high * 0x100000000 + low;\n}\n\nfunction readInt64AsNumber(view: DataView, offset: number): number {\n const low = view.getUint32(littleEndian ? offset : offset + 4, littleEndian);\n const high = view.getInt32(littleEndian ? offset + 4 : offset, littleEndian);\n return high * 0x100000000 + low;\n}\n\n/** Exact decimal text of a 64-bit two's complement integer, for values a double cannot represent. */\nfunction int64ToDecimalString(view: DataView, offset: number): string {\n let low = view.getUint32(littleEndian ? offset : offset + 4, littleEndian);\n let high = view.getUint32(littleEndian ? offset + 4 : offset, littleEndian);\n const negative = (high & 0x80000000) !== 0;\n if (negative) {\n low = (~low + 1) >>> 0;\n high = (~high + (low === 0 ? 1 : 0)) >>> 0;\n }\n const digits: number[] = [];\n while (high !== 0 || low !== 0) {\n const highQuotient = Math.floor(high / 10);\n const carried = (high % 10) * 4294967296 + low;\n digits.push(carried % 10);\n high = highQuotient;\n low = Math.floor(carried / 10);\n }\n return (negative ? \"-\" : \"\") + (digits.length > 0 ? digits.reverse().join(\"\") : \"0\");\n}\n\nfunction readInt64ArrayData(arrayData: Uint8Array): Float64Array {\n const view = new DataView(arrayData.buffer, arrayData.byteOffset, arrayData.byteLength);\n const values = new Float64Array(arrayData.byteLength / 8);\n for (let i = 0; i < values.length; i++) {\n values[i] = readInt64AsNumber(view, i * 8);\n }\n return values;\n}\n\nfunction decodeASCII(bytes: Uint8Array, offset: number, length: number): string {\n let result = \"\";\n for (let i = 0; i < length; i++) {\n result += String.fromCharCode(bytes[offset + i]);\n }\n return result;\n}\n\nfunction decodeUTF8(bytes: Uint8Array, offset: number, length: number): string {\n const decoder = new TextDecoder(\"utf-8\");\n return decoder.decode(bytes.subarray(offset, offset + length));\n}\n"]}
package/FBX/pure.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  /** Pure barrel — re-exports only side-effect-free modules */
2
2
  export { FBXFileLoader } from "./fbxFileLoader.pure.js";
3
3
  export { FBXFileLoaderMetadata } from "./fbxFileLoader.metadata.js";
4
+ export { FBXConstraintBehavior, FBXConstraintSolver } from "./fbxConstraintBehavior.js";
package/FBX/pure.js CHANGED
@@ -1,4 +1,5 @@
1
1
  /** Pure barrel — re-exports only side-effect-free modules */
2
2
  export { FBXFileLoader } from "./fbxFileLoader.pure.js";
3
3
  export { FBXFileLoaderMetadata } from "./fbxFileLoader.metadata.js";
4
+ export { FBXConstraintBehavior, FBXConstraintSolver } from "./fbxConstraintBehavior.js";
4
5
  //# sourceMappingURL=pure.js.map
package/FBX/pure.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"pure.js","sourceRoot":"","sources":["../../../../dev/loaders/src/FBX/pure.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC","sourcesContent":["/** Pure barrel — re-exports only side-effect-free modules */\nexport { FBXFileLoader } from \"./fbxFileLoader.pure\";\nexport { FBXFileLoaderMetadata } from \"./fbxFileLoader.metadata\";\n"]}
1
+ {"version":3,"file":"pure.js","sourceRoot":"","sources":["../../../../dev/loaders/src/FBX/pure.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC","sourcesContent":["/** Pure barrel — re-exports only side-effect-free modules */\nexport { FBXFileLoader } from \"./fbxFileLoader.pure\";\nexport { FBXFileLoaderMetadata } from \"./fbxFileLoader.metadata\";\nexport { FBXConstraintBehavior, FBXConstraintSolver } from \"./fbxConstraintBehavior\";\n"]}
@@ -12,6 +12,11 @@ export interface FBXProperty {
12
12
  type: FBXPropertyType;
13
13
  /** Parsed property value. */
14
14
  value: FBXPropertyValue;
15
+ /**
16
+ * Exact decimal text of an int64 whose magnitude exceeds 2^53; `value` then holds the rounded double. Object
17
+ * ids are the only int64 values where the last bits matter, and `resolveConnections` keys them by this text.
18
+ */
19
+ raw?: string;
15
20
  }
16
21
  /** A node in the FBX document tree */
17
22
  export interface FBXNode {
@@ -38,11 +43,22 @@ export declare function findDocumentNode(doc: FBXDocument, name: string): FBXNod
38
43
  /** Extract a property value by index, with type narrowing */
39
44
  export declare function getPropertyValue<T extends FBXPropertyValue>(node: FBXNode, index: number): T | undefined;
40
45
  /**
41
- * Converts an FBX object ID value to a safe JavaScript number.
46
+ * Validates an FBX object ID value: IDs are 64-bit integers, so anything non-numeric, non-finite or fractional is
47
+ * rejected. IDs beyond 2^53 are carried losslessly through the property's `raw` text by `resolveConnections`.
42
48
  * @param value - Parsed FBX object ID value
43
- * @returns The object ID, or undefined when the value is not numeric
49
+ * @returns The object ID, or undefined when the value cannot be an ID
44
50
  */
45
51
  export declare function getSafeFBXObjectId(value: unknown): number | undefined;
52
+ /** Typed array payload types produced by the parsers. */
53
+ export type FBXArrayValue = Float32Array | Float64Array | Int32Array | Uint8Array;
54
+ /**
55
+ * Returns the array payload of a node.
56
+ * 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
57
+ * scalar properties, and a one-element array degenerates to a single scalar. All of these are coalesced here.
58
+ * @param node - Node whose properties hold the array
59
+ * @returns The array, or null when the node has no numeric payload
60
+ */
61
+ export declare function getNodeArray(node: FBXNode | undefined | null): FBXArrayValue | null;
46
62
  /** Get the numeric ID from a node (first property is typically the int64 UID) */
47
63
  export declare function getNodeId(node: FBXNode): number | undefined;
48
64
  /**
@@ -23,19 +23,47 @@ export function getPropertyValue(node, index) {
23
23
  return undefined;
24
24
  }
25
25
  /**
26
- * Converts an FBX object ID value to a safe JavaScript number.
26
+ * Validates an FBX object ID value: IDs are 64-bit integers, so anything non-numeric, non-finite or fractional is
27
+ * rejected. IDs beyond 2^53 are carried losslessly through the property's `raw` text by `resolveConnections`.
27
28
  * @param value - Parsed FBX object ID value
28
- * @returns The object ID, or undefined when the value is not numeric
29
+ * @returns The object ID, or undefined when the value cannot be an ID
29
30
  */
30
31
  export function getSafeFBXObjectId(value) {
31
- if (typeof value !== "number") {
32
+ if (typeof value !== "number" || !Number.isFinite(value) || !Number.isInteger(value)) {
32
33
  return undefined;
33
34
  }
34
- if (!Number.isSafeInteger(value)) {
35
- throw new Error(`Unsafe FBX object ID ${value.toString()}: object IDs must be safe integers.`);
36
- }
37
35
  return value;
38
36
  }
37
+ /**
38
+ * Returns the array payload of a node.
39
+ * 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
40
+ * scalar properties, and a one-element array degenerates to a single scalar. All of these are coalesced here.
41
+ * @param node - Node whose properties hold the array
42
+ * @returns The array, or null when the node has no numeric payload
43
+ */
44
+ export function getNodeArray(node) {
45
+ if (!node || node.properties.length === 0) {
46
+ return null;
47
+ }
48
+ const first = node.properties[0].value;
49
+ if (node.properties.length === 1 && (first instanceof Float32Array || first instanceof Float64Array || first instanceof Int32Array || first instanceof Uint8Array)) {
50
+ return first;
51
+ }
52
+ const out = new Float64Array(node.properties.length);
53
+ for (let i = 0; i < node.properties.length; i++) {
54
+ const v = node.properties[i].value;
55
+ if (typeof v === "number") {
56
+ out[i] = v;
57
+ }
58
+ else if (typeof v === "boolean") {
59
+ out[i] = v ? 1 : 0;
60
+ }
61
+ else {
62
+ return null;
63
+ }
64
+ }
65
+ return out;
66
+ }
39
67
  /** Get the numeric ID from a node (first property is typically the int64 UID) */
40
68
  export function getNodeId(node) {
41
69
  const prop = node.properties[0];
@@ -51,15 +79,15 @@ export function getNodeId(node) {
51
79
  * - A binary null/control-character class suffix — strip it
52
80
  */
53
81
  export function cleanFBXName(fbxName) {
54
- // Strip \x00\x01 suffix (binary FBX name/class separator)
55
- const nullIdx = fbxName.indexOf("\0");
56
- if (nullIdx >= 0) {
57
- fbxName = fbxName.substring(0, nullIdx);
82
+ // Binary FBX: "Name\x00\x01Class" — the name is everything before the separator and may itself contain "::".
83
+ const sepIdx = fbxName.indexOf("\0\x01");
84
+ if (sepIdx >= 0) {
85
+ return fbxName.substring(0, sepIdx);
58
86
  }
59
- // Strip "ClassName::" prefix (ASCII FBX)
87
+ // ASCII FBX: "Class::Name" — strip only the leading class prefix ("Model::Cube::Model" -> "Cube::Model").
60
88
  const colonIdx = fbxName.indexOf("::");
61
89
  if (colonIdx >= 0) {
62
- fbxName = fbxName.substring(colonIdx + 2);
90
+ return fbxName.substring(colonIdx + 2);
63
91
  }
64
92
  return fbxName;
65
93
  }