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')
-rw-r--r--source/blender/simulation/intern/particle_mesh_emitter.cc10
-rw-r--r--source/blender/simulation/intern/particle_mesh_emitter.hh7
-rw-r--r--source/blender/simulation/intern/simulation_collect_influences.cc132
-rw-r--r--source/blender/simulation/intern/simulation_solver.cc3
4 files changed, 112 insertions, 40 deletions
diff --git a/source/blender/simulation/intern/particle_mesh_emitter.cc b/source/blender/simulation/intern/particle_mesh_emitter.cc
index c1482a29cb7..26541d550eb 100644
--- a/source/blender/simulation/intern/particle_mesh_emitter.cc
+++ b/source/blender/simulation/intern/particle_mesh_emitter.cc
@@ -346,6 +346,16 @@ void ParticleMeshEmitter::emit(ParticleEmitterContext &context) const
attributes.get<float3>("Position").copy_from(new_positions);
attributes.get<float3>("Velocity").copy_from(new_velocities);
attributes.get<float>("Birth Time").copy_from(new_birth_times);
+
+ if (action_ != nullptr) {
+ ParticleChunkContext particles{
+ *context.solve_context.state_map.lookup<ParticleSimulationState>(name),
+ IndexRange(amount),
+ attributes,
+ nullptr};
+ ParticleActionContext action_context{context.solve_context, particles};
+ action_->execute(action_context);
+ }
}
}
diff --git a/source/blender/simulation/intern/particle_mesh_emitter.hh b/source/blender/simulation/intern/particle_mesh_emitter.hh
index 601697c9986..724d79c1aec 100644
--- a/source/blender/simulation/intern/particle_mesh_emitter.hh
+++ b/source/blender/simulation/intern/particle_mesh_emitter.hh
@@ -28,14 +28,17 @@ class ParticleMeshEmitter final : public ParticleEmitter {
std::string own_state_name_;
Array<std::string> particle_names_;
const fn::MultiFunction &inputs_fn_;
+ const ParticleAction *action_;
public:
ParticleMeshEmitter(std::string own_state_name,
Array<std::string> particle_names,
- const fn::MultiFunction &inputs_fn)
+ const fn::MultiFunction &inputs_fn,
+ const ParticleAction *action)
: own_state_name_(std::move(own_state_name)),
particle_names_(particle_names),
- inputs_fn_(inputs_fn)
+ inputs_fn_(inputs_fn),
+ action_(action)
{
}
diff --git a/source/blender/simulation/intern/simulation_collect_influences.cc b/source/blender/simulation/intern/simulation_collect_influences.cc
index c309d18c43a..818415e5d88 100644
--- a/source/blender/simulation/intern/simulation_collect_influences.cc
+++ b/source/blender/simulation/intern/simulation_collect_influences.cc
@@ -367,6 +367,17 @@ static const ParticleFunction *create_particle_function_for_inputs(
return &particle_fn;
}
+static const ParticleFunction *create_particle_function_for_inputs(
+ CollectContext &context, Span<const DInputSocket *> dsockets_to_compute)
+{
+ Vector<const MFInputSocket *> sockets_to_compute;
+ for (const DInputSocket *dsocket : dsockets_to_compute) {
+ const MFInputSocket &socket = context.network_map.lookup_dummy(*dsocket);
+ sockets_to_compute.append(&socket);
+ }
+ return create_particle_function_for_inputs(context, sockets_to_compute);
+}
+
class ParticleFunctionForce : public ParticleForce {
private:
const ParticleFunction &particle_fn_;
@@ -401,11 +412,8 @@ static void create_forces_for_particle_simulation(CollectContext &context,
continue;
}
- const MFInputSocket &force_socket = context.network_map.lookup_dummy(
- origin_node.input(0, "Force"));
-
- const ParticleFunction *particle_fn = create_particle_function_for_inputs(context,
- {&force_socket});
+ const ParticleFunction *particle_fn = create_particle_function_for_inputs(
+ context, {&origin_node.input(0, "Force")});
if (particle_fn == nullptr) {
continue;
@@ -434,7 +442,7 @@ static ParticleEmitter *create_particle_emitter(CollectContext &context, const D
return nullptr;
}
- Array<const MFInputSocket *> input_sockets{dnode.inputs().size()};
+ Array<const MFInputSocket *> input_sockets{2};
for (int i : input_sockets.index_range()) {
input_sockets[i] = &context.network_map.lookup_dummy(dnode.input(i));
}
@@ -446,10 +454,13 @@ static ParticleEmitter *create_particle_emitter(CollectContext &context, const D
MultiFunction &inputs_fn = context.resources.construct<MFNetworkEvaluator>(
AT, Span<const MFOutputSocket *>(), input_sockets.as_span());
+ const ParticleAction *birth_action = create_particle_action(
+ context, dnode.input(2, "Execute"), names);
+
StringRefNull own_state_name = get_identifier(context, dnode);
context.required_states.add(own_state_name, SIM_TYPE_NAME_PARTICLE_MESH_EMITTER);
ParticleEmitter &emitter = context.resources.construct<ParticleMeshEmitter>(
- AT, own_state_name, names.as_span(), inputs_fn);
+ AT, own_state_name, names.as_span(), inputs_fn, birth_action);
return &emitter;
}
@@ -490,15 +501,10 @@ static void collect_time_step_events(CollectContext &context)
{
for (const DNode *event_dnode : nodes_by_type(context, "SimulationNodeParticleTimeStepEvent")) {
const DInputSocket &execute_input = event_dnode->input(0);
- if (execute_input.linked_sockets().size() != 1) {
- continue;
- }
-
Array<StringRefNull> particle_names = find_linked_particle_simulations(context,
event_dnode->output(0));
- const DOutputSocket &execute_source = *execute_input.linked_sockets()[0];
- const ParticleAction *action = create_particle_action(context, execute_source, particle_names);
+ const ParticleAction *action = create_particle_action(context, execute_input, particle_names);
if (action == nullptr) {
continue;
}
@@ -570,6 +576,10 @@ class SetParticleAttributeAction : public ParticleAction {
cpp_type_.copy_to_initialized_indices(
value_array.data(), attribute_array->data(), context.particles.index_mask);
}
+
+ if (attribute_name_ == "Velocity") {
+ context.particles.update_diffs_after_velocity_change();
+ }
}
};
@@ -595,21 +605,28 @@ static const ParticleAction *create_set_particle_attribute_action(
CollectContext &context, const DOutputSocket &dsocket, Span<StringRefNull> particle_names)
{
const DNode &dnode = dsocket.node();
+
+ const ParticleAction *previous_action = create_particle_action(
+ context, dnode.input(0), particle_names);
+
MFInputSocket &name_socket = context.network_map.lookup_dummy(dnode.input(1));
MFInputSocket &value_socket = name_socket.node().input(1);
std::optional<Array<std::string>> names = compute_global_string_inputs(context.network_map,
{&name_socket});
if (!names.has_value()) {
- return nullptr;
+ return previous_action;
}
std::string attribute_name = (*names)[0];
+ if (attribute_name.empty()) {
+ return previous_action;
+ }
const CPPType &attribute_type = value_socket.data_type().single_type();
const ParticleFunction *inputs_fn = create_particle_function_for_inputs(context,
{&value_socket});
if (inputs_fn == nullptr) {
- return nullptr;
+ return previous_action;
}
for (StringRef particle_name : particle_names) {
@@ -620,9 +637,6 @@ static const ParticleAction *create_set_particle_attribute_action(
ParticleAction &this_action = context.resources.construct<SetParticleAttributeAction>(
AT, attribute_name, attribute_type, *inputs_fn);
- const ParticleAction *previous_action = create_particle_action(
- context, dnode.input(0), particle_names);
-
return concatenate_actions(context, {previous_action, &this_action});
}
@@ -698,10 +712,9 @@ static const ParticleAction *create_particle_condition_action(CollectContext &co
Span<StringRefNull> particle_names)
{
const DNode &dnode = dsocket.node();
- MFInputSocket &condition_socket = context.network_map.lookup_dummy(dnode.input(0));
- const ParticleFunction *inputs_fn = create_particle_function_for_inputs(context,
- {&condition_socket});
+ const ParticleFunction *inputs_fn = create_particle_function_for_inputs(
+ context, {&dnode.input(0, "Condition")});
if (inputs_fn == nullptr) {
return nullptr;
}
@@ -718,17 +731,32 @@ static const ParticleAction *create_particle_condition_action(CollectContext &co
AT, *inputs_fn, true_action, false_action);
}
+class KillParticleAction : public ParticleAction {
+ public:
+ void execute(ParticleActionContext &context) const override
+ {
+ MutableSpan<int> dead_states = context.particles.attributes.get<int>("Dead");
+ for (int i : context.particles.index_mask) {
+ dead_states[i] = true;
+ }
+ }
+};
+
static const ParticleAction *create_particle_action(CollectContext &context,
const DOutputSocket &dsocket,
Span<StringRefNull> particle_names)
{
const DNode &dnode = dsocket.node();
- if (dnode.idname() == "SimulationNodeSetParticleAttribute") {
+ StringRef idname = dnode.idname();
+ if (idname == "SimulationNodeSetParticleAttribute") {
return create_set_particle_attribute_action(context, dsocket, particle_names);
}
- if (dnode.idname() == "SimulationNodeExecuteCondition") {
+ if (idname == "SimulationNodeExecuteCondition") {
return create_particle_condition_action(context, dsocket, particle_names);
}
+ if (idname == "SimulationNodeKillParticle") {
+ return &context.resources.construct<KillParticleAction>(AT);
+ }
return nullptr;
}
@@ -762,25 +790,38 @@ static void optimize_function_network(CollectContext &context)
class AgeReachedEvent : public ParticleEvent {
private:
std::string attribute_name_;
+ const ParticleFunction &inputs_fn_;
+ const ParticleAction &action_;
public:
- AgeReachedEvent(std::string attribute_name) : attribute_name_(std::move(attribute_name))
+ AgeReachedEvent(std::string attribute_name,
+ const ParticleFunction &inputs_fn,
+ const ParticleAction &action)
+ : attribute_name_(std::move(attribute_name)), inputs_fn_(inputs_fn), action_(action)
{
}
void filter(ParticleEventFilterContext &context) const override
{
Span<float> birth_times = context.particles.attributes.get<float>("Birth Time");
- Span<int> has_been_triggered = context.particles.attributes.get<int>(attribute_name_);
- const float age = 5.0f;
+ std::optional<Span<int>> has_been_triggered = context.particles.attributes.try_get<int>(
+ attribute_name_);
+ if (!has_been_triggered.has_value()) {
+ return;
+ }
+
+ ParticleFunctionEvaluator evaluator{inputs_fn_, context.solve_context, context.particles};
+ evaluator.compute();
+ VSpan<float> trigger_ages = evaluator.get<float>(0, "Age");
const float end_time = context.particles.integration->end_time;
for (int i : context.particles.index_mask) {
- if (has_been_triggered[i]) {
+ if ((*has_been_triggered)[i]) {
continue;
}
+ const float trigger_age = trigger_ages[i];
const float birth_time = birth_times[i];
- const float trigger_time = birth_time + age;
+ const float trigger_time = birth_time + trigger_age;
if (trigger_time > end_time) {
continue;
}
@@ -795,24 +836,41 @@ class AgeReachedEvent : public ParticleEvent {
void execute(ParticleActionContext &context) const override
{
- MutableSpan<int> dead_states = context.particles.attributes.get<int>("Dead");
MutableSpan<int> has_been_triggered = context.particles.attributes.get<int>(attribute_name_);
for (int i : context.particles.index_mask) {
- dead_states[i] = true;
has_been_triggered[i] = 1;
}
+ action_.execute(context);
}
};
static void collect_age_reached_events(CollectContext &context)
{
- /* TODO: Actually implement an Age Reached Event node. */
- std::string attribute_name = "Has Been Triggered";
- const AgeReachedEvent &event = context.resources.construct<AgeReachedEvent>(AT, attribute_name);
- for (const DNode *dnode : context.particle_simulation_nodes) {
- StringRefNull name = get_identifier(context, *dnode);
- context.influences.particle_events.add_as(name, &event);
- context.influences.particle_attributes_builder.lookup_as(name)->add<int>(attribute_name, 0);
+ for (const DNode *dnode : nodes_by_type(context, "SimulationNodeAgeReachedEvent")) {
+ const DInputSocket &age_input = dnode->input(0, "Age");
+ const DInputSocket &execute_input = dnode->input(1, "Execute");
+ Array<StringRefNull> particle_names = find_linked_particle_simulations(context,
+ dnode->output(0));
+ const ParticleAction *action = create_particle_action(context, execute_input, particle_names);
+ if (action == nullptr) {
+ continue;
+ }
+ const ParticleFunction *inputs_fn = create_particle_function_for_inputs(context, {&age_input});
+ if (inputs_fn == nullptr) {
+ continue;
+ }
+
+ std::string attribute_name = get_identifier(context, *dnode);
+ const ParticleEvent &event = context.resources.construct<AgeReachedEvent>(
+ AT, attribute_name, *inputs_fn, *action);
+ for (StringRefNull particle_name : particle_names) {
+ const bool added_attribute = context.influences.particle_attributes_builder
+ .lookup_as(particle_name)
+ ->add<int>(attribute_name, 0);
+ if (added_attribute) {
+ context.influences.particle_events.add_as(particle_name, &event);
+ }
+ }
}
}
diff --git a/source/blender/simulation/intern/simulation_solver.cc b/source/blender/simulation/intern/simulation_solver.cc
index 9f2766aa24f..d53ccd2bd49 100644
--- a/source/blender/simulation/intern/simulation_solver.cc
+++ b/source/blender/simulation/intern/simulation_solver.cc
@@ -143,8 +143,9 @@ BLI_NOINLINE static void find_next_event_per_particle(
r_next_event_indices.fill_indices(particles.index_mask, -1);
r_time_factors_to_next_event.fill_indices(particles.index_mask, 1.0f);
- Array<float> time_factors(particles.index_mask.min_array_size(), -1.0f);
+ Array<float> time_factors(particles.index_mask.min_array_size());
for (int event_index : events.index_range()) {
+ time_factors.fill(-1.0f);
ParticleEventFilterContext event_context{solve_context, particles, time_factors};
const ParticleEvent &event = *events[event_index];
event.filter(event_context);