diff options
author | Jacques Lucke <jacques@blender.org> | 2021-08-10 11:39:07 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2021-08-10 11:39:07 +0300 |
commit | 277117826fc1c745049463d4d6120849f9369f48 (patch) | |
tree | cfbfef70f2424ba87d08a3552a0ddb075bbfe5df | |
parent | 71e3f18b4ae76ee958cf20f2ac2e10172ce8aa3b (diff) |
properly interpolate selection between some domainstemp-geometry-nodes-expandable-geometry-socket-prototype
-rw-r--r-- | source/blender/blenkernel/BKE_geometry_set.hh | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/attribute_access.cc | 22 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/geometry_component_mesh.cc | 201 |
3 files changed, 224 insertions, 3 deletions
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); |