[Bf-blender-cvs] [c9b4d753362] master: Sculpt: Fair Face Sets operation for Face Set Edit

Pablo Dobarro noreply at git.blender.org
Tue Dec 15 20:34:24 CET 2020


Commit: c9b4d75336271fd0427f47a43f3bf4cb525c5252
Author: Pablo Dobarro
Date:   Mon Dec 14 17:22:20 2020 +0100
Branches: master
https://developer.blender.org/rBc9b4d75336271fd0427f47a43f3bf4cb525c5252

Sculpt: Fair Face Sets operation for Face Set Edit

This implements a mesh fairing algorithm and implements the fair
operations for Face Set edit. This edit operations create a smooth as
possible geometry patch in the area of the selected Face Set.

The mesh fairing algorithm is designed by Brett Fedack for the addon
"Mesh Fairing": https://github.com/fedackb/mesh-fairing, with some
modifications:

- The main fairing function in BKE_mesh_fair.h does not triangulate
 the mesh. For the test I did in sculpt mode results are good enough
 without triangulating the topology. Depending on the use and the
 result quality needed for a particular tool, the mesh can be
 triangulate in the affected area before starting fairing.

- Cotangents loop weights are not implemented yet. The idea is to
also expose the vertex and loop weights in a different function in
 case a tool needs to set up custom weights.

This algorithm will also be used to solve the limitations of line
project and implement the Lasso Project and Polyline Project tools.
It can also be used in tools in other areas of Blender, like Edit Mode
or future retopology tools.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D9603

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

A	source/blender/blenkernel/BKE_mesh_fair.h
M	source/blender/blenkernel/CMakeLists.txt
A	source/blender/blenkernel/intern/mesh_fair.cc
M	source/blender/editors/sculpt_paint/CMakeLists.txt
M	source/blender/editors/sculpt_paint/sculpt_face_set.c

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

