diff options
author | Alexander Gavrilov <angavrilov@gmail.com> | 2016-08-01 21:45:42 +0300 |
---|---|---|
committer | Alexander Gavrilov <angavrilov@gmail.com> | 2016-08-01 22:14:56 +0300 |
commit | 4067ab38ab6035f71b6ce3f2f610000411160d21 (patch) | |
tree | 283f82e0a06f060c0b43f4042abbbf7e68e4082d /source/blender/blenkernel/intern/particle_system.c | |
parent | 538b30250d6460c8ca27c25a58fead425131d7a9 (diff) |
Fix T48991: some particles emitted at a distance from object.
The cause seems to be that despite dt_frac being computed as
1/(subframes+1) with integer subframes value, it doesn't always
add up to exactly 1.0 due to precision limitations. If the sum
is similar to 1.00000???, the last subframe is skipped, and all
particles that were supposed to be emitted in that interval are
emitted next frame, with the code working incorrectly due to
skewed time range.
To fix, separate the code from the dynamic timestep feature that
adjusts the last subframe length into a separate function, and
use it even when dynamic timestep is disabled.
Diffstat (limited to 'source/blender/blenkernel/intern/particle_system.c')
-rw-r--r-- | source/blender/blenkernel/intern/particle_system.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index e7561ee699e..8e3e2f5d6d0 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -3311,7 +3311,7 @@ static float get_base_time_step(ParticleSettings *part) return 1.0f / (float) (part->subframes + 1); } /* Update time step size to suit current conditions. */ -static float update_timestep(ParticleSystem *psys, ParticleSimulationData *sim, float t_frac) +static void update_timestep(ParticleSystem *psys, ParticleSimulationData *sim) { float dt_target; if (sim->courant_num == 0.0f) @@ -3331,7 +3331,10 @@ static float update_timestep(ParticleSystem *psys, ParticleSimulationData *sim, psys->dt_frac = interpf(dt_target, psys->dt_frac, TIMESTEP_EXPANSION_FACTOR); else psys->dt_frac = dt_target; +} +static float sync_timestep(ParticleSystem *psys, float t_frac) +{ /* Sync with frame end if it's close. */ if (t_frac == 1.0f) return psys->dt_frac; @@ -3991,7 +3994,9 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_ printf("%f,%f,%f,%f\n", cfra+dframe+t_frac - 1.f, t_frac, dt_frac, sim->courant_num); #endif if (part->time_flag & PART_TIME_AUTOSF) - dt_frac = update_timestep(psys, sim, t_frac); + update_timestep(psys, sim); + /* Even without AUTOSF dt_frac may not add up to 1.0 due to float precision. */ + dt_frac = sync_timestep(psys, t_frac); } } } |