threex
Version:
Game Extensions for three.js http://www.threejsgames.com/extensions/
347 lines (210 loc) • 6.11 kB
JavaScript
var THREEx = THREEx || {}
THREEx.MagnetControls = function(object3d){
// export object3d
this.object3d = object3d
this.id = THREEx.MagnetControls.nextId++
// physics constant
var velocity = new THREE.Vector3()
this.velocity = velocity
var acceleration= new THREE.Vector3()
this.acceleration=acceleration
var damping = new THREE.Vector3().set(1,1,1).multiplyScalar(0.9)
this.damping = damping
this.applyForces = function(){
// handle physics
velocity.multiply(damping)
velocity.add(acceleration)
acceleration.set(0,0,0)
// update object3d position
object3d.position.add(velocity)
}
//////////////////////////////////////////////////////////////////////////////////
// force //
//////////////////////////////////////////////////////////////////////////////////
/**
* * queue bunch of funciton for physics
* * onComputeForces = []
* * this.computeForces run all of them
*/
this.computeForces = function(others, controlsIdx){
for(var i = controlsIdx+1; i < others.length; i++){
var other = others[i]
computeInteraction(this, others[i])
}
function computeInteraction(controls1, controls2){
var object3d1 = controls1.object3d
var object3d2 = controls2.object3d
var distance = object3d1.position.distanceTo(object3d2.position)
var maxDistance = 2
if( distance > maxDistance ) return
// compute force intensity
var proximity = distance/maxDistance
// console.assert(proximity>= 0 && proximity <= 1)
var easing = THREEx.MagnetControls.Easing
var intensity = easing.Cubic.In(1-proximity)*0.1
// compute force vector
var force = object3d1.position.clone()
.sub(object3d2.position)
.multiplyScalar(intensity)
// apply the force to acceleration
controls1.acceleration.add(force)
controls2.acceleration.sub(force)
}
}
}
THREEx.MagnetControls.nextId = 0
// directly from tween.js
THREEx.MagnetControls.Easing = {
Linear: {
None: function ( k ) {
return k;
}
},
Quadratic: {
In: function ( k ) {
return k * k;
},
Out: function ( k ) {
return k * ( 2 - k );
},
InOut: function ( k ) {
if ( ( k *= 2 ) < 1 ) return 0.5 * k * k;
return - 0.5 * ( --k * ( k - 2 ) - 1 );
}
},
Cubic: {
In: function ( k ) {
return k * k * k;
},
Out: function ( k ) {
return --k * k * k + 1;
},
InOut: function ( k ) {
if ( ( k *= 2 ) < 1 ) return 0.5 * k * k * k;
return 0.5 * ( ( k -= 2 ) * k * k + 2 );
}
},
Quartic: {
In: function ( k ) {
return k * k * k * k;
},
Out: function ( k ) {
return 1 - ( --k * k * k * k );
},
InOut: function ( k ) {
if ( ( k *= 2 ) < 1) return 0.5 * k * k * k * k;
return - 0.5 * ( ( k -= 2 ) * k * k * k - 2 );
}
},
Quintic: {
In: function ( k ) {
return k * k * k * k * k;
},
Out: function ( k ) {
return --k * k * k * k * k + 1;
},
InOut: function ( k ) {
if ( ( k *= 2 ) < 1 ) return 0.5 * k * k * k * k * k;
return 0.5 * ( ( k -= 2 ) * k * k * k * k + 2 );
}
},
Sinusoidal: {
In: function ( k ) {
return 1 - Math.cos( k * Math.PI / 2 );
},
Out: function ( k ) {
return Math.sin( k * Math.PI / 2 );
},
InOut: function ( k ) {
return 0.5 * ( 1 - Math.cos( Math.PI * k ) );
}
},
Exponential: {
In: function ( k ) {
return k === 0 ? 0 : Math.pow( 1024, k - 1 );
},
Out: function ( k ) {
return k === 1 ? 1 : 1 - Math.pow( 2, - 10 * k );
},
InOut: function ( k ) {
if ( k === 0 ) return 0;
if ( k === 1 ) return 1;
if ( ( k *= 2 ) < 1 ) return 0.5 * Math.pow( 1024, k - 1 );
return 0.5 * ( - Math.pow( 2, - 10 * ( k - 1 ) ) + 2 );
}
},
Circular: {
In: function ( k ) {
return 1 - Math.sqrt( 1 - k * k );
},
Out: function ( k ) {
return Math.sqrt( 1 - ( --k * k ) );
},
InOut: function ( k ) {
if ( ( k *= 2 ) < 1) return - 0.5 * ( Math.sqrt( 1 - k * k) - 1);
return 0.5 * ( Math.sqrt( 1 - ( k -= 2) * k) + 1);
}
},
Elastic: {
In: function ( k ) {
var s, a = 0.1, p = 0.4;
if ( k === 0 ) return 0;
if ( k === 1 ) return 1;
if ( !a || a < 1 ) { a = 1; s = p / 4; }
else s = p * Math.asin( 1 / a ) / ( 2 * Math.PI );
return - ( a * Math.pow( 2, 10 * ( k -= 1 ) ) * Math.sin( ( k - s ) * ( 2 * Math.PI ) / p ) );
},
Out: function ( k ) {
var s, a = 0.1, p = 0.4;
if ( k === 0 ) return 0;
if ( k === 1 ) return 1;
if ( !a || a < 1 ) { a = 1; s = p / 4; }
else s = p * Math.asin( 1 / a ) / ( 2 * Math.PI );
return ( a * Math.pow( 2, - 10 * k) * Math.sin( ( k - s ) * ( 2 * Math.PI ) / p ) + 1 );
},
InOut: function ( k ) {
var s, a = 0.1, p = 0.4;
if ( k === 0 ) return 0;
if ( k === 1 ) return 1;
if ( !a || a < 1 ) { a = 1; s = p / 4; }
else s = p * Math.asin( 1 / a ) / ( 2 * Math.PI );
if ( ( k *= 2 ) < 1 ) return - 0.5 * ( a * Math.pow( 2, 10 * ( k -= 1 ) ) * Math.sin( ( k - s ) * ( 2 * Math.PI ) / p ) );
return a * Math.pow( 2, -10 * ( k -= 1 ) ) * Math.sin( ( k - s ) * ( 2 * Math.PI ) / p ) * 0.5 + 1;
}
},
Back: {
In: function ( k ) {
var s = 1.70158;
return k * k * ( ( s + 1 ) * k - s );
},
Out: function ( k ) {
var s = 1.70158;
return --k * k * ( ( s + 1 ) * k + s ) + 1;
},
InOut: function ( k ) {
var s = 1.70158 * 1.525;
if ( ( k *= 2 ) < 1 ) return 0.5 * ( k * k * ( ( s + 1 ) * k - s ) );
return 0.5 * ( ( k -= 2 ) * k * ( ( s + 1 ) * k + s ) + 2 );
}
},
Bounce: {
In: function ( k ) {
return 1 - TWEEN.Easing.Bounce.Out( 1 - k );
},
Out: function ( k ) {
if ( k < ( 1 / 2.75 ) ) {
return 7.5625 * k * k;
} else if ( k < ( 2 / 2.75 ) ) {
return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;
} else if ( k < ( 2.5 / 2.75 ) ) {
return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;
} else {
return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;
}
},
InOut: function ( k ) {
if ( k < 0.5 ) return TWEEN.Easing.Bounce.In( k * 2 ) * 0.5;
return TWEEN.Easing.Bounce.Out( k * 2 - 1 ) * 0.5 + 0.5;
}
}
};