[Bf-blender-cvs] [f28875a998d] master: Multires: Unsubdivide and Rebuild Subdivisions

Pablo Dobarro noreply at git.blender.org
Thu Apr 30 16:53:24 CEST 2020


Commit: f28875a998d47d4ce49b852598c14f687fa63a55
Author: Pablo Dobarro
Date:   Thu Apr 30 16:47:23 2020 +0200
Branches: master
https://developer.blender.org/rBf28875a998d47d4ce49b852598c14f687fa63a55

Multires: Unsubdivide and Rebuild Subdivisions

This implements the main unsubdivide algorithm which rebuilds a base mesh and extracts the grid's data from a high resolution mesh.
It includes the Rebuild Subdivisions operator, which generates all subdivision levels down to the level 0 base mesh.

It supports:
- Rebuilding an arbitrary number of levels (Unsubdivide) or as many levels as possible down to level 0 in a single step (Rebuild Subdivisions).
- Rebuilding with already existing grids.
- Meshes with n-gons and triangles
- Meshes with more than 2 faces per edge
- Base mesh made completely out of triangles
- Meshes without poles
- Meshes with multiple disconnected elements at the same subdivision level

Reviewed By: sergey

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

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

M	release/scripts/startup/bl_ui/properties_data_modifier.py
M	source/blender/blenkernel/BKE_multires.h
M	source/blender/blenkernel/CMakeLists.txt
M	source/blender/blenkernel/intern/multires_reshape.h
M	source/blender/blenkernel/intern/multires_reshape_util.c
A	source/blender/blenkernel/intern/multires_unsubdivide.c
A	source/blender/blenkernel/intern/multires_unsubdivide.h
M	source/blender/editors/object/object_intern.h
M	source/blender/editors/object/object_modifier.c
M	source/blender/editors/object/object_ops.c

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

diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 2d2eeb65164..9a034dfe378 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -698,8 +698,10 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
         col.enabled = ob.mode != 'EDIT'
         col.operator("object.multires_subdivide", text="Subdivide")
         col.operator("object.multires_higher_levels_delete", text="Delete Higher")
+        col.operator("object.multires_unsubdivide", text="Unsubdivide")
         col.operator("object.multires_reshape", text="Reshape")
         col.operator("object.multires_base_apply", text="Apply Base")
