@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.
Files changed (72) 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/USD/usdCommandProtocol.d.ts +20 -4
  66. package/USD/usdCommandProtocol.js +25 -3
  67. package/USD/usdCommandProtocol.js.map +1 -1
  68. package/USD/usdFileLoader.pure.js +2 -0
  69. package/USD/usdFileLoader.pure.js.map +1 -1
  70. package/USD/usdSceneMaterializer.js +430 -92
  71. package/USD/usdSceneMaterializer.js.map +1 -1
  72. package/package.json +3 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animationCurve.js","sourceRoot":"","sources":["../../../../../dev/loaders/src/FBX/interpreter/animationCurve.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\n/**\n * FBX animation curve model and evaluator.\n *\n * Keys carry cubic Bezier tangents expressed the way the FBX SDK stores them: a left and right tangent with a time\n * extent (dx, as a fraction of the segment scaled by the tangent weight) and a value extent (dy). Linear and constant\n * segments are represented the same way so that a single evaluator handles every case, including the weighted\n * tangents Maya and MotionBuilder write, TCB keys, and the pre/post extrapolation modes.\n */\n\n/** FBX time units: 46186158000 ticks per second */\nexport const FBX_TIME_UNIT = 46186158000;\n\nexport type FBXInterpolationType = \"constant\" | \"linear\" | \"cubic\";\n\nexport type FBXExtrapolationMode = \"constant\" | \"repeat\" | \"mirror\" | \"slope\" | \"repeatRelative\";\n\nexport interface FBXExtrapolation {\n mode: FBXExtrapolationMode;\n /** Number of repetitions, or -1 for infinite */\n repeatCount: number;\n}\n\n/** A single keyframe */\nexport interface FBXKeyframe {\n /** Time in seconds */\n time: number;\n /** Value at this keyframe */\n value: number;\n /** Interpolation used from this key to the next key */\n interpolation: FBXInterpolationType;\n /** Constant interpolation variant */\n constantMode?: \"standard\" | \"next\";\n /** Left (incoming) tangent: time extent in seconds and value extent */\n leftDx: number;\n leftDy: number;\n /** Right (outgoing) tangent: time extent in seconds and value extent */\n rightDx: number;\n rightDy: number;\n /** Cubic outgoing slope in value units per second (derived, kept for consumers that export hermite keys) */\n rightSlope?: number;\n /** Cubic incoming slope for the next key, in value units per second (derived) */\n nextLeftSlope?: number;\n}\n\n/** An animation curve (one axis of one property) */\nexport interface FBXCurveData {\n /** Channel: \"d|X\", \"d|Y\", \"d|Z\" */\n channel: string;\n /** Keyframes */\n keys: FBXKeyframe[];\n /** True for baked sample curves that should be connected as linear samples */\n isSampled?: boolean;\n preExtrapolation?: FBXExtrapolation;\n postExtrapolation?: FBXExtrapolation;\n}\n\n// Key attribute flags (KeyAttrFlags), as written by the FBX SDK.\nconst KEY_INTERPOLATION_CONSTANT = 0x2;\nconst KEY_INTERPOLATION_CUBIC = 0x8;\nconst KEY_TANGENT_TCB = 0x200;\nconst KEY_TANGENT_USER = 0x400;\nconst KEY_TANGENT_BROKEN = 0x800;\nconst KEY_CONSTANT_NEXT = 0x100;\nconst KEY_CLAMP = 0x1000;\nconst KEY_TIME_INDEPENDENT = 0x2000;\nconst KEY_CLAMP_PROGRESSIVE = 0x4000;\nconst KEY_WEIGHTED_RIGHT = 0x1000000;\nconst KEY_WEIGHTED_NEXT_LEFT = 0x2000000;\n\nconst DEFAULT_WEIGHT = 0.333333;\nconst KEY_CLAMP_THRESHOLD = 0.00001;\n\n/** Raw key attribute data for one key, after run-length decoding. */\nexport interface FBXKeyAttributes {\n flags: number;\n data: [number, number, number, number];\n}\n\n/**\n * Builds keyframes from parallel time/value arrays and their (run-length encoded) attributes, resolving every\n * tangent mode the FBX SDK writes: user, broken, auto (with clamp / progressive clamp / time-independent flags and\n * auto bias), TCB, weighted, linear and constant.\n */\nexport function buildKeyframes(times: ArrayLike<number>, values: ArrayLike<number>, attributes: (index: number) => FBXKeyAttributes): FBXKeyframe[] {\n const numKeys = Math.min(times.length, values.length);\n const keys: FBXKeyframe[] = [];\n if (numKeys === 0) {\n return keys;\n }\n\n let slopeLeft = 0;\n let weightLeft = DEFAULT_WEIGHT;\n let prevTime = 0;\n let nextTime = Number(times[0]) / FBX_TIME_UNIT;\n\n for (let i = 0; i < numKeys; i++) {\n const time = nextTime;\n const value = values[i];\n if (i + 1 < numKeys) {\n nextTime = Number(times[i + 1]) / FBX_TIME_UNIT;\n }\n const prevValue = i > 0 ? values[i - 1] : value;\n const nextValue = i + 1 < numKeys ? values[i + 1] : value;\n\n const attr = attributes(i);\n const flags = attr.flags;\n let slopeRight = attr.data[0];\n let weightRight = DEFAULT_WEIGHT;\n let nextSlopeLeft = attr.data[1];\n let nextWeightLeft = DEFAULT_WEIGHT;\n\n if ((flags & (KEY_WEIGHTED_RIGHT | KEY_WEIGHTED_NEXT_LEFT)) !== 0) {\n // Two 0.4 decimal fixed point weights packed into the bit pattern of the third float.\n const packed = floatToUint32Bits(attr.data[2]);\n if (flags & KEY_WEIGHTED_RIGHT) {\n weightRight = (packed & 0xffff) * 0.0001;\n }\n if (flags & KEY_WEIGHTED_NEXT_LEFT) {\n nextWeightLeft = (packed >>> 16) * 0.0001;\n }\n }\n\n let interpolation: FBXInterpolationType;\n let constantMode: \"standard\" | \"next\" = \"standard\";\n\n if (flags & KEY_INTERPOLATION_CONSTANT) {\n interpolation = \"constant\";\n constantMode = flags & KEY_CONSTANT_NEXT ? \"next\" : \"standard\";\n weightRight = nextWeightLeft = DEFAULT_WEIGHT;\n slopeRight = nextSlopeLeft = 0;\n } else if (flags & KEY_INTERPOLATION_CUBIC) {\n interpolation = \"cubic\";\n if (flags & KEY_TANGENT_TCB) {\n let tcbSlopeLeft = 0;\n let tcbSlopeRight = 0;\n let edge = false;\n if (i > 0 && time > prevTime) {\n tcbSlopeLeft = (value - prevValue) / (time - prevTime);\n } else {\n edge = true;\n }\n if (i + 1 < numKeys && nextTime > time) {\n tcbSlopeRight = (nextValue - value) / (nextTime - time);\n } else {\n edge = true;\n }\n const tcb = solveTcb(attr.data[0], attr.data[1], attr.data[2], tcbSlopeLeft, tcbSlopeRight, edge);\n slopeLeft = tcb.left;\n slopeRight = tcb.right;\n nextSlopeLeft = 0;\n nextWeightLeft = DEFAULT_WEIGHT;\n } else if (flags & KEY_TANGENT_USER) {\n // User tangents: slopes are stored explicitly. Unified vs broken makes no difference to evaluation.\n void KEY_TANGENT_BROKEN;\n } else {\n // Auto tangents\n if (i > 0 && i + 1 < numKeys && time > prevTime && nextTime > time) {\n if (Math.abs(slopeLeft + slopeRight) <= 0.0001) {\n slopeLeft = slopeRight = solveAutoTangent(prevTime, time, nextTime, prevValue, value, nextValue, weightLeft, weightRight, slopeRight, flags);\n } else {\n slopeLeft = solveAutoTangent(prevTime, time, nextTime, prevValue, value, nextValue, weightLeft, weightRight, -slopeLeft, flags);\n slopeRight = solveAutoTangent(prevTime, time, nextTime, prevValue, value, nextValue, weightLeft, weightRight, slopeRight, flags);\n }\n } else if (i > 0 && time > prevTime) {\n slopeLeft = slopeRight = solveAutoTangentOneSided(prevTime, time, prevValue, value, -slopeLeft, flags);\n } else if (i + 1 < numKeys && nextTime > time) {\n slopeLeft = slopeRight = solveAutoTangentOneSided(time, nextTime, value, nextValue, slopeRight, flags);\n } else {\n slopeLeft = slopeRight = 0;\n }\n }\n } else {\n // Linear or unknown interpolation: tangents match the linear segment with 1/3 weights.\n interpolation = \"linear\";\n weightRight = DEFAULT_WEIGHT;\n nextWeightLeft = DEFAULT_WEIGHT;\n const deltaTime = nextTime - time;\n slopeRight = nextSlopeLeft = deltaTime > 0 ? (nextValue - value) / deltaTime : 0;\n }\n\n const key: FBXKeyframe = { time, value, interpolation, constantMode, leftDx: 0, leftDy: 0, rightDx: 0, rightDy: 0 };\n if (time > prevTime) {\n key.leftDx = weightLeft * (time - prevTime);\n key.leftDy = key.leftDx * slopeLeft;\n }\n if (nextTime > time) {\n key.rightDx = weightRight * (nextTime - time);\n key.rightDy = key.rightDx * slopeRight;\n }\n key.rightSlope = slopeRight;\n keys.push(key);\n\n slopeLeft = nextSlopeLeft;\n weightLeft = nextWeightLeft;\n prevTime = time;\n }\n\n for (let i = 0; i + 1 < keys.length; i++) {\n const next = keys[i + 1];\n keys[i].nextLeftSlope = next.leftDx > 0 ? next.leftDy / next.leftDx : 0;\n }\n return keys;\n}\n\nconst f32 = new Float32Array(1);\nconst u32 = new Uint32Array(f32.buffer);\nfunction floatToUint32Bits(v: number): number {\n f32[0] = v;\n return u32[0];\n}\n\nfunction solveTcb(tension: number, continuity: number, bias: number, slopeLeft: number, slopeRight: number, edge: boolean): { left: number; right: number } {\n const factor = edge ? 1 : 0.5;\n const d00 = factor * (1 - tension) * (1 + bias) * (1 - continuity);\n const d01 = factor * (1 - tension) * (1 - bias) * (1 + continuity);\n const d10 = factor * (1 - tension) * (1 + bias) * (1 + continuity);\n const d11 = factor * (1 - tension) * (1 - bias) * (1 - continuity);\n return { left: d00 * slopeLeft + d01 * slopeRight, right: d10 * slopeLeft + d11 * slopeRight };\n}\n\n/** Auto tangent as the FBX SDK computes it, including clamping and auto bias. */\nexport function solveAutoTangent(\n prevTime: number,\n time: number,\n nextTime: number,\n prevValue: number,\n value: number,\n nextValue: number,\n weightLeft: number,\n weightRight: number,\n autoBias: number,\n flags: number\n): number {\n if (flags & KEY_CLAMP) {\n if (Math.min(Math.abs(prevValue - value), Math.abs(nextValue - value)) <= KEY_CLAMP_THRESHOLD) {\n return 0;\n }\n }\n\n let slope = (nextValue - prevValue) / (nextTime - prevTime);\n\n if ((flags & KEY_TIME_INDEPENDENT) === 0) {\n const slopeLeft = (value - prevValue) / (time - prevTime);\n const slopeRight = (nextValue - value) / (nextTime - time);\n const delta = (time - prevTime) / (nextTime - prevTime);\n slope = slope * 0.5 + (slopeLeft * (1 - delta) + slopeRight * delta) * 0.5;\n\n const biasWeight = Math.abs(autoBias) / 100;\n if (biasWeight > 0.0001) {\n const biasTarget = autoBias > 0 ? slopeRight : slopeLeft;\n const biasDelta = biasTarget - slope;\n slope = slope * (1 - biasWeight) + biasTarget * biasWeight;\n const absBiasWeight = biasWeight - 5;\n if (absBiasWeight > 0) {\n let biasSign = Math.abs(biasDelta) > 0.00001 ? biasDelta : autoBias;\n biasSign = biasSign > 0 ? 1 : -1;\n slope += absBiasWeight * absBiasWeight * biasSign * 40;\n }\n }\n }\n\n if (flags & KEY_CLAMP_PROGRESSIVE) {\n const slopeSign = slope >= 0 ? 1 : -1;\n let absSlope = slopeSign * slope;\n const rangeLeft = weightLeft * (time - prevTime);\n const rangeRight = weightRight * (nextTime - time);\n let maxLeft = rangeLeft > 0 ? (slopeSign * (value - prevValue)) / rangeLeft : 0;\n let maxRight = rangeRight > 0 ? (slopeSign * (nextValue - value)) / rangeRight : 0;\n if (!(maxLeft > 0)) {\n maxLeft = 0;\n }\n if (!(maxRight > 0)) {\n maxRight = 0;\n }\n absSlope = Math.min(absSlope, maxLeft, maxRight);\n slope = slopeSign * absSlope;\n }\n\n return slope;\n}\n\nfunction solveAutoTangentOneSided(t0: number, t1: number, v0: number, v1: number, autoBias: number, flags: number): number {\n if (flags & KEY_CLAMP_PROGRESSIVE) {\n return 0;\n }\n if (flags & KEY_CLAMP) {\n if (Math.abs(v1 - v0) <= KEY_CLAMP_THRESHOLD) {\n return 0;\n }\n }\n let slope = (v1 - v0) / (t1 - t0);\n if ((flags & KEY_TIME_INDEPENDENT) === 0) {\n const absBiasWeight = Math.abs(autoBias) / 100 - 5;\n if (absBiasWeight > 0) {\n slope += absBiasWeight * absBiasWeight * (autoBias > 0 ? 1 : -1) * 40;\n }\n }\n return slope;\n}\n\n/** Builds a keyframe list from explicit per-key slopes (legacy Takes and synthetic curves). */\nexport function keyframesFromSlopes(\n times: number[],\n values: number[],\n interpolation: FBXInterpolationType[],\n constantNext: boolean[],\n leftSlope: number[],\n rightSlope: number[],\n leftWeight?: number[],\n rightWeight?: number[]\n): FBXKeyframe[] {\n const keys: FBXKeyframe[] = [];\n for (let i = 0; i < times.length; i++) {\n const key: FBXKeyframe = {\n time: times[i],\n value: values[i],\n interpolation: interpolation[i],\n constantMode: constantNext[i] ? \"next\" : \"standard\",\n leftDx: 0,\n leftDy: 0,\n rightDx: 0,\n rightDy: 0,\n rightSlope: rightSlope[i],\n nextLeftSlope: i + 1 < times.length ? leftSlope[i + 1] : undefined,\n };\n if (i > 0 && times[i] > times[i - 1]) {\n key.leftDx = (leftWeight?.[i] ?? DEFAULT_WEIGHT) * (times[i] - times[i - 1]);\n key.leftDy = key.leftDx * leftSlope[i];\n }\n if (i + 1 < times.length && times[i + 1] > times[i]) {\n key.rightDx = (rightWeight?.[i] ?? DEFAULT_WEIGHT) * (times[i + 1] - times[i]);\n key.rightDy = key.rightDx * rightSlope[i];\n }\n keys.push(key);\n }\n return keys;\n}\n\n/** Reads a `Pre-Extrapolation` / `Post-Extrapolation` block: `Type` is a character code, `Repetition` a count. */\nexport function parseExtrapolation(typeValue: unknown, repetitionValue: unknown): FBXExtrapolation {\n const code = typeof typeValue === \"string\" ? typeValue.charCodeAt(0) : typeof typeValue === \"number\" ? typeValue : 0;\n let mode: FBXExtrapolationMode;\n switch (String.fromCharCode(code)) {\n case \"A\":\n mode = \"repeatRelative\";\n break;\n case \"K\":\n mode = \"slope\";\n break;\n case \"M\":\n mode = \"mirror\";\n break;\n case \"R\":\n mode = \"repeat\";\n break;\n default:\n mode = \"constant\";\n }\n let repeatCount = typeof repetitionValue === \"number\" ? repetitionValue : -1;\n if (repeatCount < 0) {\n repeatCount = -1;\n }\n return { mode, repeatCount };\n}\n\nfunction findCubicBezierT(p1: number, p2: number, x0: number): number {\n const p1_3 = p1 * 3;\n const p2_3 = p2 * 3;\n const a = p1_3 - p2_3 + 1;\n const b = p2_3 - p1_3 - p1_3;\n const c = p1_3;\n const a_3 = 3 * a;\n const b_2 = 2 * b;\n let t = x0;\n let x1: number;\n const eps = 8.881784197001252e-16;\n for (let i = 0; i < 11; i++) {\n const t2 = t * t;\n const t3 = t2 * t;\n x1 = a * t3 + b * t2 + c * t - x0;\n const d = a_3 * t2 + b_2 * t + c;\n if (d === 0) {\n break;\n }\n t -= x1 / d;\n if (i >= 2 && Math.abs(x1) <= eps) {\n break;\n }\n }\n return t;\n}\n\n/**\n * Evaluates a curve at a time in seconds, following the FBX SDK: constant/linear/cubic Bezier segments inside the\n * key range and the curve's pre/post extrapolation outside it.\n */\n/**\n * Tangent handles of the segment between two keys. Keys built by the parsers carry explicit handles; keys that\n * only carry slopes (`rightSlope` / `nextLeftSlope`) get the SDK's default one-third weighting.\n */\nfunction segmentTangents(prev: FBXKeyframe, next: FBXKeyframe): { rightDx: number; rightDy: number; leftDx: number; leftDy: number } {\n const dt = next.time - prev.time;\n const hasHandles =\n Number.isFinite(prev.rightDx) && Number.isFinite(prev.rightDy) && Number.isFinite(next.leftDx) && Number.isFinite(next.leftDy) && (prev.rightDx > 0 || next.leftDx > 0);\n if (hasHandles) {\n return { rightDx: prev.rightDx, rightDy: prev.rightDy, leftDx: next.leftDx, leftDy: next.leftDy };\n }\n const rightSlope = prev.rightSlope ?? 0;\n const leftSlope = prev.nextLeftSlope ?? (next.leftDx > 0 ? next.leftDy / next.leftDx : rightSlope);\n return { rightDx: dt / 3, rightDy: (dt / 3) * rightSlope, leftDx: dt / 3, leftDy: (dt / 3) * leftSlope };\n}\n\nexport function evaluateCurve(curve: FBXCurveData | undefined, time: number, defaultValue: number, noExtrapolation = false): number {\n if (!curve || curve.keys.length === 0) {\n return defaultValue;\n }\n const keys = curve.keys;\n if (keys.length === 1) {\n return keys[0].value;\n }\n\n const minTime = keys[0].time;\n const maxTime = keys[keys.length - 1].time;\n if (!noExtrapolation && (time < minTime || time > maxTime)) {\n return extrapolateCurve(curve, time);\n }\n\n // Binary search for the first key with time > `time`.\n let begin = 0;\n let end = keys.length;\n while (end - begin >= 8) {\n const mid = (begin + end) >> 1;\n if (keys[mid].time <= time) {\n begin = mid + 1;\n } else {\n end = mid;\n }\n }\n end = keys.length;\n for (; begin < end; begin++) {\n const next = keys[begin];\n if (next.time <= time) {\n continue;\n }\n if (begin === 0) {\n return next.value;\n }\n const prev = keys[begin - 1];\n if (prev.time === time) {\n return prev.value;\n }\n const rcpDelta = 1 / (next.time - prev.time);\n let t = (time - prev.time) * rcpDelta;\n switch (prev.interpolation) {\n case \"constant\":\n return prev.constantMode === \"next\" ? next.value : prev.value;\n case \"linear\":\n return prev.value * (1 - t) + next.value * t;\n default: {\n const tangents = segmentTangents(prev, next);\n const x1 = tangents.rightDx * rcpDelta;\n const x2 = 1 - tangents.leftDx * rcpDelta;\n t = findCubicBezierT(x1, x2, t);\n const t2 = t * t;\n const t3 = t2 * t;\n const u = 1 - t;\n const u2 = u * u;\n const u3 = u2 * u;\n const y0 = prev.value;\n const y3 = next.value;\n const y1 = y0 + tangents.rightDy;\n const y2 = y3 - tangents.leftDy;\n return u3 * y0 + 3 * (u2 * t * y1 + u * t2 * y2) + t3 * y3;\n }\n }\n }\n return keys[keys.length - 1].value;\n}\n\nfunction extrapolateCurve(curve: FBXCurveData, realTime: number): number {\n const keys = curve.keys;\n const minTime = keys[0].time;\n const maxTime = keys[keys.length - 1].time;\n const pre = realTime < minTime;\n const key = pre ? keys[0] : keys[keys.length - 1];\n const ext = (pre ? curve.preExtrapolation : curve.postExtrapolation) ?? { mode: \"constant\", repeatCount: -1 };\n\n if (ext.mode === \"constant\") {\n return key.value;\n }\n if (ext.mode === \"slope\") {\n const dx = pre ? key.rightDx : key.leftDx;\n const dy = pre ? key.rightDy : key.leftDy;\n return dx !== 0 ? key.value + dy * ((realTime - key.time) / dx) : key.value;\n }\n if (ext.repeatCount === 0) {\n return key.value;\n }\n\n // Work in KTime ticks to stay frame exact.\n const scale = FBX_TIME_UNIT;\n const min = Math.round(minTime * scale);\n const max = Math.round(maxTime * scale);\n const time = realTime * scale;\n const delta = pre ? min - time : time - max;\n const duration = max - min;\n if (!(duration >= 1)) {\n return key.value;\n }\n\n const rep = delta / duration;\n let repN = Math.floor(rep);\n let repD = delta - repN * duration;\n if (ext.repeatCount > 0 && repN >= ext.repeatCount) {\n repN = ext.repeatCount - 1;\n repD = duration;\n }\n if (ext.mode === \"mirror\") {\n const parity = repN * 0.5 - Math.floor(repN * 0.5);\n if (parity <= 0.25) {\n repD = duration - repD;\n }\n }\n if (pre) {\n repD = duration - repD;\n }\n const newTime = (min + repD) / scale;\n let value = evaluateCurve(curve, newTime, key.value, true);\n if (ext.mode === \"repeatRelative\") {\n let valueDelta = keys[keys.length - 1].value - keys[0].value;\n if (pre) {\n valueDelta = -valueDelta;\n }\n value += valueDelta * (repN + 1);\n }\n return value;\n}\n\n// ── Euler / quaternion helpers for layer blending ─────────────────────────────\n\nexport type Vec3 = [number, number, number];\nexport type Quat = [number, number, number, number];\n\nconst DEG2RAD = Math.PI / 180;\nconst RAD2DEG = 180 / Math.PI;\n\n/** Euler angles in degrees with an FBX rotation order (0=XYZ ... 5=ZYX; spheric falls back to XYZ) to a quaternion. */\nexport function eulerToQuat(v: Vec3, order: number): Quat {\n const vx = v[0] * (DEG2RAD * 0.5);\n const vy = v[1] * (DEG2RAD * 0.5);\n const vz = v[2] * (DEG2RAD * 0.5);\n const cx = Math.cos(vx),\n sx = Math.sin(vx);\n const cy = Math.cos(vy),\n sy = Math.sin(vy);\n const cz = Math.cos(vz),\n sz = Math.sin(vz);\n switch (order) {\n case 1: // XZY\n return [cx * sy * sz + cy * cz * sx, cx * cz * sy + cy * sx * sz, cx * cy * sz - cz * sx * sy, cx * cy * cz - sx * sy * sz];\n case 2: // YZX\n return [-cx * sy * sz + cy * cz * sx, cx * cz * sy - cy * sx * sz, cx * cy * sz + cz * sx * sy, cx * cy * cz + sx * sy * sz];\n case 3: // YXZ\n return [-cx * sy * sz + cy * cz * sx, cx * cz * sy + cy * sx * sz, cx * cy * sz + cz * sx * sy, cx * cy * cz - sx * sy * sz];\n case 4: // ZXY\n return [cx * sy * sz + cy * cz * sx, cx * cz * sy - cy * sx * sz, cx * cy * sz - cz * sx * sy, cx * cy * cz + sx * sy * sz];\n case 5: // ZYX\n return [cx * sy * sz + cy * cz * sx, cx * cz * sy - cy * sx * sz, cx * cy * sz + cz * sx * sy, cx * cy * cz - sx * sy * sz];\n default: // XYZ\n return [-cx * sy * sz + cy * cz * sx, cx * cz * sy + cy * sx * sz, cx * cy * sz - cz * sx * sy, cx * cy * cz + sx * sy * sz];\n }\n}\n\n/** Quaternion to Euler angles in degrees for an FBX rotation order (inverse of eulerToQuat). */\nexport function quatToEuler(q: Quat, order: number): Vec3 {\n const eps = 0.999999999;\n const [qx, qy, qz, qw] = q;\n let vx = 0,\n vy = 0,\n vz = 0;\n let t: number;\n const halfPi = Math.PI * 0.5;\n switch (order) {\n case 1: // XZY\n t = 2 * (qw * qz + qx * qy);\n if (Math.abs(t) < eps) {\n vz = Math.asin(t);\n vy = Math.atan2(2 * (qw * qy - qx * qz), 2 * (qw * qw + qx * qx) - 1);\n vx = -Math.atan2(-2 * (qw * qx - qy * qz), 2 * (qw * qw + qy * qy) - 1);\n } else {\n vz = Math.sign(t) * halfPi;\n vy = Math.atan2(2 * t * (qw * qx + qy * qz), -t * (2 * qx * qy - 2 * qw * qz));\n }\n break;\n case 2: // YZX\n t = 2 * (qw * qz - qx * qy);\n if (Math.abs(t) < eps) {\n vz = Math.asin(t);\n vx = Math.atan2(2 * (qw * qx + qy * qz), 2 * (qw * qw + qy * qy) - 1);\n vy = -Math.atan2(-2 * (qw * qy + qx * qz), 2 * (qw * qw + qx * qx) - 1);\n } else {\n vz = Math.sign(t) * halfPi;\n vx = Math.atan2(-2 * t * (qw * qy - qx * qz), t * (2 * qw * qz + 2 * qx * qy));\n }\n break;\n case 3: // YXZ\n t = 2 * (qw * qx + qy * qz);\n if (Math.abs(t) < eps) {\n vx = Math.asin(t);\n vz = Math.atan2(2 * (qw * qz - qx * qy), 2 * (qw * qw + qy * qy) - 1);\n vy = -Math.atan2(-2 * (qw * qy - qx * qz), 2 * (qw * qw + qz * qz) - 1);\n } else {\n vx = Math.sign(t) * halfPi;\n vz = Math.atan2(2 * t * (qw * qy + qx * qz), -t * (2 * qy * qz - 2 * qw * qx));\n }\n break;\n case 4: // ZXY\n t = 2 * (qw * qx - qy * qz);\n if (Math.abs(t) < eps) {\n vx = Math.asin(t);\n vy = Math.atan2(2 * (qw * qy + qx * qz), 2 * (qw * qw + qz * qz) - 1);\n vz = -Math.atan2(-2 * (qw * qz + qx * qy), 2 * (qw * qw + qy * qy) - 1);\n } else {\n vx = Math.sign(t) * halfPi;\n vy = Math.atan2(-2 * t * (qw * qz - qx * qy), t * (2 * qw * qx + 2 * qy * qz));\n }\n break;\n case 5: // ZYX\n t = 2 * (qw * qy + qx * qz);\n if (Math.abs(t) < eps) {\n vy = Math.asin(t);\n vx = Math.atan2(2 * (qw * qx - qy * qz), 2 * (qw * qw + qz * qz) - 1);\n vz = -Math.atan2(-2 * (qw * qz - qx * qy), 2 * (qw * qw + qx * qx) - 1);\n } else {\n vy = Math.sign(t) * halfPi;\n vx = Math.atan2(2 * t * (qw * qz + qx * qy), -t * (2 * qx * qz - 2 * qw * qy));\n }\n break;\n default: // XYZ\n t = 2 * (qw * qy - qx * qz);\n if (Math.abs(t) < eps) {\n vy = Math.asin(t);\n vz = Math.atan2(2 * (qw * qz + qx * qy), 2 * (qw * qw + qx * qx) - 1);\n vx = -Math.atan2(-2 * (qw * qx + qy * qz), 2 * (qw * qw + qz * qz) - 1);\n } else {\n vy = Math.sign(t) * halfPi;\n vz = Math.atan2(-2 * t * (qw * qx - qy * qz), t * (2 * qw * qy + 2 * qx * qz));\n }\n break;\n }\n return [vx * RAD2DEG, vy * RAD2DEG, vz * RAD2DEG];\n}\n\nfunction quatMul(a: Quat, b: Quat): Quat {\n return [\n a[3] * b[0] + a[0] * b[3] + a[1] * b[2] - a[2] * b[1],\n a[3] * b[1] - a[0] * b[2] + a[1] * b[3] + a[2] * b[0],\n a[3] * b[2] + a[0] * b[1] - a[1] * b[0] + a[2] * b[3],\n a[3] * b[3] - a[0] * b[0] - a[1] * b[1] - a[2] * b[2],\n ];\n}\n\nfunction quatSlerp(a: Quat, b: Quat, t: number): Quat {\n let dot = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];\n let bx = b[0],\n by = b[1],\n bz = b[2],\n bw = b[3];\n if (dot < 0) {\n dot = -dot;\n bx = -bx;\n by = -by;\n bz = -bz;\n bw = -bw;\n }\n let wa: number;\n let wb: number;\n if (dot > 0.9995) {\n wa = 1 - t;\n wb = t;\n } else {\n const omega = Math.acos(Math.min(1, dot));\n const rcpSin = 1 / Math.sin(omega);\n wa = Math.sin((1 - t) * omega) * rcpSin;\n wb = Math.sin(t * omega) * rcpSin;\n }\n const x = a[0] * wa + bx * wb;\n const y = a[1] * wa + by * wb;\n const z = a[2] * wa + bz * wb;\n const w = a[3] * wa + bw * wb;\n const len = Math.hypot(x, y, z, w) || 1;\n return [x / len, y / len, z / len, w / len];\n}\n\nfunction powAbs(v: number, e: number): number {\n return v >= 0 ? Math.pow(v, e) : -Math.pow(-v, e);\n}\n\n/** Blend semantics of an animation layer, derived from its BlendMode and accumulation modes. */\nexport interface FBXLayerBlend {\n /** Layer participates in blending (BlendMode Additive or Override Passthrough) */\n blended: boolean;\n /** Layer adds onto the result instead of replacing it (BlendMode Additive) */\n additive: boolean;\n /** Rotations compose as quaternions (RotationAccumulationMode ByLayer) */\n composeRotation: boolean;\n /** Scales compose multiplicatively (ScaleAccumulationMode Multiply) */\n composeScale: boolean;\n /** Layer weight in [0, 1] */\n weight: number;\n}\n\n/**\n * Combines one animation layer's value into the running result, exactly as the FBX SDK evaluator does.\n * `kind` selects the accumulation rule: \"R\" rotations (degrees, rotation order given), \"S\" scales, anything else linear.\n */\nexport function combineLayerValue(result: Vec3, value: Vec3, layer: FBXLayerBlend, kind: \"T\" | \"R\" | \"S\" | \"other\", rotationOrder: number): Vec3 {\n const w = layer.weight;\n if (layer.additive) {\n if (layer.composeScale && kind === \"S\") {\n return [result[0] * powAbs(value[0], w), result[1] * powAbs(value[1], w), result[2] * powAbs(value[2], w)];\n }\n if (layer.composeRotation && kind === \"R\") {\n const a = eulerToQuat(result, rotationOrder);\n const b = quatSlerp([0, 0, 0, 1], eulerToQuat(value, rotationOrder), w);\n return quatToEuler(quatMul(a, b), rotationOrder);\n }\n return [result[0] + value[0] * w, result[1] + value[1] * w, result[2] + value[2] * w];\n }\n if (layer.blended) {\n const rw = 1 - w;\n if (layer.composeScale && kind === \"S\") {\n return [powAbs(result[0], rw) * powAbs(value[0], w), powAbs(result[1], rw) * powAbs(value[1], w), powAbs(result[2], rw) * powAbs(value[2], w)];\n }\n if (layer.composeRotation && kind === \"R\") {\n return quatToEuler(quatSlerp(eulerToQuat(result, rotationOrder), eulerToQuat(value, rotationOrder), w), rotationOrder);\n }\n return [result[0] * rw + value[0] * w, result[1] * rw + value[1] * w, result[2] * rw + value[2] * w];\n }\n return [value[0], value[1], value[2]];\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */
