Flint Particle System Forum - Quadratic drag with fixed timestep 2011-12-11T05:39:17+00:00 http://flintparticles.org/forum/ Lussumo Vanilla & Feed Publisher Quadratic drag with fixed timestep http://flintparticles.org/forum/comments.php?DiscussionID=370&Focus=1247#Comment_1247 2010-07-15T10:09:44+01:00 2011-12-11T05:39:17+00:00 Xor http://flintparticles.org/forum/account.php?u=381 I needed to do some fireworks and started out with the official example. What I wanted to change was the speed the particles are emitted with, more like with real firework where the fly out really ...
I tried to use quadratic drag and set the initial velocity very high but the particles just ended up being stopped completely at their origin. Looking at the source, I identified the problem in the way the quadratic drag is calculated and the fact the the first frame when all the firework particles are spawned can be quite long.

The quadratic drag is calculated at the beginning of the frame and applied over the whole time of the frame. If the particles are really fast and the frame quite long, this can lead to the particles being stopped. In reality, the drag would lower as the speed of the particle would during the frame. The assumption that the drag is constant over the frame therefore doesn't apply and the divergence is bigger the longer the frame is.

One possible solution is to use a fixed time step. Instead of using the time the frame took to calculate the drag, the drag is calculated for a fixed, predetermined time step. This is repeated until the small steps match up the time of the frame.

This will guarantee that the drag is always applied with the same precision and setting the size of the time steps allows to specify the precision of the calculation.]]>
Quadratic drag with fixed timestep http://flintparticles.org/forum/comments.php?DiscussionID=370&Focus=1248#Comment_1248 2010-07-15T10:09:55+01:00 2010-07-15T10:10:09+01:00 Xor http://flintparticles.org/forum/account.php?u=381 Here's the updated QuadraticDrag class (only the twoD version, the theeD one should be analogous): /* * FLINT PARTICLE SYSTEM * ..................... * * Author: Richard Lord * Copyright ... /*
* FLINT PARTICLE SYSTEM
* .....................
*
* Author: Richard Lord
* Copyright (c) Richard Lord 2008-2009
* http://flintparticles.org
*
*
* Licence Agreement
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package org.flintparticles.twoD.actions
{
import org.flintparticles.common.actions.ActionBase;
import org.flintparticles.common.emitters.Emitter;
import org.flintparticles.common.particles.Particle;
import org.flintparticles.twoD.particles.Particle2D;

/**
* The QuadraticDrag action applies drag to the particle to slow it down when
* it's moving. The drag force is proportional to the square of the speed of
* the particle. For other types of drag see the LinerDrag and Friction actions.
*
* @see Friction
* @see LinearDrag
*/

public class QuadraticDrag extends ActionBase
{
private var _drag:Number;
private var _timestep:Number;

private var _accumulatedTime :Number = 0;

/**
* The constructor creates a QuadraticDrag action for use by an emitter.
* To add a QuadraticDrag to all particles created by an emitter, use the
* emitter's addAction method.
*
* @see org.flintparticles.common.emitters.Emitter#addAction()
*
* @param drag The amount of drag. A higher number produces a stronger
* drag force.
*/
public function QuadraticDrag( drag:Number = 0, timestep:Number = 0 )
{
this.drag = drag;
this.timestep = timestep;
}

/**
* The amount of drag. A higher number produces a stronger drag force.
*/
public function get drag():Number
{
return _drag;
}
public function set drag( value:Number ):void
{
_drag = value;
}

/**
* The fixed time step for the drag calculation, in seconds
*/
public function get timestep():Number
{
return _timestep;
}
public function set timestep( value:Number ):void
{
_timestep = value;
}

/**
* Calculates the drag on the particle and applies it for the period of
* time indicated.
*
* <p>This method is called by the emitter and need not be called by the
* user.</p>
*
* @param emitter The Emitter that created the particle.
* @param particle The particle to be updated.
* @param time The duration of the frame - used for time based updates.
*
* @see org.flintparticles.common.actions.Action#update()
*/
override public function update( emitter:Emitter, particle:Particle, time:Number ):void
{
var p:Particle2D = Particle2D( particle );
if( p.velX == 0 && p.velY == 0 )
{
return;
}

var step :Number = ( _timestep <= 0 ) ? time : _timestep;
_accumulatedTime += time;
while (_accumulatedTime >= step)
{
var len2:Number = p.velX * p.velX + p.velY * p.velY;
var scale:Number = 1 - _drag * step * Math.sqrt( len2 ) / p.mass;

if (scale < 0)
{
p.velX = 0;
p.velY = 0;
_accumulatedTime = 0;
break;
}
else
{
p.velX *= scale;
p.velY *= scale;
}

_accumulatedTime -= step;
}
}
}
}
]]>
Quadratic drag with fixed timestep http://flintparticles.org/forum/comments.php?DiscussionID=370&Focus=1257#Comment_1257 2010-07-24T17:37:17+01:00 2011-12-11T05:39:17+00:00 Richard http://flintparticles.org/forum/account.php?u=1 Hi Rather than apply a fixed timestep for one action only, it would be more appropriate to apply a fixed timestep to all actions. This is something that Flint can already do. Check out the ...
Rather than apply a fixed timestep for one action only, it would be more appropriate to apply a fixed timestep to all actions. This is something that Flint can already do. Check out the fixedFrameTime property of the emitter.

