[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