@babylonjs/loaders 5.16.0 → 5.18.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,281 @@
1
+ import { ArrayItem, GLTFLoader } from "../glTFLoader.js";
2
+ import { AnimationGroup } from "@babylonjs/core/Animations/animationGroup.js";
3
+ import { AnimationKeyInterpolation } from "@babylonjs/core/Animations/animationKey.js";
4
+ import { CoreAnimationPointerMap } from "./KHR_animation_pointer.map.js";
5
+ import { getDataAccessorElementCount } from "../glTFUtilities.js";
6
+ var NAME = GLTFLoader._KHRAnimationPointerName;
7
+ /**
8
+ * [Specification PR](https://github.com/KhronosGroup/glTF/pull/2147)
9
+ */
10
+ // eslint-disable-next-line @typescript-eslint/naming-convention
11
+ var KHR_animation_pointer = /** @class */ (function () {
12
+ /**
13
+ * @param loader
14
+ * @hidden
15
+ */
16
+ function KHR_animation_pointer(loader) {
17
+ /**
18
+ * used to gently ignore invalid pointer. If false, invalid pointer will throw exception.
19
+ */
20
+ this.ignoreInvalidPointer = true;
21
+ /**
22
+ * The name of this extension.
23
+ */
24
+ this.name = NAME;
25
+ this._loader = loader;
26
+ }
27
+ Object.defineProperty(KHR_animation_pointer.prototype, "enabled", {
28
+ /**
29
+ * Defines whether this extension is enabled.
30
+ */
31
+ get: function () {
32
+ return this._loader.isExtensionUsed(NAME);
33
+ },
34
+ enumerable: false,
35
+ configurable: true
36
+ });
37
+ /** @hidden */
38
+ KHR_animation_pointer.prototype.dispose = function () {
39
+ this._loader = null;
40
+ };
41
+ /**
42
+ * according to specification,
43
+ * It is not allowed to animate a glTFid property, as it does change the structure of the glTF in general
44
+ * It is not allowed to animate a name property in general.
45
+ * @param property
46
+ * @hidden
47
+ */
48
+ KHR_animation_pointer.prototype.accept = function (property) {
49
+ return property != "name";
50
+ };
51
+ KHR_animation_pointer.prototype.loadAnimationAsync = function (context, animation) {
52
+ // ensure an animation group is present.
53
+ if (!animation._babylonAnimationGroup) {
54
+ this._loader.babylonScene._blockEntityCollection = !!this._loader._assetContainer;
55
+ var group = new AnimationGroup(animation.name || "animation".concat(animation.index), this._loader.babylonScene);
56
+ group._parentContainer = this._loader._assetContainer;
57
+ this._loader.babylonScene._blockEntityCollection = false;
58
+ animation._babylonAnimationGroup = group;
59
+ }
60
+ var babylonAnimationGroup = animation._babylonAnimationGroup;
61
+ var promises = new Array();
62
+ ArrayItem.Assign(animation.channels);
63
+ ArrayItem.Assign(animation.samplers);
64
+ for (var _i = 0, _a = animation.channels; _i < _a.length; _i++) {
65
+ var channel = _a[_i];
66
+ promises.push(this._loadAnimationChannelAsync("".concat(context, "/channels/").concat(channel.index), context, animation, channel));
67
+ }
68
+ return Promise.all(promises).then(function () {
69
+ babylonAnimationGroup.normalize(0);
70
+ return babylonAnimationGroup;
71
+ });
72
+ };
73
+ /**
74
+ * @hidden Loads a glTF animation channel.
75
+ * @param context The context when loading the asset
76
+ * @param animationContext The context of the animation when loading the asset
77
+ * @param animation The glTF animation property
78
+ * @param channel The glTF animation channel property
79
+ * @param animationTargetOverride The babylon animation channel target override property. My be null.
80
+ * @returns A void promise when the channel load is complete
81
+ */
82
+ KHR_animation_pointer.prototype._loadAnimationChannelAsync = function (context, animationContext, animation, channel, animationTargetOverride) {
83
+ var _this = this;
84
+ var _a, _b;
85
+ if (animationTargetOverride === void 0) { animationTargetOverride = null; }
86
+ if (channel.target.path != "pointer" /* POINTER */) {
87
+ throw new Error("".concat(context, "/target/path: Invalid value (").concat(channel.target.path, ")"));
88
+ }
89
+ if (channel.target.node != undefined) {
90
+ // According to KHR_animation_pointer specification
91
+ // If this extension is used, the animation.channel.target.node must not be set.
92
+ // Because the node is defined, the channel is ignored and not animated due to the specification.
93
+ return Promise.resolve();
94
+ }
95
+ var pointer = (_b = (_a = channel.target.extensions) === null || _a === void 0 ? void 0 : _a.KHR_animation_pointer) === null || _b === void 0 ? void 0 : _b.pointer;
96
+ if (!pointer) {
97
+ throw new Error("".concat(context, "/target/extensions/").concat(this.name, ": Pointer is missing"));
98
+ }
99
+ var sampler = ArrayItem.Get("".concat(context, "/sampler"), animation.samplers, channel.sampler);
100
+ return this._loadAnimationSamplerAsync("".concat(context, "/samplers/").concat(channel.sampler), sampler).then(function (data) {
101
+ var _a;
102
+ // this is where we process the pointer.
103
+ var animationTarget = _this._parseAnimationPointer("".concat(context, "/extensions/").concat(_this.name, "/pointer"), pointer);
104
+ if (!animationTarget) {
105
+ return;
106
+ }
107
+ // build the keys
108
+ // build the animations into the group
109
+ var babylonAnimationGroup = animation._babylonAnimationGroup;
110
+ if (!babylonAnimationGroup) {
111
+ return;
112
+ }
113
+ var outputAccessor = ArrayItem.Get("".concat(context, "/output"), _this._loader.gltf.accessors, sampler.output);
114
+ // stride is the size of each element stored into the output buffer.
115
+ var stride = (_a = animationTarget.stride) !== null && _a !== void 0 ? _a : getDataAccessorElementCount(outputAccessor.type);
116
+ var fps = _this._loader.parent.targetFps;
117
+ // we extract the corresponding values from the read value.
118
+ // the reason for that is one GLTF value may be dispatched to several Babylon properties
119
+ // one of example is baseColorFactor which is a Color4 under GLTF and dispatched to
120
+ // - albedoColor as Color3(Color4.r,Color4.g,Color4.b)
121
+ // - alpha as Color4.a
122
+ for (var _i = 0, _b = animationTarget.properties; _i < _b.length; _i++) {
123
+ var propertyInfo = _b[_i];
124
+ // Ignore animations that have no animation valid targets.
125
+ if (!propertyInfo.isValid(animationTarget.target)) {
126
+ return;
127
+ }
128
+ // build the keys.
129
+ var keys = new Array(data.input.length);
130
+ var outputOffset = 0;
131
+ switch (data.interpolation) {
132
+ case "STEP" /* STEP */: {
133
+ for (var frameIndex = 0; frameIndex < data.input.length; frameIndex++) {
134
+ keys[frameIndex] = {
135
+ frame: data.input[frameIndex] * fps,
136
+ value: propertyInfo.get(animationTarget.target, data.output, outputOffset),
137
+ interpolation: AnimationKeyInterpolation.STEP,
138
+ };
139
+ outputOffset += stride;
140
+ }
141
+ break;
142
+ }
143
+ case "CUBICSPLINE" /* CUBICSPLINE */: {
144
+ var invfps = 1 / fps;
145
+ for (var frameIndex = 0; frameIndex < data.input.length; frameIndex++) {
146
+ var k = {
147
+ frame: data.input[frameIndex] * fps,
148
+ };
149
+ (k.inTangent = propertyInfo.get(animationTarget.target, data.output, outputOffset, invfps)), (outputOffset += stride);
150
+ (k.value = propertyInfo.get(animationTarget.target, data.output, outputOffset)), (outputOffset += stride);
151
+ (k.outTangent = propertyInfo.get(animationTarget.target, data.output, outputOffset, invfps)), (outputOffset += stride);
152
+ keys[frameIndex] = k;
153
+ }
154
+ break;
155
+ }
156
+ case "LINEAR" /* LINEAR */:
157
+ default: {
158
+ for (var frameIndex = 0; frameIndex < data.input.length; frameIndex++) {
159
+ keys[frameIndex] = {
160
+ frame: data.input[frameIndex] * fps,
161
+ value: propertyInfo.get(animationTarget.target, data.output, outputOffset),
162
+ };
163
+ outputOffset += stride;
164
+ }
165
+ break;
166
+ }
167
+ }
168
+ // each properties has its own build animation process.
169
+ // these logics are located into KHR_animation_pointer.map.ts
170
+ propertyInfo.buildAnimations(animationTarget.target, fps, keys, babylonAnimationGroup, animationTargetOverride, animationTarget.params);
171
+ }
172
+ });
173
+ };
174
+ KHR_animation_pointer.prototype._loadAnimationSamplerAsync = function (context, sampler) {
175
+ if (sampler._data) {
176
+ return sampler._data;
177
+ }
178
+ var interpolation = sampler.interpolation || "LINEAR" /* LINEAR */;
179
+ switch (interpolation) {
180
+ case "STEP" /* STEP */:
181
+ case "LINEAR" /* LINEAR */:
182
+ case "CUBICSPLINE" /* CUBICSPLINE */: {
183
+ break;
184
+ }
185
+ default: {
186
+ throw new Error("".concat(context, "/interpolation: Invalid value (").concat(sampler.interpolation, ")"));
187
+ }
188
+ }
189
+ var inputAccessor = ArrayItem.Get("".concat(context, "/input"), this._loader.gltf.accessors, sampler.input);
190
+ var outputAccessor = ArrayItem.Get("".concat(context, "/output"), this._loader.gltf.accessors, sampler.output);
191
+ sampler._data = Promise.all([
192
+ this._loader._loadFloatAccessorAsync("/accessors/".concat(inputAccessor.index), inputAccessor),
193
+ this._loader._loadFloatAccessorAsync("/accessors/".concat(outputAccessor.index), outputAccessor),
194
+ ]).then(function (_a) {
195
+ var inputData = _a[0], outputData = _a[1];
196
+ return {
197
+ input: inputData,
198
+ interpolation: interpolation,
199
+ output: outputData,
200
+ };
201
+ });
202
+ return sampler._data;
203
+ };
204
+ /**
205
+ * parsing animation pointer is the core of animation channel.
206
+ * Animation pointer is a Json pointer, which mean it locate an item into the json hierarchy.
207
+ * Consequentely the pointer has the following BNF
208
+
209
+ * <animationPointer> := <sep><assetContainer><sep><assetIndex><sep><propertyPath>
210
+ * <assetContainer> := "nodes" | "materials" | "meshes" | "cameras" | "extensions"
211
+ * <assetIndex> := <digit> | <name>
212
+ * <propertyPath> := <extensionPath> | <standardPath>
213
+ * <extensionPath> := "extensions"<sep><name><sep><standardPath>
214
+ * <standardPath> := <name> | <name><sep><standardPath>
215
+ * <sep>:= "/"
216
+ * <name> := W+
217
+ * <digit> := D+
218
+ *
219
+ * examples of pointer are
220
+ * - "/nodes/0/rotation"
221
+ * - "/materials/2/emissiveFactor"
222
+ * - "/materials/2/pbrMetallicRoughness/baseColorFactor"
223
+ * - "/materials/2/extensions/KHR_materials_emissive_strength/emissiveStrength"
224
+ * @param context
225
+ * @param pointer
226
+ * @return
227
+ */
228
+ KHR_animation_pointer.prototype._parseAnimationPointer = function (context, pointer) {
229
+ var sep = "/";
230
+ if (pointer.charAt(0) == sep) {
231
+ pointer = pointer.substring(1);
232
+ }
233
+ var parts = pointer.split(sep);
234
+ // we have a least 3 part
235
+ if (parts.length >= 3) {
236
+ var node = CoreAnimationPointerMap; // the map of possible path
237
+ var indices = [];
238
+ var getTarget = null;
239
+ for (var i = 0; i < parts.length; i++) {
240
+ var part = parts[i];
241
+ node = node[part];
242
+ if (!node) {
243
+ // nothing to do so far
244
+ break;
245
+ }
246
+ if (node.getTarget) {
247
+ getTarget = node.getTarget;
248
+ }
249
+ if (node.hasIndex) {
250
+ indices.push(parts[++i]);
251
+ // move to the next part
252
+ continue;
253
+ }
254
+ if (node.isIndex) {
255
+ indices.push(part);
256
+ // move to the next part
257
+ continue;
258
+ }
259
+ if (node.properties && getTarget) {
260
+ var t = getTarget(this._loader.gltf, indices[0]);
261
+ if (t != null) {
262
+ return {
263
+ target: t,
264
+ stride: node.getStride ? node.getStride(t) : undefined,
265
+ properties: node.properties,
266
+ params: indices,
267
+ };
268
+ }
269
+ }
270
+ }
271
+ }
272
+ if (this.ignoreInvalidPointer) {
273
+ return null;
274
+ }
275
+ throw new Error("".concat(context, " invalid pointer. ").concat(pointer));
276
+ };
277
+ return KHR_animation_pointer;
278
+ }());
279
+ export { KHR_animation_pointer };
280
+ GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_animation_pointer(loader); });
281
+ //# sourceMappingURL=KHR_animation_pointer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"KHR_animation_pointer.js","sourceRoot":"","sources":["../../../../../../../lts/loaders/generated/glTF/2.0/Extensions/KHR_animation_pointer.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { ArrayItem, GLTFLoader } from \"../glTFLoader\";\r\nimport type { Nullable } from \"core/types\";\r\nimport { AnimationGroup } from \"core/Animations/animationGroup\";\r\nimport type { IAnimatable } from \"core/Animations/animatable.interface\";\r\nimport type { IAnimation, IAnimationChannel, _IAnimationSamplerData, IAnimationSampler } from \"../glTFLoaderInterfaces\";\r\n\r\nimport { AnimationChannelTargetPath, AnimationSamplerInterpolation } from \"babylonjs-gltf2interface\";\r\nimport { AnimationKeyInterpolation } from \"core/Animations/animationKey\";\r\nimport { CoreAnimationPointerMap } from \"./KHR_animation_pointer.map\";\r\nimport type { GetGltfNodeTargetFn, IAnimationPointerPropertyInfos } from \"./KHR_animation_pointer.map\";\r\nimport { getDataAccessorElementCount } from \"../glTFUtilities\";\r\n\r\nconst NAME = GLTFLoader._KHRAnimationPointerName;\r\n\r\ninterface IAnimationChannelTarget {\r\n stride?: number;\r\n target: any;\r\n properties: Array<IAnimationPointerPropertyInfos>;\r\n params: any;\r\n}\r\n\r\n/**\r\n * [Specification PR](https://github.com/KhronosGroup/glTF/pull/2147)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_animation_pointer implements IGLTFLoaderExtension {\r\n /**\r\n * used to gently ignore invalid pointer. If false, invalid pointer will throw exception.\r\n */\r\n public ignoreInvalidPointer: boolean = true;\r\n\r\n /**\r\n * The name of this extension.\r\n */\r\n public readonly name = NAME;\r\n\r\n private _loader: GLTFLoader;\r\n\r\n /**\r\n * @param loader\r\n * @hidden\r\n */\r\n constructor(loader: GLTFLoader) {\r\n this._loader = loader;\r\n }\r\n\r\n /**\r\n * Defines whether this extension is enabled.\r\n */\r\n public get enabled(): boolean {\r\n return this._loader.isExtensionUsed(NAME);\r\n }\r\n\r\n /** @hidden */\r\n public dispose() {\r\n (this._loader as any) = null;\r\n }\r\n\r\n /**\r\n * according to specification,\r\n * It is not allowed to animate a glTFid property, as it does change the structure of the glTF in general\r\n * It is not allowed to animate a name property in general.\r\n * @param property\r\n * @hidden\r\n */\r\n public accept(property: string): boolean {\r\n return property != \"name\";\r\n }\r\n\r\n public loadAnimationAsync(context: string, animation: IAnimation): Nullable<Promise<AnimationGroup>> {\r\n // ensure an animation group is present.\r\n if (!animation._babylonAnimationGroup) {\r\n this._loader.babylonScene._blockEntityCollection = !!this._loader._assetContainer;\r\n const group = new AnimationGroup(animation.name || `animation${animation.index}`, this._loader.babylonScene);\r\n group._parentContainer = this._loader._assetContainer;\r\n this._loader.babylonScene._blockEntityCollection = false;\r\n animation._babylonAnimationGroup = group;\r\n }\r\n const babylonAnimationGroup = animation._babylonAnimationGroup;\r\n\r\n const promises = new Array<Promise<any>>();\r\n ArrayItem.Assign(animation.channels);\r\n ArrayItem.Assign(animation.samplers);\r\n\r\n for (const channel of animation.channels) {\r\n promises.push(this._loadAnimationChannelAsync(`${context}/channels/${channel.index}`, context, animation, channel));\r\n }\r\n\r\n return Promise.all(promises).then(() => {\r\n babylonAnimationGroup.normalize(0);\r\n return babylonAnimationGroup;\r\n });\r\n }\r\n\r\n /**\r\n * @hidden Loads a glTF animation channel.\r\n * @param context The context when loading the asset\r\n * @param animationContext The context of the animation when loading the asset\r\n * @param animation The glTF animation property\r\n * @param channel The glTF animation channel property\r\n * @param animationTargetOverride The babylon animation channel target override property. My be null.\r\n * @returns A void promise when the channel load is complete\r\n */\r\n public _loadAnimationChannelAsync(\r\n context: string,\r\n animationContext: string,\r\n animation: IAnimation,\r\n channel: IAnimationChannel,\r\n animationTargetOverride: Nullable<IAnimatable> = null\r\n ): Promise<void> {\r\n if (channel.target.path != AnimationChannelTargetPath.POINTER) {\r\n throw new Error(`${context}/target/path: Invalid value (${channel.target.path})`);\r\n }\r\n\r\n if (channel.target.node != undefined) {\r\n // According to KHR_animation_pointer specification\r\n // If this extension is used, the animation.channel.target.node must not be set.\r\n // Because the node is defined, the channel is ignored and not animated due to the specification.\r\n return Promise.resolve();\r\n }\r\n\r\n const pointer = channel.target.extensions?.KHR_animation_pointer?.pointer;\r\n if (!pointer) {\r\n throw new Error(`${context}/target/extensions/${this.name}: Pointer is missing`);\r\n }\r\n\r\n const sampler = ArrayItem.Get(`${context}/sampler`, animation.samplers, channel.sampler);\r\n\r\n return this._loadAnimationSamplerAsync(`${context}/samplers/${channel.sampler}`, sampler).then((data) => {\r\n // this is where we process the pointer.\r\n const animationTarget = this._parseAnimationPointer(`${context}/extensions/${this.name}/pointer`, pointer);\r\n\r\n if (!animationTarget) {\r\n return;\r\n }\r\n // build the keys\r\n // build the animations into the group\r\n const babylonAnimationGroup = animation._babylonAnimationGroup;\r\n if (!babylonAnimationGroup) {\r\n return;\r\n }\r\n\r\n const outputAccessor = ArrayItem.Get(`${context}/output`, this._loader.gltf.accessors, sampler.output);\r\n // stride is the size of each element stored into the output buffer.\r\n const stride = animationTarget.stride ?? getDataAccessorElementCount(outputAccessor.type);\r\n const fps = this._loader.parent.targetFps;\r\n\r\n // we extract the corresponding values from the read value.\r\n // the reason for that is one GLTF value may be dispatched to several Babylon properties\r\n // one of example is baseColorFactor which is a Color4 under GLTF and dispatched to\r\n // - albedoColor as Color3(Color4.r,Color4.g,Color4.b)\r\n // - alpha as Color4.a\r\n for (const propertyInfo of animationTarget.properties) {\r\n // Ignore animations that have no animation valid targets.\r\n if (!propertyInfo.isValid(animationTarget.target)) {\r\n return;\r\n }\r\n\r\n // build the keys.\r\n const keys = new Array(data.input.length);\r\n let outputOffset = 0;\r\n\r\n switch (data.interpolation) {\r\n case AnimationSamplerInterpolation.STEP: {\r\n for (let frameIndex = 0; frameIndex < data.input.length; frameIndex++) {\r\n keys[frameIndex] = {\r\n frame: data.input[frameIndex] * fps,\r\n value: propertyInfo.get(animationTarget.target, data.output, outputOffset),\r\n interpolation: AnimationKeyInterpolation.STEP,\r\n };\r\n outputOffset += stride;\r\n }\r\n break;\r\n }\r\n case AnimationSamplerInterpolation.CUBICSPLINE: {\r\n const invfps = 1 / fps;\r\n for (let frameIndex = 0; frameIndex < data.input.length; frameIndex++) {\r\n const k: any = {\r\n frame: data.input[frameIndex] * fps,\r\n };\r\n\r\n (k.inTangent = propertyInfo.get(animationTarget.target, data.output, outputOffset, invfps)), (outputOffset += stride);\r\n (k.value = propertyInfo.get(animationTarget.target, data.output, outputOffset)), (outputOffset += stride);\r\n (k.outTangent = propertyInfo.get(animationTarget.target, data.output, outputOffset, invfps)), (outputOffset += stride);\r\n\r\n keys[frameIndex] = k;\r\n }\r\n break;\r\n }\r\n case AnimationSamplerInterpolation.LINEAR:\r\n default: {\r\n for (let frameIndex = 0; frameIndex < data.input.length; frameIndex++) {\r\n keys[frameIndex] = {\r\n frame: data.input[frameIndex] * fps,\r\n value: propertyInfo.get(animationTarget.target, data.output, outputOffset),\r\n };\r\n outputOffset += stride;\r\n }\r\n break;\r\n }\r\n }\r\n\r\n // each properties has its own build animation process.\r\n // these logics are located into KHR_animation_pointer.map.ts\r\n propertyInfo.buildAnimations(animationTarget.target, fps, keys, babylonAnimationGroup, animationTargetOverride, animationTarget.params);\r\n }\r\n });\r\n }\r\n\r\n private _loadAnimationSamplerAsync(context: string, sampler: IAnimationSampler): Promise<_IAnimationSamplerData> {\r\n if (sampler._data) {\r\n return sampler._data;\r\n }\r\n\r\n const interpolation = sampler.interpolation || AnimationSamplerInterpolation.LINEAR;\r\n switch (interpolation) {\r\n case AnimationSamplerInterpolation.STEP:\r\n case AnimationSamplerInterpolation.LINEAR:\r\n case AnimationSamplerInterpolation.CUBICSPLINE: {\r\n break;\r\n }\r\n default: {\r\n throw new Error(`${context}/interpolation: Invalid value (${sampler.interpolation})`);\r\n }\r\n }\r\n\r\n const inputAccessor = ArrayItem.Get(`${context}/input`, this._loader.gltf.accessors, sampler.input);\r\n const outputAccessor = ArrayItem.Get(`${context}/output`, this._loader.gltf.accessors, sampler.output);\r\n sampler._data = Promise.all([\r\n this._loader._loadFloatAccessorAsync(`/accessors/${inputAccessor.index}`, inputAccessor),\r\n this._loader._loadFloatAccessorAsync(`/accessors/${outputAccessor.index}`, outputAccessor),\r\n ]).then(([inputData, outputData]) => {\r\n return {\r\n input: inputData,\r\n interpolation: interpolation,\r\n output: outputData,\r\n };\r\n });\r\n\r\n return sampler._data;\r\n }\r\n\r\n /**\r\n * parsing animation pointer is the core of animation channel.\r\n * Animation pointer is a Json pointer, which mean it locate an item into the json hierarchy.\r\n * Consequentely the pointer has the following BNF\r\n \r\n * <animationPointer> := <sep><assetContainer><sep><assetIndex><sep><propertyPath>\r\n * <assetContainer> := \"nodes\" | \"materials\" | \"meshes\" | \"cameras\" | \"extensions\" \r\n * <assetIndex> := <digit> | <name>\r\n * <propertyPath> := <extensionPath> | <standardPath>\r\n * <extensionPath> := \"extensions\"<sep><name><sep><standardPath>\r\n * <standardPath> := <name> | <name><sep><standardPath> \r\n * <sep>:= \"/\"\r\n * <name> := W+\r\n * <digit> := D+\r\n * \r\n * examples of pointer are\r\n * - \"/nodes/0/rotation\"\r\n * - \"/materials/2/emissiveFactor\"\r\n * - \"/materials/2/pbrMetallicRoughness/baseColorFactor\"\r\n * - \"/materials/2/extensions/KHR_materials_emissive_strength/emissiveStrength\"\r\n * @param context \r\n * @param pointer \r\n * @return \r\n */\r\n private _parseAnimationPointer(context: string, pointer: string): Nullable<IAnimationChannelTarget> {\r\n const sep = \"/\";\r\n if (pointer.charAt(0) == sep) {\r\n pointer = pointer.substring(1);\r\n }\r\n const parts = pointer.split(sep);\r\n // we have a least 3 part\r\n if (parts.length >= 3) {\r\n let node = CoreAnimationPointerMap; // the map of possible path\r\n const indices = [];\r\n let getTarget: Nullable<GetGltfNodeTargetFn> = null;\r\n for (let i = 0; i < parts.length; i++) {\r\n const part = parts[i];\r\n node = node[part];\r\n\r\n if (!node) {\r\n // nothing to do so far\r\n break;\r\n }\r\n\r\n if (node.getTarget) {\r\n getTarget = node.getTarget;\r\n }\r\n\r\n if (node.hasIndex) {\r\n indices.push(parts[++i]);\r\n // move to the next part\r\n continue;\r\n }\r\n\r\n if (node.isIndex) {\r\n indices.push(part);\r\n // move to the next part\r\n continue;\r\n }\r\n\r\n if (node.properties && getTarget) {\r\n const t = getTarget(this._loader.gltf, indices[0]);\r\n if (t != null) {\r\n return {\r\n target: t,\r\n stride: node.getStride ? node.getStride(t) : undefined,\r\n properties: node.properties,\r\n params: indices,\r\n };\r\n }\r\n }\r\n }\r\n }\r\n if (this.ignoreInvalidPointer) {\r\n return null;\r\n }\r\n throw new Error(`${context} invalid pointer. ${pointer}`);\r\n }\r\n}\r\n\r\nGLTFLoader.RegisterExtension(NAME, (loader) => new KHR_animation_pointer(loader));\r\n"]}
@@ -0,0 +1,15 @@
1
+ import type { AnimationGroup } from "@babylonjs/core/Animations/animationGroup.js";
2
+ import type { IGLTF } from "../glTFLoaderInterfaces";
3
+ import type { IAnimatable } from "@babylonjs/core/Animations/animatable.interface.js";
4
+ import type { Nullable } from "@babylonjs/core/types.js";
5
+ export declare type GetGltfNodeTargetFn = (source: IGLTF, indices: string) => any;
6
+ declare type GetValueFn = (target: any, source: Float32Array, offset: number, scale?: number) => any;
7
+ export interface IAnimationPointerPropertyInfos {
8
+ type: number;
9
+ name: string;
10
+ get: GetValueFn;
11
+ isValid(target: any): boolean;
12
+ buildAnimations(target: any, fps: number, keys: any[], group: AnimationGroup, animationTargetOverride: Nullable<IAnimatable>, params?: any): void;
13
+ }
14
+ export declare const CoreAnimationPointerMap: any;
15
+ export {};