207 lines
7.2 KiB
JavaScript
207 lines
7.2 KiB
JavaScript
define([
|
|
'../Core/Cartesian3',
|
|
'../Core/ComponentDatatype',
|
|
'../Core/defaultValue',
|
|
'../Core/defined',
|
|
'../Core/LinearSpline',
|
|
'../Core/Matrix4',
|
|
'../Core/Quaternion',
|
|
'../Core/QuaternionSpline',
|
|
'../Core/WebGLConstants',
|
|
'../Core/WeightSpline',
|
|
'../ThirdParty/GltfPipeline/getAccessorByteStride',
|
|
'../ThirdParty/GltfPipeline/numberOfComponentsForType',
|
|
'./AttributeType'
|
|
], function(
|
|
Cartesian3,
|
|
ComponentDatatype,
|
|
defaultValue,
|
|
defined,
|
|
LinearSpline,
|
|
Matrix4,
|
|
Quaternion,
|
|
QuaternionSpline,
|
|
WebGLConstants,
|
|
WeightSpline,
|
|
getAccessorByteStride,
|
|
numberOfComponentsForType,
|
|
AttributeType) {
|
|
'use strict';
|
|
|
|
/**
|
|
* @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;
|
|
};
|
|
|
|
return ModelAnimationCache;
|
|
});
|