Initial commit
This commit is contained in:
318
HTML/ThreeJS/node_modules/three/src/animation/PropertyMixer.js
generated
vendored
Normal file
318
HTML/ThreeJS/node_modules/three/src/animation/PropertyMixer.js
generated
vendored
Normal file
@@ -0,0 +1,318 @@
|
||||
import { Quaternion } from '../math/Quaternion.js';
|
||||
|
||||
class PropertyMixer {
|
||||
|
||||
constructor( binding, typeName, valueSize ) {
|
||||
|
||||
this.binding = binding;
|
||||
this.valueSize = valueSize;
|
||||
|
||||
let mixFunction,
|
||||
mixFunctionAdditive,
|
||||
setIdentity;
|
||||
|
||||
// buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ]
|
||||
//
|
||||
// interpolators can use .buffer as their .result
|
||||
// the data then goes to 'incoming'
|
||||
//
|
||||
// 'accu0' and 'accu1' are used frame-interleaved for
|
||||
// the cumulative result and are compared to detect
|
||||
// changes
|
||||
//
|
||||
// 'orig' stores the original state of the property
|
||||
//
|
||||
// 'add' is used for additive cumulative results
|
||||
//
|
||||
// 'work' is optional and is only present for quaternion types. It is used
|
||||
// to store intermediate quaternion multiplication results
|
||||
|
||||
switch ( typeName ) {
|
||||
|
||||
case 'quaternion':
|
||||
mixFunction = this._slerp;
|
||||
mixFunctionAdditive = this._slerpAdditive;
|
||||
setIdentity = this._setAdditiveIdentityQuaternion;
|
||||
|
||||
this.buffer = new Float64Array( valueSize * 6 );
|
||||
this._workIndex = 5;
|
||||
break;
|
||||
|
||||
case 'string':
|
||||
case 'bool':
|
||||
mixFunction = this._select;
|
||||
|
||||
// Use the regular mix function and for additive on these types,
|
||||
// additive is not relevant for non-numeric types
|
||||
mixFunctionAdditive = this._select;
|
||||
|
||||
setIdentity = this._setAdditiveIdentityOther;
|
||||
|
||||
this.buffer = new Array( valueSize * 5 );
|
||||
break;
|
||||
|
||||
default:
|
||||
mixFunction = this._lerp;
|
||||
mixFunctionAdditive = this._lerpAdditive;
|
||||
setIdentity = this._setAdditiveIdentityNumeric;
|
||||
|
||||
this.buffer = new Float64Array( valueSize * 5 );
|
||||
|
||||
}
|
||||
|
||||
this._mixBufferRegion = mixFunction;
|
||||
this._mixBufferRegionAdditive = mixFunctionAdditive;
|
||||
this._setIdentity = setIdentity;
|
||||
this._origIndex = 3;
|
||||
this._addIndex = 4;
|
||||
|
||||
this.cumulativeWeight = 0;
|
||||
this.cumulativeWeightAdditive = 0;
|
||||
|
||||
this.useCount = 0;
|
||||
this.referenceCount = 0;
|
||||
|
||||
}
|
||||
|
||||
// accumulate data in the 'incoming' region into 'accu<i>'
|
||||
accumulate( accuIndex, weight ) {
|
||||
|
||||
// note: happily accumulating nothing when weight = 0, the caller knows
|
||||
// the weight and shouldn't have made the call in the first place
|
||||
|
||||
const buffer = this.buffer,
|
||||
stride = this.valueSize,
|
||||
offset = accuIndex * stride + stride;
|
||||
|
||||
let currentWeight = this.cumulativeWeight;
|
||||
|
||||
if ( currentWeight === 0 ) {
|
||||
|
||||
// accuN := incoming * weight
|
||||
|
||||
for ( let i = 0; i !== stride; ++ i ) {
|
||||
|
||||
buffer[ offset + i ] = buffer[ i ];
|
||||
|
||||
}
|
||||
|
||||
currentWeight = weight;
|
||||
|
||||
} else {
|
||||
|
||||
// accuN := accuN + incoming * weight
|
||||
|
||||
currentWeight += weight;
|
||||
const mix = weight / currentWeight;
|
||||
this._mixBufferRegion( buffer, offset, 0, mix, stride );
|
||||
|
||||
}
|
||||
|
||||
this.cumulativeWeight = currentWeight;
|
||||
|
||||
}
|
||||
|
||||
// accumulate data in the 'incoming' region into 'add'
|
||||
accumulateAdditive( weight ) {
|
||||
|
||||
const buffer = this.buffer,
|
||||
stride = this.valueSize,
|
||||
offset = stride * this._addIndex;
|
||||
|
||||
if ( this.cumulativeWeightAdditive === 0 ) {
|
||||
|
||||
// add = identity
|
||||
|
||||
this._setIdentity();
|
||||
|
||||
}
|
||||
|
||||
// add := add + incoming * weight
|
||||
|
||||
this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride );
|
||||
this.cumulativeWeightAdditive += weight;
|
||||
|
||||
}
|
||||
|
||||
// apply the state of 'accu<i>' to the binding when accus differ
|
||||
apply( accuIndex ) {
|
||||
|
||||
const stride = this.valueSize,
|
||||
buffer = this.buffer,
|
||||
offset = accuIndex * stride + stride,
|
||||
|
||||
weight = this.cumulativeWeight,
|
||||
weightAdditive = this.cumulativeWeightAdditive,
|
||||
|
||||
binding = this.binding;
|
||||
|
||||
this.cumulativeWeight = 0;
|
||||
this.cumulativeWeightAdditive = 0;
|
||||
|
||||
if ( weight < 1 ) {
|
||||
|
||||
// accuN := accuN + original * ( 1 - cumulativeWeight )
|
||||
|
||||
const originalValueOffset = stride * this._origIndex;
|
||||
|
||||
this._mixBufferRegion(
|
||||
buffer, offset, originalValueOffset, 1 - weight, stride );
|
||||
|
||||
}
|
||||
|
||||
if ( weightAdditive > 0 ) {
|
||||
|
||||
// accuN := accuN + additive accuN
|
||||
|
||||
this._mixBufferRegionAdditive( buffer, offset, this._addIndex * stride, 1, stride );
|
||||
|
||||
}
|
||||
|
||||
for ( let i = stride, e = stride + stride; i !== e; ++ i ) {
|
||||
|
||||
if ( buffer[ i ] !== buffer[ i + stride ] ) {
|
||||
|
||||
// value has changed -> update scene graph
|
||||
|
||||
binding.setValue( buffer, offset );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// remember the state of the bound property and copy it to both accus
|
||||
saveOriginalState() {
|
||||
|
||||
const binding = this.binding;
|
||||
|
||||
const buffer = this.buffer,
|
||||
stride = this.valueSize,
|
||||
|
||||
originalValueOffset = stride * this._origIndex;
|
||||
|
||||
binding.getValue( buffer, originalValueOffset );
|
||||
|
||||
// accu[0..1] := orig -- initially detect changes against the original
|
||||
for ( let i = stride, e = originalValueOffset; i !== e; ++ i ) {
|
||||
|
||||
buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];
|
||||
|
||||
}
|
||||
|
||||
// Add to identity for additive
|
||||
this._setIdentity();
|
||||
|
||||
this.cumulativeWeight = 0;
|
||||
this.cumulativeWeightAdditive = 0;
|
||||
|
||||
}
|
||||
|
||||
// apply the state previously taken via 'saveOriginalState' to the binding
|
||||
restoreOriginalState() {
|
||||
|
||||
const originalValueOffset = this.valueSize * 3;
|
||||
this.binding.setValue( this.buffer, originalValueOffset );
|
||||
|
||||
}
|
||||
|
||||
_setAdditiveIdentityNumeric() {
|
||||
|
||||
const startIndex = this._addIndex * this.valueSize;
|
||||
const endIndex = startIndex + this.valueSize;
|
||||
|
||||
for ( let i = startIndex; i < endIndex; i ++ ) {
|
||||
|
||||
this.buffer[ i ] = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_setAdditiveIdentityQuaternion() {
|
||||
|
||||
this._setAdditiveIdentityNumeric();
|
||||
this.buffer[ this._addIndex * this.valueSize + 3 ] = 1;
|
||||
|
||||
}
|
||||
|
||||
_setAdditiveIdentityOther() {
|
||||
|
||||
const startIndex = this._origIndex * this.valueSize;
|
||||
const targetIndex = this._addIndex * this.valueSize;
|
||||
|
||||
for ( let i = 0; i < this.valueSize; i ++ ) {
|
||||
|
||||
this.buffer[ targetIndex + i ] = this.buffer[ startIndex + i ];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// mix functions
|
||||
|
||||
_select( buffer, dstOffset, srcOffset, t, stride ) {
|
||||
|
||||
if ( t >= 0.5 ) {
|
||||
|
||||
for ( let i = 0; i !== stride; ++ i ) {
|
||||
|
||||
buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_slerp( buffer, dstOffset, srcOffset, t ) {
|
||||
|
||||
Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );
|
||||
|
||||
}
|
||||
|
||||
_slerpAdditive( buffer, dstOffset, srcOffset, t, stride ) {
|
||||
|
||||
const workOffset = this._workIndex * stride;
|
||||
|
||||
// Store result in intermediate buffer offset
|
||||
Quaternion.multiplyQuaternionsFlat( buffer, workOffset, buffer, dstOffset, buffer, srcOffset );
|
||||
|
||||
// Slerp to the intermediate result
|
||||
Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t );
|
||||
|
||||
}
|
||||
|
||||
_lerp( buffer, dstOffset, srcOffset, t, stride ) {
|
||||
|
||||
const s = 1 - t;
|
||||
|
||||
for ( let i = 0; i !== stride; ++ i ) {
|
||||
|
||||
const j = dstOffset + i;
|
||||
|
||||
buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_lerpAdditive( buffer, dstOffset, srcOffset, t, stride ) {
|
||||
|
||||
for ( let i = 0; i !== stride; ++ i ) {
|
||||
|
||||
const j = dstOffset + i;
|
||||
|
||||
buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export { PropertyMixer };
|
||||
Reference in New Issue
Block a user