@babylonjs/loaders 9.26.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.
- package/FBX/fbxConstraintBehavior.d.ts +188 -0
- package/FBX/fbxConstraintBehavior.js +532 -0
- package/FBX/fbxConstraintBehavior.js.map +1 -0
- package/FBX/fbxFileLoader.pure.d.ts +175 -6
- package/FBX/fbxFileLoader.pure.js +1521 -286
- package/FBX/fbxFileLoader.pure.js.map +1 -1
- package/FBX/index.d.ts +4 -1
- package/FBX/index.js +1 -0
- package/FBX/index.js.map +1 -1
- package/FBX/interpreter/animation.d.ts +73 -33
- package/FBX/interpreter/animation.js +620 -223
- package/FBX/interpreter/animation.js.map +1 -1
- package/FBX/interpreter/animationCurve.d.ts +91 -0
- package/FBX/interpreter/animationCurve.js +623 -0
- package/FBX/interpreter/animationCurve.js.map +1 -0
- package/FBX/interpreter/blendShapes.js +9 -18
- package/FBX/interpreter/blendShapes.js.map +1 -1
- package/FBX/interpreter/connections.d.ts +1 -1
- package/FBX/interpreter/connections.js +173 -34
- package/FBX/interpreter/connections.js.map +1 -1
- package/FBX/interpreter/constraints.d.ts +68 -0
- package/FBX/interpreter/constraints.js +143 -0
- package/FBX/interpreter/constraints.js.map +1 -0
- package/FBX/interpreter/fbxInterpreter.d.ts +89 -4
- package/FBX/interpreter/fbxInterpreter.js +474 -122
- package/FBX/interpreter/fbxInterpreter.js.map +1 -1
- package/FBX/interpreter/geometry.d.ts +1 -1
- package/FBX/interpreter/geometry.js +150 -92
- package/FBX/interpreter/geometry.js.map +1 -1
- package/FBX/interpreter/legacyDocument.d.ts +11 -0
- package/FBX/interpreter/legacyDocument.js +425 -0
- package/FBX/interpreter/legacyDocument.js.map +1 -0
- package/FBX/interpreter/materialModel.d.ts +71 -0
- package/FBX/interpreter/materialModel.js +622 -0
- package/FBX/interpreter/materialModel.js.map +1 -0
- package/FBX/interpreter/materials.d.ts +13 -1
- package/FBX/interpreter/materials.js +88 -5
- package/FBX/interpreter/materials.js.map +1 -1
- package/FBX/interpreter/nodeTransform.d.ts +32 -0
- package/FBX/interpreter/nodeTransform.js +54 -0
- package/FBX/interpreter/nodeTransform.js.map +1 -0
- package/FBX/interpreter/nurbs.d.ts +99 -0
- package/FBX/interpreter/nurbs.js +627 -0
- package/FBX/interpreter/nurbs.js.map +1 -0
- package/FBX/interpreter/propertyTemplates.d.ts +23 -0
- package/FBX/interpreter/propertyTemplates.js +109 -2
- package/FBX/interpreter/propertyTemplates.js.map +1 -1
- package/FBX/interpreter/rig.js +16 -0
- package/FBX/interpreter/rig.js.map +1 -1
- package/FBX/interpreter/sceneDiagnostics.js +28 -3
- package/FBX/interpreter/sceneDiagnostics.js.map +1 -1
- package/FBX/interpreter/skeleton.d.ts +4 -18
- package/FBX/interpreter/skeleton.js +16 -94
- package/FBX/interpreter/skeleton.js.map +1 -1
- package/FBX/parsers/fbxAsciiParser.js +119 -9
- package/FBX/parsers/fbxAsciiParser.js.map +1 -1
- package/FBX/parsers/fbxBinaryParser.js +74 -22
- package/FBX/parsers/fbxBinaryParser.js.map +1 -1
- package/FBX/pure.d.ts +1 -0
- package/FBX/pure.js +1 -0
- package/FBX/pure.js.map +1 -1
- package/FBX/types/fbxTypes.d.ts +18 -2
- package/FBX/types/fbxTypes.js +40 -12
- package/FBX/types/fbxTypes.js.map +1 -1
- package/USD/usdCommandProtocol.d.ts +20 -4
- package/USD/usdCommandProtocol.js +25 -3
- package/USD/usdCommandProtocol.js.map +1 -1
- package/USD/usdFileLoader.pure.js +2 -0
- package/USD/usdFileLoader.pure.js.map +1 -1
- package/USD/usdSceneMaterializer.js +430 -92
- package/USD/usdSceneMaterializer.js.map +1 -1
- package/package.json +3 -3
|
@@ -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 "\n if (value.includes(\""\")) {\n value = value.split(\""\").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 +
|
|
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,
|
|
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,
|
|
50
|
-
numProperties = view.getUint32(offset + 4,
|
|
51
|
-
propertyListLen = view.getUint32(offset + 8,
|
|
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
|
|
109
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
175
|
-
const encoding = view.getUint32(offset + 4,
|
|
176
|
-
const compressedLength = view.getUint32(offset + 8,
|
|
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,
|
|
228
|
-
const high = view.getUint32(offset + 4,
|
|
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,
|
|
233
|
-
const high = view.getInt32(offset + 4,
|
|
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":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,SAAS,GAAG,wBAAwB,CAAC;AAC3C,MAAM,WAAW,GAAG,EAAE,CAAC,CAAC,6DAA6D;AAErF,mHAAmH;AACnH,qFAAqF;AACrF,IAAI,YAAY,GAAG,IAAI,CAAC;AAExB;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,MAAmB;IAC9C,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IACrC,YAAY,GAAG,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE1D,iBAAiB;IACjB,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACxC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,MAAM,CAAC,UAAU,GAAG,WAAW,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;IACjD,4CAA4C;IAC5C,MAAM,OAAO,GAAG,OAAO,IAAI,IAAI,CAAC;IAEhC,MAAM,KAAK,GAAc,EAAE,CAAC;IAC5B,IAAI,MAAM,GAAG,WAAW,CAAC;IAEzB,OAAO,MAAM,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QAC1E,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YAClB,MAAM,CAAC,qBAAqB;QAChC,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACxB,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC;IAC9B,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC9B,CAAC;AAOD,SAAS,SAAS,CAAC,IAAc,EAAE,KAAiB,EAAE,MAAc,EAAE,OAAgB,EAAE,KAAa;IACjG,mBAAmB;IACnB,IAAI,SAAiB,CAAC;IACtB,IAAI,aAAqB,CAAC;IAC1B,IAAI,eAAuB,CAAC;IAC5B,IAAI,UAAkB,CAAC;IAEvB,IAAI,OAAO,EAAE,CAAC;QACV,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC;QACzD,SAAS,GAAG,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC7C,aAAa,GAAG,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC;QACrD,eAAe,GAAG,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC;QACxD,UAAU,GAAG,EAAE,CAAC,CAAC,yBAAyB;IAC9C,CAAC;SAAM,CAAC;QACJ,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC;QACzD,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QACjD,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,YAAY,CAAC,CAAC;QACzD,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,YAAY,CAAC,CAAC;QAC3D,UAAU,GAAG,EAAE,CAAC,CAAC,yBAAyB;IAC9C,CAAC;IAED,4CAA4C;IAC5C,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,SAAS,IAAI,MAAM,IAAI,SAAS,GAAG,KAAK,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,+BAA+B,SAAS,cAAc,MAAM,EAAE,CAAC,CAAC;IACpF,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC;IAC/C,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;IAC7E,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE,OAAO,CAAC,CAAC;IAE9D,IAAI,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;IAC3C,MAAM,eAAe,GAAG,MAAM,CAAC;IAC/B,MAAM,aAAa,GAAG,eAAe,GAAG,eAAe,CAAC;IACxD,IAAI,aAAa,GAAG,SAAS,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,8CAA8C,IAAI,eAAe,MAAM,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,mBAAmB;IACnB,MAAM,UAAU,GAAkB,EAAE,CAAC;IACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;QACjE,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACjC,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC;IAC/B,CAAC;IACD,IAAI,MAAM,KAAK,aAAa,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,8CAA8C,IAAI,eAAe,MAAM,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,qEAAqE;IACrE,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,IAAI,MAAM,GAAG,SAAS,EAAE,CAAC;QACrB,OAAO,MAAM,GAAG,SAAS,EAAE,CAAC;YACxB,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;YACjE,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACjB,MAAM;YACV,CAAC;YACD,IAAI,KAAK,CAAC,SAAS,IAAI,MAAM,IAAI,KAAK,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;gBAC3D,MAAM,IAAI,KAAK,CAAC,qCAAqC,KAAK,CAAC,SAAS,cAAc,MAAM,EAAE,CAAC,CAAC;YAChG,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC1B,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC;QAC7B,CAAC;IACL,CAAC;IAED,OAAO;QACH,IAAI,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE;QACpC,SAAS;KACZ,CAAC;AACN,CAAC;AAOD,SAAS,aAAa,CAAC,IAAc,EAAE,KAAiB,EAAE,MAAc,EAAE,KAAa;IACnF,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,mBAAmB,CAAC,CAAC;IAC1D,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACpD,MAAM,IAAI,CAAC,CAAC;IAEZ,QAAQ,QAAQ,EAAE,CAAC;QACf,KAAK,GAAG,CAAC,CAAC,CAAC;YACP,+FAA+F;YAC/F,kGAAkG;YAClG,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,sBAAsB,CAAC,CAAC;YAC7D,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;YAC3B,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;gBACX,OAAO,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;YAChF,CAAC;YACD,OAAO,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,KAAK,CAAC,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;QACxF,CAAC;QACD,KAAK,GAAG,CAAC,CAAC,CAAC;YACP,mGAAmG;YACnG,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,mBAAmB,CAAC,CAAC;YAC1D,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;YAC5B,OAAO,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1E,CAAC;QACD,KAAK,GAAG,CAAC,CAAC,CAAC;YACP,QAAQ;YACR,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,oBAAoB,CAAC,CAAC;YAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YAClD,OAAO,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1E,CAAC;QACD,KAAK,GAAG,CAAC,CAAC,CAAC;YACP,QAAQ;YACR,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,oBAAoB,CAAC,CAAC;YAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YAClD,OAAO,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1E,CAAC;QACD,KAAK,GAAG,CAAC,CAAC,CAAC;YACP,UAAU;YACV,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,sBAAsB,CAAC,CAAC;YAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YACpD,OAAO,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5E,CAAC;QACD,KAAK,GAAG,CAAC,CAAC,CAAC;YACP,UAAU;YACV,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,sBAAsB,CAAC,CAAC;YAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YACpD,OAAO,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5E,CAAC;QACD,KAAK,GAAG,CAAC,CAAC,CAAC;YACP,QAAQ;YACR,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,oBAAoB,CAAC,CAAC;YAC3D,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC9C,MAAM,QAAQ,GAAgB,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YACvD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC/B,QAAQ,CAAC,GAAG,GAAG,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YACtD,CAAC;YACD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;QAChD,CAAC;QACD,KAAK,GAAG,CAAC,CAAC,CAAC;YACP,gCAAgC;YAChC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,4BAA4B,CAAC,CAAC;YACnE,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YACjD,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,0BAA0B,CAAC,CAAC;YACvE,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;YACjD,OAAO,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC;QACjF,CAAC;QACD,KAAK,GAAG,CAAC,CAAC,CAAC;YACP,yCAAyC;YACzC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,yBAAyB,CAAC,CAAC;YAChE,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YACjD,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,uBAAuB,CAAC,CAAC;YACpE,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;YACxD,OAAO,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC;QAC9E,CAAC;QACD,cAAc;QACd,KAAK,GAAG;YACJ,OAAO,kBAAkB,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QAC1E,KAAK,GAAG;YACJ,OAAO,kBAAkB,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QAC1E,KAAK,GAAG;YACJ,OAAO,kBAAkB,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QACxE,KAAK,GAAG;YACJ,OAAO,kBAAkB,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QACxE,KAAK,GAAG;YACJ,OAAO,kBAAkB,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QAC1E,KAAK,GAAG;YACJ,yEAAyE;YACzE,OAAO,kBAAkB,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QAC1E;YACI,MAAM,IAAI,KAAK,CAAC,+BAA+B,QAAQ,eAAe,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5F,CAAC;AACL,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAc,EAAE,KAAiB,EAAE,MAAc,EAAE,IAAqB,EAAE,WAAmB,EAAE,KAAa;IACpI,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,iCAAiC,IAAI,EAAE,CAAC,CAAC;IAC/E,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,gBAAgB;IAC3E,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,YAAY,CAAC,CAAC;IAClE,MAAM,IAAI,EAAE,CAAC;IACb,MAAM,kBAAkB,GAAG,WAAW,GAAG,WAAW,CAAC;IACrD,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,+BAA+B,IAAI,EAAE,CAAC,CAAC;IAE3F,IAAI,SAAqB,CAAC;IAC1B,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;QACjB,kBAAkB;QAClB,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAAC,CAAC;QACrE,SAAS,GAAG,WAAW,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;IAC5D,CAAC;SAAM,CAAC;QACJ,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,mCAAmC,QAAQ,EAAE,CAAC,CAAC;QACnE,CAAC;QACD,IAAI,gBAAgB,KAAK,kBAAkB,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CAAC,qCAAqC,IAAI,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAAC,CAAC;IAC/D,CAAC;IAED,IAAI,CAAC,YAAY,IAAI,WAAW,GAAG,CAAC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACzD,gBAAgB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAC7C,CAAC;IACD,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,UAAU,EAAE,SAAS,CAAC,UAAU,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;IAE9G,IAAI,KAA4D,CAAC;IACjE,QAAQ,IAAI,EAAE,CAAC;QACX,KAAK,WAAW;YACZ,KAAK,GAAG,IAAI,YAAY,CAAC,WAAW,CAAC,CAAC;YACtC,MAAM;QACV,KAAK,WAAW;YACZ,KAAK,GAAG,IAAI,YAAY,CAAC,WAAW,CAAC,CAAC;YACtC,MAAM;QACV,KAAK,SAAS;YACV,KAAK,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;YACpC,MAAM;QACV,KAAK,WAAW;YACZ,KAAK,GAAG,SAAS,CAAC;YAClB,MAAM;QACV,KAAK,SAAS;YACV,KAAK,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;YACtC,MAAM;QACV;YACI,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO;QACH,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;QACzB,UAAU,EAAE,MAAM,GAAG,gBAAgB;KACxC,CAAC;AACN,CAAC;AAED,SAAS,WAAW,CAAC,KAAiB,EAAE,MAAc,EAAE,UAAkB,EAAE,KAAa,EAAE,OAAe;IACtG,IAAI,MAAM,GAAG,CAAC,IAAI,UAAU,GAAG,CAAC,IAAI,MAAM,GAAG,UAAU,GAAG,KAAK,IAAI,MAAM,GAAG,UAAU,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC;QACxG,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,2BAA2B,CAAC,CAAC;IAC3D,CAAC;AACL,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAgB,EAAE,WAAmB;IAC3D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC;QAC/D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,WAAW,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;YACvD,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAChB,CAAC;IACL,CAAC;AACL,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAc,EAAE,MAAc;IACtD,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,YAAY,CAAC,CAAC;IAC7E,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC9E,OAAO,IAAI,GAAG,WAAW,GAAG,GAAG,CAAC;AACpC,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAc,EAAE,MAAc;IACrD,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,YAAY,CAAC,CAAC;IAC7E,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC7E,OAAO,IAAI,GAAG,WAAW,GAAG,GAAG,CAAC;AACpC,CAAC;AAED,qGAAqG;AACrG,SAAS,oBAAoB,CAAC,IAAc,EAAE,MAAc;IACxD,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,YAAY,CAAC,CAAC;IAC3E,IAAI,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC5E,MAAM,QAAQ,GAAG,CAAC,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAC3C,IAAI,QAAQ,EAAE,CAAC;QACX,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;QACvB,IAAI,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC/C,CAAC;IACD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,OAAO,IAAI,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;QAC7B,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC,GAAG,UAAU,GAAG,GAAG,CAAC;QAC/C,MAAM,CAAC,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;QAC1B,IAAI,GAAG,YAAY,CAAC;QACpB,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AACzF,CAAC;AAED,SAAS,kBAAkB,CAAC,SAAqB;IAC7C,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,UAAU,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IACxF,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,SAAS,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;IAC1D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,SAAS,WAAW,CAAC,KAAiB,EAAE,MAAc,EAAE,MAAc;IAClE,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9B,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,SAAS,UAAU,CAAC,KAAiB,EAAE,MAAc,EAAE,MAAc;IACjE,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC;IACzC,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;AACnE,CAAC","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"]}
|
package/FBX/types/fbxTypes.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
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
|
|
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
|
/**
|
package/FBX/types/fbxTypes.js
CHANGED
|
@@ -23,19 +23,47 @@ export function getPropertyValue(node, index) {
|
|
|
23
23
|
return undefined;
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
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
|
|
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
|
-
//
|
|
55
|
-
const
|
|
56
|
-
if (
|
|
57
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
90
|
+
return fbxName.substring(colonIdx + 2);
|
|
63
91
|
}
|
|
64
92
|
return fbxName;
|
|
65
93
|
}
|