From 0b50ea51ccdf8ac5b7f1cecee027c1ddd1b9620f Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 23 Jul 2020 23:03:19 +0200 Subject: Particles: simulate partial time steps on newly emitted particles --- .../blender/simulation/intern/simulation_solver.cc | 61 +++++++++++++++------- .../intern/simulation_solver_influences.hh | 10 ++++ 2 files changed, 51 insertions(+), 20 deletions(-) (limited to 'source/blender/simulation') diff --git a/source/blender/simulation/intern/simulation_solver.cc b/source/blender/simulation/intern/simulation_solver.cc index 2bd9e72eeac..1ed60022e2d 100644 --- a/source/blender/simulation/intern/simulation_solver.cc +++ b/source/blender/simulation/intern/simulation_solver.cc @@ -129,35 +129,32 @@ static void ensure_attributes_exist(ParticleSimulationState *state, const fn::At } } -BLI_NOINLINE static void simulate_existing_particles(SimulationSolveContext &solve_context, - ParticleSimulationState &state, - const fn::AttributesInfo &attributes_info) +BLI_NOINLINE static void simulate_particle_chunk(SimulationSolveContext &solve_context, + ParticleSimulationState &state, + fn::MutableAttributesRef attributes, + MutableSpan remaining_durations, + float end_time) { - CustomDataAttributesRef custom_data_attributes{ - state.attributes, state.tot_particles, attributes_info}; - fn::MutableAttributesRef attributes = custom_data_attributes; + int particle_amount = attributes.size(); + Array force_vectors{particle_amount, {0, 0, 0}}; + Span forces = solve_context.influences().get_particle_forces( + state.head.name); - Array force_vectors{state.tot_particles, {0, 0, 0}}; - const Vector *forces = - solve_context.influences().particle_forces.lookup_ptr(state.head.name); + ParticleChunkContext particle_chunk_context{IndexMask(particle_amount), attributes}; + ParticleForceContext particle_force_context{ + solve_context, particle_chunk_context, force_vectors}; - if (forces != nullptr) { - ParticleChunkContext particle_chunk_context{IndexMask(state.tot_particles), attributes}; - ParticleForceContext particle_force_context{ - solve_context, particle_chunk_context, force_vectors}; - - for (const ParticleForce *force : *forces) { - force->add_force(particle_force_context); - } + for (const ParticleForce *force : forces) { + force->add_force(particle_force_context); } MutableSpan positions = attributes.get("Position"); MutableSpan velocities = attributes.get("Velocity"); MutableSpan birth_times = attributes.get("Birth Time"); MutableSpan dead_states = attributes.get("Dead"); - float end_time = solve_context.solve_interval().end(); - float time_step = solve_context.solve_interval().duration(); - for (int i : positions.index_range()) { + + for (int i : IndexRange(particle_amount)) { + const float time_step = remaining_durations[i]; velocities[i] += force_vectors[i] * time_step; positions[i] += velocities[i] * time_step; @@ -167,6 +164,19 @@ BLI_NOINLINE static void simulate_existing_particles(SimulationSolveContext &sol } } +BLI_NOINLINE static void simulate_existing_particles(SimulationSolveContext &solve_context, + ParticleSimulationState &state, + const fn::AttributesInfo &attributes_info) +{ + CustomDataAttributesRef custom_data_attributes{ + state.attributes, state.tot_particles, attributes_info}; + fn::MutableAttributesRef attributes = custom_data_attributes; + + Array remaining_durations(state.tot_particles, solve_context.solve_interval().duration()); + simulate_particle_chunk( + solve_context, state, attributes, remaining_durations, solve_context.solve_interval().end()); +} + BLI_NOINLINE static void run_emitters(SimulationSolveContext &solve_context, ParticleAllocators &particle_allocators) { @@ -301,6 +311,17 @@ void solve_simulation_time_step(Simulation &simulation, for (ParticleSimulationState *state : particle_simulation_states) { ParticleAllocator &allocator = *particle_allocators.try_get_allocator(state->head.name); + + for (fn::MutableAttributesRef attributes : allocator.get_allocations()) { + Array remaining_durations(attributes.size()); + Span birth_times = attributes.get("Birth Time"); + const float end_time = solve_context.solve_interval().end(); + for (int i : attributes.index_range()) { + remaining_durations[i] = end_time - birth_times[i]; + } + simulate_particle_chunk(solve_context, *state, attributes, remaining_durations, end_time); + } + remove_dead_and_add_new_particles(*state, allocator); } diff --git a/source/blender/simulation/intern/simulation_solver_influences.hh b/source/blender/simulation/intern/simulation_solver_influences.hh index 8d5e171bea0..0eb4dfbaf69 100644 --- a/source/blender/simulation/intern/simulation_solver_influences.hh +++ b/source/blender/simulation/intern/simulation_solver_influences.hh @@ -48,9 +48,19 @@ class ParticleForce { }; struct SimulationInfluences { + /* TODO: Use a special type for a map that contains vectors. */ Map> particle_forces; Map particle_attributes_builder; Vector particle_emitters; + + Span get_particle_forces(StringRef particle_name) const + { + const Vector *forces = particle_forces.lookup_ptr(particle_name); + if (forces == nullptr) { + return {}; + } + return *forces; + } }; class SimulationStateMap { -- cgit v1.2.3