[Bf-blender-cvs] [cfb50f6581e] functions: implement multiple density modes in Mesh Emitter node

Jacques Lucke noreply at git.blender.org
Mon Sep 9 17:23:06 CEST 2019


Commit: cfb50f6581eb13b19525e6fadcfa78b101cc2cb5
Author: Jacques Lucke
Date:   Mon Sep 9 17:22:54 2019 +0200
Branches: functions
https://developer.blender.org/rBcfb50f6581eb13b19525e6fadcfa78b101cc2cb5

implement multiple density modes in Mesh Emitter node

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

M	release/scripts/startup/nodes/bparticle_nodes/mesh_emitter.py
M	source/blender/simulations/bparticles/emitters.cpp
M	source/blender/simulations/bparticles/emitters.hpp
M	source/blender/simulations/bparticles/node_frontend.cpp

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

diff --git a/release/scripts/startup/nodes/bparticle_nodes/mesh_emitter.py b/release/scripts/startup/nodes/bparticle_nodes/mesh_emitter.py
index c4301204eb5..52a9e01cfa3 100644
--- a/release/scripts/startup/nodes/bparticle_nodes/mesh_emitter.py
+++ b/release/scripts/startup/nodes/bparticle_nodes/mesh_emitter.py
@@ -9,9 +9,27 @@ class MeshEmitterNode(bpy.types.Node, BParticlesNode):
 
     execute_on_birth__prop: NodeBuilder.ExecuteInputProperty()
 
+    density_mode: EnumProperty(
+        name="Density Mode",
+        items=[
+            ('UNIFORM', "Uniform", "", 'NONE', 0),
+            ('VERTEX_WEIGHTS', "Vertex Weights", "", 'NONE', 1),
+            ('FALLOFF', "Falloff", "", 'NONE', 2),
+        ],
+        update=BParticlesNode.sync_tree,
+    )
+
     def declaration(self, builder: NodeBuilder):
         builder.fixed_input("object", "Object", "Object")
         builder.fixed_input("rate", "Rate", "Float", default=10)
-        builder.fixed_input("density_vertex_group", "Density Group", "Text")
+
+        if self.density_mode == 'VERTEX_WEIGHTS':
+            builder.fixed_input("density_vertex_group", "Density Group", "Text")
+        elif self.density_mode == 'FALLOFF':
+            builder.fixed_input("density_falloff", "Density Falloff", "Falloff")
+
         builder.execute_input("execute_on_birth", "Execute on Birth", "execute_on_birth__prop")
         builder.particle_effector_output("emitter", "Emitter")
+
+    def draw(self, layout):
+        layout.prop(self, "density_mode")
diff --git a/source/blender/simulations/bparticles/emitters.cpp b/source/blender/simulations/bparticles/emitters.cpp
index cff72746fa8..ab9c221506f 100644
--- a/source/blender/simulations/bparticles/emitters.cpp
+++ b/source/blender/simulations/bparticles/emitters.cpp
@@ -65,23 +65,6 @@ static float3 random_point_in_triangle(float3 a, float3 b, float3 c)
   return a + dir1 * rand1 + dir2 * rand2;
 }
 
-static BLI_NOINLINE void get_all_vertex_weights(Object *ob,
-                                                Mesh *mesh,
-                                                StringRefNull group_name,
-                                                MutableArrayRef<float> r_vertex_weights)
-{
-  MDeformVert *vertices = mesh->dvert;
-  int group_index = defgroup_name_index(ob, group_name.data());
-  if (group_index == -1 || vertices == nullptr) {
-    r_vertex_weights.fill(0);
-    return;
-  }
-
-  for (uint i = 0; i < mesh->totvert; i++) {
-    r_vertex_weights[i] = defvert_find_weight(vertices + i, group_index);
-  }
-}
-
 static BLI_NOINLINE void get_average_triangle_weights(const Mesh *mesh,
                                                       ArrayRef<MLoopTri> looptris,
                                                       ArrayRef<float> vertex_weights,
@@ -196,23 +179,6 @@ static BLI_NOINLINE void compute_triangle_areas(Mesh *mesh,
   }
 }
 
-static BLI_NOINLINE void triangle_weights_from_vertex_weights(
-    Object *object,
-    StringRefNull group_name,
-    ArrayRef<MLoopTri> triangles,
-    MutableArrayRef<float> r_triangle_weights)
-{
-  BLI_assert(triangles.size() == r_triangle_weights.size());
-  BLI_assert(object->type == OB_MESH);
-
-  Mesh *mesh = (Mesh *)object->data;
-
-  TemporaryArray<float> vertex_weights(mesh->totvert);
-  get_all_vertex_weights(object, mesh, group_name, vertex_weights);
-
-  get_average_triangle_weights(mesh, triangles, vertex_weights, r_triangle_weights);
-}
-
 static BLI_NOINLINE bool sample_weighted_buckets(uint sample_amount,
                                                  ArrayRef<float> weights,
                                                  MutableArrayRef<uint> r_samples)
@@ -286,11 +252,13 @@ void SurfaceEmitter::emit(EmitterInterface &interface)
   }
 
   TemporaryArray<float> triangle_weights(triangles.size());
