[Bf-blender-cvs] [2d4f8209a79] functions: optimize Get Nearest Point when the object is the same for every element

Jacques Lucke noreply at git.blender.org
Fri Nov 15 16:04:13 CET 2019


Commit: 2d4f8209a79777b77ffac4587970eeadb8e0ff00
Author: Jacques Lucke
Date:   Fri Nov 15 16:03:54 2019 +0100
Branches: functions
https://developer.blender.org/rB2d4f8209a79777b77ffac4587970eeadb8e0ff00

optimize Get Nearest Point when the object is the same for every element

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

M	source/blender/blenlib/BLI_virtual_list_ref.h
M	source/blender/functions/intern/multi_functions/mixed.cc

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

diff --git a/source/blender/blenlib/BLI_virtual_list_ref.h b/source/blender/blenlib/BLI_virtual_list_ref.h
index 582794ce8e9..0789425f612 100644
--- a/source/blender/blenlib/BLI_virtual_list_ref.h
+++ b/source/blender/blenlib/BLI_virtual_list_ref.h
@@ -102,6 +102,24 @@ template<typename T> class VirtualListRef {
     return VirtualListRef::FromRepeatedArray(array.begin(), array.size(), virtual_size);
   }
 
+  bool all_equal(ArrayRef<uint> indices) const
+  {
+    if (indices.size() == 0) {
+      return true;
+    }
+    if (m_category == Category::Single) {
+      return true;
+    }
+
+    const T &first_value = (*this)[indices.first()];
+    for (uint i : indices.drop_front(1)) {
+      if (first_value != (*this)[i]) {
+        return false;
+      }
+    }
+    return true;
+  }
+
   const T &operator[](uint index) const
   {
     BLI_assert(index < m_virtual_size);
diff --git a/source/blender/functions/intern/multi_functions/mixed.cc b/source/blender/functions/intern/multi_functions/mixed.cc
index d3568ccd536..a684d2a2d5e 100644
--- a/source/blender/functions/intern/multi_functions/mixed.cc
+++ b/source/blender/functions/intern/multi_functions/mixed.cc
@@ -607,6 +607,16 @@ MF_ClosestPointOnObject::MF_ClosestPointOnObject()
   this->set_signature(signature);
 }
 
+static BVHTreeNearest get_nearest_point(BVHTreeFromMesh *bvhtree_data, float3 point)
+{
+  BVHTreeNearest nearest = {0};
+  nearest.dist_sq = 10000000.0f;
+  nearest.index = -1;
+  BLI_bvhtree_find_nearest(
+      bvhtree_data->tree, point, &nearest, bvhtree_data->nearest_callback, (void *)bvhtree_data);
+  return nearest;
+}
+
 void MF_ClosestPointOnObject::call(MFMask mask, MFParams params, MFContext context) const
 {
   auto context_data = context.element_contexts().find_first<ExternalDataCacheContext>();
@@ -621,32 +631,53 @@ void MF_ClosestPointOnObject::call(MFMask mask, MFParams params, MFContext conte
     return;
   }
 
-  for (uint i : mask.indices()) {
-    Object *object = objects[i];
+  if (mask.indices().size() > 0 && objects.all_equal(mask.indices())) {
+    Object *object = objects[mask.indices()[0]];
     if (object == nullptr) {
-      r_points[i] = {0, 0, 0};
-      continue;
+      r_points.fill_indices(mask.indices(), {0, 0, 0});
+      return;
     }
 
     BVHTreeFromMesh *bvhtree = context_data.value().data->get_bvh_tree(object);
     if (bvhtree == nullptr) {
-      r_points[i] = {0, 0, 0};
-      continue;
+      r_points.fill_indices(mask.indices(), {0, 0, 0});
+      return;
     }
 
-    BVHTreeNearest nearest = {0};
-    nearest.dist_sq = 10000000.0f;
-    nearest.index = -1;
-    BLI_bvhtree_find_nearest(
-        bvhtree->tree, positions[i], &nearest, bvhtree->nearest_callback, (void *)bvhtree);
+    float4x4 local_to_world_matrix = object->obmat;
+    for (uint i : mask.indices()) {
+      BVHTreeNearest nearest = get_nearest_point(bvhtree, positions[i]);
+      if (nearest.index == -1) {
+        r_points[i] = {0, 0, 0};
+        continue;
+      }
 
-    if (nearest.index == -1) {
-      r_points[i] = {0, 0, 0};
-      continue;
+      r_points[i] = local_to_world_matrix.transform_position(nearest.co);
     }
+  }
+  else {
+    for (uint i : mask.indices()) {
+      Object *object = objects[i];
+      if (object == nullptr) {
+        r_points[i] = {0, 0, 0};
+        continue;
+      }
 
-    float4x4 local_to_world_matrix = object->obmat;
-    r_points[i] = local_to_world_matrix.transform_position(nearest.co);
+      BVHTreeFromMesh *bvhtree = context_data.value().data->get_bvh_tree(object);
+      if (bvhtree == nullptr) {
+        r_points[i] = {0, 0, 0};
+        continue;
+      }
+
+      BVHTreeNearest nearest = get_nearest_point(bvhtree, positions[i]);
+      if (nearest.index == -1) {
+        r_points[i] = {0, 0, 0};
+        continue;
+      }
+
+      float4x4 local_to_world_matrix = object->obmat;
+      r_points[i] = local_to_world_matrix.transform_position(nearest.co);
+    }
   }
 }



More information about the Bf-blender-cvs mailing list