123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- import Cartesian3 from "../Core/Cartesian3.js";
- import ComponentDatatype from "../Core/ComponentDatatype.js";
- import ConstantSpline from "../Core/ConstantSpline.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 MorphWeightSpline from "../Core/MorphWeightSpline.js";
- import Quaternion from "../Core/Quaternion.js";
- import QuaternionSpline from "../Core/QuaternionSpline.js";
- import Spline from "../Core/Spline.js";
- import WebGLConstants from "../Core/WebGLConstants.js";
- import getAccessorByteStride from "./GltfPipeline/getAccessorByteStride.js";
- import numberOfComponentsForType from "./GltfPipeline/numberOfComponentsForType.js";
- import AttributeType from "./AttributeType.js";
- /**
- * @private
- */
- function ModelAnimationCache() {}
- const dataUriRegex = /^data\:/i;
- function getAccessorKey(model, accessor) {
- const gltf = model.gltf;
- const buffers = gltf.buffers;
- const bufferViews = gltf.bufferViews;
- const bufferView = bufferViews[accessor.bufferView];
- const buffer = buffers[bufferView.buffer];
- const byteOffset = bufferView.byteOffset + accessor.byteOffset;
- const byteLength = accessor.count * numberOfComponentsForType(accessor.type);
- const uriKey = dataUriRegex.test(buffer.uri) ? "" : buffer.uri;
- return `${model.cacheKey}//${uriKey}/${byteOffset}/${byteLength}`;
- }
- const cachedAnimationParameters = {};
- ModelAnimationCache.getAnimationParameterValues = function (model, accessor) {
- const key = getAccessorKey(model, accessor);
- let values = cachedAnimationParameters[key];
- if (!defined(values)) {
- // Cache miss
- const gltf = model.gltf;
- const buffers = gltf.buffers;
- const bufferViews = gltf.bufferViews;
- const bufferView = bufferViews[accessor.bufferView];
- const bufferId = bufferView.buffer;
- const buffer = buffers[bufferId];
- const source = buffer.extras._pipeline.source;
- const componentType = accessor.componentType;
- const type = accessor.type;
- const numberOfComponents = numberOfComponentsForType(type);
- const count = accessor.count;
- const byteStride = getAccessorByteStride(gltf, accessor);
- values = new Array(count);
- const accessorByteOffset = defaultValue(accessor.byteOffset, 0);
- let byteOffset = bufferView.byteOffset + accessorByteOffset;
- for (let i = 0; i < count; i++) {
- const 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;
- };
- const cachedAnimationSplines = {};
- function getAnimationSplineKey(model, animationName, samplerName) {
- return `${model.cacheKey}//${animationName}/${samplerName}`;
- }
- function SteppedSpline(backingSpline) {
- this._spline = backingSpline;
- this._lastTimeIndex = 0;
- }
- SteppedSpline.prototype.findTimeInterval = Spline.prototype.findTimeInterval;
- SteppedSpline.prototype.evaluate = function (time, result) {
- const i = (this._lastTimeIndex = this.findTimeInterval(
- time,
- this._lastTimeIndex
- ));
- const times = this._spline.times;
- const steppedTime = time >= times[i + 1] ? times[i + 1] : times[i];
- return this._spline.evaluate(steppedTime, result);
- };
- Object.defineProperties(SteppedSpline.prototype, {
- times: {
- get: function () {
- return this._spline.times;
- },
- },
- });
- SteppedSpline.prototype.wrapTime = function (time) {
- return this._spline.wrapTime(time);
- };
- SteppedSpline.prototype.clampTime = function (time) {
- return this._spline.clampTime(time);
- };
- ModelAnimationCache.getAnimationSpline = function (
- model,
- animationName,
- animation,
- samplerName,
- sampler,
- input,
- path,
- output
- ) {
- const key = getAnimationSplineKey(model, animationName, samplerName);
- let spline = cachedAnimationSplines[key];
- if (!defined(spline)) {
- const times = input;
- const controlPoints = output;
- if (times.length === 1 && controlPoints.length === 1) {
- spline = new ConstantSpline(controlPoints[0]);
- } else if (
- sampler.interpolation === "LINEAR" ||
- sampler.interpolation === "STEP"
- ) {
- 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 MorphWeightSpline({
- times: times,
- weights: controlPoints,
- });
- }
- if (defined(spline) && sampler.interpolation === "STEP") {
- spline = new SteppedSpline(spline);
- }
- }
- if (defined(model.cacheKey)) {
- // Only cache when we can create a unique id
- cachedAnimationSplines[key] = spline;
- }
- }
- return spline;
- };
- const cachedSkinInverseBindMatrices = {};
- ModelAnimationCache.getSkinInverseBindMatrices = function (model, accessor) {
- const key = getAccessorKey(model, accessor);
- let matrices = cachedSkinInverseBindMatrices[key];
- if (!defined(matrices)) {
- // Cache miss
- const gltf = model.gltf;
- const buffers = gltf.buffers;
- const bufferViews = gltf.bufferViews;
- const bufferViewId = accessor.bufferView;
- const bufferView = bufferViews[bufferViewId];
- const bufferId = bufferView.buffer;
- const buffer = buffers[bufferId];
- const source = buffer.extras._pipeline.source;
- const componentType = accessor.componentType;
- const type = accessor.type;
- const count = accessor.count;
- const byteStride = getAccessorByteStride(gltf, accessor);
- let byteOffset = bufferView.byteOffset + accessor.byteOffset;
- const numberOfComponents = numberOfComponentsForType(type);
- matrices = new Array(count);
- if (componentType === WebGLConstants.FLOAT && type === AttributeType.MAT4) {
- for (let i = 0; i < count; ++i) {
- const 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;
|