cesium
Version:
CesiumJS is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.
189 lines (156 loc) • 7.29 kB
JavaScript
import Cartesian3 from '../Core/Cartesian3.js';
import ComponentDatatype from '../Core/ComponentDatatype.js';
import defaultValue from '../Core/defaultValue.js';
import defined from '../Core/defined.js';
import LinearSpline from '../Core/LinearSpline.js';
import Matrix4 from '../Core/Matrix4.js';
import Quaternion from '../Core/Quaternion.js';
import QuaternionSpline from '../Core/QuaternionSpline.js';
import WebGLConstants from '../Core/WebGLConstants.js';
import WeightSpline from '../Core/WeightSpline.js';
import getAccessorByteStride from '../ThirdParty/GltfPipeline/getAccessorByteStride.js';
import numberOfComponentsForType from '../ThirdParty/GltfPipeline/numberOfComponentsForType.js';
import AttributeType from './AttributeType.js';
/**
* @private
*/
function ModelAnimationCache() {
}
var dataUriRegex = /^data\:/i;
function getAccessorKey(model, accessor) {
var gltf = model.gltf;
var buffers = gltf.buffers;
var bufferViews = gltf.bufferViews;
var bufferView = bufferViews[accessor.bufferView];
var buffer = buffers[bufferView.buffer];
var byteOffset = bufferView.byteOffset + accessor.byteOffset;
var byteLength = accessor.count * numberOfComponentsForType(accessor.type);
var uriKey = dataUriRegex.test(buffer.uri) ? '' : buffer.uri;
return model.cacheKey + '//' + uriKey + '/' + byteOffset + '/' + byteLength;
}
var cachedAnimationParameters = {
};
ModelAnimationCache.getAnimationParameterValues = function(model, accessor) {
var key = getAccessorKey(model, accessor);
var values = cachedAnimationParameters[key];
if (!defined(values)) {
// Cache miss
var gltf = model.gltf;
var buffers = gltf.buffers;
var bufferViews = gltf.bufferViews;
var bufferView = bufferViews[accessor.bufferView];
var bufferId = bufferView.buffer;
var buffer = buffers[bufferId];
var source = buffer.extras._pipeline.source;
var componentType = accessor.componentType;
var type = accessor.type;
var numberOfComponents = numberOfComponentsForType(type);
var count = accessor.count;
var byteStride = getAccessorByteStride(gltf, accessor);
values = new Array(count);
var accessorByteOffset = defaultValue(accessor.byteOffset, 0);
var byteOffset = bufferView.byteOffset + accessorByteOffset;
for (var i = 0; i < count; i++) {
var typedArrayView = ComponentDatatype.createArrayBufferView(componentType, source.buffer, source.byteOffset + byteOffset, numberOfComponents);
if (type === 'SCALAR') {
values[i] = typedArrayView[0];
} else if (type === 'VEC3') {
values[i] = Cartesian3.fromArray(typedArrayView);
} else if (type === 'VEC4') {
values[i] = Quaternion.unpack(typedArrayView);
}
byteOffset += byteStride;
}
// GLTF_SPEC: Support more parameter types when glTF supports targeting materials. https://github.com/KhronosGroup/glTF/issues/142
if (defined(model.cacheKey)) {
// Only cache when we can create a unique id
cachedAnimationParameters[key] = values;
}
}
return values;
};
var cachedAnimationSplines = {
};
function getAnimationSplineKey(model, animationName, samplerName) {
return model.cacheKey + '//' + animationName + '/' + samplerName;
}
function ConstantSpline(value) {
this._value = value;
}
ConstantSpline.prototype.evaluate = function(time, result) {
return this._value;
};
ConstantSpline.prototype.wrapTime = function(time) {
return 0.0;
};
ConstantSpline.prototype.clampTime = function(time) {
return 0.0;
};
ModelAnimationCache.getAnimationSpline = function(model, animationName, animation, samplerName, sampler, input, path, output) {
var key = getAnimationSplineKey(model, animationName, samplerName);
var spline = cachedAnimationSplines[key];
if (!defined(spline)) {
var times = input;
var controlPoints = output;
if ((times.length === 1) && (controlPoints.length === 1)) {
spline = new ConstantSpline(controlPoints[0]);
} else if (sampler.interpolation === 'LINEAR') {
if (path === 'translation' || path === 'scale') {
spline = new LinearSpline({
times : times,
points : controlPoints
});
} else if (path === 'rotation') {
spline = new QuaternionSpline({
times : times,
points : controlPoints
});
} else if (path === 'weights') {
spline = new WeightSpline({
times : times,
weights : controlPoints
});
}
// GLTF_SPEC: Support more parameter types when glTF supports targeting materials. https://github.com/KhronosGroup/glTF/issues/142
}
if (defined(model.cacheKey)) {
// Only cache when we can create a unique id
cachedAnimationSplines[key] = spline;
}
}
return spline;
};
var cachedSkinInverseBindMatrices = {
};
ModelAnimationCache.getSkinInverseBindMatrices = function(model, accessor) {
var key = getAccessorKey(model, accessor);
var matrices = cachedSkinInverseBindMatrices[key];
if (!defined(matrices)) {
// Cache miss
var gltf = model.gltf;
var buffers = gltf.buffers;
var bufferViews = gltf.bufferViews;
var bufferViewId = accessor.bufferView;
var bufferView = bufferViews[bufferViewId];
var bufferId = bufferView.buffer;
var buffer = buffers[bufferId];
var source = buffer.extras._pipeline.source;
var componentType = accessor.componentType;
var type = accessor.type;
var count = accessor.count;
var byteStride = getAccessorByteStride(gltf, accessor);
var byteOffset = bufferView.byteOffset + accessor.byteOffset;
var numberOfComponents = numberOfComponentsForType(type);
matrices = new Array(count);
if ((componentType === WebGLConstants.FLOAT) && (type === AttributeType.MAT4)) {
for (var i = 0; i < count; ++i) {
var typedArrayView = ComponentDatatype.createArrayBufferView(componentType, source.buffer, source.byteOffset + byteOffset, numberOfComponents);
matrices[i] = Matrix4.fromArray(typedArrayView);
byteOffset += byteStride;
}
}
cachedSkinInverseBindMatrices[key] = matrices;
}
return matrices;
};
export default ModelAnimationCache;