[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