[Bf-blender-cvs] [adb4dd911b9] master: Point Cloud: Support set origin and apply scale operators

Hans Goudey noreply at git.blender.org
Mon Jan 2 17:16:53 CET 2023


Commit: adb4dd911b9183e1fb903e553f75a4a0df2d6717
Author: Hans Goudey
Date:   Mon Jan 2 10:49:57 2023 -0500
Branches: master
https://developer.blender.org/rBadb4dd911b9183e1fb903e553f75a4a0df2d6717

Point Cloud: Support set origin and apply scale operators

Move some functions for transforming a span of vectors to a header
and call them from these functions, just like was done for curves
objects recently.

Resolves T102027, T102026

Differential Revision: https://developer.blender.org/D16883

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

M	source/blender/editors/object/object_transform.cc

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

diff --git a/source/blender/editors/object/object_transform.cc b/source/blender/editors/object/object_transform.cc
index 672c04d8db6..539260cd27f 100644
--- a/source/blender/editors/object/object_transform.cc
+++ b/source/blender/editors/object/object_transform.cc
@@ -19,6 +19,7 @@
 #include "DNA_mesh_types.h"
 #include "DNA_meta_types.h"
 #include "DNA_object_types.h"
+#include "DNA_pointcloud_types.h"
 #include "DNA_scene_types.h"
 
 #include "BLI_array.hh"
@@ -44,6 +45,7 @@
 #include "BKE_mesh.h"
 #include "BKE_multires.h"
 #include "BKE_object.h"
+#include "BKE_pointcloud.h"
 #include "BKE_report.h"
 #include "BKE_scene.h"
 #include "BKE_tracking.h"
@@ -639,6 +641,17 @@ static bool apply_objects_internal_need_single_user(bContext *C)
   return (ID_REAL_USERS(ob->data) > CTX_DATA_COUNT(C, selected_editable_objects));
 }
 
+static void transform_positions(blender::MutableSpan<blender::float3> positions,
+                                const blender::float4x4 &matrix)
+{
+  using namespace blender;
+  threading::parallel_for(positions.index_range(), 1024, [&](const IndexRange range) {
+    for (float3 &position : positions.slice(range)) {
+      position = matrix * position;
+    }
+  });
+}
+
 static int apply_objects_internal(bContext *C,
                                   ReportList *reports,
                                   bool apply_loc,
@@ -647,6 +660,7 @@ static int apply_objects_internal(bContext *C,
                                   bool do_props,
                                   bool do_single_user)
 {
+  using namespace blender;
   Main *bmain = CTX_data_main(C);
   Scene *scene = CTX_data_scene(C);
   Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
@@ -696,7 +710,8 @@ static int apply_objects_internal(bContext *C,
              OB_SURF,
              OB_FONT,
              OB_GPENCIL,
-             OB_CURVES)) {
+             OB_CURVES,
+             OB_POINTCLOUD)) {
       ID *obdata = static_cast<ID *>(ob->data);
       if (!do_multi_user && ID_REAL_USERS(obdata) > 1) {
         BKE_reportf(reports,
@@ -932,6 +947,14 @@ static int apply_objects_internal(bContext *C,
       blender::bke::CurvesGeometry::wrap(curves.geometry).transform(mat);
       blender::bke::CurvesGeometry::wrap(curves.geometry).calculate_bezier_auto_handles();
     }
+    else if (ob->type == OB_POINTCLOUD) {
+      PointCloud &pointcloud = *static_cast<PointCloud *>(ob->data);
+      bke::MutableAttributeAccessor attributes = pointcloud.attributes_for_write();
+      bke::SpanAttributeWriter position = attributes.lookup_or_add_for_write_span<float3>(
+          "position", ATTR_DOMAIN_POINT);
+      transform_positions(position.span, float4x4(mat));
+      position.finish();
+    }
     else if (ob->type == OB_CAMERA) {
       MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
 
@@ -1230,8 +1253,29 @@ enum {
   ORIGIN_TO_CENTER_OF_MASS_VOLUME,
 };
 
+static float3 calculate_mean(const blender::Span<blender::float3> values)
+{
+  if (values.is_empty()) {
+    return float3(0);
+  }
+  /* TODO: Use a method that avoids overflow. */
+  return std::accumulate(values.begin(), values.end(), float3(0)) / values.size();
+}
+
+static void translate_positions(blender::MutableSpan<blender::float3> positions,
+                                const blender::float3 &translation)
+{
+  using namespace blender;
+  threading::parallel_for(positions.index_range(), 2048, [&](const IndexRange range) {
+    for (float3 &position : positions.slice(range)) {
+      position += translation;
+    }
+  });
+}
+
 static int object_origin_set_exec(bContext *C, wmOperator *op)
 {
+  using namespace blender;
   Main *bmain = CTX_data_main(C);
   Scene *scene = CTX_data_scene(C);
   Object *obact = CTX_data_active_object(C);
@@ -1653,9 +1697,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
         }
       }
       else if (around == V3D_AROUND_CENTER_MEDIAN) {
-        Span<float3> positions = curves.positions();
-        cent = std::accumulate(positions.begin(), positions.end(), float3(0)) /
-               curves.points_num();
+        cent = calculate_mean(curves.positions());
       }
 
       tot_change++;
@@ -1663,6 +1705,39 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
       curves_id.id.tag |= LIB_TAG_DOIT;
       do_inverse_offset = true;
     }
+    else if (ob->type == OB_POINTCLOUD) {
+      PointCloud &pointcloud = *static_cast<PointCloud *>(ob->data);
+      bke::MutableAttributeAccessor attributes = pointcloud.attributes_for_write();
+      bke::SpanAttributeWriter positions = attributes.lookup_or_add_for_write_span<float3>(
+          "position", ATTR_DOMAIN_POINT);
+      if (ELEM(centermode, ORIGIN_TO_CENTER_OF_MASS_SURFACE, ORIGIN_TO_CENTER_OF_MASS_VOLUME) ||
+          !ELEM(around, V3D_AROUND_CENTER_BOUNDS, V3D_AROUND_CENTER_MEDIAN)) {
+        BKE_report(op->reports,
+                   RPT_WARNING,
+                   "Point cloud object does not support this set origin operation");
+        continue;
+      }
+
+      if (centermode == ORIGIN_TO_CURSOR) {
+        /* Done. */
+      }
+      else if (around == V3D_AROUND_CENTER_BOUNDS) {
+        float3 min(std::numeric_limits<float>::max());
+        float3 max(-std::numeric_limits<float>::max());
+        if (pointcloud.bounds_min_max(min, max)) {
+          cent = math::midpoint(min, max);
+        }
+      }
+      else if (around == V3D_AROUND_CENTER_MEDIAN) {
+        cent = calculate_mean(positions.span);
+      }
+
+      tot_change++;
+      translate_positions(positions.span, -cent);
+      positions.finish();
+      pointcloud.id.tag |= LIB_TAG_DOIT;
+      do_inverse_offset = true;
+    }
 
     /* offset other selected objects */
     if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) {



More information about the Bf-blender-cvs mailing list