+        col.operator("object.multires_rebuild_subdiv", text="Rebuild Subdivisions")
         col.prop(md, "uv_smooth", text="")
         col.prop(md, "show_only_control_edges")
         col.prop(md, "use_creases")
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
index e55d050a533..62366f7952b 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -110,6 +110,11 @@ void multiresModifier_del_levels(struct MultiresModifierData *mmd,
 void multiresModifier_base_apply(struct Depsgraph *depsgraph,
                                  struct Object *object,
                                  struct MultiresModifierData *mmd);
+int multiresModifier_rebuild_subdiv(struct Depsgraph *depsgraph,
+                                    struct Object *object,
+                                    struct MultiresModifierData *mmd,
+                                    int rebuild_limit,
+                                    bool switch_view_to_lower_level);
 void multiresModifier_subdivide_legacy(struct MultiresModifierData *mmd,
                                        struct Scene *scene,
                                        struct Object *ob,
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 40c8c2c9ad2..688e71da8da 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -178,6 +178,7 @@ set(SRC
   intern/multires_reshape_util.c
   intern/multires_reshape_vertcos.c
   intern/multires_subdiv.c
+  intern/multires_unsubdivide.c
   intern/nla.c
   intern/node.c
   intern/object.c
@@ -397,6 +398,7 @@ set(SRC
   intern/lib_intern.h
   intern/multires_inline.h
   intern/multires_reshape.h
+  intern/multires_unsubdivide.h
   intern/pbvh_intern.h
   intern/subdiv_converter.h
   intern/subdiv_inline.h
diff --git a/source/blender/blenkernel/intern/multires_reshape.h b/source/blender/blenkernel/intern/multires_reshape.h
index bf5b03f51d9..3b06e126f15 100644
--- a/source/blender/blenkernel/intern/multires_reshape.h
+++ b/source/blender/blenkernel/intern/multires_reshape.h
@@ -156,6 +156,11 @@ bool multires_reshape_context_create_from_object(MultiresReshapeContext *reshape
                                                  struct Object *object,
                                                  struct MultiresModifierData *mmd);
 
+bool multires_reshape_context_create_from_base_mesh(MultiresReshapeContext *reshape_context,
+                                                    struct Depsgraph *depsgraph,
+                                                    struct Object *object,
+                                                    struct MultiresModifierData *mmd);
+
 bool multires_reshape_context_create_from_ccg(MultiresReshapeContext *reshape_context,
                                               struct SubdivCCG *subdiv_ccg,
                                               struct Mesh *base_mesh,
diff --git a/source/blender/blenkernel/intern/multires_reshape_util.c b/source/blender/blenkernel/intern/multires_reshape_util.c
index 2313aafab30..4d54b7b6e87 100644
--- a/source/blender/blenkernel/intern/multires_reshape_util.c
+++ b/source/blender/blenkernel/intern/multires_reshape_util.c
@@ -152,6 +152,39 @@ static bool context_verify_or_free(MultiresReshapeContext *reshape_context)
   return is_valid;
 }
 
+bool multires_reshape_context_create_from_base_mesh(MultiresReshapeContext *reshape_context,
+                                                    Depsgraph *depsgraph,
+                                                    Object *object,
+                                                    MultiresModifierData *mmd)
+{
+  context_zero(reshape_context);
+
+  const bool use_render_params = false;
+  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+  Mesh *base_mesh = (Mesh *)object->data;
+
+  reshape_context->depsgraph = depsgraph;
+  reshape_context->object = object;
+  reshape_context->mmd = mmd;
+
+  reshape_context->base_mesh = base_mesh;
+
+  reshape_context->subdiv = multires_reshape_create_subdiv(NULL, object, mmd);
+  reshape_context->need_free_subdiv = true;
+
+  reshape_context->reshape.level = multires_get_level(
+      scene_eval, object, mmd, use_render_params, true);
+  reshape_context->reshape.grid_size = BKE_subdiv_grid_size_from_level(
+      reshape_context->reshape.level);
+
+  reshape_context->top.level = mmd->totlvl;
+  reshape_context->top.grid_size = BKE_subdiv_grid_size_from_level(reshape_context->top.level);
+
+  context_init_commoon(reshape_context);
+
+  return context_verify_or_free(reshape_context);
+}
+
 bool multires_reshape_context_create_from_object(MultiresReshapeContext *reshape_context,
                                                  Depsgraph *depsgraph,
                                                  Object *object,
@@ -272,9 +305,9 @@ void multires_reshape_context_free(MultiresReshapeContext *reshape_context)
 
   multires_reshape_free_original_grids(reshape_context);
 
-  MEM_freeN(reshape_context->face_start_grid_index);
-  MEM_freeN(reshape_context->ptex_start_grid_index);
-  MEM_freeN(reshape_context->grid_to_face_index);
+  MEM_SAFE_FREE(reshape_context->face_start_grid_index);
+  MEM_SAFE_FREE(reshape_context->ptex_start_grid_index);
+  MEM_SAFE_FREE(reshape_context->grid_to_face_index);
 }
 
 /** \} */
diff --git a/source/blender/blenkernel/intern/multires_unsubdivide.c b/source/blender/blenkernel/intern/multires_unsubdivide.c
new file mode 100644
index 00000000000..0aa75d2f5a0
--- /dev/null
+++ b/source/blender/blenkernel/intern/multires_unsubdivide.c
@@ -0,0 +1,1243 @@
+/*
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_gsqueue.h"
+#include "BLI_math_vector.h"
+
+#include "BKE_customdata.h"
+#include "BKE_lib_id.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
+#include "BKE_modifier.h"
+#include "BKE_multires.h"
+#include "BKE_subdiv.h"
+#include "BKE_subsurf.h"
+
+#include "bmesh.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "multires_reshape.h"
+#include "multires_unsubdivide.h"
+
+/* This implements the unsubdivide algorithm, which generates a lower resolution base mesh and its
+ * corresponding grids to match a given original mesh. */
+
+/* This is done in the following steps:
+ * - If there are already grids in the original mesh, convert them from tangent displacement to
+object space coordinates.
+ * - Assign datalayers to the original mesh to map vertices to a new base mesh. These datalayes
+store the indicies of the elements in the original mesh. This way the original inidices are
+preserved when doing mesh modifications (removing and disolving vertices) when building the new
+base mesh.
+ * - Try to find a lower resolution base mesh. This is done by flood fill operation that tags the
+center vertices of the lower level grid. If the algorithm can tag all vertices correctly, the lower
+level base mesh is generated by dissolving the tagged vertices.
+ * - Use the datalayers to map vertices from the base mesh to the original mesh and original to
+base mesh.
+ * - Find two adjacent vertices on the base mesh to a given vertex to map that loop from base mesh
+to original mesh
+ * - Extract the grid from the original mesh from that loop. If there are no grids in the original
+mesh, build the new grid directly from the vertex coordinates by iterating in a grid pattern over
+them. If there are grids in the original mesh, iterate in a grid pattern over the polys, reorder
+all the coordinates of the grid in that poly and copy those coordinates to the new base mesh grid.
+ * - Copy the new grid data over to a new allocated MDISP layer with the appropiate size to store
+the new levels.
+ * - Convert the grid data from object space to tangent displacement.
+ */
+
+/* Used to check if a vertex is in a disconnected element ID. */
+static bool is_vertex_in_id(BMVert *v, int *elem_id, int elem)
+{
+  const int v_index = BM_elem_index_get(v);
+  return elem_id[v_index] == elem;
+}
+
+static bool is_vertex_pole_three(BMVert *v)
+{
+  return !BM_vert_is_boundary(v) && (BM_vert_edge_count(v) == 3);
+}
+
+static bool is_vertex_pole(BMVert *v)
+{
+  return !BM_vert_is_boundary(v) && (BM_vert_edge_count(v) == 3 || BM_vert_edge_count(v) >= 5);
+}
+
+/* Returns the first pole that is found in an element ID. */
+/* Tries to give priority to 3 vert poles as they generally generate better results in

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list