! IMPORTANT ! This is a PopcornFX v1 page. PopcornFX v2 documentation can be found here
|
Last update: v1.10.0 - Main page :
Particle evolvers
The physics evolver is the most frequently found evolver in a standard particle evolve state. It is the main dynamics evolver, that will make your particles move with velocity, acceleration, friction, force-fields, velocity fields, and scene interactions (collisions and impulse distribution in your own physical simulation, allowing you to create particles that will actually push your own physics objects around in your scene)
Node properties
Field name
|
Default value
|
Description
|
Dynamics
|
|
|
ConstantAcceleration
|
{0,0,0}
|
Constant acceleration to apply to the particles. Usually, this will be gravity.
|
ConstantVelocityField
|
{0,0,0}
|
Constant velocity field to advect the particles against. Usually, this will be wind. Will be combined with 'VelocityFieldSampler'
|
Mass
|
1
|
INVERSE mass (1.0 / mass) of the particles. Affects drag and force calculations if you supply an external 'Force' particle field. (See 'ForceField' in the 'Field customization' category)
|
Drag
|
0
|
Amount of drag affecting the particles. This will allow the particles to be affected by external winds and turbulent flows. The higher the value, the stronger the drag. 0.0 means no drag.
|
DragType
|
Linear
|
Type of drag to apply.
Linear : default velocity dependent drag. Velocity decreases towards zero (similarly to exponential damping).
Aerodynamic : Realistic aerodynamic drag, more costly squared-velocity dependent drag computation (Currently disabled in SDK v1.9.0)
|
SceneWindInfluence
|
0
|
How much the ingame wind affects the particles. See the Wind backdrop
|
VelocityFieldSampler
|
<none>
|
Name of the sampler to use as a velocity / wind field. (affects particles based on their 'Drag' and 'Mass'). Will be combined with 'ConstantVelocityField'.
Typically a CParticleSamplerProceduralTurbulence
|
IntegrationStrategy
|
Adaptive
|
Integration strategy to use when evaluating motion equations.
Fast : simplest and fastest form. It assumes high constant framerate, and will produce inconsistent particle motion if the framerate is jerky.
Stable : evaluates the full analytical motion integrals, and will lead to physically correct results no matter what the simulation steps are. It is also slightly slower than the 'Fast' version.
Adaptive : switches between 'Fast' and 'Stable' versions based on the simulation timestep, and the 'IntegrationDtTreshold' value
See #Choosing the integration strategy for more details
|
IntegrationDtTreshold
|
0.02
|
Only used if 'IntegrationStrategy' is set to 'Adaptive'. The integration will switch from 'Fast' to 'Stable' if the simulation timestep becomes greater than 'IntegrationDtTreshold'.
|
Collisions
|
|
|
FilterID
|
0
|
Custom low-level FilterID that will be passed to the ingame collision callbacks, allowing code to track and filter "Physical layers" of particles
|
WorldInteractionMode
|
None
|
Type of collision handling performed.
None : No collisions with world
OneWay : Particles collide with world, world repels particles
TwoWay : Particles collide with world, world repels particles, particles apply forces on world.
|
DieOnContact
|
false
|
If checked, the particle will die as soon as a collision is detected. Active only if WorldInteractionMode is not set to 'None'.
|
BouncesBeforeDeath
|
1
|
Number of bounces before the particle is forced to die. 0 = never dies because of collisions. If death on first contact is needed, activate the 'DieOnContact' property
range : [0, 127]
|
BounceRestitution
|
0.5
|
Determines how much the particle will bounce back. 0 = doesn't bounce, 1 = bounces back with the full pre-impact speed.
range : [0, 1]
|
ContactFrictionModel
|
Absorbsive
|
v1.9.0 Friction model to apply :
Coulomb : traditional, more realistic behaviour, with a separate friction property
Absorbsive
|
ContactFriction
|
0.7
|
v1.9.0
0 = no friction, for examples of physically-based friction coefficients, see here: coefficients of friction
|
Collisions: Events
|
|
|
EventOnCollide
|
"OnCollide"
|
Name of the event to trigger when a collision is detected
|
EventUsesPostContactVelocity
|
false
|
If active, will forward the post-contact (bounced) velocity to the triggered events
|
EventTransformsMode
|
ContactSurface
|
Determines the way the triggered event's transforms will be built
World : v1.10.0 transforms will be aligned to the world axes.
ContactSurface : transforms will be aligned to the surface normal.
PreContactVelocity : transforms will be aligned to the particle's velocity before collision.
PostContactVelocity : transforms will be aligned to the particle's velocity after collision.
|
EventIsSticky
|
false
|
If enabled, the action spawned by the OnCollide event will be parented to the ingame object that was hit
|
Collisions: Advanced
|
|
|
BounceOffset
|
0.002
|
Offset along the contact normal the particle is displaced by after it has collided. useful to avoid numerical imprecisions with low bounce restitutions, or large bounce counts. Should be kept small
|
WeightBounceWithNdotV
|
false
|
if activated, bounce restutution will be scaled down when the particle collide at grazing angles with the surface.
|
MaxIterations
|
1
|
v1.9.0 Control the max number of scene raycast iterations the physics evolver will perform when intersecting the scene. 1 gives the best performance.
|
StopIfFinalIterationHits
|
false
|
v1.9.0 If enabled and the last move iteration collided, will not keep the particle at the last impact location to avoid risking penetrating the scene.
|
CollisionQueryType (EXPERIMENTAL)
|
Raytrace
|
Tells the runtime which kind of collision queries to perform with the world.
Raytrace : when moving, the particles will trace a ray in the world along their movement to see if they collide. This assumes the particle is an infinitely small point.
SphereSweep : more compute-intensive. When moving, the particles will be treated as a sphere swept into the world, and produce more realistic collisions.
|
SweepRadiusFactor (EXPERIMENTAL)
|
1.0f
|
Factor to apply to the particle sweep radius field, controls how large the particle appears to the collision system.
|
IgnoreSurfaceProperties
|
false
|
if checked, Particles will ignore surface properties on hit.
|
RestitutionCombineMode
|
Surface
|
v1.9.0 Defines how the particle restitution and contact surface restitution are combined.
- Surface : uses the combine mode of the game engine
- Average : averages both frictions : (a+b)/2
- Multiplies : multiplies both frictions together : a*b
- Min : uses the smallest friction : min(a,b)
- Max : uses the largest friction : max(a,b)
|
FrictionCombineMode
|
Surface
|
v1.9.0 Defines how the particle friction and contact surface friction are combined.
- Surface : uses the combine mode of the game engine
- Average : averages both frictions : (a+b)/2
- Multiplies : multiplies both frictions together : a*b
- Min : uses the smallest friction : min(a,b)
- Max : uses the largest friction : max(a,b)
|
Field customization
|
|
|
PositionField
|
"Position"
|
If this field is declared as a <float3>, it will be used as the particle position
|
VelocityField
|
"Velocity"
|
If this field is declared as a <float3>, it will be used as the particle velocity
|
MassField
|
"Mass"
|
If this field is declared as a <float>, it will be scaled by the static 'Mass' field, before being used as the particle INVERSE mass (1.0 / mass)..
|
AccelField
|
"Accel"
|
If this field is declared as a <float3>, it will be used as an acceleration affecting particles. (in addition to 'ConstantAcceleration' and 'ForceField')
|
ForceField
|
"Force"
|
If this field is declared as a <float3>, it will be used as a force affecting particles. (in addition to 'ConstantAcceleration' and 'AccelField')
|
VelocityFieldField
|
"Velocity"
|
If this field is declared as a <float3>, it will be used as the VelocityField (Wind Field) and OVERRIDE VelocityFieldSampler.
|
BounceRestitutionField
|
"BounceRestitution"
|
If this field is declared as a <float>, it will be scaled by the static 'BounceRestitution' field, before being used as the particle bounce restitution.
|
ContactFrictionField
|
"Friction"
|
If this field is declared as a <float>, it will be scaled by the static 'ContactFriction' field, before being used as the particle contact/impact friction.
|
CollisionCountField
|
"CollisionCount"
|
If this field is declared as an <int>, it will be incremented by the evolver each time the particle collides.
|
SweepRadiusField (EXPERIMENTAL)
|
"Size"
|
Name of the field the physics evolver should use as the sweep radius of the particles, type = <float>. If empty, uses 'SweepRadiusFactor' as a constant sweep radius
|
|
|
Auto-fields
The physics evolver automatically creates, if they don't exist, the following particle fields:
Name
|
Type
|
Footprint
|
TransformMode
|
self access to field
|
Position |
float3 |
16 bytes |
Transform |
read/write
|
Velocity |
float3 |
16 bytes |
Rotate |
read/write
|
if 'WorldInteractionMode' != None , the following fields are also added:
|
PrevPosition |
float3 |
16 bytes |
none |
read/write
|
CollisionFlags |
u8 |
1 bytes |
none |
read/write
|
Advanced
Choosing the integration strategy
The physics evolver implements two main movement integration computations:
- Fast : Pretty fast, and uses simplified movement equations to approximate the movement. When the simulation step becomes too large (low FPS, high time factor, excessively high accelerations), You will start seeing glitches. Note that this might occur some times if the framerate of your final games becomes jerky, with occasional spikes at lower framerates, or if there is a framerate stall at the start of a level, or when streaming-in resources, etc...
- Stable : a bit slower (although not much slower, you will hardly notice a real difference between the two, except perhaps for pretty hardcore effects), however, it evaluates the full motion equations integrals, with friction + acceleration, and therefore produces a rock-solid motion, no matter what the timestep is.
The image below shows four simple fountains:
- number 1 and 4 have downward gravity and friction
- number 2 and 3 only have a downward gravity.
- number 1 and 2 use the 'Stable' integrator.
- number 3 and 4 use the 'Fast' integrator.
For the sake of the demonstration, the timestep has been exaggerately increased : The framerate was clamped to 15 fps, and the time scale was set to 4x, producing huge simulation steps of 4 * (1/15) = 0.26 seconds per frame. (when usually, the steps are closer to 0.016 seconds per frame)
At normal framerates and time scales, fountains 4 is strictly identical to fountain 1, same goes for fountains 3 and 2.
As you can see, the fountains 3 and 4 differ pretty badly from the reference shape of fountains 1 and 2, due only to the approximations of the 'Fast'
version.
You can tell the physics evolver which one it should use, using the 'IntegrationStrategy'
property.
There is also a third option in addition to 'Fast'
and 'Stable'
, which is the default value when creating a new physics evolver: 'Adaptive'
The 'Adaptive'
mode will basically switch between 'Fast'
and 'Stable'
based on the input timestep. it the timestep becomes larger than the value in the 'IntegrationDtTreshold' property, the evolver will switch to the 'Stable'
version. If it gets lower, it will switch back to the 'Fast'
version.
The value of 'IntegrationDtTreshold'
is basically 1 / framerate
.
If you want the 'Stable'
version to kick in when your framerate drops below 60 fps, you should set 'IntegrationDtTreshold'
to 1/60, so to 0.01666
By default, it is set to 0.02 (which is 50 fps)
Dealing with turbulences at low framerates
Even with the 'Stable' integrator, there can be visual glitches when sampling
turbulences in the physics evolver.
At high framerates, the particles will precisely follow the turbulent flow. At low framerates, they will appear as drifting away from it, and/or following a coarser version of the flow.
To address that issue, we first have to understand why. Here are a few pictures illustrating what happens at different framerates to a particle advected across a turbulent flow:
 |
60 fps : particle follows closely the turbulence
|
 |
30 fps : particle jumps larger steps and error accumulates end position diverges a bit.
|
 |
15 fps : huge jumps across the turbulence field unpredictable path, inconsistent with original turbulence.
|
One solution to that problem is to use the Micro-Updates feature of the
evolve states. They basically allow you to tell the state to subdivite its update step into multiple sub-updates if the framerate gets too low, keeping the sampling errors low.
 |
15 fps + micro-updates : particle follows closely the turbulence
|
To customize the Micro-Updates behavior, click on the particle state in the treeview, and tweak the following properties:
'MicroUpdatesMinFPS'
: minimum number of updates per second this state should run at.
'MaxMicroUpdatesPerFrame'
: maximum number of sub-steps acceptable (to avoid the simulation going down a vicious circles of more updates causing slower framerate causing more updates causing slower framerate, etc...
For more details on tweaking the micro-updates, see the micro-updates section in the evolve state page.