[Bf-blender-cvs] [454c1a5de4c] master: Voxel Remesh: Fix poles and preserve volume

Pablo Dobarro noreply at git.blender.org
Thu Sep 26 16:29:22 CEST 2019


Commit: 454c1a5de4cf5e8c3b867571ad2107bd6d9c75e6
Author: Pablo Dobarro
Date:   Thu Sep 26 16:28:56 2019 +0200
Branches: master
https://developer.blender.org/rB454c1a5de4cf5e8c3b867571ad2107bd6d9c75e6

Voxel Remesh: Fix poles and preserve volume

This commit fixes most of the issues we currently have in the voxel remesher. Mesh volume is preserved when doing multiple iterations, so the sculpt won't shrink and smooth each time you run the remesher. Mesh topology is much better, fixing most issues related to mask extraction and other topology based operations.

Reviewed By: jbakker

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

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

M	release/scripts/startup/bl_ui/properties_data_mesh.py
M	release/scripts/startup/bl_ui/space_view3d_toolbar.py
M	source/blender/blenkernel/BKE_mesh_remesh_voxel.h
M	source/blender/blenkernel/BKE_shrinkwrap.h
M	source/blender/blenkernel/intern/mesh_remesh_voxel.c
M	source/blender/blenkernel/intern/shrinkwrap.c
M	source/blender/editors/object/object_remesh.c
M	source/blender/makesdna/DNA_mesh_defaults.h
M	source/blender/makesdna/DNA_mesh_types.h
M	source/blender/makesrna/intern/rna_mesh.c

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

diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index 0794c3a1039..906969e9af4 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -476,7 +476,9 @@ class DATA_PT_remesh(MeshButtonsPanel, Panel):
         col = layout.column()
         if (mesh.remesh_mode == 'VOXEL'):
             col.prop(mesh, "remesh_voxel_size")
+            col.prop(mesh, "remesh_fix_poles")
             col.prop(mesh, "remesh_smooth_normals")
+            col.prop(mesh, "remesh_preserve_volume")
             col.prop(mesh, "remesh_preserve_paint_mask")
             col.operator("object.voxel_remesh", text="Voxel Remesh")
         else:
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 761b813d576..96a27ae796c 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -1234,7 +1234,9 @@ class VIEW3D_PT_sculpt_voxel_remesh(Panel, View3DPaintPanel):
         col = layout.column()
         mesh = context.active_object.data
         col.prop(mesh, "remesh_voxel_size")
+        col.prop(mesh, "remesh_fix_poles")
         col.prop(mesh, "remesh_smooth_normals")
+        col.prop(mesh, "remesh_preserve_volume")
         col.prop(mesh, "remesh_preserve_paint_mask")
         col.operator("object.voxel_remesh", text="Remesh")
 
diff --git a/source/blender/blenkernel/BKE_mesh_remesh_voxel.h b/source/blender/blenkernel/BKE_mesh_remesh_voxel.h
index a1bcd515c17..16c22baf9b0 100644
--- a/source/blender/blenkernel/BKE_mesh_remesh_voxel.h
+++ b/source/blender/blenkernel/BKE_mesh_remesh_voxel.h
@@ -39,6 +39,8 @@ struct Mesh *BKE_mesh_remesh_voxel_ovdb_volume_to_mesh_nomain(struct OpenVDBLeve
                                                               double adaptivity,
                                                               bool relax_disoriented_triangles);
 #endif
