buffered-interpolation
Version:
A class for handling interpolation of networked THREE.js objects.
2 lines (1 loc) • 3.19 kB
JavaScript
const INITIALIZING=0,BUFFERING=1,PLAYING=2,MODE_LERP=0,MODE_HERMITE=1,vectorPool=[],quatPool=[],framePool=[],getPooledVector=()=>vectorPool.shift()||new THREE.Vector3,getPooledQuaternion=()=>quatPool.shift()||new THREE.Quaternion,getPooledFrame=()=>{let a=framePool.pop();return a||(a={position:new THREE.Vector3,velocity:new THREE.Vector3,scale:new THREE.Vector3,quaternion:new THREE.Quaternion,time:0}),a},freeFrame=a=>framePool.push(a);class InterpolationBuffer{constructor(a=MODE_LERP,b=.15){this.state=INITIALIZING,this.buffer=[],this.bufferTime=1e3*b,this.time=0,this.mode=a,this.originFrame=getPooledFrame(),this.position=new THREE.Vector3,this.quaternion=new THREE.Quaternion,this.scale=new THREE.Vector3(1,1,1)}hermite(a,b,c,d,e,f){const g=b*b,h=b*b*b;a.copy(c.multiplyScalar(2*h-3*g+1)),a.add(d.multiplyScalar(-2*h+3*g)),a.add(e.multiplyScalar(h-2*g+b)),a.add(f.multiplyScalar(h-g))}lerp(a,b,c,d){a.lerpVectors(b,c,d)}slerp(a,b,c,d){THREE.Quaternion.slerp(b,c,a,d)}updateOriginFrameToBufferTail(){freeFrame(this.originFrame),this.originFrame=this.buffer.shift()}appendBuffer(a,b,c,d){const e=0<this.buffer.length?this.buffer[this.buffer.length-1]:null;if(e&&e.time===this.time)a&&e.position.copy(a),b&&e.velocity.copy(b),c&&e.quaternion.copy(c),d&&e.scale.copy(d);else{const f=e||this.originFrame,g=getPooledFrame();g.position.copy(a||f.position),g.velocity.copy(b||f.velocity),g.quaternion.copy(c||f.quaternion),g.scale.copy(d||f.scale),g.time=this.time,this.buffer.push(g)}}setTarget(a,b,c,d){this.appendBuffer(a,b,c,d)}setPosition(a,b){this.appendBuffer(a,b,null,null)}setQuaternion(a){this.appendBuffer(null,null,a,null)}setScale(a){this.appendBuffer(null,null,null,a)}update(a){if(this.state===INITIALIZING&&0<this.buffer.length&&(this.updateOriginFrameToBufferTail(),this.position.copy(this.originFrame.position),this.quaternion.copy(this.originFrame.quaternion),this.scale.copy(this.originFrame.scale),this.state=BUFFERING),this.state===BUFFERING&&0<this.buffer.length&&this.time>this.bufferTime&&(this.state=PLAYING),this.state===PLAYING){const b=this.time-this.bufferTime;for(;0<this.buffer.length&&b>this.buffer[0].time;)1<this.buffer.length?this.updateOriginFrameToBufferTail():(this.originFrame.position.copy(this.buffer[0].position),this.originFrame.velocity.copy(this.buffer[0].velocity),this.originFrame.quaternion.copy(this.buffer[0].quaternion),this.originFrame.scale.copy(this.buffer[0].scale),this.originFrame.time=this.buffer[0].time,this.buffer[0].time=this.time+a);if(0<this.buffer.length&&0<this.buffer[0].time){const a=this.buffer[0],c=a.time-this.originFrame.time,d=(b-this.originFrame.time)/c;this.mode===MODE_LERP?this.lerp(this.position,this.originFrame.position,a.position,d):this.mode===MODE_HERMITE&&this.hermite(this.position,d,this.originFrame.position,a.position,this.originFrame.velocity.multiplyScalar(c),a.velocity.multiplyScalar(c)),this.slerp(this.quaternion,this.originFrame.quaternion,a.quaternion,d),this.lerp(this.scale,this.originFrame.scale,a.scale,d)}}this.state!==INITIALIZING&&(this.time+=a)}getPosition(){return this.position}getQuaternion(){return this.quaternion}getScale(){return this.scale}}module.exports=InterpolationBuffer;