If you prefer to use a variable frame time but limit the maximum to minimise he effect of long frame times, you can set the maximumFrameTime of the emitter instead. The default value for the maximumFrameTime is 0.1 seconds.]]>
Quadratic drag with fixed timestep http://flintparticles.org/forum/comments.php?DiscussionID=370&Focus=1264#Comment_1264 2010-07-26T09:56:55+01:00 2010-07-26T09:59:14+01:00 Xor http://flintparticles.org/forum/account.php?u=381 Hi Richard, Thanks for the suggestions but I don't think either option really does what I need. * fixedFrameTime, as I understand it, will advance the particle system's time by a fixed time step ...
Thanks for the suggestions but I don't think either option really does what I need.
* fixedFrameTime, as I understand it, will advance the particle system's time by a fixed time step each frame, regardless how long the flash frame actually took. This will make particle system progress slower/faster based on the frame rate and will throw off timing when I rely on particle systems to finish in a certain time.
* maximumFrameTime, similarly, affects the timing of the particle system on very low frame rates by lagging it behind.

What the fixed time step I added to QuadraticDrag does is that it catches up to the flash time, i.e. it executes many small steps during a flash frame until it reaches the current time. Physics simulations often do something similar to make sure the timing is the same regardless of the dynamic time step that is used.

I also don't want to turn this on for other actions. Where it's possible to losslessly use bigger time steps to keep up with the flash time and to improve performance it's the best thing to do. In this particular case the calculation deviates very much with large time steps and that's why I added it directly to QuadraticDrag.

This could be factored out into as a feature of emitters in addition to fixedFrameTime or as a base property of actions. I'm not sure how specialized the need for a fixed time step is concerning what I needed it for and how the issue affects QuadraticDrag particularly.]]>
Quadratic drag with fixed timestep http://flintparticles.org/forum/comments.php?DiscussionID=370&Focus=1269#Comment_1269 2010-07-27T07:50:15+01:00 2011-12-11T05:39:17+00:00 Richard http://flintparticles.org/forum/account.php?u=1 Hi Sorry, I misunderstood what you were doing - I should have read your code as well as the text. Yes, this would be a nice feature to add into the emitter as an option. It's also possible to ...
Sorry, I misunderstood what you were doing - I should have read your code as well as the text. Yes, this would be a nice feature to add into the emitter as an option. It's also possible to manage the emitter's timestep externally to the class - if you set the emitter's useInternalTick property to false, it becomes your responsibility to call the emitter's update() method with an appropriate timestep.

Perhaps what's really needed is a set of time managers that can be applied to emitters to manage the update loop in different ways.

Thanks for the ideas & code.
Richard]]>