+
+struct Mesh *BKE_mesh_remesh_voxel_fix_poles(struct Mesh *mesh);
 struct Mesh *BKE_mesh_remesh_voxel_to_mesh_nomain(struct Mesh *mesh, float voxel_size);
 struct Mesh *BKE_mesh_remesh_quadriflow_to_mesh_nomain(struct Mesh *mesh,
                                                        int target_faces,
diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h
index e3d19a3d807..e90b1429c9d 100644
--- a/source/blender/blenkernel/BKE_shrinkwrap.h
+++ b/source/blender/blenkernel/BKE_shrinkwrap.h
@@ -115,6 +115,11 @@ void BKE_shrinkwrap_mesh_nearest_surface_deform(struct bContext *C,
                                                 struct Object *ob_source,
                                                 struct Object *ob_target);
 
+/* Used in object_remesh.c to preserve the details and volume in the voxel remesher */
+void BKE_shrinkwrap_remesh_target_project(struct Mesh *src_me,
+                                          struct Mesh *target_me,
+                                          struct Object *ob_target);
+
 /*
  * This function casts a ray in the given BVHTree.
  * but it takes into consideration the space_transform, that is:
diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.c b/source/blender/blenkernel/intern/mesh_remesh_voxel.c
index ff7ff947e1d..92e180601d7 100644
--- a/source/blender/blenkernel/intern/mesh_remesh_voxel.c
+++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.c
@@ -38,6 +38,7 @@
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
 
+#include "BKE_editmesh.h"
 #include "BKE_mesh.h"
 #include "BKE_mesh_runtime.h"
 #include "BKE_library.h"
@@ -45,6 +46,8 @@
 #include "BKE_bvhutils.h"
 #include "BKE_mesh_remesh_voxel.h" /* own include */
 
+#include "bmesh_tools.h"
+
 #ifdef WITH_OPENVDB
 #  include "openvdb_capi.h"
 #endif
@@ -348,3 +351,106 @@ void BKE_remesh_reproject_paint_mask(Mesh *target, Mesh *source)
   }
   free_bvhtree_from_mesh(&bvhtree);
 }
+
+struct Mesh *BKE_mesh_remesh_voxel_fix_poles(struct Mesh *mesh)
+{
+  const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
+  BMesh *bm;
+  bm = BM_mesh_create(&allocsize,
+                      &((struct BMeshCreateParams){
+                          .use_toolflags = true,
+                      }));
+
+  BM_mesh_bm_from_me(bm,
+                     mesh,
+                     (&(struct BMeshFromMeshParams){
+                         .calc_face_normal = true,
+                     }));
+
+  BMVert *v;
+  BMEdge *ed, *ed_next;
+  BMFace *f, *f_next;
+  BMIter iter_a, iter_b;
+
+  /* Merge 3 edge poles vertices that exist in the same face */
+  BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+  BM_ITER_MESH_MUTABLE (f, f_next, &iter_a, bm, BM_FACES_OF_MESH) {
+    BMVert *v1, *v2;
+    v1 = NULL;
+    v2 = NULL;
+    BM_ITER_ELEM (v, &iter_b, f, BM_VERTS_OF_FACE) {
+      if (BM_vert_edge_count(v) == 3) {
+        if (v1) {
+          v2 = v;
+        }
+        else {
+          v1 = v;
+        }
+      }
+    }
+    if (v1 && v2 && (v1 != v2) && !BM_edge_exists(v1, v2)) {
+      BM_face_kill(bm, f);
+      BMEdge *e = BM_edge_create(bm, v1, v2, NULL, BM_CREATE_NOP);
+      BM_elem_flag_set(e, BM_ELEM_TAG, true);
+    }
+  }
+
+  BM_ITER_MESH_MUTABLE (ed, ed_next, &iter_a, bm, BM_EDGES_OF_MESH) {
+    if (BM_elem_flag_test(ed, BM_ELEM_TAG)) {
+      float co[3];
+      mid_v3_v3v3(co, ed->v1->co, ed->v2->co);
+      BMVert *vc = BM_edge_collapse(bm, ed, ed->v1, true, true);
+      copy_v3_v3(vc->co, co);
+    }
+  }
+
+  /* Delete faces with a 3 edge pole in all their vertices */
+  BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+  BM_ITER_MESH (f, &iter_a, bm, BM_FACES_OF_MESH) {
+    bool dissolve = true;
+    BM_ITER_ELEM (v, &iter_b, f, BM_VERTS_OF_FACE) {
+      if (BM_vert_edge_count(v) != 3) {
+        dissolve = false;
+      }
+    }
+    if (dissolve) {
+      BM_ITER_ELEM (v, &iter_b, f, BM_VERTS_OF_FACE) {
+        BM_elem_flag_set(v, BM_ELEM_TAG, true);
+      }
+    }
+  }
+  BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_VERTS);
+
+  BM_ITER_MESH (ed, &iter_a, bm, BM_EDGES_OF_MESH) {
+    if (BM_edge_face_count(ed) != 2) {
+      BM_elem_flag_set(ed, BM_ELEM_TAG, true);
+    }
+  }
+  BM_mesh_edgenet(bm, false, true);
+
+  /* Smooth the result */
+  for (int i = 0; i < 4; i++) {
+    BM_ITER_MESH (v, &iter_a, bm, BM_VERTS_OF_MESH) {
+      float co[3];
+      zero_v3(co);
+      BM_ITER_ELEM (ed, &iter_b, v, BM_EDGES_OF_VERT) {
+        BMVert *vert = BM_edge_other_vert(ed, v);
+        add_v3_v3(co, vert->co);
+      }
+      mul_v3_fl(co, 1.0f / (float)BM_vert_edge_count(v));
+      mid_v3_v3v3(v->co, v->co, co);
+    }
+  }
+
+  BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
+
+  Mesh *result = BKE_mesh_from_bmesh_nomain(bm,
+                                            (&(struct BMeshToMeshParams){
+                                                .calc_object_remap = false,
+                                            }),
+                                            mesh);
+
+  BKE_id_free(NULL, mesh);
+  BM_mesh_free(bm);
+  return result;
+}
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index 992ceda7b74..797ae0f0a8a 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -1506,3 +1506,37 @@ void BKE_shrinkwrap_mesh_nearest_surface_deform(struct bContext *C,
 
   MEM_freeN(vertexCos);
 }
