[Bf-blender-cvs] [277117826fc] temp-geometry-nodes-expandable-geometry-socket-prototype: properly interpolate selection between some domains

Jacques Lucke noreply at git.blender.org
Tue Aug 10 10:39:14 CEST 2021


Commit: 277117826fc1c745049463d4d6120849f9369f48
Author: Jacques Lucke
Date:   Tue Aug 10 10:39:07 2021 +0200
Branches: temp-geometry-nodes-expandable-geometry-socket-prototype
https://developer.blender.org/rB277117826fc1c745049463d4d6120849f9369f48

properly interpolate selection between some domains

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

M	source/blender/blenkernel/BKE_geometry_set.hh
M	source/blender/blenkernel/intern/attribute_access.cc
M	source/blender/blenkernel/intern/geometry_component_mesh.cc

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

diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 42e9ce82278..e046c7de994 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -345,6 +345,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/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index aa0af294bc3..221a98fdfec 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -988,9 +988,25 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_r
 
   std::unique_ptr<blender::fn::GVArray> varray = std::move(attribute.varray);
   if (domain != ATTR_DOMAIN_AUTO && attribute.domain != domain) {
-    varray = this->attribute_try_adapt_domain(std::move(varray), attribute.domain, domain);
-    if (!varray) {
-      return {};
+    if (this->type() == GEO_COMPONENT_TYPE_MESH && data_type == CD_PROP_BOOL &&
+        varray->type().is<bool>()) {
+      /* TODO: Not all boolean attributes are selections. */
+      const MeshComponent &mesh_component = static_cast<const MeshComponent &>(*this);
+      blender::VArrayPtr<bool> varray_bool =
+          std::make_unique<blender::fn::VArray_For_OwnedGVArray<bool>>(std::move(varray));
+      varray_bool = mesh_component.adapt_selection(
+          std::move(varray_bool), attribute.domain, domain);
+      if (!varray_bool) {
+        return {};
+      }
+      varray = std::make_unique<blender::fn::GVArray_For_OwnedVArray<bool>>(
+          std::move(varray_bool));
+    }
+    else {
+      varray = this->attribute_try_adapt_domain(std::move(varray), attribute.domain, domain);
+      if (!varray) {
+        return {};
+      }
     }
   }
 
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);



More information about the Bf-blender-cvs mailing list