Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2021-08-10 11:39:07 +0300
committerJacques Lucke <jacques@blender.org>2021-08-10 11:39:07 +0300
commit277117826fc1c745049463d4d6120849f9369f48 (patch)
treecfbfef70f2424ba87d08a3552a0ddb075bbfe5df
parent71e3f18b4ae76ee958cf20f2ac2e10172ce8aa3b (diff)
properly interpolate selection between some domainstemp-geometry-nodes-expandable-geometry-socket-prototype
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.hh4
-rw-r--r--source/blender/blenkernel/intern/attribute_access.cc22
-rw-r--r--source/blender/blenkernel/intern/geometry_component_mesh.cc201
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);