From 228ddebb885247f2ae7755869e63e534370776c9 Mon Sep 17 00:00:00 2001 From: zz85 Date: Wed, 4 Jan 2012 13:42:07 +0800 Subject: [PATCH] update Spark.js and Tween.js libraries --- examples/js/Sparks.js | 264 +++++++++++++++++++++++++++++++++++++++--- examples/js/Tween.js | 17 +-- 2 files changed, 257 insertions(+), 24 deletions(-) diff --git a/examples/js/Sparks.js b/examples/js/Sparks.js index b673053e37..3b6399471a 100644 --- a/examples/js/Sparks.js +++ b/examples/js/Sparks.js @@ -17,7 +17,6 @@ var SPARKS = {}; * Creates and Manages Particles *********************************/ - SPARKS.Emitter = function (counter) { this._counter = counter ? counter : new SPARKS.SteadyCounter(10); // provides number of particles to produce @@ -41,6 +40,7 @@ SPARKS.Emitter.prototype = { _timer: null, _lastTime: null, _timerStep: 10, + _velocityVerlet: true, // run its built in timer / stepping start: function() { @@ -66,12 +66,29 @@ SPARKS.Emitter.prototype = { var time = Date.now(); var elapsed = time - emitter._lastTime; - while(elapsed >= emitter._TIMESTEP) { - emitter.update(emitter._TIMESTEP / 1000); - elapsed -= emitter._TIMESTEP; + if (!this._velocityVerlet) { + // if elapsed is way higher than time step, (usually after switching tabs, or excution cached in ff) + // we will drop cycles. perhaps set to a limit of 10 or something? + var maxBlock = emitter._TIMESTEP * 20; + + if (elapsed >= maxBlock) { + //console.log('warning: sparks.js is fast fowarding engine, skipping steps', elapsed / emitter._TIMESTEP); + //emitter.update( (elapsed - maxBlock) / 1000); + elapsed = maxBlock; + } + + while(elapsed >= emitter._TIMESTEP) { + emitter.update(emitter._TIMESTEP / 1000); + elapsed -= emitter._TIMESTEP; + } + emitter._lastTime = time - elapsed; + + } else { + emitter.update(elapsed/1000); + emitter._lastTime = time; } - emitter._lastTime = time - elapsed; + if (emitter._isRunning) setTimeout(emitter.step, emitter._timerStep, emitter); @@ -129,6 +146,8 @@ SPARKS.Emitter.prototype = { } } + this.dispatchEvent("loopUpdated"); + }, createParticle: function() { @@ -154,6 +173,21 @@ SPARKS.Emitter.prototype = { addAction: function (action) { this._actions.push(action); }, + + removeInitializer: function (initializer) { + var index = this._initializers.indexOf(initializer); + if (index > -1) { + this._initializers.splice( index, 1 ); + } + }, + + removeAction: function (action) { + var index = this._actions.indexOf(action); + if (index > -1) { + this._actions.splice( index, 1 ); + } + //console.log('removeAction', index, this._actions); + }, addCallback: function(name, callback) { this.callbacks[name] = callback; @@ -171,18 +205,63 @@ SPARKS.Emitter.prototype = { }; +/* + * Constant Names for + * Events called by emitter.dispatchEvent() + * + */ +SPARKS.EVENT_PARTICLE_CREATED = "created" +SPARKS.EVENT_PARTICLE_UPDATED = "updated" +SPARKS.EVENT_PARTICLE_DEAD = "dead"; +SPARKS.EVENT_LOOP_UPDATED = "loopUpdated"; + + + +/* + * Steady Counter attempts to produces a particle rate steadily + * + */ + // Number of particles per seconds SPARKS.SteadyCounter = function(rate) { this.rate = rate; + // we use a shortfall counter to make up for slow emitters + this.leftover = 0; + }; SPARKS.SteadyCounter.prototype.updateEmitter = function(emitter, time) { - - return Math.floor(time * this.rate); + + var targetRelease = time * this.rate + this.leftover; + var actualRelease = Math.floor(targetRelease); + + this.leftover = targetRelease - actualRelease; + + return actualRelease; }; +/* + * Shot Counter produces specified particles + * on a single impluse or burst + */ + +SPARKS.ShotCounter = function(particles) { + this.particles = particles; + this.used = false; +}; + +SPARKS.ShotCounter.prototype.updateEmitter = function(emitter, time) { + + if (this.used) { + return 0; + } else { + this.used = true; + } + + return this.particles; +}; /******************************** @@ -220,6 +299,7 @@ SPARKS.Particle = function() { this.position = SPARKS.VectorPool.get().set(0,0,0); //new THREE.Vector3( 0, 0, 0 ); this.velocity = SPARKS.VectorPool.get().set(0,0,0); //new THREE.Vector3( 0, 0, 0 ); + this._oldvelocity = SPARKS.VectorPool.get().set(0,0,0); // rotation vec3 // angVelocity vec3 // faceAxis vec3 @@ -276,17 +356,61 @@ SPARKS.Move = function() { }; SPARKS.Move.prototype.update = function(emitter, particle, time) { - + // attempt verlet velocity updating. var p = particle.position; - var v = particle.velocity; + var v = particle.velocity; + var old = particle._oldvelocity; + + if (this._velocityVerlet) { + p.x += (v.x + old.x) * 0.5 * time; + p.y += (v.y + old.y) * 0.5 * time; + p.z += (v.z + old.z) * 0.5 * time; + } else { + p.x += v.x * time; + p.y += v.y * time; + p.z += v.z * time; + } + + // OldVel = Vel; + // Vel = Vel + Accel * dt; + // Pos = Pos + (vel + Vel + Accel * dt) * 0.5 * dt; + + + +}; + +/* Marks particles found in specified zone dead */ +SPARKS.DeathZone = function(zone) { + this.zone = zone; +}; + +SPARKS.DeathZone.prototype.update = function(emitter, particle, time) { - p.x += v.x * time; - p.y += v.y * time; - p.z += v.z * time; + if (this.zone.contains(particle.position)) { + particle.isDead = true; + } }; +/* + * SPARKS.ActionZone applies an action when particle is found in zone + */ +SPARKS.ActionZone = function(action, zone) { + this.action = action; + this.zone = zone; +}; + +SPARKS.ActionZone.prototype.update = function(emitter, particle, time) { + + if (this.zone.contains(particle.position)) { + this.action.update( emitter, particle, time ); + } + +}; +/* + * Accelerate action affects velocity in specified 3d direction + */ SPARKS.Accelerate = function(x,y,z) { if (x instanceof THREE.Vector3) { @@ -303,12 +427,63 @@ SPARKS.Accelerate.prototype.update = function(emitter, particle, time) { var v = particle.velocity; + particle._oldvelocity.set(v.x, v.y, v.z); + v.x += acc.x * time; v.y += acc.y * time; v.z += acc.z * time; }; +/* + * Accelerate Factor accelerate based on a factor of particle's velocity. + */ +SPARKS.AccelerateFactor = function(factor) { + this.factor = factor; +}; + +SPARKS.AccelerateFactor.prototype.update = function(emitter, particle, time) { + var factor = this.factor; + + var v = particle.velocity; + var len = v.length(); + var adjFactor; + if (len>0) { + + adjFactor = factor * time / len; + adjFactor += 1; + + v.multiplyScalar(adjFactor); + // v.x *= adjFactor; + // v.y *= adjFactor; + // v.z *= adjFactor; + } + +}; + +/* +AccelerateNormal + * AccelerateVelocity affects velocity based on its velocity direction + */ +SPARKS.AccelerateVelocity = function(factor) { + + this.factor = factor; + +}; + +SPARKS.AccelerateVelocity.prototype.update = function(emitter, particle, time) { + var factor = this.factor; + + var v = particle.velocity; + + + v.z += - v.x * factor; + v.y += v.z * factor; + v.x += v.y * factor; + +}; + + /* Set the max ammount of x,y,z drift movements in a second */ SPARKS.RandomDrift = function(x,y,z) { if (x instanceof THREE.Vector3) { @@ -373,8 +548,6 @@ SPARKS.LineZone.prototype.getLocation = function() { }; // Basically a RectangleZone - - SPARKS.ParallelogramZone = function(corner, side1, side2) { this.corner = corner; this.side1 = side1; @@ -390,6 +563,65 @@ SPARKS.ParallelogramZone.prototype.getLocation = function() { }; +SPARKS.CubeZone = function(position, x, y, z) { + this.position = position; + this.x = x; + this.y = y; + this.z = z; +}; + +SPARKS.CubeZone.prototype.getLocation = function() { + //TODO use pool? + + var location = this.position.clone(); + location.x += Math.random() * this.x; + location.y += Math.random() * this.y; + location.z += Math.random() * this.z; + + return location; + +}; + + +SPARKS.CubeZone.prototype.contains = function(position) { + + var startX = this.position.x; + var startY = this.position.y; + var startZ = this.position.z; + var x = this.x; // width + var y = this.y; // depth + var z = this.z; // height + + if (x<0) { + startX += x; + x = Math.abs(x); + } + + if (y<0) { + startY += y; + y = Math.abs(y); + } + + if (z<0) { + startZ += z; + z = Math.abs(z); + } + + var diffX = position.x - startX; + var diffY = position.y - startY; + var diffZ = position.z - startZ; + + if ( (diffX > 0) && (diffX < x) && + (diffY > 0) && (diffY < y) && + (diffZ > 0) && (diffZ < z) ) { + return true; + } + + return false; + +}; + + /** * The constructor creates a DiscZone 3D zone. @@ -513,7 +745,7 @@ SPARKS.Target = function(target, callback) { this.callback = callback; }; -SPARKS.Target.prototype.initialize = function( emitter, particle) { +SPARKS.Target.prototype.initialize = function( emitter, particle ) { if (this.callback) { particle.target = this.callback(); @@ -597,4 +829,4 @@ SPARKS.Utils = { } } -}; +}; \ No newline at end of file diff --git a/examples/js/Tween.js b/examples/js/Tween.js index d1d3fff5ec..67824ab9f0 100644 --- a/examples/js/Tween.js +++ b/examples/js/Tween.js @@ -1,12 +1,13 @@ -// tween.js r2 - http://github.com/sole/tween.js -var TWEEN=TWEEN||function(){var a,e,c,d,f=[];return{start:function(g){c=setInterval(this.update,1E3/(g||60))},stop:function(){clearInterval(c)},add:function(g){f.push(g)},getAll:function(){return f},removeAll:function(){f=[]},remove:function(g){a=f.indexOf(g);a!==-1&&f.splice(a,1)},update:function(){a=0;e=f.length;for(d=(new Date).getTime();a1?1:b;i=n(b);for(h in c)a[h]=e[h]+c[h]*i;l!==null&&l.call(a,i);if(b==1){m!==null&&m.call(a);k!==null&&k.start();return false}return true}};TWEEN.Easing={Linear:{},Quadratic:{},Cubic:{},Quartic:{},Quintic:{},Sinusoidal:{},Exponential:{},Circular:{},Elastic:{},Back:{},Bounce:{}};TWEEN.Easing.Linear.EaseNone=function(a){return a}; +// tween.js r5 - http://github.com/sole/tween.js +var TWEEN=TWEEN||function(){var a,e,c=60,b=false,h=[];return{setFPS:function(f){c=f||60},start:function(f){arguments.length!=0&&this.setFPS(f);e=setInterval(this.update,1E3/c)},stop:function(){clearInterval(e)},setAutostart:function(f){(b=f)&&!e&&this.start()},add:function(f){h.push(f);b&&!e&&this.start()},getAll:function(){return h},removeAll:function(){h=[]},remove:function(f){a=h.indexOf(f);a!==-1&&h.splice(a,1)},update:function(f){a=0;num_tweens=h.length;for(f=f||Date.now();a1?1:d;i=n(d);for(g in c)a[g]=e[g]+c[g]*i;l!==null&&l.call(a,i);if(d==1){m!==null&&m.call(a);k!==null&&k.start();return false}return true}};TWEEN.Easing={Linear:{},Quadratic:{},Cubic:{},Quartic:{},Quintic:{},Sinusoidal:{},Exponential:{},Circular:{},Elastic:{},Back:{},Bounce:{}};TWEEN.Easing.Linear.EaseNone=function(a){return a}; TWEEN.Easing.Quadratic.EaseIn=function(a){return a*a};TWEEN.Easing.Quadratic.EaseOut=function(a){return-a*(a-2)};TWEEN.Easing.Quadratic.EaseInOut=function(a){if((a*=2)<1)return 0.5*a*a;return-0.5*(--a*(a-2)-1)};TWEEN.Easing.Cubic.EaseIn=function(a){return a*a*a};TWEEN.Easing.Cubic.EaseOut=function(a){return--a*a*a+1};TWEEN.Easing.Cubic.EaseInOut=function(a){if((a*=2)<1)return 0.5*a*a*a;return 0.5*((a-=2)*a*a+2)};TWEEN.Easing.Quartic.EaseIn=function(a){return a*a*a*a}; TWEEN.Easing.Quartic.EaseOut=function(a){return-(--a*a*a*a-1)};TWEEN.Easing.Quartic.EaseInOut=function(a){if((a*=2)<1)return 0.5*a*a*a*a;return-0.5*((a-=2)*a*a*a-2)};TWEEN.Easing.Quintic.EaseIn=function(a){return a*a*a*a*a};TWEEN.Easing.Quintic.EaseOut=function(a){return(a-=1)*a*a*a*a+1};TWEEN.Easing.Quintic.EaseInOut=function(a){if((a*=2)<1)return 0.5*a*a*a*a*a;return 0.5*((a-=2)*a*a*a*a+2)};TWEEN.Easing.Sinusoidal.EaseIn=function(a){return-Math.cos(a*Math.PI/2)+1}; TWEEN.Easing.Sinusoidal.EaseOut=function(a){return Math.sin(a*Math.PI/2)};TWEEN.Easing.Sinusoidal.EaseInOut=function(a){return-0.5*(Math.cos(Math.PI*a)-1)};TWEEN.Easing.Exponential.EaseIn=function(a){return a==0?0:Math.pow(2,10*(a-1))};TWEEN.Easing.Exponential.EaseOut=function(a){return a==1?1:-Math.pow(2,-10*a)+1};TWEEN.Easing.Exponential.EaseInOut=function(a){if(a==0)return 0;if(a==1)return 1;if((a*=2)<1)return 0.5*Math.pow(2,10*(a-1));return 0.5*(-Math.pow(2,-10*(a-1))+2)}; -TWEEN.Easing.Circular.EaseIn=function(a){return-(Math.sqrt(1-a*a)-1)};TWEEN.Easing.Circular.EaseOut=function(a){return Math.sqrt(1- --a*a)};TWEEN.Easing.Circular.EaseInOut=function(a){if((a/=0.5)<1)return-0.5*(Math.sqrt(1-a*a)-1);return 0.5*(Math.sqrt(1-(a-=2)*a)+1)};TWEEN.Easing.Elastic.EaseIn=function(a){var e,c=0.1,d=0.4;if(a==0)return 0;if(a==1)return 1;d||(d=0.3);if(!c||c<1){c=1;e=d/4}else e=d/(2*Math.PI)*Math.asin(1/c);return-(c*Math.pow(2,10*(a-=1))*Math.sin((a-e)*2*Math.PI/d))}; -TWEEN.Easing.Elastic.EaseOut=function(a){var e,c=0.1,d=0.4;if(a==0)return 0;if(a==1)return 1;d||(d=0.3);if(!c||c<1){c=1;e=d/4}else e=d/(2*Math.PI)*Math.asin(1/c);return c*Math.pow(2,-10*a)*Math.sin((a-e)*2*Math.PI/d)+1}; -TWEEN.Easing.Elastic.EaseInOut=function(a){var e,c=0.1,d=0.4;if(a==0)return 0;if(a==1)return 1;d||(d=0.3);if(!c||c<1){c=1;e=d/4}else e=d/(2*Math.PI)*Math.asin(1/c);if((a*=2)<1)return-0.5*c*Math.pow(2,10*(a-=1))*Math.sin((a-e)*2*Math.PI/d);return c*Math.pow(2,-10*(a-=1))*Math.sin((a-e)*2*Math.PI/d)*0.5+1};TWEEN.Easing.Back.EaseIn=function(a){return a*a*(2.70158*a-1.70158)};TWEEN.Easing.Back.EaseOut=function(a){return(a-=1)*a*(2.70158*a+1.70158)+1}; +TWEEN.Easing.Circular.EaseIn=function(a){return-(Math.sqrt(1-a*a)-1)};TWEEN.Easing.Circular.EaseOut=function(a){return Math.sqrt(1- --a*a)};TWEEN.Easing.Circular.EaseInOut=function(a){if((a/=0.5)<1)return-0.5*(Math.sqrt(1-a*a)-1);return 0.5*(Math.sqrt(1-(a-=2)*a)+1)};TWEEN.Easing.Elastic.EaseIn=function(a){var e,c=0.1,b=0.4;if(a==0)return 0;if(a==1)return 1;b||(b=0.3);if(!c||c<1){c=1;e=b/4}else e=b/(2*Math.PI)*Math.asin(1/c);return-(c*Math.pow(2,10*(a-=1))*Math.sin((a-e)*2*Math.PI/b))}; +TWEEN.Easing.Elastic.EaseOut=function(a){var e,c=0.1,b=0.4;if(a==0)return 0;if(a==1)return 1;b||(b=0.3);if(!c||c<1){c=1;e=b/4}else e=b/(2*Math.PI)*Math.asin(1/c);return c*Math.pow(2,-10*a)*Math.sin((a-e)*2*Math.PI/b)+1}; +TWEEN.Easing.Elastic.EaseInOut=function(a){var e,c=0.1,b=0.4;if(a==0)return 0;if(a==1)return 1;b||(b=0.3);if(!c||c<1){c=1;e=b/4}else e=b/(2*Math.PI)*Math.asin(1/c);if((a*=2)<1)return-0.5*c*Math.pow(2,10*(a-=1))*Math.sin((a-e)*2*Math.PI/b);return c*Math.pow(2,-10*(a-=1))*Math.sin((a-e)*2*Math.PI/b)*0.5+1};TWEEN.Easing.Back.EaseIn=function(a){return a*a*(2.70158*a-1.70158)};TWEEN.Easing.Back.EaseOut=function(a){return(a-=1)*a*(2.70158*a+1.70158)+1}; TWEEN.Easing.Back.EaseInOut=function(a){if((a*=2)<1)return 0.5*a*a*(3.5949095*a-2.5949095);return 0.5*((a-=2)*a*(3.5949095*a+2.5949095)+2)};TWEEN.Easing.Bounce.EaseIn=function(a){return 1-TWEEN.Easing.Bounce.EaseOut(1-a)};TWEEN.Easing.Bounce.EaseOut=function(a){return(a/=1)<1/2.75?7.5625*a*a:a<2/2.75?7.5625*(a-=1.5/2.75)*a+0.75:a<2.5/2.75?7.5625*(a-=2.25/2.75)*a+0.9375:7.5625*(a-=2.625/2.75)*a+0.984375}; -TWEEN.Easing.Bounce.EaseInOut=function(a){if(a<0.5)return TWEEN.Easing.Bounce.EaseIn(a*2)*0.5;return TWEEN.Easing.Bounce.EaseOut(a*2-1)*0.5+0.5}; +TWEEN.Easing.Bounce.EaseInOut=function(a){if(a<0.5)return TWEEN.Easing.Bounce.EaseIn(a*2)*0.5;return TWEEN.Easing.Bounce.EaseOut(a*2-1)*0.5+0.5}; \ No newline at end of file -- GitLab