From 766edbdf1f82389d89dc708b1e0d36efeaba0888 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 23 Jul 2020 17:57:11 +0200 Subject: Particles: improve mesh emitter Particles are now emitted from vertices of the mesh. --- source/blender/simulation/CMakeLists.txt | 3 + .../simulation/intern/particle_mesh_emitter.cc | 147 +++++++++++ .../simulation/intern/particle_mesh_emitter.hh | 47 ++++ .../intern/simulation_collect_influences.cc | 87 +------ .../intern/simulation_collect_influences.hh | 2 +- .../blender/simulation/intern/simulation_solver.cc | 3 +- .../blender/simulation/intern/simulation_solver.hh | 241 +----------------- .../intern/simulation_solver_influences.hh | 270 +++++++++++++++++++++ source/blender/simulation/intern/time_interval.hh | 2 +- 9 files changed, 476 insertions(+), 326 deletions(-) create mode 100644 source/blender/simulation/intern/particle_mesh_emitter.cc create mode 100644 source/blender/simulation/intern/particle_mesh_emitter.hh create mode 100644 source/blender/simulation/intern/simulation_solver_influences.hh (limited to 'source/blender/simulation') diff --git a/source/blender/simulation/CMakeLists.txt b/source/blender/simulation/CMakeLists.txt index 243b056db74..6466a6e67d4 100644 --- a/source/blender/simulation/CMakeLists.txt +++ b/source/blender/simulation/CMakeLists.txt @@ -43,6 +43,7 @@ set(SRC intern/implicit_eigen.cpp intern/particle_allocator.cc intern/particle_function.cc + intern/particle_mesh_emitter.cc intern/simulation_collect_influences.cc intern/simulation_solver.cc intern/simulation_update.cc @@ -52,7 +53,9 @@ set(SRC intern/implicit.h intern/particle_allocator.hh intern/particle_function.hh + intern/particle_mesh_emitter.hh intern/simulation_collect_influences.hh + intern/simulation_solver_influences.hh intern/simulation_solver.hh intern/time_interval.hh diff --git a/source/blender/simulation/intern/particle_mesh_emitter.cc b/source/blender/simulation/intern/particle_mesh_emitter.cc new file mode 100644 index 00000000000..ab2ee0c81ed --- /dev/null +++ b/source/blender/simulation/intern/particle_mesh_emitter.cc @@ -0,0 +1,147 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "particle_mesh_emitter.hh" + +#include "BLI_float4x4.hh" +#include "BLI_rand.hh" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" + +namespace blender::sim { + +struct EmitterSettings { + const Object *object; + float rate; +}; + +static void compute_birth_times(float rate, + TimeInterval emit_interval, + ParticleMeshEmitterSimulationState &state, + Vector &r_birth_times) +{ + const float time_between_particles = 1.0f / rate; + int counter = 0; + while (true) { + counter++; + const float time_offset = counter * time_between_particles; + const float birth_time = state.last_birth_time + time_offset; + if (birth_time > emit_interval.end()) { + break; + } + if (birth_time <= emit_interval.start()) { + continue; + } + r_birth_times.append(birth_time); + } +} + +static void compute_new_particle_attributes(EmitterSettings &settings, + TimeInterval emit_interval, + ParticleMeshEmitterSimulationState &state, + Vector &r_positions, + Vector &r_velocities, + Vector &r_birth_times) +{ + if (settings.object == nullptr) { + return; + } + if (settings.rate <= 0.000001f) { + return; + } + if (settings.object->type != OB_MESH) { + return; + } + const Mesh &mesh = *(Mesh *)settings.object->data; + if (mesh.totvert == 0) { + return; + } + + float4x4 local_to_world = settings.object->obmat; + + const float start_time = emit_interval.start(); + const uint32_t seed = DefaultHash{}(state.head.name); + RandomNumberGenerator rng{(*(uint32_t *)&start_time) ^ seed}; + + compute_birth_times(settings.rate, emit_interval, state, r_birth_times); + if (r_birth_times.is_empty()) { + return; + } + + state.last_birth_time = r_birth_times.last(); + + for (int i : r_birth_times.index_range()) { + UNUSED_VARS(i); + const int vertex_index = rng.get_int32() % mesh.totvert; + float3 vertex_position = mesh.mvert[vertex_index].co; + r_positions.append(local_to_world * vertex_position); + r_velocities.append(rng.get_unit_float3()); + } +} + +static EmitterSettings compute_settings(const fn::MultiFunction &inputs_fn, + ParticleEmitterContext &context) +{ + EmitterSettings parameters; + + fn::MFContextBuilder mf_context; + mf_context.add_global_context("PersistentDataHandleMap", &context.solve_context().handle_map()); + + fn::MFParamsBuilder mf_params{inputs_fn, 1}; + bke::PersistentObjectHandle object_handle; + mf_params.add_uninitialized_single_output(&object_handle, "Object"); + mf_params.add_uninitialized_single_output(¶meters.rate, "Rate"); + + inputs_fn.call(IndexRange(1), mf_params, mf_context); + + parameters.object = context.solve_context().handle_map().lookup(object_handle); + return parameters; +} + +void ParticleMeshEmitter::emit(ParticleEmitterContext &context) const +{ + auto *state = context.lookup_state(own_state_name_); + if (state == nullptr) { + return; + } + + EmitterSettings settings = compute_settings(inputs_fn_, context); + + Vector new_positions; + Vector new_velocities; + Vector new_birth_times; + + compute_new_particle_attributes( + settings, context.emit_interval(), *state, new_positions, new_velocities, new_birth_times); + + for (StringRef name : particle_names_) { + ParticleAllocator *allocator = context.try_get_particle_allocator(name); + if (allocator == nullptr) { + continue; + } + + int amount = new_positions.size(); + fn::MutableAttributesRef attributes = allocator->allocate(amount); + + attributes.get("Position").copy_from(new_positions); + attributes.get("Velocity").copy_from(new_velocities); + attributes.get("Birth Time").copy_from(new_birth_times); + } +} + +} // namespace blender::sim diff --git a/source/blender/simulation/intern/particle_mesh_emitter.hh b/source/blender/simulation/intern/particle_mesh_emitter.hh new file mode 100644 index 00000000000..8ad7b6f15f2 --- /dev/null +++ b/source/blender/simulation/intern/particle_mesh_emitter.hh @@ -0,0 +1,47 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __SIM_PARTICLE_MESH_EMITTER_HH__ +#define __SIM_PARTICLE_MESH_EMITTER_HH__ + +#include "simulation_solver_influences.hh" + +#include "FN_multi_function.hh" + +namespace blender::sim { + +class ParticleMeshEmitter final : public ParticleEmitter { + private: + std::string own_state_name_; + Array particle_names_; + const fn::MultiFunction &inputs_fn_; + + public: + ParticleMeshEmitter(std::string own_state_name, + Array particle_names, + const fn::MultiFunction &inputs_fn) + : own_state_name_(std::move(own_state_name)), + particle_names_(particle_names), + inputs_fn_(inputs_fn) + { + } + + void emit(ParticleEmitterContext &context) const override; +}; + +} // namespace blender::sim + +#endif /* __SIM_PARTICLE_MESH_EMITTER_HH__ */ diff --git a/source/blender/simulation/intern/simulation_collect_influences.cc b/source/blender/simulation/intern/simulation_collect_influences.cc index 876d0b50fc1..eebfe8b864e 100644 --- a/source/blender/simulation/intern/simulation_collect_influences.cc +++ b/source/blender/simulation/intern/simulation_collect_influences.cc @@ -16,6 +16,7 @@ #include "simulation_collect_influences.hh" #include "particle_function.hh" +#include "particle_mesh_emitter.hh" #include "FN_attributes_ref.hh" #include "FN_multi_function_network_evaluation.hh" @@ -279,83 +280,6 @@ static void collect_forces(nodes::MFNetworkTreeMap &network_map, } } -class MyBasicEmitter : public ParticleEmitter { - private: - Array names_; - std::string my_state_; - const fn::MultiFunction &inputs_fn_; - uint32_t seed_; - - public: - MyBasicEmitter(Array names, - std::string my_state, - const fn::MultiFunction &inputs_fn, - uint32_t seed) - : names_(std::move(names)), - my_state_(std::move(my_state)), - inputs_fn_(inputs_fn), - seed_(seed) - { - } - - void emit(ParticleEmitterContext &context) const override - { - auto *state = context.solve_context().state_map().lookup( - my_state_); - if (state == nullptr) { - return; - } - - fn::MFContextBuilder mf_context; - mf_context.add_global_context("PersistentDataHandleMap", - &context.solve_context().handle_map()); - - fn::MFParamsBuilder mf_params{inputs_fn_, 1}; - bke::PersistentObjectHandle object_handle; - float rate; - mf_params.add_uninitialized_single_output(&object_handle); - mf_params.add_uninitialized_single_output(&rate); - inputs_fn_.call(IndexRange(1), mf_params, mf_context); - - const Object *object = context.solve_context().handle_map().lookup(object_handle); - if (object == nullptr) { - return; - } - - Vector new_positions; - Vector new_velocities; - Vector new_birth_times; - - TimeInterval time_interval = context.simulation_time_interval(); - float start_time = time_interval.start(); - RandomNumberGenerator rng{(*(uint32_t *)&start_time) ^ seed_}; - - const float time_between_particles = 1.0f / rate; - while (state->last_birth_time + time_between_particles < time_interval.end()) { - new_positions.append(rng.get_unit_float3() * 0.3 + float3(object->loc)); - new_velocities.append(rng.get_unit_float3()); - const float birth_time = state->last_birth_time + time_between_particles; - new_birth_times.append(birth_time); - state->last_birth_time = birth_time; - } - - for (StringRef name : names_) { - ParticleAllocator *allocator = context.try_get_particle_allocator(name); - if (allocator == nullptr) { - return; - } - - int amount = new_positions.size(); - fn::MutableAttributesRef attributes = allocator->allocate(amount); - - initialized_copy_n(new_positions.data(), amount, attributes.get("Position").data()); - initialized_copy_n(new_velocities.data(), amount, attributes.get("Velocity").data()); - initialized_copy_n( - new_birth_times.data(), amount, attributes.get("Birth Time").data()); - } - } -}; - static Vector find_linked_particle_simulations( const nodes::DOutputSocket &output_socket) { @@ -396,11 +320,10 @@ static ParticleEmitter *create_particle_emitter(const nodes::DNode &dnode, fn::MultiFunction &inputs_fn = resources.construct( AT, Span(), input_sockets.as_span()); - std::string my_state_name = dnode_to_path(dnode); - r_required_states.add(my_state_name, SIM_TYPE_NAME_PARTICLE_MESH_EMITTER); - uint32_t seed = DefaultHash{}(my_state_name); - ParticleEmitter &emitter = resources.construct( - AT, std::move(names), std::move(my_state_name), inputs_fn, seed); + std::string own_state_name = dnode_to_path(dnode); + r_required_states.add(own_state_name, SIM_TYPE_NAME_PARTICLE_MESH_EMITTER); + ParticleEmitter &emitter = resources.construct( + AT, std::move(own_state_name), std::move(names), inputs_fn); return &emitter; } diff --git a/source/blender/simulation/intern/simulation_collect_influences.hh b/source/blender/simulation/intern/simulation_collect_influences.hh index 42cbea6977e..caf5a8c4ffa 100644 --- a/source/blender/simulation/intern/simulation_collect_influences.hh +++ b/source/blender/simulation/intern/simulation_collect_influences.hh @@ -21,7 +21,7 @@ #include "BLI_resource_collector.hh" -#include "simulation_solver.hh" +#include "simulation_solver_influences.hh" namespace blender::sim { diff --git a/source/blender/simulation/intern/simulation_solver.cc b/source/blender/simulation/intern/simulation_solver.cc index 9c70bdaa7b6..0328b5a0042 100644 --- a/source/blender/simulation/intern/simulation_solver.cc +++ b/source/blender/simulation/intern/simulation_solver.cc @@ -272,7 +272,6 @@ void solve_simulation_time_step(Simulation &simulation, TimeInterval(simulation.current_simulation_time, time_step), state_map, handle_map}; - TimeInterval simulation_time_interval{simulation.current_simulation_time, time_step}; Span particle_simulation_states = state_map.lookup(); @@ -305,7 +304,7 @@ void solve_simulation_time_step(Simulation &simulation, remove_dead_and_add_new_particles(*state, allocator); } - simulation.current_simulation_time = simulation_time_interval.end(); + simulation.current_simulation_time = solve_context.solve_interval().end(); } } // namespace blender::sim diff --git a/source/blender/simulation/intern/simulation_solver.hh b/source/blender/simulation/intern/simulation_solver.hh index 02c58da37f5..ccf4855a9a1 100644 --- a/source/blender/simulation/intern/simulation_solver.hh +++ b/source/blender/simulation/intern/simulation_solver.hh @@ -17,251 +17,12 @@ #ifndef __SIM_SIMULATION_SOLVER_HH__ #define __SIM_SIMULATION_SOLVER_HH__ -#include "BLI_float3.hh" -#include "BLI_span.hh" - -#include "DNA_simulation_types.h" - -#include "FN_attributes_ref.hh" - -#include "BKE_persistent_data_handle.hh" -#include "BKE_simulation.h" - -#include "particle_allocator.hh" -#include "time_interval.hh" +#include "simulation_collect_influences.hh" struct Depsgraph; namespace blender::sim { -class ParticleEmitterContext; -class ParticleForceContext; - -class ParticleEmitter { - public: - virtual ~ParticleEmitter(); - virtual void emit(ParticleEmitterContext &context) const = 0; -}; - -class ParticleForce { - public: - virtual ~ParticleForce(); - virtual void add_force(ParticleForceContext &context) const = 0; -}; - -struct SimulationInfluences { - Map> particle_forces; - Map particle_attributes_builder; - Vector particle_emitters; -}; - -class SimulationStateMap { - private: - Map states_by_name_; - Map> states_by_type_; - - public: - void add(SimulationState *state) - { - states_by_name_.add_new(state->name, state); - states_by_type_.lookup_or_add_default(state->type).append(state); - } - - template StateType *lookup(StringRef name) const - { - const char *type = BKE_simulation_get_state_type_name(); - return (StateType *)this->lookup_name_type(name, type); - } - - template Span lookup() const - { - const char *type = BKE_simulation_get_state_type_name(); - return this->lookup_type(type).cast(); - } - - SimulationState *lookup_name_type(StringRef name, StringRef type) const - { - SimulationState *state = states_by_name_.lookup_default_as(name, nullptr); - if (state == nullptr) { - return nullptr; - } - if (state->type == type) { - return state; - } - return nullptr; - } - - Span lookup_type(StringRef type) const - { - const Vector *states = states_by_type_.lookup_ptr_as(type); - if (states == nullptr) { - return {}; - } - else { - return states->as_span(); - } - } -}; - -class SimulationSolveContext { - private: - Simulation &simulation_; - Depsgraph &depsgraph_; - const SimulationInfluences &influences_; - TimeInterval solve_interval_; - const SimulationStateMap &state_map_; - const bke::PersistentDataHandleMap &id_handle_map_; - - public: - SimulationSolveContext(Simulation &simulation, - Depsgraph &depsgraph, - const SimulationInfluences &influences, - TimeInterval solve_interval, - const SimulationStateMap &state_map, - const bke::PersistentDataHandleMap &handle_map) - : simulation_(simulation), - depsgraph_(depsgraph), - influences_(influences), - solve_interval_(solve_interval), - state_map_(state_map), - id_handle_map_(handle_map) - { - } - - TimeInterval solve_interval() const - { - return solve_interval_; - } - - const SimulationInfluences &influences() const - { - return influences_; - } - - const bke::PersistentDataHandleMap &handle_map() const - { - return id_handle_map_; - } - - const SimulationStateMap &state_map() const - { - return state_map_; - } -}; - -class ParticleAllocators { - private: - Map> &allocators_; - - public: - ParticleAllocators(Map> &allocators) - : allocators_(allocators) - { - } - - ParticleAllocator *try_get_allocator(StringRef particle_simulation_name) - { - auto *ptr = allocators_.lookup_ptr_as(particle_simulation_name); - if (ptr != nullptr) { - return ptr->get(); - } - else { - return nullptr; - } - } -}; - -class ParticleChunkContext { - private: - IndexMask index_mask_; - fn::MutableAttributesRef attributes_; - - public: - ParticleChunkContext(IndexMask index_mask, fn::MutableAttributesRef attributes) - : index_mask_(index_mask), attributes_(attributes) - { - } - - IndexMask index_mask() const - { - return index_mask_; - } - - fn::MutableAttributesRef attributes() - { - return attributes_; - } - - fn::AttributesRef attributes() const - { - return attributes_; - } -}; - -class ParticleEmitterContext { - private: - SimulationSolveContext &solve_context_; - ParticleAllocators &particle_allocators_; - TimeInterval simulation_time_interval_; - - public: - ParticleEmitterContext(SimulationSolveContext &solve_context, - ParticleAllocators &particle_allocators, - TimeInterval simulation_time_interval) - : solve_context_(solve_context), - particle_allocators_(particle_allocators), - simulation_time_interval_(simulation_time_interval) - { - } - - SimulationSolveContext &solve_context() - { - return solve_context_; - } - - ParticleAllocator *try_get_particle_allocator(StringRef particle_simulation_name) - { - return particle_allocators_.try_get_allocator(particle_simulation_name); - } - - TimeInterval simulation_time_interval() const - { - return simulation_time_interval_; - } -}; - -class ParticleForceContext { - private: - SimulationSolveContext &solve_context_; - const ParticleChunkContext &particle_chunk_context_; - MutableSpan force_dst_; - - public: - ParticleForceContext(SimulationSolveContext &solve_context, - const ParticleChunkContext &particle_chunk_context, - MutableSpan force_dst) - : solve_context_(solve_context), - particle_chunk_context_(particle_chunk_context), - force_dst_(force_dst) - { - } - - SimulationSolveContext &solve_context() - { - return solve_context_; - } - - const ParticleChunkContext &particle_chunk() const - { - return particle_chunk_context_; - } - - MutableSpan force_dst() - { - return force_dst_; - } -}; - void initialize_simulation_states(Simulation &simulation, Depsgraph &depsgraph, const SimulationInfluences &influences, diff --git a/source/blender/simulation/intern/simulation_solver_influences.hh b/source/blender/simulation/intern/simulation_solver_influences.hh new file mode 100644 index 00000000000..8d5e171bea0 --- /dev/null +++ b/source/blender/simulation/intern/simulation_solver_influences.hh @@ -0,0 +1,270 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __SIM_SIMULATION_SOLVER_INFLUENCES_HH__ +#define __SIM_SIMULATION_SOLVER_INFLUENCES_HH__ + +#include "BLI_float3.hh" +#include "BLI_span.hh" + +#include "DNA_simulation_types.h" + +#include "FN_attributes_ref.hh" + +#include "BKE_persistent_data_handle.hh" +#include "BKE_simulation.h" + +#include "particle_allocator.hh" +#include "time_interval.hh" + +namespace blender::sim { + +class ParticleEmitterContext; +class ParticleForceContext; + +class ParticleEmitter { + public: + virtual ~ParticleEmitter(); + virtual void emit(ParticleEmitterContext &context) const = 0; +}; + +class ParticleForce { + public: + virtual ~ParticleForce(); + virtual void add_force(ParticleForceContext &context) const = 0; +}; + +struct SimulationInfluences { + Map> particle_forces; + Map particle_attributes_builder; + Vector particle_emitters; +}; + +class SimulationStateMap { + private: + Map states_by_name_; + Map> states_by_type_; + + public: + void add(SimulationState *state) + { + states_by_name_.add_new(state->name, state); + states_by_type_.lookup_or_add_default(state->type).append(state); + } + + template StateType *lookup(StringRef name) const + { + const char *type = BKE_simulation_get_state_type_name(); + return (StateType *)this->lookup_name_type(name, type); + } + + template Span lookup() const + { + const char *type = BKE_simulation_get_state_type_name(); + return this->lookup_type(type).cast(); + } + + SimulationState *lookup_name_type(StringRef name, StringRef type) const + { + SimulationState *state = states_by_name_.lookup_default_as(name, nullptr); + if (state == nullptr) { + return nullptr; + } + if (state->type == type) { + return state; + } + return nullptr; + } + + Span lookup_type(StringRef type) const + { + const Vector *states = states_by_type_.lookup_ptr_as(type); + if (states == nullptr) { + return {}; + } + else { + return states->as_span(); + } + } +}; + +class SimulationSolveContext { + private: + Simulation &simulation_; + Depsgraph &depsgraph_; + const SimulationInfluences &influences_; + TimeInterval solve_interval_; + const SimulationStateMap &state_map_; + const bke::PersistentDataHandleMap &id_handle_map_; + + public: + SimulationSolveContext(Simulation &simulation, + Depsgraph &depsgraph, + const SimulationInfluences &influences, + TimeInterval solve_interval, + const SimulationStateMap &state_map, + const bke::PersistentDataHandleMap &handle_map) + : simulation_(simulation), + depsgraph_(depsgraph), + influences_(influences), + solve_interval_(solve_interval), + state_map_(state_map), + id_handle_map_(handle_map) + { + } + + TimeInterval solve_interval() const + { + return solve_interval_; + } + + const SimulationInfluences &influences() const + { + return influences_; + } + + const bke::PersistentDataHandleMap &handle_map() const + { + return id_handle_map_; + } + + const SimulationStateMap &state_map() const + { + return state_map_; + } +}; + +class ParticleAllocators { + private: + Map> &allocators_; + + public: + ParticleAllocators(Map> &allocators) + : allocators_(allocators) + { + } + + ParticleAllocator *try_get_allocator(StringRef particle_simulation_name) + { + auto *ptr = allocators_.lookup_ptr_as(particle_simulation_name); + if (ptr != nullptr) { + return ptr->get(); + } + else { + return nullptr; + } + } +}; + +class ParticleChunkContext { + private: + IndexMask index_mask_; + fn::MutableAttributesRef attributes_; + + public: + ParticleChunkContext(IndexMask index_mask, fn::MutableAttributesRef attributes) + : index_mask_(index_mask), attributes_(attributes) + { + } + + IndexMask index_mask() const + { + return index_mask_; + } + + fn::MutableAttributesRef attributes() + { + return attributes_; + } + + fn::AttributesRef attributes() const + { + return attributes_; + } +}; + +class ParticleEmitterContext { + private: + SimulationSolveContext &solve_context_; + ParticleAllocators &particle_allocators_; + TimeInterval emit_interval_; + + public: + ParticleEmitterContext(SimulationSolveContext &solve_context, + ParticleAllocators &particle_allocators, + TimeInterval emit_interval) + : solve_context_(solve_context), + particle_allocators_(particle_allocators), + emit_interval_(emit_interval) + { + } + + template StateType *lookup_state(StringRef name) + { + return solve_context_.state_map().lookup(name); + } + + SimulationSolveContext &solve_context() + { + return solve_context_; + } + + ParticleAllocator *try_get_particle_allocator(StringRef particle_simulation_name) + { + return particle_allocators_.try_get_allocator(particle_simulation_name); + } + + TimeInterval emit_interval() const + { + return emit_interval_; + } +}; + +class ParticleForceContext { + private: + SimulationSolveContext &solve_context_; + const ParticleChunkContext &particle_chunk_context_; + MutableSpan force_dst_; + + public: + ParticleForceContext(SimulationSolveContext &solve_context, + const ParticleChunkContext &particle_chunk_context, + MutableSpan force_dst) + : solve_context_(solve_context), + particle_chunk_context_(particle_chunk_context), + force_dst_(force_dst) + { + } + + SimulationSolveContext &solve_context() + { + return solve_context_; + } + + const ParticleChunkContext &particle_chunk() const + { + return particle_chunk_context_; + } + + MutableSpan force_dst() + { + return force_dst_; + } +}; + +} // namespace blender::sim + +#endif /* __SIM_SIMULATION_SOLVER_INFLUENCES_HH__ */ diff --git a/source/blender/simulation/intern/time_interval.hh b/source/blender/simulation/intern/time_interval.hh index 49600dd10de..75ef4b21c33 100644 --- a/source/blender/simulation/intern/time_interval.hh +++ b/source/blender/simulation/intern/time_interval.hh @@ -22,7 +22,7 @@ namespace blender::sim { /** - * The start time is inclusive and the end time is exclusive. The duration is zero, the interval + * The start time is exclusive and the end time is inclusive. If the duration is zero, the interval * describes a single point in time. */ class TimeInterval { -- cgit v1.2.3