import "@babylonjs/loaders/glTF"; import { Animation } from "@babylonjs/core/Animations/animation.js"; import { AnimationPropertyInfo } from "@babylonjs/loaders/glTF/2.0/glTFLoaderAnimation.js"; import { SetInterpolationForKey } from "@babylonjs/loaders/glTF/2.0/Extensions/objectModelMapping.js"; // Babylon 9.25.0 registers metallicFactor twice and omits roughnessFactor. // Its metallic-roughness texture pointer paths also omit KHR_texture_transform. // Keep these corrections covered by actual glTF animation playback tests. class MaterialProperty extends AnimationPropertyInfo { buildAnimations(target: any, name: string, fps: number, keys: any[]) { return Object.values(target._data || {}).map((data: any) => ({ babylonAnimatable: data.babylonMaterial, babylonAnimation: this._buildAnimation(name, fps, keys), })); } } const scalar = (property: string, index = 0, stride = 1) => new MaterialProperty( Animation.ANIMATIONTYPE_FLOAT, property, (_target, source, offset, scale) => source[offset + index] * scale, () => stride, ); SetInterpolationForKey("/materials/{}/pbrMetallicRoughness/metallicFactor", [scalar("metallic")]); SetInterpolationForKey("/materials/{}/pbrMetallicRoughness/roughnessFactor", [scalar("roughness")]); const texturePath = "/materials/{}/pbrMetallicRoughness/metallicRoughnessTexture/extensions/KHR_texture_transform/"; SetInterpolationForKey(texturePath + "offset", [scalar("metallicTexture.uOffset", 0, 2), scalar("metallicTexture.vOffset", 1, 2)]); SetInterpolationForKey(texturePath + "scale", [scalar("metallicTexture.uScale", 0, 2), scalar("metallicTexture.vScale", 1, 2)]); SetInterpolationForKey(texturePath + "rotation", [new MaterialProperty(Animation.ANIMATIONTYPE_FLOAT, "metallicTexture.wAng", (_t, s, o, scale) => -s[o] * scale, () => 1)]); // xmag/ymag are scalar half-extents; both sides use the same sample. class CameraProperty extends AnimationPropertyInfo { buildAnimations(target: any, name: string, fps: number, keys: any[]) { return [{ babylonAnimatable: target._babylonCamera, babylonAnimation: this._buildAnimation(name, fps, keys) }]; } } for (const [axis, negative, positive] of [["xmag", "orthoLeft", "orthoRight"], ["ymag", "orthoBottom", "orthoTop"]]) { SetInterpolationForKey(`/cameras/{}/orthographic/${axis}`, [ new CameraProperty(Animation.ANIMATIONTYPE_FLOAT, negative, (_t, s, o, scale) => -s[o] * scale, () => 1), new CameraProperty(Animation.ANIMATIONTYPE_FLOAT, positive, (_t, s, o, scale) => s[o] * scale, () => 1), ]); }