2
- import { findChildByName, getPropertyValue, cleanFBXName } from "../types/fbxTypes.js";
2
+ import { getPropertyEntries } from "./propertyTemplates.js";
3
+ import { findChildByName, getPropertyValue, cleanFBXName, getNodeArray } from "../types/fbxTypes.js";
3
4
  import { getChildren } from "./connections.js";
4
5
  /**
5
6
  * Extract all blend shape deformers from the FBX scene.
@@ -38,19 +39,9 @@ function extractBlendShape(deformerId, _deformerNode, objectMap) {
38
39
  const channelName = cleanFBXName(getPropertyValue(channelNode, 1) ?? "MorphTarget");
39
40
  // Read DeformPercent from Properties70
40
41
  let deformPercent = 0;
41
- const props70 = findChildByName(channelNode, "Properties70");
42
- if (props70) {
43
- for (const p of props70.children) {
44
- if (p.name !== "P") {
45
- continue;
46
- }
47
- const pName = getPropertyValue(p, 0);
48
- if (pName === "DeformPercent") {
49
- const val = p.properties[4]?.value;
50
- if (typeof val === "number") {
51
- deformPercent = val;
52
- }
53
- }
42
+ for (const entry of getPropertyEntries(channelNode)) {
43
+ if (entry.name === "DeformPercent" && typeof entry.values[0] === "number") {
44
+ deformPercent = entry.values[0];
54
45
  }
55
46
  }
56
47
  const rawFullWeights = extractFullWeights(channelNode);
@@ -91,7 +82,7 @@ function extractBlendShape(deformerId, _deformerNode, objectMap) {
91
82
  }
92
83
  function extractFullWeights(channelNode) {
93
84
  const fullWeightsNode = findChildByName(channelNode, "FullWeights");
94
- const rawFullWeights = fullWeightsNode?.properties[0]?.value;
85
+ const rawFullWeights = getNodeArray(fullWeightsNode);
95
86
  if (!rawFullWeights) {
96
87
  return null;
97
88
  }
@@ -142,8 +133,8 @@ function extractShape(shapeNode) {
142
133
  if (!indexesNode || !verticesNode) {
143
134
  return null;
144
135
  }
145
- const rawIndices = indexesNode.properties[0]?.value;
146
- const rawVertices = verticesNode.properties[0]?.value;
136
+ const rawIndices = getNodeArray(indexesNode);
137
+ const rawVertices = getNodeArray(verticesNode);
147
138
  if (!rawIndices || !rawVertices) {
148
139
  return null;
149
140
  }
@@ -166,7 +157,7 @@ function extractShape(shapeNode) {
166
157
  let normals = null;
167
158
  const normalsNode = findChildByName(shapeNode, "Normals");
168
159
  if (normalsNode) {
169
- const rawNormals = normalsNode.properties[0]?.value;
160
+ const rawNormals = getNodeArray(normalsNode);
170
161
  if (rawNormals instanceof Float64Array) {
171
162
  normals = rawNormals;
172
163
  }
@@ -1 +1 @@
1
- {"version":3,"file":"blendShapes.js","sourceRoot":"","sources":["../../../../../dev/loaders/src/FBX/interpreter/blendShapes.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\r\nimport { type FBXNode, findChildByName, getPropertyValue, cleanFBXName } from \"../types/fbxTypes\";\r\n\r\nimport { type FBXObjectMap, getChildren } from \"./connections\";\r\n\r\n/** A single morph target (shape) within a blend shape channel */\r\nexport interface FBXShapeData {\r\n /** Sparse vertex indices affected by this shape */\r\n indices: Uint32Array;\r\n /** Absolute vertex positions for affected vertices [x,y,z,...] */\r\n vertices: Float64Array;\r\n /** Normals for affected vertices [x,y,z,...] (optional) */\r\n normals: Float64Array | null;\r\n}\r\n\r\nexport interface FBXBlendShapeDiagnostic {\r\n type: \"full-weights-mismatch\" | \"missing-full-weights\";\r\n message: string;\r\n channelId: number;\r\n channelName: string;\r\n}\r\n\r\n/** A blend shape channel (one animatable morph target) */\r\nexport interface FBXBlendShapeChannelData {\r\n /** Channel name */\r\n name: string;\r\n /** Channel node ID */\r\n id: number;\r\n /** Default weight (0-100 in FBX) */\r\n deformPercent: number;\r\n /** Shape geometry (typically one per channel, but FBX supports in-between shapes) */\r\n shapes: FBXShapeData[];\r\n /** In-between full weights in FBX DeformPercent units (0-100), one per shape when present */\r\n fullWeights: number[] | null;\r\n /** Recoverable blend-shape diagnostics */\r\n diagnostics: FBXBlendShapeDiagnostic[];\r\n}\r\n\r\n/** A blend shape deformer attached to a geometry */\r\nexport interface FBXBlendShapeData {\r\n /** Deformer ID */\r\n id: number;\r\n /** Geometry ID this blend shape is attached to */\r\n geometryId: number;\r\n /** Channels (each is an animatable morph target) */\r\n channels: FBXBlendShapeChannelData[];\r\n}\r\n\r\n/**\r\n * Extract all blend shape deformers from the FBX scene.\r\n */\r\nexport function extractBlendShapes(objectMap: FBXObjectMap): FBXBlendShapeData[] {\r\n const blendShapes: FBXBlendShapeData[] = [];\r\n\r\n for (const [id, node] of Array.from(objectMap.objects)) {\r\n if (node.name === \"Deformer\" && getPropertyValue<string>(node, 2) === \"BlendShape\") {\r\n const bs = extractBlendShape(id, node, objectMap);\r\n if (bs) {\r\n blendShapes.push(bs);\r\n }\r\n }\r\n }\r\n\r\n return blendShapes;\r\n}\r\n\r\nfunction extractBlendShape(deformerId: number, _deformerNode: FBXNode, objectMap: FBXObjectMap): FBXBlendShapeData | null {\r\n // Find the geometry this blend shape is attached to\r\n const parent = objectMap.parentOf.get(deformerId);\r\n if (!parent) {\r\n return null;\r\n }\r\n\r\n const parentNode = objectMap.objects.get(parent.id);\r\n if (!parentNode || parentNode.name !== \"Geometry\") {\r\n return null;\r\n }\r\n\r\n const geometryId = parent.id;\r\n\r\n // Find BlendShapeChannel children\r\n const channels: FBXBlendShapeChannelData[] = [];\r\n const channelChildren = getChildren(objectMap, deformerId, \"Deformer\");\r\n\r\n for (const { id: channelId, node: channelNode } of channelChildren) {\r\n const subType = getPropertyValue<string>(channelNode, 2);\r\n if (subType !== \"BlendShapeChannel\") {\r\n continue;\r\n }\r\n\r\n const channelName = cleanFBXName(getPropertyValue<string>(channelNode, 1) ?? \"MorphTarget\");\r\n\r\n // Read DeformPercent from Properties70\r\n let deformPercent = 0;\r\n const props70 = findChildByName(channelNode, \"Properties70\");\r\n if (props70) {\r\n for (const p of props70.children) {\r\n if (p.name !== \"P\") {\r\n continue;\r\n }\r\n const pName = getPropertyValue<string>(p, 0);\r\n if (pName === \"DeformPercent\") {\r\n const val = p.properties[4]?.value;\r\n if (typeof val === \"number\") {\r\n deformPercent = val;\r\n }\r\n }\r\n }\r\n }\r\n\r\n const rawFullWeights = extractFullWeights(channelNode);\r\n\r\n // Find connected Shape geometries\r\n const shapes: FBXShapeData[] = [];\r\n const shapeChildren = getChildren(objectMap, channelId, \"Geometry\");\r\n\r\n for (const { node: shapeNode } of shapeChildren) {\r\n const shapeSubType = getPropertyValue<string>(shapeNode, 2);\r\n if (shapeSubType !== \"Shape\") {\r\n continue;\r\n }\r\n\r\n const shape = extractShape(shapeNode);\r\n if (shape) {\r\n shapes.push(shape);\r\n }\r\n }\r\n\r\n if (shapes.length > 0) {\r\n const diagnostics: FBXBlendShapeDiagnostic[] = [];\r\n const fullWeights = normalizeFullWeights(rawFullWeights, shapes, channelId, channelName, diagnostics);\r\n channels.push({\r\n name: channelName,\r\n id: channelId,\r\n deformPercent,\r\n shapes: sortShapesByFullWeight(shapes, fullWeights),\r\n fullWeights: fullWeights ? [...fullWeights].sort((a, b) => a - b) : null,\r\n diagnostics,\r\n });\r\n }\r\n }\r\n\r\n if (channels.length === 0) {\r\n return null;\r\n }\r\n\r\n return {\r\n id: deformerId,\r\n geometryId,\r\n channels,\r\n };\r\n}\r\n\r\nfunction extractFullWeights(channelNode: FBXNode): number[] | null {\r\n const fullWeightsNode = findChildByName(channelNode, \"FullWeights\");\r\n const rawFullWeights = fullWeightsNode?.properties[0]?.value;\r\n if (!rawFullWeights) {\r\n return null;\r\n }\r\n\r\n if (rawFullWeights instanceof Float64Array || rawFullWeights instanceof Float32Array || rawFullWeights instanceof Int32Array) {\r\n return Array.from(rawFullWeights, (value) => Number(value));\r\n }\r\n return null;\r\n}\r\n\r\nfunction normalizeFullWeights(\r\n fullWeights: number[] | null,\r\n shapes: FBXShapeData[],\r\n channelId: number,\r\n channelName: string,\r\n diagnostics: FBXBlendShapeDiagnostic[]\r\n): number[] | null {\r\n if (!fullWeights) {\r\n if (shapes.length > 1) {\r\n diagnostics.push({\r\n type: \"missing-full-weights\",\r\n message: \"Blend shape channel has multiple shapes but no FullWeights; using the first shape for compatibility.\",\r\n channelId,\r\n channelName,\r\n });\r\n }\r\n return null;\r\n }\r\n\r\n if (fullWeights.length !== shapes.length) {\r\n if (shapes.length === 1) {\r\n return null;\r\n }\r\n\r\n diagnostics.push({\r\n type: \"full-weights-mismatch\",\r\n message: `FullWeights length ${fullWeights.length} does not match shape count ${shapes.length}; using the first shape for compatibility.`,\r\n channelId,\r\n channelName,\r\n });\r\n return null;\r\n }\r\n\r\n return fullWeights;\r\n}\r\n\r\nfunction sortShapesByFullWeight(shapes: FBXShapeData[], fullWeights: number[] | null): FBXShapeData[] {\r\n if (!fullWeights || fullWeights.length !== shapes.length) {\r\n return shapes.length > 1 ? [shapes[0]] : shapes;\r\n }\r\n\r\n return shapes\r\n .map((shape, index) => ({ shape, weight: fullWeights[index] }))\r\n .sort((a, b) => a.weight - b.weight)\r\n .map((entry) => entry.shape);\r\n}\r\n\r\nfunction extractShape(shapeNode: FBXNode): FBXShapeData | null {\r\n // Shape has: Indexes (sparse vertex indices), Vertices (delta offsets from base), Normals (optional delta)\r\n const indexesNode = findChildByName(shapeNode, \"Indexes\");\r\n const verticesNode = findChildByName(shapeNode, \"Vertices\");\r\n\r\n if (!indexesNode || !verticesNode) {\r\n return null;\r\n }\r\n\r\n const rawIndices = indexesNode.properties[0]?.value;\r\n const rawVertices = verticesNode.properties[0]?.value;\r\n\r\n if (!rawIndices || !rawVertices) {\r\n return null;\r\n }\r\n\r\n const indices = toUint32Array(rawIndices);\r\n if (!indices) {\r\n return null;\r\n }\r\n\r\n // Convert vertices\r\n let vertices: Float64Array;\r\n if (rawVertices instanceof Float64Array) {\r\n vertices = rawVertices;\r\n } else if (rawVertices instanceof Float32Array) {\r\n vertices = new Float64Array(rawVertices);\r\n } else {\r\n return null;\r\n }\r\n\r\n // Optional normals\r\n let normals: Float64Array | null = null;\r\n const normalsNode = findChildByName(shapeNode, \"Normals\");\r\n if (normalsNode) {\r\n const rawNormals = normalsNode.properties[0]?.value;\r\n if (rawNormals instanceof Float64Array) {\r\n normals = rawNormals;\r\n } else if (rawNormals instanceof Float32Array) {\r\n normals = new Float64Array(rawNormals);\r\n }\r\n }\r\n\r\n return { indices, vertices, normals };\r\n}\r\n\r\nfunction toUint32Array(value: unknown): Uint32Array | null {\r\n if (value instanceof Uint32Array) {\r\n return value;\r\n }\r\n if (value instanceof Int32Array || value instanceof Float32Array || value instanceof Float64Array) {\r\n const result = new Uint32Array(value.length);\r\n for (let i = 0; i < value.length; i++) {\r\n result[i] = value[i];\r\n }\r\n return result;\r\n }\r\n return null;\r\n}\r\n"]}
1
+ {"version":3,"file":"blendShapes.js","sourceRoot":"","sources":["../../../../../dev/loaders/src/FBX/interpreter/blendShapes.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\nimport { getPropertyEntries } from \"./propertyTemplates\";\nimport { type FBXNode, findChildByName, getPropertyValue, cleanFBXName, getNodeArray } from \"../types/fbxTypes\";\n\nimport { type FBXObjectMap, getChildren } from \"./connections\";\n\n/** A single morph target (shape) within a blend shape channel */\nexport interface FBXShapeData {\n /** Sparse vertex indices affected by this shape */\n indices: Uint32Array;\n /** Absolute vertex positions for affected vertices [x,y,z,...] */\n vertices: Float64Array;\n /** Normals for affected vertices [x,y,z,...] (optional) */\n normals: Float64Array | null;\n}\n\nexport interface FBXBlendShapeDiagnostic {\n type: \"full-weights-mismatch\" | \"missing-full-weights\";\n message: string;\n channelId: number;\n channelName: string;\n}\n\n/** A blend shape channel (one animatable morph target) */\nexport interface FBXBlendShapeChannelData {\n /** Channel name */\n name: string;\n /** Channel node ID */\n id: number;\n /** Default weight (0-100 in FBX) */\n deformPercent: number;\n /** Shape geometry (typically one per channel, but FBX supports in-between shapes) */\n shapes: FBXShapeData[];\n /** In-between full weights in FBX DeformPercent units (0-100), one per shape when present */\n fullWeights: number[] | null;\n /** Recoverable blend-shape diagnostics */\n diagnostics: FBXBlendShapeDiagnostic[];\n}\n\n/** A blend shape deformer attached to a geometry */\nexport interface FBXBlendShapeData {\n /** Deformer ID */\n id: number;\n /** Geometry ID this blend shape is attached to */\n geometryId: number;\n /** Channels (each is an animatable morph target) */\n channels: FBXBlendShapeChannelData[];\n}\n\n/**\n * Extract all blend shape deformers from the FBX scene.\n */\nexport function extractBlendShapes(objectMap: FBXObjectMap): FBXBlendShapeData[] {\n const blendShapes: FBXBlendShapeData[] = [];\n\n for (const [id, node] of Array.from(objectMap.objects)) {\n if (node.name === \"Deformer\" && getPropertyValue<string>(node, 2) === \"BlendShape\") {\n const bs = extractBlendShape(id, node, objectMap);\n if (bs) {\n blendShapes.push(bs);\n }\n }\n }\n\n return blendShapes;\n}\n\nfunction extractBlendShape(deformerId: number, _deformerNode: FBXNode, objectMap: FBXObjectMap): FBXBlendShapeData | null {\n // Find the geometry this blend shape is attached to\n const parent = objectMap.parentOf.get(deformerId);\n if (!parent) {\n return null;\n }\n\n const parentNode = objectMap.objects.get(parent.id);\n if (!parentNode || parentNode.name !== \"Geometry\") {\n return null;\n }\n\n const geometryId = parent.id;\n\n // Find BlendShapeChannel children\n const channels: FBXBlendShapeChannelData[] = [];\n const channelChildren = getChildren(objectMap, deformerId, \"Deformer\");\n\n for (const { id: channelId, node: channelNode } of channelChildren) {\n const subType = getPropertyValue<string>(channelNode, 2);\n if (subType !== \"BlendShapeChannel\") {\n continue;\n }\n\n const channelName = cleanFBXName(getPropertyValue<string>(channelNode, 1) ?? \"MorphTarget\");\n\n // Read DeformPercent from Properties70\n let deformPercent = 0;\n for (const entry of getPropertyEntries(channelNode)) {\n if (entry.name === \"DeformPercent\" && typeof entry.values[0] === \"number\") {\n deformPercent = entry.values[0];\n }\n }\n\n const rawFullWeights = extractFullWeights(channelNode);\n\n // Find connected Shape geometries\n const shapes: FBXShapeData[] = [];\n const shapeChildren = getChildren(objectMap, channelId, \"Geometry\");\n\n for (const { node: shapeNode } of shapeChildren) {\n const shapeSubType = getPropertyValue<string>(shapeNode, 2);\n if (shapeSubType !== \"Shape\") {\n continue;\n }\n\n const shape = extractShape(shapeNode);\n if (shape) {\n shapes.push(shape);\n }\n }\n\n if (shapes.length > 0) {\n const diagnostics: FBXBlendShapeDiagnostic[] = [];\n const fullWeights = normalizeFullWeights(rawFullWeights, shapes, channelId, channelName, diagnostics);\n channels.push({\n name: channelName,\n id: channelId,\n deformPercent,\n shapes: sortShapesByFullWeight(shapes, fullWeights),\n fullWeights: fullWeights ? [...fullWeights].sort((a, b) => a - b) : null,\n diagnostics,\n });\n }\n }\n\n if (channels.length === 0) {\n return null;\n }\n\n return {\n id: deformerId,\n geometryId,\n channels,\n };\n}\n\nfunction extractFullWeights(channelNode: FBXNode): number[] | null {\n const fullWeightsNode = findChildByName(channelNode, \"FullWeights\");\n const rawFullWeights = getNodeArray(fullWeightsNode);\n if (!rawFullWeights) {\n return null;\n }\n\n if (rawFullWeights instanceof Float64Array || rawFullWeights instanceof Float32Array || rawFullWeights instanceof Int32Array) {\n return Array.from(rawFullWeights, (value) => Number(value));\n }\n return null;\n}\n\nfunction normalizeFullWeights(\n fullWeights: number[] | null,\n shapes: FBXShapeData[],\n channelId: number,\n channelName: string,\n diagnostics: FBXBlendShapeDiagnostic[]\n): number[] | null {\n if (!fullWeights) {\n if (shapes.length > 1) {\n diagnostics.push({\n type: \"missing-full-weights\",\n message: \"Blend shape channel has multiple shapes but no FullWeights; using the first shape for compatibility.\",\n channelId,\n channelName,\n });\n }\n return null;\n }\n\n if (fullWeights.length !== shapes.length) {\n if (shapes.length === 1) {\n return null;\n }\n\n diagnostics.push({\n type: \"full-weights-mismatch\",\n message: `FullWeights length ${fullWeights.length} does not match shape count ${shapes.length}; using the first shape for compatibility.`,\n channelId,\n channelName,\n });\n return null;\n }\n\n return fullWeights;\n}\n\nfunction sortShapesByFullWeight(shapes: FBXShapeData[], fullWeights: number[] | null): FBXShapeData[] {\n if (!fullWeights || fullWeights.length !== shapes.length) {\n return shapes.length > 1 ? [shapes[0]] : shapes;\n }\n\n return shapes\n .map((shape, index) => ({ shape, weight: fullWeights[index] }))\n .sort((a, b) => a.weight - b.weight)\n .map((entry) => entry.shape);\n}\n\nfunction extractShape(shapeNode: FBXNode): FBXShapeData | null {\n // Shape has: Indexes (sparse vertex indices), Vertices (delta offsets from base), Normals (optional delta)\n const indexesNode = findChildByName(shapeNode, \"Indexes\");\n const verticesNode = findChildByName(shapeNode, \"Vertices\");\n\n if (!indexesNode || !verticesNode) {\n return null;\n }\n\n const rawIndices = getNodeArray(indexesNode);\n const rawVertices = getNodeArray(verticesNode);\n\n if (!rawIndices || !rawVertices) {\n return null;\n }\n\n const indices = toUint32Array(rawIndices);\n if (!indices) {\n return null;\n }\n\n // Convert vertices\n let vertices: Float64Array;\n if (rawVertices instanceof Float64Array) {\n vertices = rawVertices;\n } else if (rawVertices instanceof Float32Array) {\n vertices = new Float64Array(rawVertices);\n } else {\n return null;\n }\n\n // Optional normals\n let normals: Float64Array | null = null;\n const normalsNode = findChildByName(shapeNode, \"Normals\");\n if (normalsNode) {\n const rawNormals = getNodeArray(normalsNode);\n if (rawNormals instanceof Float64Array) {\n normals = rawNormals;\n } else if (rawNormals instanceof Float32Array) {\n normals = new Float64Array(rawNormals);\n }\n }\n\n return { indices, vertices, normals };\n}\n\nfunction toUint32Array(value: unknown): Uint32Array | null {\n if (value instanceof Uint32Array) {\n return value;\n }\n if (value instanceof Int32Array || value instanceof Float32Array || value instanceof Float64Array) {\n const result = new Uint32Array(value.length);\n for (let i = 0; i < value.length; i++) {\n result[i] = value[i];\n }\n return result;\n }\n return null;\n}\n"]}
@@ -19,7 +19,7 @@ export interface FBXObjectEntry {
19
19
  /** Object node. */
20
20
  node: FBXNode;
21
21
  /** Source of the object entry. */
22
- source: "Objects" | "legacySyntheticGeometry";
22
+ source: "Objects" | "legacySyntheticGeometry" | "legacySyntheticAttribute" | "legacySyntheticBlendShape";
23
23
  /** Legacy string object name, when applicable. */
24
24
  legacyName?: string;
25
25
  /** True if the object was synthesized for legacy compatibility. */
@@ -12,14 +12,85 @@ export function resolveConnections(doc) {
12
12
  const connections = [];
13
13
  const connectionEntries = [];
14
14
  const diagnostics = [];
15
+ // Legacy (6.x and older) objects are identified by their full "Class::Name" string, exactly as the SDK does,
16
+ // so that a material, texture and video sharing a base name stay distinct. Connections that only carry the
17
+ // bare name fall back to the first object with that name.
15
18
  const legacyIds = new Map();
19
+ const legacyIdsByCleanName = new Map();
16
20
  const syntheticLegacyIds = new Map();
17
- let nextLegacyId = -1;
18
- const getLegacyId = (name) => {
19
- let id = legacyIds.get(name);
21
+ const legacyGeometryByModelId = new Map();
22
+ // Every numeric id the file uses is reserved up front so that synthetic ids (legacy objects, inline shapes)
23
+ // and the stand-ins for ids beyond 2^53 never collide with a real object.
24
+ const objectsNode = findDocumentNode(doc, "Objects");
25
+ const connectionsNode = findDocumentNode(doc, "Connections");
26
+ const usedIds = new Set();
27
+ const reserve = (property) => {
28
+ const value = property?.value;
29
+ if (typeof value === "number" && Number.isSafeInteger(value)) {
30
+ usedIds.add(value);
31
+ }
32
+ };
33
+ for (const obj of objectsNode?.children ?? []) {
34
+ reserve(obj.properties[0]);
35
+ }
36
+ for (const c of connectionsNode?.children ?? []) {
37
+ reserve(c.properties[1]);
38
+ reserve(c.properties[2]);
39
+ reserve(c.properties[3]);
40
+ }
41
+ let nextSyntheticId = -1;
42
+ const allocateId = () => {
43
+ while (usedIds.has(nextSyntheticId)) {
44
+ nextSyntheticId--;
45
+ }
46
+ const id = nextSyntheticId--;
47
+ usedIds.add(id);
48
+ return id;
49
+ };
50
+ // Ids whose magnitude exceeds 2^53 are keyed by their exact decimal text; distinct texts get distinct ids.
51
+ const remappedIds = new Map();
52
+ const numericIdOf = (property) => {
53
+ if (!property) {
54
+ return undefined;
55
+ }
56
+ if (property.raw !== undefined) {
57
+ let id = remappedIds.get(property.raw);
58
+ if (id === undefined) {
59
+ id = allocateId();
60
+ remappedIds.set(property.raw, id);
61
+ }
62
+ return id;
63
+ }
64
+ return getSafeFBXObjectId(property.value);
65
+ };
66
+ const toObjectId = (property) => {
67
+ const numericId = numericIdOf(property);
68
+ if (numericId !== undefined) {
69
+ return numericId;
70
+ }
71
+ const value = property?.value;
72
+ if (typeof value !== "string") {
73
+ return undefined;
74
+ }
75
+ const direct = legacyIds.get(value);
76
+ if (direct !== undefined) {
77
+ return direct;
78
+ }
79
+ const legacyName = cleanFBXName(value);
80
+ if (legacyName === "Scene") {
81
+ return 0;
82
+ }
83
+ return legacyIdsByCleanName.get(legacyName);
84
+ };
85
+ const getLegacyId = (rawName) => {
86
+ let id = legacyIds.get(rawName);
20
87
  if (id === undefined) {
21
- id = nextLegacyId--;
22
- legacyIds.set(name, id);
88
+ id = allocateId();
89
+ legacyIds.set(rawName, id);
90
+ const clean = cleanFBXName(rawName);
91
+ if (!legacyIdsByCleanName.has(clean)) {
92
+ legacyIdsByCleanName.set(clean, id);
93
+ }
23
94
  }
24
95
  return id;
25
96
  };
@@ -31,50 +102,117 @@ export function resolveConnections(doc) {
31
102
  }
32
103
  let id = idsByName.get(name);
33
104
  if (id === undefined) {
34
- id = nextLegacyId--;
105
+ id = allocateId();
35
106
  idsByName.set(name, id);
36
107
  }
37
108
  return id;
38
109
  };
110
+ /** Turns `Shape` children of a geometry into a BlendShape deformer with one channel and shape geometry each. */
111
+ const synthesizeInlineShapes = (owner, geometryId, key) => {
112
+ const shapes = owner.children.filter((c) => c.name === "Shape");
113
+ if (shapes.length === 0) {
114
+ return;
115
+ }
116
+ const deformerId = getSyntheticLegacyId("BlendShape", key);
117
+ const deformer = createLegacyObject("Deformer", deformerId, `Deformer::${cleanFBXName(key)}`, "BlendShape", [createVersionNode(100)]);
118
+ objects.set(deformerId, deformer);
119
+ objectEntries.push({ id: deformerId, node: deformer, source: "legacySyntheticBlendShape", legacyName: key, synthetic: true });
120
+ addConnection(connections, childrenOf, parentOf, diagnostics, "OO", deformerId, geometryId);
121
+ for (const shape of shapes) {
122
+ const shapeName = cleanFBXName(getPropertyValue(shape, 0) ?? "Shape");
123
+ const channelId = getSyntheticLegacyId("BlendShapeChannel", `${key}|${shapeName}`);
124
+ const channel = createLegacyObject("Deformer", channelId, `SubDeformer::${shapeName}`, "BlendShapeChannel", [
125
+ createVersionNode(100),
126
+ { name: "DeformPercent", properties: [{ type: "float64", value: 0 }], children: [] },
127
+ {
128
+ name: "Properties60",
129
+ properties: [],
130
+ children: [
131
+ {
132
+ name: "Property",
133
+ properties: [
134
+ { type: "string", value: "DeformPercent" },
135
+ { type: "string", value: "Number" },
136
+ { type: "string", value: "A" },
137
+ { type: "float64", value: 0 },
138
+ ],
139
+ children: [],
140
+ },
141
+ ],
142
+ },
143
+ ]);
144
+ objects.set(channelId, channel);
145
+ objectEntries.push({ id: channelId, node: channel, source: "legacySyntheticBlendShape", legacyName: `${key}|${shapeName}`, synthetic: true });
146
+ addConnection(connections, childrenOf, parentOf, diagnostics, "OO", channelId, deformerId);
147
+ const shapeId = getSyntheticLegacyId("Shape", `${key}|${shapeName}`);
148
+ const shapeGeometry = createLegacyObject("Geometry", shapeId, `Geometry::${shapeName}`, "Shape", shape.children);
149
+ objects.set(shapeId, shapeGeometry);
150
+ objectEntries.push({ id: shapeId, node: shapeGeometry, source: "legacySyntheticBlendShape", legacyName: `${key}|${shapeName}`, synthetic: true });
151
+ addConnection(connections, childrenOf, parentOf, diagnostics, "OO", shapeId, channelId);
152
+ }
153
+ };
39
154
  // Build object map from Objects section
40
- const objectsNode = findDocumentNode(doc, "Objects");
41
155
  if (objectsNode) {
42
156
  for (const obj of objectsNode.children) {
43
157
  const idProp = obj.properties[0];
44
158
  if (idProp) {
45
- const id = toObjectNumber(idProp.value);
159
+ const id = numericIdOf(idProp);
46
160
  if (id !== undefined) {
47
161
  objects.set(id, obj);
48
162
  objectEntries.push({ id, node: obj, source: "Objects", synthetic: false });
163
+ if (obj.name === "Geometry" && getPropertyValue(obj, 2) === "Mesh") {
164
+ // FBX 7.1 stores blend shapes inline in the geometry, like 6.x files.
165
+ synthesizeInlineShapes(obj, id, String(id));
166
+ }
49
167
  }
50
168
  else if (typeof idProp.value === "string") {
51
- const legacyName = cleanFBXName(idProp.value);
169
+ const legacyName = idProp.value;
52
170
  const id = getLegacyId(legacyName);
53
171
  const normalized = normalizeLegacyObject(obj, id);
54
172
  objects.set(id, normalized);
55
173
  objectEntries.push({ id, node: normalized, source: "Objects", legacyName, synthetic: false });
56
- if (obj.name === "Model" && getPropertyValue(obj, 1) === "Mesh") {
174
+ const legacySubType = obj.name === "Model" ? getPropertyValue(obj, 1) : undefined;
175
+ if (legacySubType === "Mesh") {
57
176
  const geometryId = getSyntheticLegacyId("Geometry", legacyName);
58
177
  const geometry = createLegacyGeometry(obj, geometryId);
59
178
  objects.set(geometryId, geometry);
60
179
  objectEntries.push({ id: geometryId, node: geometry, source: "legacySyntheticGeometry", legacyName, synthetic: true });
61
180
  addConnection(connections, childrenOf, parentOf, diagnostics, "OO", geometryId, id);
181
+ legacyGeometryByModelId.set(id, geometryId);
182
+ // Inline blend shapes become a BlendShape deformer with one channel and one shape geometry each.
183
+ synthesizeInlineShapes(obj, geometryId, legacyName);
184
+ }
185
+ else if (legacySubType === "Light" || legacySubType === "Camera") {
186
+ // 6.x lights and cameras keep their attribute properties on the model; expose them as a NodeAttribute.
187
+ const attributeId = getSyntheticLegacyId("NodeAttribute", legacyName);
188
+ const attribute = createLegacyObject("NodeAttribute", attributeId, `NodeAttribute::${cleanFBXName(legacyName)}`, legacySubType, obj.children);
189
+ objects.set(attributeId, attribute);
190
+ objectEntries.push({ id: attributeId, node: attribute, source: "legacySyntheticAttribute", legacyName, synthetic: true });
191
+ addConnection(connections, childrenOf, parentOf, diagnostics, "OO", attributeId, id);
62
192
  }
63
193
  }
64
194
  }
65
195
  }
66
196
  }
67
197
  // Parse connections
68
- const connectionsNode = findDocumentNode(doc, "Connections");
69
198
  if (connectionsNode) {
70
199
  for (const c of connectionsNode.children) {
71
200
  if (c.name !== "C" && c.name !== "Connect") {
72
201
  continue;
73
202
  }
74
203
  const connectionIndex = connectionEntries.length;
75
- const type = getPropertyValue(c, 0);
76
- const childIdRaw = c.properties[1]?.value;
77
- const parentIdRaw = c.properties[2]?.value;
204
+ let type = getPropertyValue(c, 0);
205
+ let childIdRaw = c.properties[1];
206
+ let parentIdRaw = c.properties[2];
207
+ let poPropertyName;
208
+ // "PO" connects a property of the first object to the second object (6.x constraints use it for
209
+ // "Constrained Object"); it is the mirror image of "OP", so store it as OP from the object to the owner.
210
+ if (type === "PO" && typeof c.properties[2]?.value === "string" && c.properties.length > 3) {
211
+ type = "OP";
212
+ poPropertyName = c.properties[2].value;
213
+ childIdRaw = c.properties[3];
214
+ parentIdRaw = c.properties[1];
215
+ }
78
216
  const entry = {
79
217
  source: c.name,
80
218
  rawType: type,
@@ -82,8 +220,8 @@ export function resolveConnections(doc) {
82
220
  };
83
221
  connectionEntries.push(entry);
84
222
  if (type !== "OO" && type !== "OP") {
85
- const childId = childIdRaw === undefined ? undefined : toObjectId(childIdRaw, legacyIds);
86
- const parentId = parentIdRaw === undefined ? undefined : toObjectId(parentIdRaw, legacyIds);
223
+ const childId = toObjectId(childIdRaw);
224
+ const parentId = toObjectId(parentIdRaw);
87
225
  diagnostics.push({
88
226
  reason: "unsupported-connection-type",
89
227
  message: `Unsupported FBX connection type '${type ?? ""}' was not added to the graph.`,
@@ -103,8 +241,12 @@ export function resolveConnections(doc) {
103
241
  });
104
242
  continue;
105
243
  }
106
- const childId = toObjectId(childIdRaw, legacyIds);
107
- const parentId = toObjectId(parentIdRaw, legacyIds);
244
+ const childId = toObjectId(childIdRaw);
245
+ let parentId = toObjectId(parentIdRaw);
246
+ // 6.x deformers connect to the model; the importer expects them on the geometry.
247
+ if (childId !== undefined && parentId !== undefined && objects.get(childId)?.name === "Deformer") {
248
+ parentId = legacyGeometryByModelId.get(parentId) ?? parentId;
249
+ }
108
250
  if (childId === undefined || parentId === undefined) {
109
251
  diagnostics.push({
110
252
  reason: "unresolved-legacy-endpoint",
@@ -114,7 +256,7 @@ export function resolveConnections(doc) {
114
256
  });
115
257
  continue;
116
258
  }
117
- const propertyName = type === "OP" && c.properties.length > 3 ? getPropertyValue(c, 3) : undefined;
259
+ const propertyName = poPropertyName ?? (type === "OP" && c.properties.length > 3 ? getPropertyValue(c, 3) : undefined);
118
260
  entry.childId = childId;
119
261
  entry.parentId = parentId;
120
262
  entry.propertyName = propertyName;
@@ -169,22 +311,19 @@ export function getChildren(map, parentId, nodeName) {
169
311
  }
170
312
  return result;
171
313
  }
172
- function toObjectNumber(value) {
173
- return getSafeFBXObjectId(value);
314
+ function createVersionNode(version) {
315
+ return { name: "Version", properties: [{ type: "int32", value: version }], children: [] };
174
316
  }
175
- function toObjectId(value, legacyIds) {
176
- const numericId = toObjectNumber(value);
177
- if (numericId !== undefined) {
178
- return numericId;
179
- }
180
- if (typeof value !== "string") {
181
- return undefined;
182
- }
183
- const legacyName = cleanFBXName(value);
184
- if (legacyName === "Scene") {
185
- return 0;
186
- }
187
- return legacyIds.get(legacyName);
317
+ function createLegacyObject(nodeName, id, name, subType, children) {
318
+ return {
319
+ name: nodeName,
320
+ properties: [
321
+ { type: "int64", value: id },
322
+ { type: "string", value: name },
323
+ { type: "string", value: subType },
324
+ ],
325
+ children,
326
+ };
188
327
  }
189
328
  function addConnection(connections, childrenOf, parentOf, diagnostics, type, childId, parentId, propertyName, connectionIndex) {
190
329
  connections.push({ type, childId, parentId, propertyName });