+
+void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object *ob_target)
+{
+  ShrinkwrapModifierData ssmd = {0};
+  int totvert;
+
+  ssmd.target = ob_target;
+  ssmd.shrinkType = MOD_SHRINKWRAP_TARGET_PROJECT;
+  ssmd.shrinkMode = MOD_SHRINKWRAP_ON_SURFACE;
+  ssmd.keepDist = 0.0f;
+
+  float(*vertexCos)[3] = BKE_mesh_vert_coords_alloc(src_me, &totvert);
+
+  ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData;
+
+  calc.smd = &ssmd;
+  calc.numVerts = src_me->totvert;
+  calc.vertexCos = vertexCos;
+  calc.vgroup = -1;
+  calc.target = target_me;
+  calc.keepDist = ssmd.keepDist;
+  BLI_SPACE_TRANSFORM_SETUP(&calc.local2target, ob_target, ob_target);
+
+  ShrinkwrapTreeData tree;
+  if (BKE_shrinkwrap_init_tree(&tree, calc.target, ssmd.shrinkType, ssmd.shrinkMode, false)) {
+    calc.tree = &tree;
+    TIMEIT_BENCH(shrinkwrap_calc_nearest_surface_point(&calc), deform_surface);
+    BKE_shrinkwrap_free_tree(&tree);
+  }
+
+  BKE_mesh_vert_coords_apply(src_me, vertexCos);
+
+  MEM_freeN(vertexCos);
+}
diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c
index d4e7ee04da8..6075867b552 100644
--- a/source/blender/editors/object/object_remesh.c
+++ b/source/blender/editors/object/object_remesh.c
@@ -42,10 +42,13 @@
 #include "BKE_global.h"
 #include "BKE_main.h"
 #include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
+#include "BKE_library.h"
 #include "BKE_object.h"
 #include "BKE_paint.h"
 #include "BKE_report.h"
 #include "BKE_scene.h"
+#include "BKE_shrinkwrap.h"
 #include "BKE_customdata.h"
 #include "BKE_mesh_remesh_voxel.h"
 
@@ -112,23 +115,22 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op)
     return OPERATOR_CANCELLED;
   }
 
-  Mesh *obj_mesh_copy = NULL;
-  if (mesh->flag & ME_REMESH_REPROJECT_PAINT_MASK) {
-    obj_mesh_copy = BKE_mesh_new_nomain_from_template(mesh, mesh->totvert, 0, 0, 0, 0);
-    CustomData_copy(
-        &mesh->vdata, &obj_mesh_copy->vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, mesh->totvert);
-    for (int i = 0; i < mesh->totvert; i++) {
-      copy_v3_v3(obj_mesh_copy->mvert[i].co, mesh->mvert[i].co);
-    }
+  if (mesh->flag & ME_REMESH_FIX_POLES) {
+    new_mesh = BKE_mesh_remesh_voxel_fix_poles(new_mesh);
   }
 
-  BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob, &CD_MASK_MESH, true);
+  if (mesh->flag & ME_REMESH_REPROJECT_VOLUME) {
+    BKE_mesh_runtime_clear_geometry(mesh);
+    BKE_shrinkwrap_remesh_target_project(new_mesh, mesh, ob);
+  }
 
   if (mesh->flag & ME_REMESH_REPROJECT_PAINT_MASK) {
-    BKE_reme

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list