Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPablo Dobarro <pablodp606@gmail.com>2020-04-30 16:15:19 +0300
committerPablo Dobarro <pablodp606@gmail.com>2020-04-30 17:57:29 +0300
commit134619fabbc550afb275260b17c9c7910e7a1c53 (patch)
treed0695c31d909d040c7a6ad4308d0ea79bf40c00c
parentf28875a998d47d4ce49b852598c14f687fa63a55 (diff)
Multires: Subdivide Simple and Subdivide Linear
This introduces two alternative subdivision modes that generates displacement on the grids that look as Simple subdivisions but while using the Catmull-Clark subdivision type in the modifier. This way, Simple and Catmull-Clark subdivision can be combined when creating new levels if needed, for example, to sculpt hard surface objects. Subdivide simple smooths the sculpted data when creating a new subdivision level. Subdivide linear also preserves the sharpness in the sculpted data. Reviewed By: sergey Differential Revision: https://developer.blender.org/D7415
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py10
-rw-r--r--source/blender/blenkernel/BKE_multires.h16
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/intern/multires.c9
-rw-r--r--source/blender/blenkernel/intern/multires_reshape.c36
-rw-r--r--source/blender/blenkernel/intern/multires_reshape.h5
-rw-r--r--source/blender/blenkernel/intern/multires_reshape_smooth.c74
-rw-r--r--source/blender/blenkernel/intern/multires_reshape_subdivide.c106
-rw-r--r--source/blender/editors/object/object_modifier.c29
9 files changed, 248 insertions, 38 deletions
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 9a034dfe378..6e6bcd81cdc 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -696,7 +696,15 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col = split.column()
col.enabled = ob.mode != 'EDIT'
- col.operator("object.multires_subdivide", text="Subdivide")
+ op = col.operator("object.multires_subdivide", text="Subdivide")
+ op.mode = 'CATMULL_CLARK'
+
+ op = col.operator("object.multires_subdivide", text="Subdivide Simple")
+ op.mode = 'SIMPLE'
+
+ op = col.operator("object.multires_subdivide", text="Subdivide Linear")
+ op.mode = 'LINEAR'
+
col.operator("object.multires_higher_levels_delete", text="Delete Higher")
col.operator("object.multires_unsubdivide", text="Unsubdivide")
col.operator("object.multires_reshape", text="Reshape")
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
index 62366f7952b..927aad287a6 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -180,13 +180,25 @@ bool multiresModifier_reshapeFromCCG(const int tot_level,
struct SubdivCCG *subdiv_ccg);
/* Subdivide multires displacement once. */
-void multiresModifier_subdivide(struct Object *object, struct MultiresModifierData *mmd);
+
+typedef enum eMultiresSubdivideModeType {
+ MULTIRES_SUBDIVIDE_CATMULL_CLARK,
+ MULTIRES_SUBDIVIDE_SIMPLE,
+ MULTIRES_SUBDIVIDE_LINEAR,
+} eMultiresSubdivideModeType;
+
+void multiresModifier_subdivide(struct Object *object,
+ struct MultiresModifierData *mmd,
+ const eMultiresSubdivideModeType mode);
+void multires_subdivide_create_tangent_displacement_linear_grids(struct Object *object,
+ struct MultiresModifierData *mmd);
/* Subdivide displacement to the given level.
* If level is lower than the current top level nothing happens. */
void multiresModifier_subdivide_to_level(struct Object *object,
struct MultiresModifierData *mmd,
- const int top_level);
+ const int top_level,
+ const eMultiresSubdivideModeType mode);
/* Subdivision integration, defined in multires_subdiv.c */
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 688e71da8da..57d173d9f56 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -175,6 +175,7 @@ set(SRC
intern/multires_reshape_apply_base.c
intern/multires_reshape_ccg.c
intern/multires_reshape_smooth.c
+ intern/multires_reshape_subdivide.c
intern/multires_reshape_util.c
intern/multires_reshape_vertcos.c
intern/multires_subdiv.c
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 317c59182ed..d79dbbb7d32 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -2234,7 +2234,14 @@ void multiresModifier_sync_levels_ex(Object *ob_dst,
}
if (mmd_src->totlvl > mmd_dst->totlvl) {
- multiresModifier_subdivide_to_level(ob_dst, mmd_dst, mmd_src->totlvl);
+ if (mmd_dst->simple) {
+ multiresModifier_subdivide_to_level(
+ ob_dst, mmd_dst, mmd_src->totlvl, MULTIRES_SUBDIVIDE_SIMPLE);
+ }
+ else {
+ multiresModifier_subdivide_to_level(
+ ob_dst, mmd_dst, mmd_src->totlvl, MULTIRES_SUBDIVIDE_CATMULL_CLARK);
+ }
}
else {
multires_del_higher(mmd_dst, ob_dst, mmd_src->totlvl);
diff --git a/source/blender/blenkernel/intern/multires_reshape.c b/source/blender/blenkernel/intern/multires_reshape.c
index 9b3242ba73a..480a1d0b2a0 100644
--- a/source/blender/blenkernel/intern/multires_reshape.c
+++ b/source/blender/blenkernel/intern/multires_reshape.c
@@ -28,8 +28,6 @@
#include "DNA_modifier_types.h"
#include "DNA_scene_types.h"
-#include "BLI_math_vector.h"
-
#include "BKE_customdata.h"
#include "BKE_lib_id.h"
#include "BKE_mesh.h"
@@ -37,6 +35,8 @@
#include "BKE_modifier.h"
#include "BKE_multires.h"
#include "BKE_subdiv.h"
+#include "BKE_subsurf.h"
+#include "BLI_math_vector.h"
#include "DEG_depsgraph_query.h"
@@ -171,15 +171,18 @@ bool multiresModifier_reshapeFromCCG(const int tot_level,
/** \name Subdivision
* \{ */
-void multiresModifier_subdivide(Object *object, MultiresModifierData *mmd)
+void multiresModifier_subdivide(Object *object,
+ MultiresModifierData *mmd,
+ const eMultiresSubdivideModeType mode)
{
const int top_level = mmd->totlvl + 1;
- multiresModifier_subdivide_to_level(object, mmd, top_level);
+ multiresModifier_subdivide_to_level(object, mmd, top_level, mode);
}
void multiresModifier_subdivide_to_level(struct Object *object,
struct MultiresModifierData *mmd,
- const int top_level)
+ const int top_level,
+ const eMultiresSubdivideModeType mode)
{
if (top_level <= mmd->totlvl) {
return;
@@ -196,7 +199,12 @@ void multiresModifier_subdivide_to_level(struct Object *object,
}
if (!has_mdisps || top_level == 1) {
multires_reshape_ensure_grids(coarse_mesh, top_level);
- multires_set_tot_level(object, mmd, top_level);
+ if (ELEM(mode, MULTIRES_SUBDIVIDE_LINEAR, MULTIRES_SUBDIVIDE_SIMPLE)) {
+ multires_subdivide_create_tangent_displacement_linear_grids(object, mmd);
+ }
+ else {
+ multires_set_tot_level(object, mmd, top_level);
+ }
return;
}
@@ -205,16 +213,22 @@ void multiresModifier_subdivide_to_level(struct Object *object,
if (!multires_reshape_context_create_from_subdivide(&reshape_context, object, mmd, top_level)) {
return;
}
+
multires_reshape_store_original_grids(&reshape_context);
multires_reshape_ensure_grids(coarse_mesh, reshape_context.top.level);
multires_reshape_assign_final_coords_from_orig_mdisps(&reshape_context);
- /* Free original grids which makes it so smoothing with details thinks all the details were
- * added against base mesh's limit surface. This is similar behavior to as if we've done all
- * displacement in sculpt mode at the old top level and then propagated to the new top level. */
- multires_reshape_free_original_grids(&reshape_context);
+ if (ELEM(mode, MULTIRES_SUBDIVIDE_LINEAR, MULTIRES_SUBDIVIDE_SIMPLE)) {
+ multires_reshape_smooth_object_grids(&reshape_context, mode);
+ }
+ else {
+ /* Free original grids which makes it so smoothing with details thinks all the details were
+ * added against base mesh's limit surface. This is similar behavior to as if we've done all
+ * displacement in sculpt mode at the old top level and then propagated to the new top level.*/
+ multires_reshape_free_original_grids(&reshape_context);
- multires_reshape_smooth_object_grids_with_details(&reshape_context);
+ multires_reshape_smooth_object_grids_with_details(&reshape_context);
+ }
multires_reshape_object_grids_to_tangent_displacement(&reshape_context);
multires_reshape_context_free(&reshape_context);
diff --git a/source/blender/blenkernel/intern/multires_reshape.h b/source/blender/blenkernel/intern/multires_reshape.h
index 3b06e126f15..e3127885aa3 100644
--- a/source/blender/blenkernel/intern/multires_reshape.h
+++ b/source/blender/blenkernel/intern/multires_reshape.h
@@ -25,6 +25,7 @@
#define __BKE_INTERN_MULTIRES_RESHAPE_H__
#include "BLI_sys_types.h"
+#include "BKE_multires.h"
struct Depsgraph;
struct GridPaintMask;
@@ -289,7 +290,8 @@ void multires_reshape_smooth_object_grids_with_details(
*
* Makes it so surface on top level looks smooth. Details are not preserved
*/
-void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_context);
+void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_context,
+ const enum eMultiresSubdivideModeType mode);
/* --------------------------------------------------------------------
* Displacement, space conversion.
@@ -324,5 +326,4 @@ void multires_reshape_apply_base_refine_from_base(MultiresReshapeContext *reshap
*
* NOTE: Will re-evaluate all leading modifiers, so it's not cheap. */
void multires_reshape_apply_base_refine_from_deform(MultiresReshapeContext *reshape_context);
-
#endif /* __BKE_INTERN_MULTIRES_RESHAPE_H__ */
diff --git a/source/blender/blenkernel/intern/multires_reshape_smooth.c b/source/blender/blenkernel/intern/multires_reshape_smooth.c
index 22864143f80..3ddd20720d5 100644
--- a/source/blender/blenkernel/intern/multires_reshape_smooth.c
+++ b/source/blender/blenkernel/intern/multires_reshape_smooth.c
@@ -119,6 +119,14 @@ typedef struct MultiresReshapeSmoothContext {
Subdiv *reshape_subdiv;
SurfaceGrid *base_surface_grids;
+
+ /* Defines how displacement is interpolated on the higher levels (for example, whether
+ * displacement is smoothed in Catmull-Clark mode or interpolated linearly preserving sharp edges
+ * of the current sculpt level).
+ *
+ * NOTE: Uses same enumerator type as Subdivide operator, since the values are the same and
+ * decoupling type just adds extra headache to convert one enumerator to another. */
+ eMultiresSubdivideModeType smoothing_type;
} MultiresReshapeSmoothContext;
/** \} */
@@ -412,15 +420,17 @@ static int get_reshape_level_resolution(const MultiresReshapeContext *reshape_co
static char get_effective_edge_crease_char(
const MultiresReshapeSmoothContext *reshape_smooth_context, const MEdge *base_edge)
{
- const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
- if (reshape_context->subdiv->settings.is_simple) {
+ if (ELEM(reshape_smooth_context->smoothing_type,
+ MULTIRES_SUBDIVIDE_LINEAR,
+ MULTIRES_SUBDIVIDE_SIMPLE)) {
return 255;
}
return base_edge->crease;
}
static void context_init(MultiresReshapeSmoothContext *reshape_smooth_context,
- const MultiresReshapeContext *reshape_context)
+ const MultiresReshapeContext *reshape_context,
+ const eMultiresSubdivideModeType mode)
{
reshape_smooth_context->reshape_context = reshape_context;
@@ -440,6 +450,8 @@ static void context_init(MultiresReshapeSmoothContext *reshape_smooth_context,
reshape_smooth_context->non_loose_base_edge_map = NULL;
reshape_smooth_context->reshape_subdiv = NULL;
reshape_smooth_context->base_surface_grids = NULL;
+
+ reshape_smooth_context->smoothing_type = mode;
}
static void context_free_geometry(MultiresReshapeSmoothContext *reshape_smooth_context)
@@ -474,12 +486,14 @@ static void context_free(MultiresReshapeSmoothContext *reshape_smooth_context)
static bool foreach_topology_info(const SubdivForeachContext *foreach_context,
const int num_vertices,
- const int UNUSED(num_edges),
+ const int num_edges,
const int num_loops,
const int num_polygons)
{
MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data;
- const int max_edges = reshape_smooth_context->geometry.max_edges;
+ const int max_edges = reshape_smooth_context->smoothing_type == MULTIRES_SUBDIVIDE_LINEAR ?
+ num_edges :
+ reshape_smooth_context->geometry.max_edges;
/* NOTE: Calloc so the counters are re-set to 0 "for free". */
reshape_smooth_context->geometry.num_vertices = num_vertices;
@@ -672,6 +686,22 @@ static void foreach_vertex_of_loose_edge(const struct SubdivForeachContext *fore
}
}
+static void store_edge(MultiresReshapeSmoothContext *reshape_smooth_context,
+ const int subdiv_v1,
+ const int subdiv_v2,
+ const char crease)
+{
+ /* This is a bit overhead to use atomics in such a simple function called from many threads,
+ * but this allows to save quite measurable amount of memory. */
+ const int edge_index = atomic_fetch_and_add_z(&reshape_smooth_context->geometry.num_edges, 1);
+ BLI_assert(edge_index < reshape_smooth_context->geometry.max_edges);
+
+ Edge *edge = &reshape_smooth_context->geometry.edges[edge_index];
+ edge->v1 = subdiv_v1;
+ edge->v2 = subdiv_v2;
+ edge->sharpness = BKE_subdiv_edge_crease_to_sharpness_char(crease);
+}
+
static void foreach_edge(const struct SubdivForeachContext *foreach_context,
void *UNUSED(tls),
const int coarse_edge_index,
@@ -682,8 +712,15 @@ static void foreach_edge(const struct SubdivForeachContext *foreach_context,
MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data;
const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
- /* Ignore all inner face edges as they have sharpness of zero. */
- if (coarse_edge_index == ORIGINDEX_NONE) {
+ if (reshape_smooth_context->smoothing_type == MULTIRES_SUBDIVIDE_LINEAR) {
+ store_edge(reshape_smooth_context, subdiv_v1, subdiv_v2, (char)255);
+ return;
+ }
+
+ /* Ignore all inner face edges as they have sharpness of zero when using Catmull-Clark mode. In
+ * simple mode, all edges have maximum sharpness, so they can't be skipped. */
+ if (coarse_edge_index == ORIGINDEX_NONE &&
+ reshape_smooth_context->smoothing_type != MULTIRES_SUBDIVIDE_SIMPLE) {
return;
}
/* Ignore all loose edges as well, as they are not communicated to the OpenSubdiv. */
@@ -697,16 +734,7 @@ static void foreach_edge(const struct SubdivForeachContext *foreach_context,
if (crease == 0) {
return;
}
-
- /* This is a bit overhead to use atomics in such a simple function called from many threads,
- * but this allows to save quite measurable amount of memory. */
- const int edge_index = atomic_fetch_and_add_z(&reshape_smooth_context->geometry.num_edges, 1);
- BLI_assert(edge_index < reshape_smooth_context->geometry.max_edges);
-
- Edge *edge = &reshape_smooth_context->geometry.edges[edge_index];
- edge->v1 = subdiv_v1;
- edge->v2 = subdiv_v2;
- edge->sharpness = BKE_subdiv_edge_crease_to_sharpness_char(crease);
+ store_edge(reshape_smooth_context, subdiv_v1, subdiv_v2, crease);
}
static void geometry_init_loose_information(MultiresReshapeSmoothContext *reshape_smooth_context)
@@ -1212,7 +1240,12 @@ void multires_reshape_smooth_object_grids_with_details(
}
MultiresReshapeSmoothContext reshape_smooth_context;
- context_init(&reshape_smooth_context, reshape_context);
+ if (reshape_context->mmd->simple) {
+ context_init(&reshape_smooth_context, reshape_context, MULTIRES_SUBDIVIDE_SIMPLE);
+ }
+ else {
+ context_init(&reshape_smooth_context, reshape_context, MULTIRES_SUBDIVIDE_CATMULL_CLARK);
+ }
geometry_create(&reshape_smooth_context);
@@ -1228,7 +1261,8 @@ void multires_reshape_smooth_object_grids_with_details(
context_free(&reshape_smooth_context);
}
-void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_context)
+void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_context,
+ const eMultiresSubdivideModeType mode)
{
const int level_difference = (reshape_context->top.level - reshape_context->reshape.level);
if (level_difference == 0) {
@@ -1237,7 +1271,7 @@ void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_
}
MultiresReshapeSmoothContext reshape_smooth_context;
- context_init(&reshape_smooth_context, reshape_context);
+ context_init(&reshape_smooth_context, reshape_context, mode);
geometry_create(&reshape_smooth_context);
diff --git a/source/blender/blenkernel/intern/multires_reshape_subdivide.c b/source/blender/blenkernel/intern/multires_reshape_subdivide.c
new file mode 100644
index 00000000000..16c67da27fe
--- /dev/null
+++ b/source/blender/blenkernel/intern/multires_reshape_subdivide.c
@@ -0,0 +1,106 @@
+/*
+ * 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 "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 "BLI_math_vector.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "multires_reshape.h"
+
+void multires_subdivide_create_object_space_linear_grids(Mesh *mesh)
+{
+ MDisps *mdisps = CustomData_get_layer(&mesh->ldata, CD_MDISPS);
+ const int totpoly = mesh->totpoly;
+ for (int p = 0; p < totpoly; p++) {
+ MPoly *poly = &mesh->mpoly[p];
+ float poly_center[3];
+ BKE_mesh_calc_poly_center(poly, &mesh->mloop[poly->loopstart], mesh->mvert, poly_center);
+ for (int l = 0; l < poly->totloop; l++) {
+ const int loop_index = poly->loopstart + l;
+
+ float(*disps)[3] = mdisps[loop_index].disps;
+ mdisps[loop_index].totdisp = 4;
+ mdisps[loop_index].level = 1;
+
+ int prev_loop_index = l - 1 >= 0 ? loop_index - 1 : loop_index + poly->totloop - 1;
+ int next_loop_index = l + 1 < poly->totloop ? loop_index + 1 : poly->loopstart;
+
+ MLoop *loop = &mesh->mloop[loop_index];
+ MLoop *loop_next = &mesh->mloop[next_loop_index];
+ MLoop *loop_prev = &mesh->mloop[prev_loop_index];
+
+ copy_v3_v3(disps[0], poly_center);
+ mid_v3_v3v3(disps[1], mesh->mvert[loop->v].co, mesh->mvert[loop_next->v].co);
+ mid_v3_v3v3(disps[2], mesh->mvert[loop->v].co, mesh->mvert[loop_prev->v].co);
+ copy_v3_v3(disps[3], mesh->mvert[loop->v].co);
+ }
+ }
+}
+
+void multires_subdivide_create_tangent_displacement_linear_grids(Object *object,
+ MultiresModifierData *mmd)
+{
+ Mesh *coarse_mesh = object->data;
+ multires_force_sculpt_rebuild(object);
+
+ MultiresReshapeContext reshape_context;
+
+ const int new_top_level = mmd->totlvl + 1;
+
+ const bool has_mdisps = CustomData_has_layer(&coarse_mesh->ldata, CD_MDISPS);
+ if (!has_mdisps) {
+ CustomData_add_layer(&coarse_mesh->ldata, CD_MDISPS, CD_CALLOC, NULL, coarse_mesh->totloop);
+ }
+
+ if (new_top_level == 1) {
+ /* No MDISPS. Create new grids for level 1 using the edges mid point and poly centers. */
+ multires_reshape_ensure_grids(coarse_mesh, 1);
+ multires_subdivide_create_object_space_linear_grids(coarse_mesh);
+ }
+
+ /* Convert the new grids to tangent displacement. */
+ multires_set_tot_level(object, mmd, new_top_level);
+
+ if (!multires_reshape_context_create_from_subdivide(
+ &reshape_context, object, mmd, new_top_level)) {
+ return;
+ }
+
+ multires_reshape_object_grids_to_tangent_displacement(&reshape_context);
+ multires_reshape_context_free(&reshape_context);
+}
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 938ae1f52bf..bcc5bf3e1ae 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -1433,6 +1433,25 @@ void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot)
/** \name Multires Subdivide Operator
* \{ */
+static EnumPropertyItem prop_multires_subdivide_mode_type[] = {
+ {MULTIRES_SUBDIVIDE_CATMULL_CLARK,
+ "CATMULL_CLARK",
+ 0,
+ "Catmull-Clark",
+ "Create a new level using Catmull-Clark subdivisions"},
+ {MULTIRES_SUBDIVIDE_SIMPLE,
+ "SIMPLE",
+ 0,
+ "Simple",
+ "Create a new level using simple subdivisions"},
+ {MULTIRES_SUBDIVIDE_LINEAR,
+ "LINEAR",
+ 0,
+ "Linear",
+ "Create a new level using linear interpolation of the sculpted displacement"},
+ {0, NULL, 0, NULL, NULL},
+};
+
static int multires_subdivide_exec(bContext *C, wmOperator *op)
{
Object *object = ED_object_active_context(C);
@@ -1443,7 +1462,9 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- multiresModifier_subdivide(object, mmd);
+ const eMultiresSubdivideModeType subdivide_mode = (eMultiresSubdivideModeType)(
+ RNA_enum_get(op->ptr, "mode"));
+ multiresModifier_subdivide(object, mmd, subdivide_mode);
ED_object_iter_other(
CTX_data_main(C), object, true, ED_object_multires_update_totlevels_cb, &mmd->totlvl);
@@ -1482,6 +1503,12 @@ void OBJECT_OT_multires_subdivide(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
+ RNA_def_enum(ot->srna,
+ "mode",
+ prop_multires_subdivide_mode_type,
+ MULTIRES_SUBDIVIDE_CATMULL_CLARK,
+ "Subdivision Mode",
+ "How the mesh is going to be subdivided to create a new level");
}
/** \} */