Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/simulation/intern/simulation_collect_influences.cc')
-rw-r--r--source/blender/simulation/intern/simulation_collect_influences.cc178
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