diff options
Diffstat (limited to 'source/blender/simulation/intern/simulation_collect_influences.cc')
-rw-r--r-- | source/blender/simulation/intern/simulation_collect_influences.cc | 178 |
1 files changed, 147 insertions, 31 deletions
diff --git a/source/blender/simulation/intern/simulation_collect_influences.cc b/source/blender/simulation/intern/simulation_collect_influences.cc index d4161b06a00..4760063daca 100644 --- a/source/blender/simulation/intern/simulation_collect_influences.cc +++ b/source/blender/simulation/intern/simulation_collect_influences.cc @@ -50,31 +50,51 @@ static Span<const nodes::DNode *> get_particle_simulation_nodes(const nodes::Der return tree.nodes_by_type("SimulationNodeParticleSimulation"); } -static std::optional<Array<std::string>> compute_global_string_inputs( - nodes::MFNetworkTreeMap &network_map, Span<const fn::MFInputSocket *> sockets) +/* Returns true on success. */ +static bool compute_global_inputs(nodes::MFNetworkTreeMap &network_map, + ResourceCollector &resources, + Span<const fn::MFInputSocket *> sockets, + MutableSpan<fn::GMutableSpan> r_results) { int amount = sockets.size(); if (amount == 0) { - return Array<std::string>(); + return true; } if (network_map.network().have_dummy_or_unlinked_dependencies(sockets)) { - return {}; + return false; } fn::MFNetworkEvaluator network_fn{{}, sockets}; - fn::MFParamsBuilder params{network_fn, 1}; - - Array<std::string> strings(amount, NoInitialization()); - for (int i : IndexRange(amount)) { - params.add_uninitialized_single_output( - fn::GMutableSpan(fn::CPPType::get<std::string>(), strings.data() + i, 1)); + for (int param_index : network_fn.param_indices()) { + fn::MFParamType param_type = network_fn.param_type(param_index); + BLI_assert(param_type.category() == fn::MFParamType::Category::SingleOutput); /* For now. */ + const fn::CPPType &type = param_type.data_type().single_type(); + void *buffer = resources.linear_allocator().allocate(type.size(), type.alignment()); + resources.add(buffer, type.destruct_cb(), AT); + fn::GMutableSpan span{type, buffer, 1}; + r_results[param_index] = span; + params.add_uninitialized_single_output(span); } - fn::MFContextBuilder context; - network_fn.call({0}, params, context); + network_fn.call(IndexRange(1), params, context); + return true; +} +static std::optional<Array<std::string>> compute_global_string_inputs( + nodes::MFNetworkTreeMap &network_map, Span<const fn::MFInputSocket *> sockets) +{ + ResourceCollector local_resources; + Array<fn::GMutableSpan> computed_values(sockets.size(), NoInitialization()); + if (!compute_global_inputs(network_map, local_resources, sockets, computed_values)) { + return {}; + } + + Array<std::string> strings(sockets.size()); + for (int i : sockets.index_range()) { + strings[i] = std::move(computed_values[i].typed<std::string>()[0]); + } return strings; } @@ -203,7 +223,8 @@ class ParticleFunctionForce : public ParticleForce { IndexMask mask = context.particle_chunk().index_mask(); MutableSpan<float3> r_combined_force = context.force_dst(); - ParticleFunctionEvaluator evaluator{particle_fn_, context.particle_chunk()}; + ParticleFunctionEvaluator evaluator{ + particle_fn_, context.solve_context(), context.particle_chunk()}; evaluator.compute(); fn::VSpan<float3> forces = evaluator.get<float3>(0, "Force"); @@ -258,44 +279,120 @@ static void collect_forces(nodes::MFNetworkTreeMap &network_map, class MyBasicEmitter : public ParticleEmitter { private: - std::string name_; + Array<std::string> names_; + const fn::MultiFunction &inputs_fn_; + uint32_t seed_; public: - MyBasicEmitter(std::string name) : name_(std::move(name)) + MyBasicEmitter(Array<std::string> names, const fn::MultiFunction &inputs_fn, uint32_t seed) + : names_(std::move(names)), inputs_fn_(inputs_fn), seed_(seed) { } void emit(ParticleEmitterContext &context) const override { - ParticleAllocator *allocator = context.try_get_particle_allocator(name_); - if (allocator == nullptr) { + 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; } - fn::MutableAttributesRef attributes = allocator->allocate(10); - RandomNumberGenerator rng{(uint32_t)context.simulation_time_interval().start() ^ - (uint32_t)DefaultHash<std::string>{}(name_)}; + Vector<float3> new_positions; + Vector<float3> new_velocities; + Vector<float> new_birth_times; + + float start_time = context.simulation_time_interval().start(); + RandomNumberGenerator rng{(*(uint32_t *)&start_time) ^ seed_}; + + int amount = rate * 10; + for (int i : IndexRange(amount)) { + UNUSED_VARS(i); + new_positions.append(rng.get_unit_float3() * 0.3 + float3(object->loc)); + new_velocities.append(rng.get_unit_float3()); + new_birth_times.append(context.simulation_time_interval().start()); + } + + for (StringRef name : names_) { + ParticleAllocator *allocator = context.try_get_particle_allocator(name); + if (allocator == nullptr) { + return; + } - MutableSpan<float3> positions = attributes.get<float3>("Position"); - MutableSpan<float3> velocities = attributes.get<float3>("Velocity"); - MutableSpan<float> birth_times = attributes.get<float>("Birth Time"); + fn::MutableAttributesRef attributes = allocator->allocate(amount); - for (int i : IndexRange(attributes.size())) { - positions[i] = rng.get_unit_float3(); - velocities[i] = rng.get_unit_float3(); - birth_times[i] = context.simulation_time_interval().start(); + initialized_copy_n(new_positions.data(), amount, attributes.get<float3>("Position").data()); + initialized_copy_n(new_velocities.data(), amount, attributes.get<float3>("Velocity").data()); + initialized_copy_n( + new_birth_times.data(), amount, attributes.get<float>("Birth Time").data()); } } }; +static Vector<const nodes::DNode *> find_linked_particle_simulations( + const nodes::DOutputSocket &output_socket) +{ + Vector<const nodes::DNode *> simulation_nodes; + for (const nodes::DInputSocket *target_socket : output_socket.linked_sockets()) { + if (target_socket->node().idname() == "SimulationNodeParticleSimulation") { + simulation_nodes.append(&target_socket->node()); + } + } + return simulation_nodes; +} + +static ParticleEmitter *create_particle_emitter(const nodes::DNode &dnode, + ResourceCollector &resources, + nodes::MFNetworkTreeMap &network_map) +{ + Vector<const nodes::DNode *> simulation_dnodes = find_linked_particle_simulations( + dnode.output(0)); + if (simulation_dnodes.size() == 0) { + return nullptr; + } + + Array<std::string> names{simulation_dnodes.size()}; + for (int i : simulation_dnodes.index_range()) { + names[i] = dnode_to_path(*simulation_dnodes[i]); + } + + Array<const fn::MFInputSocket *> input_sockets{dnode.inputs().size()}; + for (int i : input_sockets.index_range()) { + input_sockets[i] = &network_map.lookup_dummy(dnode.input(i)); + } + + if (network_map.network().have_dummy_or_unlinked_dependencies(input_sockets)) { + return nullptr; + } + + fn::MultiFunction &inputs_fn = resources.construct<fn::MFNetworkEvaluator>( + AT, Span<const fn::MFOutputSocket *>(), input_sockets.as_span()); + + uint32_t seed = DefaultHash<std::string>{}(dnode_to_path(dnode)); + ParticleEmitter &emitter = resources.construct<MyBasicEmitter>( + AT, std::move(names), inputs_fn, seed); + return &emitter; +} + static void collect_emitters(nodes::MFNetworkTreeMap &network_map, ResourceCollector &resources, SimulationInfluences &r_influences) { - for (const nodes::DNode *dnode : get_particle_simulation_nodes(network_map.tree())) { - std::string name = dnode_to_path(*dnode); - ParticleEmitter &emitter = resources.construct<MyBasicEmitter>(AT, name); - r_influences.particle_emitters.append(&emitter); + for (const nodes::DNode *dnode : + network_map.tree().nodes_by_type("SimulationNodeParticleMeshEmitter")) { + ParticleEmitter *emitter = create_particle_emitter(*dnode, resources, network_map); + if (emitter != nullptr) { + r_influences.particle_emitters.append(emitter); + } } } @@ -316,6 +413,23 @@ static void prepare_particle_attribute_builders(nodes::MFNetworkTreeMap &network } } +static void find_used_data_blocks(const nodes::DerivedNodeTree &tree, + SimulationInfluences &r_influences) +{ + const bNodeSocketType *socktype = nodeSocketTypeFind("NodeSocketObject"); + BLI_assert(socktype != nullptr); + + for (const nodes::DInputSocket *dsocket : tree.input_sockets()) { + const bNodeSocket *bsocket = dsocket->bsocket(); + if (bsocket->typeinfo == socktype) { + Object *value = ((const bNodeSocketValueObject *)bsocket->default_value)->value; + if (value != nullptr) { + r_influences.used_data_blocks.add(&value->id); + } + } + } +} + void collect_simulation_influences(Simulation &simulation, ResourceCollector &resources, SimulationInfluences &r_influences, @@ -343,6 +457,8 @@ void collect_simulation_influences(Simulation &simulation, for (const nodes::DNode *dnode : get_particle_simulation_nodes(tree)) { r_states_info.particle_simulation_names.add(dnode_to_path(*dnode)); } + + find_used_data_blocks(tree, r_influences); } } // namespace blender::sim |