[Bf-blender-cvs] [01e97d117f3] functions: initial experimental Mesh Force node

Jacques Lucke noreply at git.blender.org
Tue Sep 10 14:24:16 CEST 2019


Commit: 01e97d117f3f528ff1bd948fccab861e1a9c2485
Author: Jacques Lucke
Date:   Tue Sep 10 14:23:52 2019 +0200
Branches: functions
https://developer.blender.org/rB01e97d117f3f528ff1bd948fccab861e1a9c2485

initial experimental Mesh Force node

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

M	release/scripts/startup/nodes/bparticle_nodes/forces.py
M	source/blender/blenlib/BLI_math.hpp
M	source/blender/simulations/bparticles/forces.cpp
M	source/blender/simulations/bparticles/forces.hpp
M	source/blender/simulations/bparticles/node_frontend.cpp

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

diff --git a/release/scripts/startup/nodes/bparticle_nodes/forces.py b/release/scripts/startup/nodes/bparticle_nodes/forces.py
index 54bc6e497d0..411ee283b5a 100644
--- a/release/scripts/startup/nodes/bparticle_nodes/forces.py
+++ b/release/scripts/startup/nodes/bparticle_nodes/forces.py
@@ -3,6 +3,7 @@ from bpy.props import *
 from .. base import BParticlesNode
 from .. node_builder import NodeBuilder
 
+
 class TurbulenceForceNode(bpy.types.Node, BParticlesNode):
     bl_idname = "bp_TurbulenceForceNode"
     bl_label = "Turbulence Force"
@@ -27,6 +28,16 @@ class DragForceNode(bpy.types.Node, BParticlesNode):
     bl_label = "Drag Force"
 
     def declaration(self, builder: NodeBuilder):
-        builder.fixed_input("strength", "Strength", 'Float', default=1)
+        builder.fixed_input("strength", "Strength", "Float", default=1)
         builder.fixed_input("falloff", "Falloff", "Falloff")
         builder.particle_effector_output("force", "Force")
+
+
+class MeshForceNode(bpy.types.Node, BParticlesNode):
+    bl_idname = "bp_MeshForceNode"
+    bl_label = "Mesh Force"
+
+    def declaration(self, builder: NodeBuilder):
+        builder.fixed_input("object", "Object", "Object")
+        builder.fixed_input("strength", "Strength", "Float", default=1)
+        builder.particle_effector_output("force", "Force")
diff --git a/source/blender/blenlib/BLI_math.hpp b/source/blender/blenlib/BLI_math.hpp
index 335d494c994..3f4e8e8914c 100644
--- a/source/blender/blenlib/BLI_math.hpp
+++ b/source/blender/blenlib/BLI_math.hpp
@@ -150,6 +150,11 @@ struct float3 {
     return len_v3(*this);
   }
 
+  float length_squared() const
+  {
+    return len_squared_v3(*this);
+  }
+
   void reflect(float3 normal)
   {
     *this = this->reflected(normal);
diff --git a/source/blender/simulations/bparticles/forces.cpp b/source/blender/simulations/bparticles/forces.cpp
index eb9e0fe9e00..99b9fd84041 100644
--- a/source/blender/simulations/bparticles/forces.cpp
+++ b/source/blender/simulations/bparticles/forces.cpp
@@ -59,4 +59,38 @@ void DragForce::add_force(ForceInterface &interface)
   }
 }
 
+void MeshForce::add_force(ForceInterface &interface)
+{
+  MutableArrayRef<float3> destination = interface.combined_destination();
+  auto positions = interface.attributes().get<float3>("Position");
+
+  auto inputs = m_compute_inputs->compute(interface);
+
+  for (uint pindex : interface.pindices()) {
+    float3 position = positions[pindex];
+    float3 local_position = m_world_to_local.transform_position(position);
+
+    BVHTreeNearest nearest = {0};
+    nearest.dist_sq = 10000.0f;
+    nearest.index = -1;
+    BLI_bvhtree_find_nearest(m_bvhtree_data.tree,
+                             local_position,
+                             &nearest,
+                             m_bvhtree_data.nearest_callback,
+                             (void *)&m_bvhtree_data);
+
+    if (nearest.index == -1) {
+      continue;
+    }
+
+    float3 difference_local = float3(nearest.co) - local_position;
+    float3 difference = m_local_to_world.transform_direction(difference_local);
+    float distance_squared = difference.length_squared();
+    float factor = 1 / std::max(0.1f, distance_squared);
+
+    float strength = inputs->get<float>("Strength", 1, pindex);
+    destination[pindex] += difference * strength * factor;
+  }
+}
+
 }  // namespace BParticles
