nanogl-gltf
Version:
76 lines (75 loc) • 2.66 kB
JavaScript
import Gltf2 from '../types/Gltf2';
import GltfTypes from '../types/GltfTypes';
function applyTranslation(node, value) {
node.position.set(value);
node.invalidate();
}
function applyRotation(node, value) {
node.rotation.set(value);
node.invalidate();
}
function applyScale(node, value) {
node.scale.set(value);
node.invalidate();
}
function applyWeights(node, value) {
node.weights.set(value);
}
function getApplyFunctionFromPath(path) {
switch (path) {
case Gltf2.AnimationChannelTargetPath.TRANSLATION:
return applyTranslation;
case Gltf2.AnimationChannelTargetPath.ROTATION:
return applyRotation;
case Gltf2.AnimationChannelTargetPath.SCALE:
return applyScale;
case Gltf2.AnimationChannelTargetPath.WEIGHTS:
return applyWeights;
default:
throw new Error('unsupported path ' + path);
}
}
/**
* The AnimationChannel element contains the data to animate a node property.
*/
export default class AnimationChannel {
constructor() {
this.gltftype = GltfTypes.ANIMATION_CHANNEL;
}
/**
* Parse the AnimationChannel data, create the SamplerEvaluator and the valueHolder.
*
* Is async as it needs to wait for the target Node to be created.
* @param gltfLoader GLTFLoader to use
* @param data Data to parse
*/
async parse(gltfLoader, data) {
this._active = false;
this.path = data.target.path;
this.applyFunction = getApplyFunctionFromPath(this.path);
if (data.target.node !== undefined) {
this._active = true;
this.node = await gltfLoader.getElement(GltfTypes.NODE, data.target.node);
let numElems = 1;
if (this.path === Gltf2.AnimationChannelTargetPath.WEIGHTS) {
numElems = this.node.mesh.primitives[0].targets.length;
}
gltfLoader._loadElement(data.elementParent).then(animation => {
this.sampler = animation.getSampler(data.sampler);
this.evaluator = this.sampler.createEvaluator(this.path, numElems);
this.valueHolder = this.evaluator.createElementHolder();
});
}
}
/**
* Evaluate the animation at a given time, and apply the animation value to the corresponding node property,
* with the corresponding interpolation function.
* @param t Time to evaluate the animation at
*/
evaluate(t) {
if (this._active) {
this.evaluator.evaluate(this.valueHolder, t);
this.applyFunction(this.node, this.valueHolder);
}
}
}