[Bf-blender-cvs] [fa9d1cb2a99] temp-geometry-nodes-fields-prototype: properly adapt selection domain

Jacques Lucke noreply at git.blender.org
Mon Aug 9 19:31:44 CEST 2021


Commit: fa9d1cb2a9977980c697c0595cd6dd87007f000d
Author: Jacques Lucke
Date:   Mon Aug 9 19:31:32 2021 +0200
Branches: temp-geometry-nodes-fields-prototype
https://developer.blender.org/rBfa9d1cb2a9977980c697c0595cd6dd87007f000d

properly adapt selection domain

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

M	source/blender/blenkernel/BKE_geometry_set.hh
M	source/blender/blenkernel/intern/geometry_component_mesh.cc
M	source/blender/functions/FN_generic_virtual_array.hh
M	source/blender/nodes/geometry/node_geometry_util.cc
M	source/blender/nodes/geometry/nodes/node_geo_extrude.cc

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

diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 4118a1013d4..55a239f6a5c 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -396,6 +396,10 @@ class MeshComponent : public GeometryComponent {
       const AttributeDomain from_domain,
       const AttributeDomain to_domain) const final;
 
+  blender::VArrayPtr<bool> adapt_selection(blender::VArrayPtr<bool> selection,
+                                           AttributeDomain from_domain,
+                                           AttributeDomain to_domain) const;
+
   bool is_empty() const final;
 
   bool owns_direct_data() const override;
diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc
index ef93a3f9b3f..d694cdc634d 100644
--- a/source/blender/blenkernel/intern/geometry_component_mesh.cc
+++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc
@@ -651,6 +651,207 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
   return {};
 }
 