diff --git a/source/blender/simulations/bparticles/forces.hpp b/source/blender/simulations/bparticles/forces.hpp
index 88a04f47470..a1581f6b9ed 100644
--- a/source/blender/simulations/bparticles/forces.hpp
+++ b/source/blender/simulations/bparticles/forces.hpp
@@ -1,6 +1,12 @@
 #pragma once
 
 #include "BKE_falloff.hpp"
+#include "BKE_bvhutils.h"
+
+#include "BLI_kdopbvh.h"
+#include "BLI_kdtree.h"
+
+#include "DNA_object_types.h"
 
 #include "actions.hpp"
 #include "force_interface.hpp"
@@ -8,6 +14,7 @@
 namespace BParticles {
 
 using BKE::Falloff;
+using BLI::float4x4;
 
 class Force {
  public:
@@ -56,4 +63,26 @@ class DragForce : public Force {
   void add_force(ForceInterface &interface) override;
 };
 
+class MeshForce : public Force {
+ private:
+  std::unique_ptr<ParticleFunction> m_compute_inputs;
+  Object *m_object;
+  BVHTreeFromMesh m_bvhtree_data;
+  float4x4 m_local_to_world;
+  float4x4 m_world_to_local;
+
+ public:
+  MeshForce(std::unique_ptr<ParticleFunction> compute_inputs, Object *object)
+      : m_compute_inputs(std::move(compute_inputs)), m_object(object)
+  {
+    BLI_assert(object->type == OB_MESH);
+    m_local_to_world = m_object->obmat;
+    m_world_to_local = m_local_to_world.inverted__LocRotScale();
+
+    BKE_bvhtree_from_mesh_get(&m_bvhtree_data, (Mesh *)object->data, BVHTREE_FROM_LOOPTRI, 2);
+  }
+
+  void add_force(ForceInterface &interface) override;
+};
+
 }  // namespace BParticles
diff --git a/source/blender/simulations/bparticles/node_frontend.cpp b/source/blender/simulations/bparticles/node_frontend.cpp
index c965cd95265..ed39912ce12 100644
--- a/source/blender/simulations/bparticles/node_frontend.cpp
+++ b/source/blender/simulations/bparticles/node_frontend.cpp
@@ -571,6 +571,39 @@ static void PARSE_size_over_time(BehaviorCollector &collector,
   }
 }
 
+static void PARSE_mesh_force(BehaviorCollector &collector,
+                             VTreeDataGraph &vtree_data_graph,
+                             WorldTransition &UNUSED(world_transition),
+                             VirtualNode *vnode)
+{
+
+  FunctionGraph fgraph(
+      vtree_data_graph.graph(), {}, {vtree_data_graph.lookup_socket(vnode->input(0, "Object"))});
+  auto fn = fgraph.new_function("Find Object");
+  FN::fgraph_add_TupleCallBody(fn, fgraph);
+  FN::TupleCallBody &body = fn->body<TupleCallBody>();
+
+  FN_TUPLE_CALL_ALLOC_TUPLES(body, fn_in, fn_out);
+  body.call__setup_execution_context(fn_in, fn_out);
+
+  Object *object = fn_out.relocate_out<ObjectW>(0).ptr();
+  if (object == nullptr || object->type != OB_MESH) {
+    return;
+  }
+
+  Vector<std::string> type_names = find_connected_particle_type_names(vnode->output(0, "Force"));
+  for (std::string &type_name : type_names) {
+    auto fn_or_error = create_particle_function(vnode, vtree_data_graph);
+    if (fn_or_error.is_error()) {
+      continue;
+    }
+    std::unique_ptr<ParticleFunction> compute_inputs = fn_or_error.extract_value();
+
+    Force *force = new MeshForce(std::move(compute_inputs), object);
+    collector.m_forces.add(type_name, force);
+  }
+}
+
 BLI_LAZY_INIT_STATIC(StringMap<ParseNodeCallback>, get_node_parsers)
 {
   StringMap<ParseNodeCallback> map;
@@ -584,6 +617,7 @@ BLI_LAZY_INIT_STATIC(StringMap<ParseNodeCallback>, get_node_parsers)
   map.add_new("bp_MeshCollisionEventNode", PARSE_mesh_collision);
   map.add_new("bp_SizeOverTimeNode", PARSE_size_over_time);
   map.add_new("bp_DragForceNode", PARSE_drag_force);
+  map.add_new("bp_MeshForceNode", PARSE_mesh_force);
   return map;
 }



More information about the Bf-blender-cvs mailing list