[Bf-blender-cvs] [58452b095db] functions: initial test for spawning new particles in an action

Jacques Lucke noreply at git.blender.org
Fri Jun 28 12:31:11 CEST 2019


Commit: 58452b095db403f34e1d3f09794dddcff81e39dd
Author: Jacques Lucke
Date:   Fri Jun 28 11:32:08 2019 +0200
Branches: functions
https://developer.blender.org/rB58452b095db403f34e1d3f09794dddcff81e39dd

initial test for spawning new particles in an action

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

M	source/blender/simulations/bparticles/actions.cpp
M	source/blender/simulations/bparticles/actions.hpp
M	source/blender/simulations/bparticles/c_wrapper.cpp
M	source/blender/simulations/bparticles/core.cpp
M	source/blender/simulations/bparticles/core.hpp
M	source/blender/simulations/bparticles/simulate.cpp

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

diff --git a/source/blender/simulations/bparticles/actions.cpp b/source/blender/simulations/bparticles/actions.cpp
index aebfb128fc5..2c526a724d6 100644
--- a/source/blender/simulations/bparticles/actions.cpp
+++ b/source/blender/simulations/bparticles/actions.cpp
@@ -14,7 +14,7 @@ class KillAction : public Action {
   }
 };
 
-class MoveAction : public BParticles::Action {
+class MoveAction : public Action {
  private:
   float3 m_offset;
 
@@ -34,6 +34,28 @@ class MoveAction : public BParticles::Action {
   }
 };
 
+class SpawnAction : public Action {
+  void execute(ActionInterface &interface) override
+  {
+    ParticleSet &particles = interface.particles();
+
+    auto positions = particles.attributes().get_float3("Position");
+
+    SmallVector<float3> new_positions;
+    SmallVector<float3> new_velocities;
+
+    for (uint i : particles.range()) {
+      uint pindex = particles.get_particle_index(i);
+      new_positions.append(positions[pindex] + float3(20, 0, 0));
+      new_velocities.append(float3(1, 1, 10));
+    }
+
+    auto &target = interface.request_emit_target(0, particles.size());
+    target.set_float3("Position", new_positions);
+    target.set_float3("Velocity", new_velocities);
+  }
+};
+
 std::unique_ptr<Action> ACTION_kill()
 {
   Action *action = new KillAction();
@@ -46,4 +68,10 @@ std::unique_ptr<Action> ACTION_move(float3 offset)
   return std::unique_ptr<Action>(action);
 }
 
+std::unique_ptr<Action> ACTION_spawn()
+{
+  Action *action = new SpawnAction();
+  return std::unique_ptr<Action>(action);
+}
+
 }  // namespace BParticles
diff --git a/source/blender/simulations/bparticles/actions.hpp b/source/blender/simulations/bparticles/actions.hpp
index e8edc9daa64..4e31d7c192e 100644
--- a/source/blender/simulations/bparticles/actions.hpp
+++ b/source/blender/simulations/bparticles/actions.hpp
@@ -6,5 +6,6 @@ namespace BParticles {
 
 std::unique_ptr<Action> ACTION_kill();
 std::unique_ptr<Action> ACTION_move(float3 offset);
+std::unique_ptr<Action> ACTION_spawn();
 
 }  // namespace BParticles
diff --git a/source/blender/simulations/bparticles/c_wrapper.cpp b/source/blender/simulations/bparticles/c_wrapper.cpp
index 81a03613fad..4350118f99f 100644
--- a/source/blender/simulations/bparticles/c_wrapper.cpp
+++ b/source/blender/simulations/bparticles/c_wrapper.cpp
@@ -157,7 +157,7 @@ void BParticles_simulate_modifier(NodeParticlesModifierData *npmd,
   }
   type0->m_forces.append(FORCE_directional({0, 0, -2}).release());
   type0->m_events.append(EVENT_age_reached(3.0f).release());
-  type0->m_actions.append(ACTION_move({0, 1, 0}).release());
+  type0->m_actions.append(ACTION_spawn().release());
 
   auto *type1 = new ModifierParticleType();
   description.m_types.add_new(1, type1);
diff --git a/source/blender/simulations/bparticles/core.cpp b/source/blender/simulations/bparticles/core.cpp
index e92bf67834e..1cb6f8533a2 100644
--- a/source/blender/simulations/bparticles/core.cpp
+++ b/source/blender/simulations/bparticles/core.cpp
@@ -63,6 +63,36 @@ ParticlesBlock &BlockAllocator::get_non_full_block(uint particle_type_id)
   return block;
 }
 
+void BlockAllocator::allocate_block_ranges(uint particle_type_id,
+                                           uint size,
+                                           SmallVector<ParticlesBlock *> &r_blocks,
+                                           SmallVector<Range<uint>> &r_ranges)
+{
+  uint remaining_size = size;
+  while (remaining_size > 0) {
+    ParticlesBlock &block = this->get_non_full_block(particle_type_id);
+
+    uint size_to_use = std::min(block.inactive_amount(), remaining_size);
+    Range<uint> range(block.active_amount(), block.active_amount() + size_to_use);
+    block.active_amount() += size_to_use;
+
+    r_blocks.append(&block);
+    r_ranges.append(range);
+
+    AttributeArrays attributes = block.slice(range);
+    for (uint i : attributes.info().attribute_indices()) {
+      attributes.init_default(i);
+    }
+
+    remaining_size -= size_to_use;
+  }
+}
+
+AttributesInfo &BlockAllocator::attributes_info(uint particle_type_id)
+{
+  return m_state.particle_container(particle_type_id).attributes_info();
+}
+
 /* Emitter Interface
  ******************************************/
 