diff --git a/source/blender/blenkernel/BKE_mesh_fair.h b/source/blender/blenkernel/BKE_mesh_fair.h
new file mode 100644
index 00000000000..2d5c85d4129
--- /dev/null
+++ b/source/blender/blenkernel/BKE_mesh_fair.h
@@ -0,0 +1,56 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Mesh Fairing algorithm designed by Brett Fedack, used in the addon "Mesh Fairing":
+ * https://github.com/fedackb/mesh-fairing.
+ */
+
+#pragma once
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "BLI_utildefines.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Mesh Fairing. */
+/* Creates a smooth as possible geometry patch in a defined area. Different values of depth allow
+ * to minimize changes in the vertex positions or tangency in the affected area. */
+
+typedef enum eMeshFairingDepth {
+  MESH_FAIRING_DEPTH_POSITION = 1,
+  MESH_FAIRING_DEPTH_TANGENCY = 2,
+} eMeshFairingDepth;
+
+/* affect_vertices is used to define the fairing area. Indexed by vertex index, set to true when
+ * the vertex should be modified by fairing. */
+void BKE_bmesh_prefair_and_fair_vertices(struct BMesh *bm,
+                                         bool *affect_vertices,
+                                         const eMeshFairingDepth depth);
+
+/* This function can optionally use the MVert coordinates of deform_mverts to read and write the
+ * fairing result. When NULL, the function will use mesh->mverts directly. */
+void BKE_mesh_prefair_and_fair_vertices(struct Mesh *mesh,
+                                        struct MVert *deform_mverts,
+                                        bool *affect_vertices,
+                                        const eMeshFairingDepth depth);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 0067e1c8209..ae0a180311c 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -42,6 +42,7 @@ set(INC
   ../simulation
   ../../../intern/ghost
   ../../../intern/glew-mx
+  ../../../intern/eigen
   ../../../intern/guardedalloc
   ../../../intern/iksolver/extern
   ../../../intern/atomic
@@ -170,6 +171,7 @@ set(SRC
   intern/mesh.c
   intern/mesh_convert.c
   intern/mesh_evaluate.c
+  intern/mesh_fair.cc
   intern/mesh_iterators.c
   intern/mesh_mapping.c
   intern/mesh_merge.c
@@ -353,6 +355,7 @@ set(SRC
   BKE_mball_tessellate.h
   BKE_mesh.h
   BKE_mesh_iterators.h
+  BKE_mesh_fair.h
   BKE_mesh_mapping.h
   BKE_mesh_mirror.h
   BKE_mesh_remap.h
diff --git a/source/blender/blenkernel/intern/mesh_fair.cc b/source/blender/blenkernel/intern/mesh_fair.cc
new file mode 100644
index 00000000000..527288d06cf
--- /dev/null
+++ b/source/blender/blenkernel/intern/mesh_fair.cc
@@ -0,0 +1,505 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Mesh Fairing algorithm designed by Brett Fedack, used in the addon "Mesh Fairing":
+ * https://github.com/fedackb/mesh-fairing.
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "BLI_map.hh"
+#include "BLI_math.h"
+#include "BLI_vector.hh"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_fair.h"
+#include "BKE_mesh_mapping.h"
+
+#include "bmesh.h"
+#include "bmesh_tools.h"
+
+#include "MEM_guardedalloc.h"
+#include "eigen_capi.h"
+
+using blender::Map;
+using blender::Vector;
+using std::array;
+
+class VertexWeight {
+ public:
+  virtual float weight_at_index(const int index) = 0;
+  virtual ~VertexWeight() = default;
+};
+
+class LoopWeight {
+ public:
+  virtual float weight_at_index(const int index) = 0;
+  virtual ~LoopWeight() = default;
+};
+
+class FairingContext {
+ public:
+  /* Get coordinates of vertices which are adjacent to the loop with specified index. */
+  virtual void adjacents_coords_from_loop(const int loop,
+                                          float r_adj_next[3],
+                                          float r_adj_prev[3]) = 0;
+
+  /* Get the other vertex index for a loop. */
+  virtual int other_vertex_index_from_loop(const int loop, const unsigned int v) = 0;
+
+  int vertex_count_get()
+  {
+    return totvert_;
+  }
+
+  int loop_count_get()
+  {
+    return totvert_;
+  }
+
+  MeshElemMap *vertex_loop_map_get(const int v)
+  {
+    return &vlmap_[v];
+  }
+
+  float *vertex_deformation_co_get(const int v)
+  {
+    return co_[v];
+  }
+
+  virtual ~FairingContext() = default;
+
+  void fair_vertices(bool *affected,
+                     const eMeshFairingDepth depth,
+                     VertexWeight *vertex_weight,
+                     LoopWeight *loop_weight)
+  {
+
+    fair_vertices_ex(affected, (int)depth, vertex_weight, loop_weight);
+  }
+
+ protected:
+  Vector<float *> co_;
+
+  int totvert_;
+  int totloop_;
+
+  MeshElemMap *vlmap_;
+  int *vlmap_mem_;
+
+ private:
+  void fair_setup_fairing(const int v,
+                          const int i,
+                          LinearSolver *solver,
+                          float multiplier,
+                          const int depth,
+                          Map<int, int> &vert_col_map,
+                          VertexWeight *vertex_weight,
+                          LoopWeight *loop_weight)
+  {
+    if (depth == 0) {
+      if (vert_col_map.contains(v)) {
+        const int j = vert_col_map.lookup(v);
+        EIG_linear_solver_matrix_add(solver, i, j, -multiplier);
+        return;
+      }
+      for (int j = 0; j < 3; j++) {
+        EIG_linear_solver_right_hand_side_add(solver, j, i, multiplier * co_[v][j]);
+      }
+      return;
+    }
+
+    float w_ij_sum = 0;
+    const float w_i = vertex_weight->weight_at_index(v);
+    MeshElemMap *vlmap_elem = &vlmap_[v];
+    for (int l = 0; l < vlmap_elem->count; l++) {
+      const int l_index = vlmap_elem->indices[l];
+      const int other_vert = other_vertex_index_from_loop(l_index, v);
+      const float w_ij = loop_weight->weight_at_index(l_index);
+      w_ij_sum += w_ij;
+      fair_setup_fairing(other_vert,
+                         i,
+                         solver,
+                         w_i * w_ij * multiplier,
+                         depth - 1,
+                         vert_col_map,
+                         vertex_weight,
+                         loop_weight);
+    }
+    fair_setup_fairing(v,
+                       i,
+                       solver,
+                       -1 * w_i * w_ij_sum * multiplier,
+                       depth - 1,
+                       vert_col_map,
+                       vertex_weight,
+                       loop_weight);
+  }
+
+  void fair_vertices_ex(bool *affected,
+                        const int order,
+                        VertexWeight *vertex_weight,
+                        LoopWeight *loop_weight)
+  {
+    Map<int, int> vert_col_map;
+    int num_affected_vertices = 0;
+    for (int i = 0; i < totvert_; i++) {
+      if (!affected[i]) {
+        continue;
+      }
+      vert_col_map.add(i, num_affected_vertices);
+      num_affected_vertices++;
+    }
+
+    /* Early return, nothing to do. */
+    if (num_affected_vertices == 0 || num_affected_vertices == totvert_) {
+      return;
+    }
+
+    /* Setup fairing matrices */
+    LinearSolver *solver = EIG_linear_solver_new(num_affected_vertices, num_affected_vertices, 3);
+    for (auto item : vert_col_map.items()) {
+      const int v = item.key;
+      const int col = item.value;
+      fair_setup_fairing(v, col, solver, 1.0f, order, vert_col_map, vertex_weight, loop_weight);
+    }
+
+    /* Solve linear system */
+    EIG_linear_solver_solve(solver);
+
+    /* Copy the result back to the mesh */
+    for (auto item : vert_col_map.items()) {
+      const int v = item.key;
+      const int col = item.value;
+      for (int j = 0; j < 3; j++) {
+        co_[v][j] = EIG_linear_solver_variable_get(solver, j, col);
+      }
+    }
+
+    /* Free solver data */
+    EIG_linear_solver_delete(solver);
+  }
+};
+
+class MeshFairingContext : public FairingContext {
+ public:
+  MeshFairingContext(Mesh *mesh, MVert *deform_mverts)
+  {
+    totvert_ = mesh->totvert;
+    totloop_ = mesh->totloop;
+
+    medge_ = mesh->medge;
+    mpoly_ = mesh->mpoly;
+    mloop_ = mesh->mloop;
+    BKE_mesh_vert_loop_map_create(&vlmap_,
+                                  &vlmap_mem_,
+                                  mesh->mpoly,
+                                  mesh->mloop,
+                                  mesh->totvert,
+                                  mesh->totpoly,
+                                  mesh->totloop);
+
+    /* Deformation coords. */
+    co_.reserve(mesh->totvert);
+    if (deform_mverts) {
+      for (int i = 0; i < mesh->totvert; i++) {
+        co_[i] = deform_mverts[i].co;
+      }
+    }
+    else {
+      for (i

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list