[Bf-blender-cvs] [5554851f15c] functions: refactor moving particles to next event time

Jacques Lucke noreply at git.blender.org
Tue Jun 18 18:25:52 CEST 2019


Commit: 5554851f15c28e6cfd0bdda5737f2953b0e8caf2
Author: Jacques Lucke
Date:   Tue Jun 18 18:23:10 2019 +0200
Branches: functions
https://developer.blender.org/rB5554851f15c28e6cfd0bdda5737f2953b0e8caf2

refactor moving particles to next event time

===================================================================

M	source/blender/simulations/bparticles/playground_solver.cpp

===================================================================

diff --git a/source/blender/simulations/bparticles/playground_solver.cpp b/source/blender/simulations/bparticles/playground_solver.cpp
index a8e9b8805d3..0485de8a1be 100644
--- a/source/blender/simulations/bparticles/playground_solver.cpp
+++ b/source/blender/simulations/bparticles/playground_solver.cpp
@@ -6,34 +6,48 @@
 
 namespace BParticles {
 
-class MoveUpAction : public BParticles::Action {
+class MoveAction : public BParticles::Action {
+ private:
+  float3 m_offset;
+
  public:
+  MoveAction(float3 offset) : m_offset(offset)
+  {
+  }
+
   void execute(AttributeArrays attributes, ArrayRef<uint> indices_mask) override
   {
     auto positions = attributes.get_float3("Position");
 
     for (uint pindex : indices_mask) {
-      positions[pindex].y += 5.0f;
+      positions[pindex] += m_offset;
     }
   }
 };
 
 class HitPlaneEvent : public PositionalEvent {
+ private:
+  float m_value;
+
  public:
-  virtual void filter(AttributeArrays attributes,
-                      ArrayRef<uint> indices_mask,
-                      ArrayRef<float3> next_movement,
-                      SmallVector<uint> &r_filtered_indices,
-                      SmallVector<float> &r_time_factors) override
+  HitPlaneEvent(float value) : m_value(value)
+  {
+  }
+
+  void filter(AttributeArrays attributes,
+              ArrayRef<uint> indices_mask,
+              ArrayRef<float3> next_movement,
+              SmallVector<uint> &r_filtered_indices,
+              SmallVector<float> &r_time_factors) override
   {
     auto positions = attributes.get_float3("Position");
 
     for (uint i = 0; i < indices_mask.size(); i++) {
       uint pindex = indices_mask[i];
 
-      if (positions[pindex].y < 2.0f && positions[pindex].y + next_movement[i].y >= 2.0f) {
-        float time_factor = (2.0f - positions[pindex].y) / next_movement[i].y;
-        r_filtered_indices.append(pindex);
+      if (positions[pindex].y < m_value && positions[pindex].y + next_movement[i].y >= m_value) {
+        float time_factor = (m_value - positions[pindex].y) / next_movement[i].y;
+        r_filtered_indices.append(i);
         r_time_factors.append(time_factor);
       }
     }
@@ -56,6 +70,13 @@ class SimpleSolver : public Solver {
   AttributesInfo m_attributes;
   SmallVector<EmitterInfo> m_emitter_infos;
 
+  struct EventWithAction {
+    PositionalEvent *event;
+    Action *action;
+  };
+
+  SmallVector<EventWithAction> m_events;
+
  public:
   SimpleSolver(Description &description) : m_description(description)
   {
@@ -77,6 +98,9 @@ class SimpleSolver : public Solver {
 
     m_attributes = AttributesInfo(
         byte_attributes.values(), float_attributes.values(), float3_attributes.values());
+
+    m_events.append({new HitPlaneEvent(1.0f), new MoveAction({0, 2, 0})});
+    m_events.append({new HitPlaneEvent(5.0f), new MoveAction({0, 2, -2})});
   }
 
   StateBase *init() override
@@ -166,6 +190,11 @@ class SimpleSolver : public Solver {
     }
   }
 
+  struct EventIndexAtTime {
+    int index = -1;
+    float time_factor = 2.0f; /* Just has to be > 1.0f. */
+  };
+
   BLI_NOINLINE void step_slice_to_next_event(MyState &UNUSED(state),
                                              AttributeArrays attributes,
                                              ArrayRef<uint> indices_mask,
@@ -179,50 +208,110 @@ class SimpleSolver : public Solver {
     this->integrate_particles(
         attributes, indices_mask, time_diffs, position_offsets, velocity_offsets);
 
-    auto positions = attributes.get_float3("Position");
-    auto velocities = attributes.get_float3("Velocity");
+    SmallVector<EventIndexAtTime> first_event_per_particle(indices_mask.size());
+    this->find_next_events(attributes, indices_mask, position_offsets, first_event_per_particle);
+    this->forward_particles_to_next_event(
+        attributes, indices_mask, first_event_per_particle, position_offsets, velocity_offsets);
+
+    SmallVector<SmallVector<uint>> particles_per_event(m_events.size());
+    this->find_particles_per_event(indices_mask, first_event_per_particle, particles_per_event);
+    this->run_actions(attributes, particles_per_event);
+
+    this->find_unfinished_particles(indices_mask,
+                                    first_event_per_particle,
+                                    time_diffs,
+                                    r_unfinished_mask,
+                                    r_unfinished_time_diffs);
+  }
 
-    HitPlaneEvent event;
-    SmallVector<uint> triggered_indices;
-    SmallVector<float> triggered_time_factors;
-    event.filter(
-        attributes, indices_mask, position_offsets, triggered_indices, triggered_time_factors);
-
-    if (triggered_indices.size() == 0) {
-      /* Finalize all particles. */
-      for (uint i = 0; i < indices_mask.size(); i++) {
-        uint pindex = indices_mask[i];
-        positions[pindex] += position_offsets[pindex];
-        velocities[pindex] += velocity_offsets[pindex];
+  BLI_NOINLINE void find_next_events(AttributeArrays attributes,
+                                     ArrayRef<uint> indices_mask,
+                                     ArrayRef<float3> position_offsets,
+                                     ArrayRef<EventIndexAtTime> r_first_event_per_particle)
+  {
+    for (uint event_index = 0; event_index < m_events.size(); event_index++) {
+      SmallVector<uint> triggered_indices;
+      SmallVector<float> triggered_time_factors;
+      m_events[event_index].event->filter(
+          attributes, indices_mask, position_offsets, triggered_indices, triggered_time_factors);
+
+      for (uint i = 0; i < triggered_indices.size(); i++) {
+        uint index = triggered_indices[i];
+        if (triggered_time_factors[i] < r_first_event_per_particle[index].time_factor) {
+          r_first_event_per_particle[index].index = event_index;
+          r_first_event_per_particle[index].time_factor = triggered_time_factors[i];
+        }
       }
     }
-    else {
-      uint used_triggered_count = 0;
-      for (uint i = 0; i < indices_mask.size(); i++) {
-        uint pindex = indices_mask[i];
-
-        if (used_triggered_count < triggered_indices.size()) {
-          uint next_triggered_affected_index = triggered_indices[used_triggered_count];
-          if (pindex == next_triggered_affected_index) {
-            float partial_time_factor = triggered_time_factors[used_triggered_count];
-            positions[pindex] += position_offsets[i] * partial_time_factor;
-            velocities[pindex] += velocity_offsets[i] * partial_time_factor;
-            r_unfinished_time_diffs.append(time_diffs[i] * (1.0f - partial_time_factor));
-            used_triggered_count++;
-            continue;
-          }
-        }
+  }
 
+  BLI_NOINLINE void forward_particles_to_next_event(
+      AttributeArrays attributes,
+      ArrayRef<uint> indices_mask,
+      ArrayRef<EventIndexAtTime> first_event_per_particle,
+      ArrayRef<float3> position_offsets,
+      ArrayRef<float3> velocity_offsets)
+  {
+    auto positions = attributes.get_float3("Position");
+    auto velocities = attributes.get_float3("Velocity");
+
+    for (uint i = 0; i < indices_mask.size(); i++) {
+      uint pindex = indices_mask[i];
+      int event_index = first_event_per_particle[i].index;
+      if (event_index == -1) {
+        /* Particle has no event. */
         positions[pindex] += position_offsets[i];
         velocities[pindex] += velocity_offsets[i];
       }
+      else {
+        /* Particle has an event. */
+        float time_factor = first_event_per_particle[i].time_factor;
+        BLI_assert(time_factor >= 0.0f && time_factor <= 1.0f);
+
+        positions[pindex] += time_factor * position_offsets[i];
+        velocities[pindex] += time_factor * velocity_offsets[i];
+      }
+    }
+  }
+
+  BLI_NOINLINE void find_particles_per_event(ArrayRef<uint> indices_mask,
+                                             ArrayRef<EventIndexAtTime> first_event_per_particle,
+                                             ArrayRef<SmallVector<uint>> r_particles_per_event)
+  {
+    for (uint i = 0; i < indices_mask.size(); i++) {
+      uint pindex = indices_mask[i];
+      int event_index = first_event_per_particle[i].index;
+      if (event_index != -1) {
+        r_particles_per_event[event_index].append(pindex);
+      }
     }
+  }
+
+  BLI_NOINLINE void find_unfinished_particles(ArrayRef<uint> indices_mask,
+                                              ArrayRef<EventIndexAtTime> first_event_per_particle,
+                                              ArrayRef<float> time_diffs,
+                                              SmallVector<uint> &r_unfinished_mask,
+                                              SmallVector<float> &r_unfinished_time_diffs)
+  {
+    for (uint i = 0; i < indices_mask.size(); i++) {
+      uint pindex = indices_mask[i];
+      int event_index = first_event_per_particle[i].index;
+      if (event_index != -1) {
+        float time_factor = first_event_per_particle[i].time_factor;
+        float remaining_time = time_diffs[i] * (1.0f - time_factor);
 
-    MoveUpAction action;
-    action.execute(attributes, triggered_indices);
+        r_unfinished_mask.append(pindex);
+        r_unfinished_time_diffs.append(remaining_time);
+      }
+    }
+  }
 
-    for (uint pindex : triggered_indices) {
-      r_unfinished_mask.append(pindex);
+  BLI_NOINLINE void run_actions(AttributeArrays attributes,
+                                ArrayRef<SmallVector<uint>> particles_per_event)
+  {
+    for (uint event_index = 0; event_index < m_events.size(); event_index++) {
+      Action *action = m_events[event_index].action;
+      action->execute(attributes, particles_per_event[event_index]);
     }
   }
 
@@ -405,7 +494,7 @@ class SimpleSolver : public Solver {
       index += positions.size();
     }
   }
-};
+};  // namespace BParticles
 
 Solver *new_playground_solver(Description &description)
 {



More information about the Bf-blender-cvs mailing list