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
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/intern/mesh_remesh_voxel.c2
-rw-r--r--source/blender/editors/mesh/editmesh_mask_extract.c179
-rw-r--r--source/blender/editors/mesh/mesh_intern.h1
-rw-r--r--source/blender/editors/mesh/mesh_ops.c1
4 files changed, 183 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.c b/source/blender/blenkernel/intern/mesh_remesh_voxel.c
index ba8ed5facad..41546498da0 100644
--- a/source/blender/blenkernel/intern/mesh_remesh_voxel.c
+++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.c
@@ -446,6 +446,8 @@ struct Mesh *BKE_mesh_remesh_voxel_fix_poles(struct Mesh *mesh)
}
}
+ BM_mesh_normals_update(bm);
+
BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
BM_mesh_elem_hflag_enable_all(bm, BM_FACE, BM_ELEM_TAG, false);
BMO_op_callf(bm,
diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c
index 25d3118b3a9..40430bccf16 100644
--- a/source/blender/editors/mesh/editmesh_mask_extract.c
+++ b/source/blender/editors/mesh/editmesh_mask_extract.c
@@ -52,6 +52,8 @@
#include "ED_sculpt.h"
#include "ED_view3d.h"
+#include "bmesh_tools.h"
+
#include "MEM_guardedalloc.h"
#include "mesh_intern.h" /* own include */
@@ -277,3 +279,180 @@ void MESH_OT_paint_mask_extract(wmOperatorType *ot)
"Extract as Solid",
"Extract the mask as a solid object with a solidify modifier");
}
+
+static void slice_paint_mask(BMesh *bm, bool invert, bool fill_holes, float mask_threshold)
+{
+ BMVert *v;
+ BMFace *f;
+ BMIter iter;
+ BMIter face_iter;
+
+ /* Delete all masked faces */
+ const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
+ BLI_assert(cd_vert_mask_offset != -1);
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ bool keep_face = true;
+ BM_ITER_ELEM (v, &face_iter, f, BM_VERTS_OF_FACE) {
+ const float mask = BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset);
+ if (mask < mask_threshold) {
+ keep_face = false;
+ break;
+ }
+ }
+ if (invert) {
+ keep_face = !keep_face;
+ }
+ BM_elem_flag_set(f, BM_ELEM_TAG, keep_face);
+ }
+
+ BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_FACES);
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+ BM_mesh_elem_hflag_enable_all(bm, BM_EDGE, BM_ELEM_TAG, false);
+
+ if (fill_holes) {
+ BM_mesh_edgenet(bm, false, true);
+ BM_mesh_normals_update(bm);
+ BMO_op_callf(bm,
+ (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE),
+ "triangulate faces=%hf quad_method=%i ngon_method=%i",
+ BM_ELEM_TAG,
+ 0,
+ 0);
+
+ BM_mesh_elem_hflag_enable_all(bm, BM_FACE, BM_ELEM_TAG, false);
+ BMO_op_callf(bm,
+ (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE),
+ "recalc_face_normals faces=%hf",
+ BM_ELEM_TAG);
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+ }
+}
+
+static int paint_mask_slice_exec(bContext *C, wmOperator *op)
+{
+ struct Main *bmain = CTX_data_main(C);
+ Object *ob = CTX_data_active_object(C);
+ View3D *v3d = CTX_wm_view3d(C);
+
+ Mesh *mesh = ob->data;
+ Mesh *new_mesh = BKE_mesh_copy(bmain, mesh);
+
+ if (ob->mode == OB_MODE_SCULPT) {
+ ED_sculpt_undo_geometry_begin(ob, "mask slice");
+ }
+
+ BMesh *bm;
+ const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(new_mesh);
+ bm = BM_mesh_create(&allocsize,
+ &((struct BMeshCreateParams){
+ .use_toolflags = true,
+ }));
+
+ BM_mesh_bm_from_me(bm,
+ new_mesh,
+ (&(struct BMeshFromMeshParams){
+ .calc_face_normal = true,
+ }));
+
+ slice_paint_mask(
+ bm, false, RNA_boolean_get(op->ptr, "fill_holes"), RNA_float_get(op->ptr, "mask_threshold"));
+ BKE_id_free(bmain, new_mesh);
+ new_mesh = BKE_mesh_from_bmesh_nomain(bm,
+ (&(struct BMeshToMeshParams){
+ .calc_object_remap = false,
+ }),
+ mesh);
+ BM_mesh_free(bm);
+
+ if (RNA_boolean_get(op->ptr, "new_object")) {
+ ushort local_view_bits = 0;
+ if (v3d && v3d->localvd) {
+ local_view_bits = v3d->local_view_uuid;
+ }
+ Object *new_ob = ED_object_add_type(
+ C, OB_MESH, NULL, ob->loc, ob->rot, false, local_view_bits);
+ Mesh *new_ob_mesh = BKE_mesh_copy(bmain, mesh);
+
+ const BMAllocTemplate allocsize_new_ob = BMALLOC_TEMPLATE_FROM_ME(new_ob_mesh);
+ bm = BM_mesh_create(&allocsize_new_ob,
+ &((struct BMeshCreateParams){
+ .use_toolflags = true,
+ }));
+
+ BM_mesh_bm_from_me(bm,
+ new_ob_mesh,
+ (&(struct BMeshFromMeshParams){
+ .calc_face_normal = true,
+ }));
+
+ slice_paint_mask(bm,
+ true,
+ RNA_boolean_get(op->ptr, "fill_holes"),
+ RNA_float_get(op->ptr, "mask_threshold"));
+ BKE_id_free(bmain, new_ob_mesh);
+ new_ob_mesh = BKE_mesh_from_bmesh_nomain(bm,
+ (&(struct BMeshToMeshParams){
+ .calc_object_remap = false,
+ }),
+ mesh);
+ BM_mesh_free(bm);
+
+ BKE_mesh_nomain_to_mesh(new_ob_mesh, new_ob->data, new_ob, &CD_MASK_MESH, true);
+ BKE_mesh_calc_normals(new_ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, new_ob);
+ BKE_mesh_batch_cache_dirty_tag(new_ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&new_ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, new_ob->data);
+ }
+
+ BKE_mesh_nomain_to_mesh(new_mesh, ob->data, ob, &CD_MASK_MESH, true);
+ BKE_mesh_calc_normals(ob->data);
+
+ if (ob->mode == OB_MODE_SCULPT) {
+ ED_sculpt_undo_geometry_end(ob);
+ }
+
+ BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_paint_mask_slice(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+ /* identifiers */
+ ot->name = "Mask Slice";
+ ot->description = "Slices the paint mask from the mesh";
+ ot->idname = "MESH_OT_paint_mask_slice";
+
+ /* api callbacks */
+ ot->poll = paint_mask_extract_poll;
+ ot->exec = paint_mask_slice_exec;
+
+ ot->flag = OPTYPE_REGISTER;
+
+ RNA_def_float(
+ ot->srna,
+ "mask_threshold",
+ 0.5f,
+ 0.0f,
+ 1.0f,
+ "Threshold",
+ "Minimum mask value to consider the vertex valid to extract a face from the original mesh",
+ 0.0f,
+ 1.0f);
+ prop = RNA_def_boolean(
+ ot->srna, "fill_holes", true, "Fill Holes", "Fill holes after slicing the mask");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna,
+ "new_object",
+ true,
+ "Slice to New Object",
+ "Create a new object from the sliced mask");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 8d340d93c0a..594429d4925 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -253,6 +253,7 @@ void MESH_OT_mod_weighted_strength(struct wmOperatorType *ot);
/* *** editmesh_mask_extract.c *** */
void MESH_OT_paint_mask_extract(struct wmOperatorType *ot);
+void MESH_OT_paint_mask_slice(struct wmOperatorType *ot);
struct wmKeyMap *point_normals_modal_keymap(wmKeyConfig *keyconf);
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index 4105f853868..d467a963799 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -195,6 +195,7 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_symmetry_snap);
WM_operatortype_append(MESH_OT_paint_mask_extract);
+ WM_operatortype_append(MESH_OT_paint_mask_slice);
WM_operatortype_append(MESH_OT_point_normals);
WM_operatortype_append(MESH_OT_merge_normals);