| Server IP : 210.245.233.93 / Your IP : 216.73.216.226 Web Server : Apache/2.2.15 (CentOS) System : Linux webserver2.onesolution.com.hk 2.6.32-754.35.1.el6.x86_64 #1 SMP Sat Nov 7 12:42:14 UTC 2020 x86_64 User : apache ( 48) PHP Version : 5.3.3 Disable Function : exec, shell_exec, system, passthru, popen, proc_open, pcntl_exec MySQL : ON | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /var/www/hkosl.com/3dweb/src/animation/ |
Upload File : |
import { Quaternion } from '../math/Quaternion.js';
/**
*
* Buffered scene graph property that allows weighted accumulation.
*
*
* @author Ben Houston / http://clara.io/
* @author David Sarno / http://lighthaus.us/
* @author tschw
*/
function PropertyMixer( binding, typeName, valueSize ) {
this.binding = binding;
this.valueSize = valueSize;
var 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;
}
Object.assign( PropertyMixer.prototype, {
// accumulate data in the 'incoming' region into 'accu<i>'
accumulate: function ( 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
var buffer = this.buffer,
stride = this.valueSize,
offset = accuIndex * stride + stride,
currentWeight = this.cumulativeWeight;
if ( currentWeight === 0 ) {
// accuN := incoming * weight
for ( var i = 0; i !== stride; ++ i ) {
buffer[ offset + i ] = buffer[ i ];
}
currentWeight = weight;
} else {
// accuN := accuN + incoming * weight
currentWeight += weight;
var mix = weight / currentWeight;
this._mixBufferRegion( buffer, offset, 0, mix, stride );
}
this.cumulativeWeight = currentWeight;
},
// accumulate data in the 'incoming' region into 'add'
accumulateAdditive: function ( weight ) {
var 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: function ( accuIndex ) {
var 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 )
var 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 ( var 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: function () {
var binding = this.binding;
var 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 ( var 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: function () {
var originalValueOffset = this.valueSize * 3;
this.binding.setValue( this.buffer, originalValueOffset );
},
_setAdditiveIdentityNumeric: function () {
var startIndex = this._addIndex * this.valueSize;
this.buffer.fill( 0, startIndex, startIndex + this.valueSize );
},
_setAdditiveIdentityQuaternion: function () {
this._setAdditiveIdentityNumeric();
this.buffer[ this._addIndex * 4 + 3 ] = 1;
},
_setAdditiveIdentityOther: function () {
var startIndex = this._origIndex * this.valueSize;
var targetIndex = this._addIndex * this.valueSize;
this.buffer.copyWithin( targetIndex, startIndex, this.valueSize );
},
// mix functions
_select: function ( buffer, dstOffset, srcOffset, t, stride ) {
if ( t >= 0.5 ) {
for ( var i = 0; i !== stride; ++ i ) {
buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
}
}
},
_slerp: function ( buffer, dstOffset, srcOffset, t ) {
Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );
},
_slerpAdditive: function ( buffer, dstOffset, srcOffset, t, stride ) {
var 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: function ( buffer, dstOffset, srcOffset, t, stride ) {
var s = 1 - t;
for ( var i = 0; i !== stride; ++ i ) {
var j = dstOffset + i;
buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
}
},
_lerpAdditive: function ( buffer, dstOffset, srcOffset, t, stride ) {
for ( var i = 0; i !== stride; ++ i ) {
var j = dstOffset + i;
buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t;
}
}
} );
export { PropertyMixer };