@@ -77,31 +107,34 @@ TimeSpanEmitTarget &EmitterInterface::request(uint particle_type_id, uint size)
 {
   SmallVector<ParticlesBlock *> blocks;
   SmallVector<Range<uint>> ranges;
+  m_block_allocator.allocate_block_ranges(particle_type_id, size, blocks, ranges);
+  AttributesInfo &attributes_info = m_block_allocator.attributes_info(particle_type_id);
 
-  uint remaining_size = size;
-  while (remaining_size > 0) {
-    ParticlesBlock &block = m_block_allocator.get_non_full_block(particle_type_id);
-
-    uint size_to_use = std::min(block.inactive_amount(), remaining_size);
-    Range<uint> range(block.active_amount(), block.active_amount() + size_to_use);
-    block.active_amount() += size_to_use;
-
-    blocks.append(&block);
-    ranges.append(range);
+  auto *target = new TimeSpanEmitTarget(particle_type_id, attributes_info, blocks, ranges);
+  m_targets.append(target);
+  return *target;
+}
 
-    AttributeArrays attributes = block.slice(range);
-    for (uint i : attributes.info().attribute_indices()) {
-      attributes.init_default(i);
-    }
+/* Action Interface
+ **************************************/
 
-    remaining_size -= size_to_use;
+ActionInterface::~ActionInterface()
+{
+  for (InstantEmitTarget *target : m_emit_targets) {
+    delete target;
   }
+}
+
+InstantEmitTarget &ActionInterface::request_emit_target(uint particle_type_id, uint size)
+{
+  SmallVector<ParticlesBlock *> blocks;
+  SmallVector<Range<uint>> ranges;
+  m_block_allocator.allocate_block_ranges(particle_type_id, size, blocks, ranges);
+  AttributesInfo &attributes_info = m_block_allocator.attributes_info(particle_type_id);
 
-  ParticlesContainer &container = m_block_allocator.particles_state().particle_container(
-      particle_type_id);
-  m_targets.append(
-      new TimeSpanEmitTarget(particle_type_id, container.attributes_info(), blocks, ranges));
-  return *m_targets.last();
+  auto *target = new InstantEmitTarget(particle_type_id, attributes_info, blocks, ranges);
+  m_emit_targets.append(target);
+  return *target;
 }
 
 /* EmitTarget
diff --git a/source/blender/simulations/bparticles/core.hpp b/source/blender/simulations/bparticles/core.hpp
index 5be647a6d3f..c419df320d3 100644
--- a/source/blender/simulations/bparticles/core.hpp
+++ b/source/blender/simulations/bparticles/core.hpp
@@ -74,6 +74,12 @@ class BlockAllocator {
   BlockAllocator(ParticlesState &state);
 
   ParticlesBlock &get_non_full_block(uint particle_type_id);
+  void allocate_block_ranges(uint particle_type_id,
+                             uint size,
+                             SmallVector<ParticlesBlock *> &r_blocks,
+                             SmallVector<Range<uint>> &r_ranges);
+
+  AttributesInfo &attributes_info(uint particle_type_id);
 
   ParticlesState &particles_state()
   {
@@ -157,6 +163,17 @@ class EmitTargetBase {
   void fill_elements(uint index, void *value);
 };
 
+class InstantEmitTarget : public EmitTargetBase {
+ public:
+  InstantEmitTarget(uint particle_type_id,
+                    AttributesInfo &attributes_info,
+                    ArrayRef<ParticlesBlock *> blocks,
+                    ArrayRef<Range<uint>> ranges)
+      : EmitTargetBase(particle_type_id, attributes_info, blocks, ranges)
+  {
+  }
+};
+
 class TimeSpanEmitTarget : public EmitTargetBase {
  private:
   SmallVector<float> m_birth_moments;
@@ -328,6 +345,7 @@ class ActionInterface {
  private:
   ParticleSet m_particles;
   BlockAllocator &m_block_allocator;
+  SmallVector<InstantEmitTarget *> m_emit_targets;
 
  public:
   ActionInterface(ParticleSet particles, BlockAllocator &block_allocator)
@@ -335,6 +353,8 @@ class ActionInterface {
   {
   }
 
+  ~ActionInterface();
+
   BlockAllocator &block_allocator()
   {
     return m_block_allocator;
@@ -344,6 +364,13 @@ class ActionInterface {
   {
     return m_particles;
   }
+
+  InstantEmitTarget &request_emit_target(uint particle_type_id, uint size);
+
+  ArrayRef<InstantEmitTarget *> emit_targets()
+  {
+    return m_emit_targets;
+  }
 };
 
 class Action {
diff --git a/source/blender/simulations/bparticles/simulate.cpp b/source/blender/simulations/bparticles/simulate.cpp
index ecb28062c6d..fd027b91b0d 100644
--- a/source/blender/simulations/bparticles/simulate.cpp
+++ b/source/blender/simulations/bparticles/simulate.cpp
@@ -130,6 +130,11 @@ BLI_NOINLINE static void run_actions(BlockAllocator &block_allocator,
 
     ActionInterface interface(particles, block_allocator);
     action->execute(interface);
+
+    for (InstantEmitTarget *target_ptr : interface.emit_targets()) {
+      InstantEmitTarget &target = *target_ptr;
+      target.fill_float("Birth Time", block_allocator.particles_state().m_current_time);
+    }
   }
 }



More information about the Bf-blender-cvs mailing list