[Bf-blender-cvs] [bffe7c58d9f] soc-2021-adaptive-cloth: adaptive_cloth: mesh: collapse edge rewrite to fix bugs

ishbosamiya noreply at git.blender.org
Mon Aug 9 11:13:25 CEST 2021


Commit: bffe7c58d9fa83a28bd3bbb3056a994d3a302721
Author: ishbosamiya
Date:   Tue Aug 3 22:15:59 2021 +0530
Branches: soc-2021-adaptive-cloth
https://developer.blender.org/rBbffe7c58d9fa83a28bd3bbb3056a994d3a302721

adaptive_cloth: mesh: collapse edge rewrite to fix bugs

Found a lot of bugs in collapse edge routine using the debug
tool so needed a rewrite of this function.

Need to still add across seams support.

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

M	source/blender/blenkernel/BKE_cloth_remesh.hh

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

diff --git a/source/blender/blenkernel/BKE_cloth_remesh.hh b/source/blender/blenkernel/BKE_cloth_remesh.hh
index 1e46df2c0d3..6c89a00a9f6 100644
--- a/source/blender/blenkernel/BKE_cloth_remesh.hh
+++ b/source/blender/blenkernel/BKE_cloth_remesh.hh
@@ -77,6 +77,7 @@ Mesh *BKE_cloth_remesh(struct Object *ob, struct ClothModifierData *clmd, struct
 #  include "msgpack.hpp"
 #  include "msgpack/adaptor/define_decl.hpp"
 
+#  include "BLI_array.hh"
 #  include "BLI_float2.hh"
 #  include "BLI_float2_msgpack.hh"
 #  include "BLI_float3.hh"
@@ -85,6 +86,7 @@ Mesh *BKE_cloth_remesh(struct Object *ob, struct ClothModifierData *clmd, struct
 #  include "BLI_generational_arena_msgpack.hh"
 #  include "BLI_map.hh"
 #  include "BLI_map_msgpack.hh"
+#  include "BLI_set.hh"
 #  include "BLI_vector.hh"
 #  include "BLI_vector_msgpack.hh"
 
@@ -1816,6 +1818,7 @@ template<typename END, typename EVD, typename EED, typename EFD> class Mesh {
                                                          bool verts_swapped,
                                                          bool across_seams)
   {
+    /* TODO(ish): write the below thing */
     /* Let the vert remove be `v1`, node to remove be `n1`, the other
      * vert, node be `v2`, `n2`.
      *
@@ -1846,114 +1849,108 @@ template<typename END, typename EVD, typename EED, typename EFD> class Mesh {
     blender::Vector<Edge<EED>> deleted_edges;
     blender::Vector<Face<EFD>> deleted_faces;
 
+    /* TODO(ish): add support for across seams */
+    BLI_assert(across_seams == false);
+
     auto &e = this->get_checked_edge(edge_index);
-    auto [v1_a, v2_a] = this->get_checked_verts_of_edge(e, verts_swapped);
-    auto &n1 = this->get_checked_node_of_vert(v1_a);
-    auto &n2 = this->get_checked_node_of_vert(v2_a);
+    auto [v1, v2] = this->get_checked_verts_of_edge(e, verts_swapped);
+    auto v1_index = v1.self_index;
+    auto v2_index = v2.self_index;
+    auto &n1 = this->get_checked_node_of_vert(v1);
+    auto &n2 = this->get_checked_node_of_vert(v2);
     auto n1_index = n1.self_index;
     auto n2_index = n2.self_index;
 
-    blender::Vector<EdgeIndex> edge_indices = {edge_index};
-    if (across_seams) {
-      edge_indices = this->get_connecting_edge_indices(n1, n2);
-    }
-
-    for (const auto &edge_index : edge_indices) {
-      auto &e = this->get_checked_edge(edge_index);
-      auto [v1_b, v2_b] = this->get_checked_verts_of_edge(e, verts_swapped);
-      auto v1_index = v1_b.self_index;
-      auto v2_index = v2_b.self_index;
-      /* Need to swap the verts if v1 does not point to n1 */
-      if (v1_b.node.value() != n1_index) {
-        std::swap(v1_index, v2_index);
-      }
-      BLI_assert(this->get_checked_vert(v1_index).node.value() == n1_index);
+    auto v1_face_indices = this->get_checked_face_indices_of_vert(v1);
 
-      /* delete all the faces that `e` refers to */
-      auto e_faces = e.faces;
-      for (const auto &face_index : e_faces) {
-        auto &e = this->get_checked_edge(edge_index);
-        this->delink_face_edges(face_index);
-        auto face = this->delete_face(face_index);
-
-        auto &ov = this->get_checked_other_vert(e, face);
+    /* Create the new faces by swapping v1 with v2 */
+    {
+      for (const auto &face_index : v1_face_indices) {
+        auto &f = this->get_checked_face(face_index);
 
-        auto op_v1_ov_edge_index = this->get_connecting_edge_index(v1_index, ov.self_index);
-        BLI_assert(op_v1_ov_edge_index);
-        auto v1_ov_edge = this->get_checked_edge(op_v1_ov_edge_index.value());
-        /* delete `v1_ov_edge` only if it doesn't have any faces */
-        if (v1_ov_edge.faces.is_empty()) {
-          auto v1_ov_edge = this->delete_edge(op_v1_ov_edge_index.value());
-          deleted_edges.append(std::move(v1_ov_edge));
+        /* Cannot create face between v2, v2, ov */
+        if (f.has_vert_index(v2_index)) {
+          continue;
         }
-        deleted_faces.append(std::move(face));
-      }
 
-      auto &v1_c = this->get_checked_vert(v1_index);
-      auto v1_edge_indices = v1_c.edges;
+        BLI_assert(f.get_verts().size() == 3);
 
-      /* edges should have verts (v2, vx) instead of (v1, vx) and the
-       * face should have (v2, vx, vy) instead of (v1, vx, vy) */
-      for (const auto &v1_vx_edge_index : v1_edge_indices) {
-        Edge<EED> &v1_vx_edge = this->get_checked_edge(v1_vx_edge_index);
+        blender::Array<VertIndex> vert_indices(f.get_verts().as_span());
 
-        BLI_assert(v1_vx_edge.verts);
-        auto &verts = v1_vx_edge.verts.value();
-
-        if (v1_vx_edge.has_vert(v2_index)) {
-          /* don't need to mess with (v1, v2), only (v1, vx) */
-          continue;
+        bool v2_exists = false;
+        for (auto &vert_index : vert_indices) {
+          if (vert_index == v2_index) {
+            v2_exists = true;
+            break;
+          }
+          if (vert_index == v1_index) {
+            vert_index = v2_index;
+            break;
+          }
         }
 
-        if (std::get<0>(verts) == v1_index) {
-          v1_vx_edge.verts = {std::get<1>(verts), v2_index};
-        }
-        else {
-          v1_vx_edge.verts = {std::get<0>(verts), v2_index};
+        if (v2_exists) {
+          continue;
         }
 
-        /* since the edge no longer refers to `v1`, we should remove the
-         * edge from `v1.edges` */
-        v1_c.edges.remove_first_occurrence_and_reorder(v1_vx_edge_index);
-
-        /* replace `v1` with `v2` in the face  */
-        for (const auto face_index : v1_vx_edge.faces) {
-          Face<EFD> &face = this->get_checked_face(face_index);
-          /* the face may not contain `v1` */
-          auto pos = face.verts.first_index_of_try(v1_index);
-          if (pos != -1) {
-            face.verts[pos] = v2_index;
+        // Create the edges between v2 and the other verts
+        {
+          for (const auto &vert_index : vert_indices) {
+            if (vert_index == v2_index) {
+              continue;
+            }
+            /* It is possible to have a connecting edge between
+             * vert_index and v2_index, in case of this, don't create
+             * a new edge */
+            if (this->get_connecting_edge_index(vert_index, v2_index)) {
+              continue;
+            }
+            auto &new_e = this->add_empty_edge();
+            new_e.verts = {v2_index, vert_index};
+            this->add_edge_ref_to_verts(new_e);
+
+            added_edges.append(new_e.self_index);
           }
         }
-      }
 
-      /* delete e */
-      {
-        auto e = this->delete_edge(edge_index);
-        deleted_edges.append(std::move(e));
-      }
-      /* delete v1 */
-      {
-        auto v1 = this->delete_vert(v1_index);
-        deleted_verts.append(std::move(v1));
+        auto &new_f = this->add_face_triangulated(
+            vert_indices[0], vert_indices[1], vert_indices[2], f.normal);
+
+        added_faces.append(new_f.self_index);
       }
     }
 
-    /* if `n1` has any verts, make them point to `v2` and then delete `n1` */
+    /* Delete all the faces around v1 */
+    for (const auto &face_index : v1_face_indices) {
+      this->delink_face_edges(face_index);
+      auto f = this->delete_face(face_index);
+
+      deleted_faces.append(f);
+    }
+
+    /* Delete all the edges around v1 */
+    for (const auto &e_index : v1.get_edges()) {
+      auto e = this->delete_edge(e_index);
+
+      deleted_edges.append(e);
+    }
+
+    /* delete the Vert v1 */
     {
-      auto &n1 = this->get_checked_node(n1_index);
+      auto v1 = this->delete_vert(v1_index);
 
-      auto n1_verts = n1.verts;
-      for (const auto &vert_index : n1_verts) {
-        auto &v1 = this->get_checked_vert(vert_index);
-        v1.node = n2_index;
-        n1.verts.remove_first_occurrence_and_reorder(v1.self_index);
-      }
+      deleted_verts.append(v1);
+    }
 
-      {
+    /* delete the Node n1 */
+    {
+      /* TODO(ish): ensure that nothing refers to this anymore when
+       * across_seams is true */
+      auto n1 = this->get_checked_node(n1_index);
+      if (n1.get_verts().is_empty()) {
         auto n1 = this->delete_node(n1_index);
-        BLI_assert(n1.verts.is_empty());
-        deleted_nodes.append(std::move(n1));
+
+        deleted_nodes.append(n1);
       }
     }
 
@@ -2373,6 +2370,21 @@ template<typename END, typename EVD, typename EED, typename EFD> class Mesh {
     return op_face.value().get();
   }
 
+  blender::Set<FaceIndex> get_checked_face_indices_of_vert(const Vert<EVD> &vert) const
+  {
+    blender::Set<FaceIndex> face_indices;
+
+    for (const auto &edge_index : vert.get_edges()) {
+      const auto &edge = this->get_checked_edge(edge_index);
+
+      for (const auto &face_index : edge.get_faces()) {
+        face_indices.add(face_index);
+      }
+    }
+
+    return face_indices;
+  }
+
   inline std::tuple<Vert<EVD> &, Vert<EVD> &> get_checked_verts_of_edge(const Edge<EED> &edge,
                                                                         bool verts_swapped)
   {
@@ -2530,6 +2542,22 @@ template<typename END, typename EVD, typename EED, typename EFD> class Mesh {
     return this->faces.get(face_index).value().get();
   }
 
+  Face<EFD> &add_face_triangulated(const VertIndex v1_index,
+                                   const VertIndex v2_index,
+                                   const VertIndex v3_index,
+                                   float3 normal)
+  {
+    auto &f = this->add_empty_face(normal);
+
+    f.verts.append(v1_index);
+    f.verts.append(v2_index);
+    f.verts.append(v3_index);
+
+    this->add_face_ref_to_edges(f);
+
+    return f;
+  }
+
   /**
    * Adds an empty node with interpolation of the elements of `node_1`
    * and `node_2`.



More information about the Bf-blender-cvs mailing list