diff options
author | Jacques Lucke <jacques@blender.org> | 2020-07-24 00:03:19 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2020-07-24 00:03:19 +0300 |
commit | 0b50ea51ccdf8ac5b7f1cecee027c1ddd1b9620f (patch) | |
tree | 4abdcafe13cb598009a84e51807476ccb461cf0d | |
parent | f359672c3589c5c474abe1de78fcf39dd59e3532 (diff) |
Particles: simulate partial time steps on newly emitted particles
-rw-r--r-- | source/blender/simulation/intern/simulation_solver.cc | 61 | ||||
-rw-r--r-- | source/blender/simulation/intern/simulation_solver_influences.hh | 10 |
2 files changed, 51 insertions, 20 deletions
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<float> 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<float3> force_vectors{particle_amount, {0, 0, 0}}; + Span<const ParticleForce *> forces = solve_context.influences().get_particle_forces( + state.head.name); - Array<float3> force_vectors{state.tot_particles, {0, 0, 0}}; - const Vector<const ParticleForce *> *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<float3> positions = attributes.get<float3>("Position"); MutableSpan<float3> velocities = attributes.get<float3>("Velocity"); MutableSpan<float> birth_times = attributes.get<float>("Birth Time"); MutableSpan<int> dead_states = attributes.get<int>("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<float> 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<float> remaining_durations(attributes.size()); + Span<float> birth_times = attributes.get<float>("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<std::string, Vector<const ParticleForce *>> particle_forces; Map<std::string, fn::AttributesInfoBuilder *> particle_attributes_builder; Vector<const ParticleEmitter *> particle_emitters; + + Span<const ParticleForce *> get_particle_forces(StringRef particle_name) const + { + const Vector<const ParticleForce *> *forces = particle_forces.lookup_ptr(particle_name); + if (forces == nullptr) { + return {}; + } + return *forces; + } }; class SimulationStateMap { |