From 3b9e16a4f7b8deca23ba8d2a02ef9182eb9d6bb4 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 28 Jul 2020 12:03:02 +0200 Subject: Particles: initial support for the Time input node --- .../blender/simulation/intern/particle_function.cc | 6 +- .../blender/simulation/intern/particle_function.hh | 7 +- .../intern/simulation_collect_influences.cc | 95 ++++++++++++++++++++-- 3 files changed, 97 insertions(+), 11 deletions(-) (limited to 'source/blender/simulation/intern') diff --git a/source/blender/simulation/intern/particle_function.cc b/source/blender/simulation/intern/particle_function.cc index d1e9019a85a..035e6d50e21 100644 --- a/source/blender/simulation/intern/particle_function.cc +++ b/source/blender/simulation/intern/particle_function.cc @@ -116,8 +116,9 @@ void ParticleFunctionEvaluator::compute_globals() fn::MFParamsBuilder params(*particle_fn_.global_fn_, mask_.min_array_size()); /* Add input parameters. */ + ParticleFunctionInputContext input_context{solve_context_, particles_}; for (const ParticleFunctionInput *input : particle_fn_.global_inputs_) { - input->add_input(particles_.attributes, params, resources_); + input->add_input(input_context, params, resources_); } /* Add output parameters. */ @@ -143,8 +144,9 @@ void ParticleFunctionEvaluator::compute_per_particle() fn::MFParamsBuilder params(*particle_fn_.per_particle_fn_, mask_.min_array_size()); /* Add input parameters. */ + ParticleFunctionInputContext input_context{solve_context_, particles_}; for (const ParticleFunctionInput *input : particle_fn_.per_particle_inputs_) { - input->add_input(particles_.attributes, params, resources_); + input->add_input(input_context, params, resources_); } /* Add output parameters. */ diff --git a/source/blender/simulation/intern/particle_function.hh b/source/blender/simulation/intern/particle_function.hh index abe0aae8522..c9b35640b47 100644 --- a/source/blender/simulation/intern/particle_function.hh +++ b/source/blender/simulation/intern/particle_function.hh @@ -26,10 +26,15 @@ namespace blender::sim { +struct ParticleFunctionInputContext { + const SimulationSolveContext &solve_context; + const ParticleChunkContext &particles; +}; + class ParticleFunctionInput { public: virtual ~ParticleFunctionInput() = default; - virtual void add_input(fn::AttributesRef attributes, + virtual void add_input(ParticleFunctionInputContext &context, fn::MFParamsBuilder ¶ms, ResourceCollector &resources) const = 0; }; diff --git a/source/blender/simulation/intern/simulation_collect_influences.cc b/source/blender/simulation/intern/simulation_collect_influences.cc index 40a29c95d25..4d339f9e323 100644 --- a/source/blender/simulation/intern/simulation_collect_influences.cc +++ b/source/blender/simulation/intern/simulation_collect_influences.cc @@ -28,12 +28,15 @@ #include "BLI_hash.h" #include "BLI_rand.hh" +#include "BLI_set.hh" namespace blender::sim { using fn::GVSpan; using fn::MFContextBuilder; using fn::MFDataType; +using fn::MFDummyNode; +using fn::MFFunctionNode; using fn::MFInputSocket; using fn::MFNetwork; using fn::MFNetworkEvaluator; @@ -53,6 +56,8 @@ using nodes::NodeTreeRefMap; struct DummyDataSources { Map particle_attributes; + Set simulation_time; + Set scene_time; }; extern "C" { @@ -226,6 +231,47 @@ static void prepare_particle_attribute_nodes(CollectContext &context) } } +static void prepare_time_input_nodes(CollectContext &context) +{ + Span time_input_dnodes = nodes_by_type(context, "SimulationNodeTime"); + Vector simulation_time_inputs; + Vector scene_time_inputs; + for (const DNode *dnode : time_input_dnodes) { + NodeSimInputTimeType type = (NodeSimInputTimeType)dnode->node_ref().bnode()->custom1; + switch (type) { + case NODE_SIM_INPUT_SIMULATION_TIME: { + simulation_time_inputs.append(dnode); + break; + } + case NODE_SIM_INPUT_SCENE_TIME: { + scene_time_inputs.append(dnode); + break; + } + } + } + + if (simulation_time_inputs.size() > 0) { + MFOutputSocket &new_socket = context.network.add_input("Simulation Time", + MFDataType::ForSingle()); + for (const DNode *dnode : simulation_time_inputs) { + MFOutputSocket &old_socket = context.network_map.lookup_dummy(dnode->output(0)); + context.network.relink(old_socket, new_socket); + context.network.remove(old_socket.node()); + } + context.data_sources.simulation_time.add(&new_socket); + } + if (scene_time_inputs.size() > 0) { + MFOutputSocket &new_socket = context.network.add_input("Scene Time", + MFDataType::ForSingle()); + for (const DNode *dnode : scene_time_inputs) { + MFOutputSocket &old_socket = context.network_map.lookup_dummy(dnode->output(0)); + context.network.relink(old_socket, new_socket); + context.network.remove(old_socket.node()); + } + context.data_sources.scene_time.add(&new_socket); + } +} + class ParticleAttributeInput : public ParticleFunctionInput { private: std::string attribute_name_; @@ -237,11 +283,12 @@ class ParticleAttributeInput : public ParticleFunctionInput { { } - void add_input(AttributesRef attributes, + void add_input(ParticleFunctionInputContext &context, MFParamsBuilder ¶ms, ResourceCollector &UNUSED(resources)) const override { - std::optional span = attributes.try_get(attribute_name_, attribute_type_); + std::optional span = context.particles.attributes.try_get(attribute_name_, + attribute_type_); if (span.has_value()) { params.add_readonly_single_input(*span); } @@ -251,6 +298,29 @@ class ParticleAttributeInput : public ParticleFunctionInput { } }; +class SceneTimeInput : public ParticleFunctionInput { + void add_input(ParticleFunctionInputContext &context, + MFParamsBuilder ¶ms, + ResourceCollector &resources) const override + { + const float time = DEG_get_ctime(&context.solve_context.depsgraph); + float *time_ptr = &resources.construct(AT, time); + params.add_readonly_single_input(time_ptr); + } +}; + +class SimulationTimeInput : public ParticleFunctionInput { + void add_input(ParticleFunctionInputContext &context, + MFParamsBuilder ¶ms, + ResourceCollector &resources) const override + { + /* TODO: Vary this per particle. */ + const float time = context.solve_context.solve_interval.stop(); + float *time_ptr = &resources.construct(AT, time); + params.add_readonly_single_input(time_ptr); + } +}; + static const ParticleFunction *create_particle_function_for_inputs( CollectContext &context, Span sockets_to_compute) { @@ -264,13 +334,21 @@ static const ParticleFunction *create_particle_function_for_inputs( Vector per_particle_inputs; for (const MFOutputSocket *socket : dummy_deps) { - const std::string *attribute_name = context.data_sources.particle_attributes.lookup_ptr( - socket); - if (attribute_name == nullptr) { - return nullptr; + if (context.data_sources.particle_attributes.contains(socket)) { + const std::string *attribute_name = context.data_sources.particle_attributes.lookup_ptr( + socket); + if (attribute_name == nullptr) { + return nullptr; + } + per_particle_inputs.append(&context.resources.construct( + AT, *attribute_name, socket->data_type().single_type())); + } + else if (context.data_sources.scene_time.contains(socket)) { + per_particle_inputs.append(&context.resources.construct(AT)); + } + else if (context.data_sources.simulation_time.contains(socket)) { + per_particle_inputs.append(&context.resources.construct(AT)); } - per_particle_inputs.append(&context.resources.construct( - AT, *attribute_name, socket->data_type().single_type())); } const MultiFunction &per_particle_fn = context.resources.construct( @@ -689,6 +767,7 @@ void collect_simulation_influences(Simulation &simulation, initialize_particle_attribute_builders(context); prepare_particle_attribute_nodes(context); + prepare_time_input_nodes(context); collect_forces(context); collect_emitters(context); -- cgit v1.2.3