+namespace blender::bke::adapt_selection_domain {
+static VArrayPtr<bool> varray_from_array(Array<bool> array)
+{
+  return std::make_unique<VArray_For_ArrayContainer<Array<bool>>>(std::move(array));
+}
+
+static VArrayPtr<bool> adapt_selection_point_to_face(const Mesh &mesh, VArrayPtr<bool> selection)
+{
+  Array<bool> new_selection(mesh.totpoly);
+  for (const int poly_index : IndexRange(mesh.totpoly)) {
+    const MPoly &poly = mesh.mpoly[poly_index];
+    bool poly_is_selected = true;
+    for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
+      const MLoop &loop = mesh.mloop[loop_index];
+      if (!selection->get(loop.v)) {
+        poly_is_selected = false;
+        break;
+      }
+    }
+    new_selection[poly_index] = poly_is_selected;
+  }
+  return varray_from_array(std::move(new_selection));
+}
+
+static VArrayPtr<bool> adapt_selection_point_to_corner(const Mesh &mesh, VArrayPtr<bool> selection)
+{
+  Array<bool> new_selection(mesh.totloop);
+  for (const int loop_index : IndexRange(mesh.totloop)) {
+    const MLoop &loop = mesh.mloop[loop_index];
+    new_selection[loop_index] = selection->get(loop.v);
+  }
+  return varray_from_array(std::move(new_selection));
+}
+
+static VArrayPtr<bool> adapt_selection_point_to_edge(const Mesh &mesh, VArrayPtr<bool> selection)
+{
+  Array<bool> new_selection(mesh.totedge);
+  for (const int edge_index : IndexRange(mesh.totedge)) {
+    const MEdge &edge = mesh.medge[edge_index];
+    const bool edge_is_selected = selection->get(edge.v1) && selection->get(edge.v2);
+    new_selection[edge_index] = edge_is_selected;
+  }
+  return varray_from_array(std::move(new_selection));
+}
+
+static VArrayPtr<bool> adapt_selection_edge_to_point(const Mesh &mesh, VArrayPtr<bool> selection)
+{
+  Array<bool> new_selection(mesh.totvert, false);
+  for (const int edge_index : IndexRange(mesh.totedge)) {
+    if (selection->get(edge_index)) {
+      const MEdge &edge = mesh.medge[edge_index];
+      new_selection[edge.v1] = true;
+      new_selection[edge.v2] = true;
+    }
+  }
+  return varray_from_array(std::move(new_selection));
+}
+
+static VArrayPtr<bool> adapt_selection_edge_to_face(const Mesh &mesh, VArrayPtr<bool> selection)
+{
+  Array<bool> new_selection(mesh.totpoly);
+  for (const int poly_index : IndexRange(mesh.totpoly)) {
+    const MPoly &poly = mesh.mpoly[poly_index];
+    bool poly_is_selected = true;
+    for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
+      const MLoop &loop = mesh.mloop[loop_index];
+      if (!selection->get(loop.e)) {
+        poly_is_selected = false;
+        break;
+      }
+    }
+    new_selection[poly_index] = poly_is_selected;
+  }
+  return varray_from_array(std::move(new_selection));
+}
+
+static VArrayPtr<bool> adapt_selection_face_to_point(const Mesh &mesh, VArrayPtr<bool> selection)
+{
+  Array<bool> new_selection(mesh.totvert, false);
+  for (const int poly_index : IndexRange(mesh.totpoly)) {
+    const MPoly &poly = mesh.mpoly[poly_index];
+    if (selection->get(poly_index)) {
+      for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
+        const MLoop &loop = mesh.mloop[loop_index];
+        BLI_assert(loop.v < mesh.totvert);
+        new_selection[loop.v] = true;
+      }
+    }
+  }
+  return varray_from_array(std::move(new_selection));
+}
+
+static VArrayPtr<bool> adapt_selection_face_to_edge(const Mesh &mesh, VArrayPtr<bool> selection)
+{
+  Array<bool> new_selection(mesh.totedge, false);
+  for (const int poly_index : IndexRange(mesh.totpoly)) {
+    const MPoly &poly = mesh.mpoly[poly_index];
+    if (selection->get(poly_index)) {
+      for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
+        const MLoop &loop = mesh.mloop[loop_index];
+        new_selection[loop.e] = true;
+      }
+    }
+  }
+  return varray_from_array(std::move(new_selection));
+}
+
+static VArrayPtr<bool> adapt_selection_face_to_corner(const Mesh &mesh, VArrayPtr<bool> selection)
+{
+  Array<bool> new_selection(mesh.totloop);
+  for (const int poly_index : IndexRange(mesh.totpoly)) {
+    const MPoly &poly = mesh.mpoly[poly_index];
+    const bool is_selected = selection->get(poly_index);
+    for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
+      new_selection[loop_index] = is_selected;
+    }
+  }
+  return varray_from_array(std::move(new_selection));
+}
+
+}  // namespace blender::bke::adapt_selection_domain
+
+blender::VArrayPtr<bool> MeshComponent::adapt_selection(blender::VArrayPtr<bool> selection,
+                                                        const AttributeDomain from_domain,
+                                                        const AttributeDomain to_domain) const
+{
+  using namespace blender::bke::adapt_selection_domain;
+
+  const int from_domain_size = this->attribute_domain_size(from_domain);
+  BLI_assert(selection->size() == from_domain_size);
+
+  if (from_domain == to_domain) {
+    return selection;
+  }
+  if (from_domain_size == 0) {
+    return selection;
+  }
+  if (selection->is_single()) {
+    return selection;
+  }
+
+  switch (from_domain) {
+    case ATTR_DOMAIN_CORNER: {
+      switch (to_domain) {
+        case ATTR_DOMAIN_POINT:
+          break;
+        case ATTR_DOMAIN_FACE:
+          break;
+        case ATTR_DOMAIN_EDGE:
+          break;
+        default:
+          break;
+      }
+      break;
+    }
+    case ATTR_DOMAIN_POINT: {
+      switch (to_domain) {
+        case ATTR_DOMAIN_CORNER:
+          return adapt_selection_point_to_corner(*mesh_, std::move(selection));
+        case ATTR_DOMAIN_FACE:
+          return adapt_selection_point_to_face(*mesh_, std::move(selection));
+        case ATTR_DOMAIN_EDGE:
+          return adapt_selection_point_to_edge(*mesh_, std::move(selection));
+        default:
+          break;
+      }
+      break;
+    }
+    case ATTR_DOMAIN_FACE: {
+      switch (to_domain) {
+        case ATTR_DOMAIN_POINT:
+          return adapt_selection_face_to_point(*mesh_, std::move(selection));
+        case ATTR_DOMAIN_CORNER:
+          return adapt_selection_face_to_corner(*mesh_, std::move(selection));
+        case ATTR_DOMAIN_EDGE:
+          return adapt_selection_face_to_edge(*mesh_, std::move(selection));
+        default:
+          break;
+      }
+      break;
+    }
+    case ATTR_DOMAIN_EDGE: {
+      switch (to_domain) {
+        case ATTR_DOMAIN_CORNER:
+          break;
+        case ATTR_DOMAIN_POINT:
+          return adapt_selection_edge_to_point(*mesh_, std::move(selection));
+        case ATTR_DOMAIN_FACE:
+          return adapt_selection_edge_to_face(*mesh_, std::move(selection));
+        default:
+          break;
+      }
+      break;
+    }
+    default:
+      break;
+  }
+
+  return {};
+}
+
 static Mesh *get_mesh_from_component_for_write(GeometryComponent &component)
 {
   BLI_assert(component.type() == GEO_COMPONENT_TYPE_MESH);
diff --git a/source/blender/functions/FN_generic_virtual_array.hh b/source/blender/functions/FN_generic_virtual_array.hh
index be810c89a16..e2ba603415b 100644
--- a/source/blender/functions/FN_generic_virtual_array.hh
+++ b/source/blender/functions/FN_generic_virtual_array.hh
@@ -365,7 +365,7 @@ template<typename T> class GVArray_For_VArray : public GVArray {
   {
   }
 
-  GVArray_For_VArray(std::unique_ptr<VArray<T>> varray)
+  GVArray_For_VArray(std::unique_ptr<const VArray<T>> varray)
       : GVArray_For_VArray(optional_ptr<const VArray<T>>(std::move(varray)))
   {
   }
@@ -437,7 +437,13 @@ template<typename T> class VArray_For_GVArray : public VArray<T> {
     BLI_assert(varray_->type().template is<T>());
   }
 
-  VArray_For_GVArray(optional_ptr<const GVArray> varray) : varray_(std::move(varray))
+  VArray_For_GVArray(optional_ptr<const GVArray> varray)
+      : VArray<T>(varray->size()), varray_(std::move(varray))
+  {
+  }
+
+  VArray_For_GVArray(GVArrayPtr varray)
+      : VArray_For_GVArray(optional_ptr<const GVArray>(std::move(varray)))
   {
   }
 
diff --git a/source/blender/nodes/geometry/node_geometry_util.cc b/source/blender/nodes/geometry/node_geometry_util.cc
index 4ea12190ae8..1fd24061300 100644
--- a/source/blender/nodes/geometry/node_geometry_util.cc
+++ b/source/blender/nodes/geometry/node_geometry_util.cc
@@ -124,13 +124,34 @@ void prepare_field_inputs(bke::FieldInputs &field_inputs,
       }
       GVArrayPtr varray = std::move(attribute.varray);
       if (attribute.domain != domain) {
-        varray = component.attribute_try_adapt_domain(std::move(varray), attribute.domain, domain);
+        /* TODO: Not all boolean attributes are selections. */
+        if (varray->type().is<bool>() && component.type() == GEO_COMPONENT_TYPE_MESH) {
+          const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
+          VArrayPtr<bool> varray_bool = std::make_unique<fn::VArray_For_GVArray<bool>>(
+              std::move(varray));
+          varray_bool = mesh_component.adapt_selection(
+              std::move(varray_bool), attribute.domain, domain);
+          if

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list