-  if (m_density_group.size() > 0) {
-    triangle_weights_from_vertex_weights(m_object, m_density_group, triangles, triangle_weights);
-  }
-  else {
-    compute_triangle_areas(mesh, triangles, triangle_weights);
+  get_average_triangle_weights(mesh, triangles, m_vertex_weights, triangle_weights);
+
+  TemporaryArray<float> triangle_areas(triangles.size());
+  compute_triangle_areas(mesh, triangles, triangle_areas);
+
+  for (uint i = 0; i < triangles.size(); i++) {
+    triangle_weights[i] *= triangle_areas[i];
   }
 
   TemporaryArray<uint> triangles_to_sample(particles_to_emit);
diff --git a/source/blender/simulations/bparticles/emitters.hpp b/source/blender/simulations/bparticles/emitters.hpp
index 4fb193fe780..a7e55fed8ab 100644
--- a/source/blender/simulations/bparticles/emitters.hpp
+++ b/source/blender/simulations/bparticles/emitters.hpp
@@ -19,7 +19,8 @@ class SurfaceEmitter : public Emitter {
   Object *m_object;
   VaryingFloat4x4 m_transform;
   float m_rate;
-  std::string m_density_group;
+
+  Vector<float> m_vertex_weights;
 
  public:
   SurfaceEmitter(Vector<std::string> types_to_emit,
@@ -27,13 +28,13 @@ class SurfaceEmitter : public Emitter {
                  Object *object,
                  VaryingFloat4x4 transform,
                  float rate,
-                 StringRef density_group)
+                 Vector<float> vertex_weights)
       : m_types_to_emit(std::move(types_to_emit)),
         m_on_birth_action(std::move(on_birth_action)),
         m_object(object),
         m_transform(transform),
         m_rate(rate),
-        m_density_group(density_group)
+        m_vertex_weights(std::move(vertex_weights))
   {
   }
 
diff --git a/source/blender/simulations/bparticles/node_frontend.cpp b/source/blender/simulations/bparticles/node_frontend.cpp
index e3b43a79836..b3dc9500055 100644
--- a/source/blender/simulations/bparticles/node_frontend.cpp
+++ b/source/blender/simulations/bparticles/node_frontend.cpp
@@ -1,4 +1,7 @@
 #include "BKE_node_tree.hpp"
+#include "BKE_deform.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
 
 #include "BLI_timeit.hpp"
 #include "BLI_multi_map.hpp"
@@ -291,6 +294,59 @@ static void PARSE_point_emitter(BehaviorCollector &collector,
   collector.m_emitters.append(emitter);
 }
 
+static Vector<float> compute_emitter_vertex_weights(VirtualNode *vnode,
+                                                    Tuple &fn_out,
+                                                    Object *object)
+{
+  PointerRNA rna = vnode->rna();
+  uint density_mode = RNA_enum_get(&rna, "density_mode");
+
+  Mesh *mesh = (Mesh *)object->data;
+  Vector<float> vertex_weights(mesh->totvert);
+
+  if (density_mode == 0) {
+    /* Mode: 'UNIFORM' */
+    vertex_weights.fill(1.0f);
+  }
+  else if (density_mode == 1) {
+    /* Mode: 'VERTEX_WEIGHTS' */
+    auto group_name = fn_out.relocate_out<FN::Types::StringW>(2);
+
+    MDeformVert *vertices = mesh->dvert;
+    int group_index = defgroup_name_index(object, group_name->data());
+    if (group_index == -1 || vertices == nullptr) {
+      vertex_weights.fill(0);
+    }
+    else {
+      for (uint i = 0; i < mesh->totvert; i++) {
+        vertex_weights[i] = defvert_find_weight(vertices + i, group_index);
+      }
+    }
+  }
+  else if (density_mode == 2) {
+    /* Mode: 'FALLOFF' */
+    auto falloff = fn_out.relocate_out<FN::Types::FalloffW>(2);
+
+    float4x4 transform = object->obmat;
+
+    TemporaryArray<float3> vertex_positions(mesh->totvert);
+    TemporaryVector<uint> indices(mesh->totvert);
+    for (uint i = 0; i < mesh->totvert; i++) {
+      vertex_positions[i] = transform.transform_position(mesh->mvert[i].co);
+      indices[i] = i;
+    }
+    AttributesDeclaration info_declaration;
+    info_declaration.add<float3>("Position", {0, 0, 0});
+    AttributesInfo info(info_declaration);
+
+    std::array<void *, 1> buffers = {(void *)vertex_positions.begin()};
+    AttributesRef attributes{info, buffers, (uint)mesh->totvert};
+    falloff->compute(attributes, indices, vertex_weights);
+  }
+
+  return vertex_weights;
+}
+
 static void PARSE_mesh_emitter(BehaviorCollector &collector,
                                VTreeDataGraph &vtree_data_graph,
                                WorldTransition &world_transition,
@@ -306,10 +362,12 @@ static void PARSE_mesh_emitter(BehaviorCollector &collector,
       vtree_data_graph, vnode, "Execute on Birth");
 
   Object *object = fn_out.relocate_out<ObjectW>(0).ptr();
-  if (object == nullptr) {
+  if (object == nullptr || object->type != OB_MESH) {
     return;
   }
 
+  auto vertex_weights = compute_emitter_vertex_weights(vnode, fn_out, object);
+
   VaryingFloat4x4 transform = world_transition.update_float4x4(
       vnode->name(), "Transform", object->obmat);
   Vector<std::string> type_names = find_connected_particle_type_names(vnode->output(0, "Emitter"));
@@ -318,7 +376,7 @@ static void PARSE_mesh_emitter(BehaviorCollector &collector,
                                         object,
                                         transform,
                                         body.get_output<float>(fn_out, 1, "Rate"),
-                                        StringRef(fn_out.relocate_out<StringW>(2).ref()));
+                                        std::move(vertex_weights));
   collector.m_emitters.append(emitter);
 }



More information about the Bf-blender-cvs mailing list