[Bf-blender-cvs] [3a7b5693d1f] sculpt-mode-features: Sculpt: Paint mask extract operator [WIP]
Pablo Dobarro
noreply at git.blender.org
Sat Jun 29 18:04:44 CEST 2019
Commit: 3a7b5693d1f2c709e55fdd90cf847c84238aa4ae
Author: Pablo Dobarro
Date: Sat Jun 29 18:05:00 2019 +0200
Branches: sculpt-mode-features
https://developer.blender.org/rB3a7b5693d1f2c709e55fdd90cf847c84238aa4ae
Sculpt: Paint mask extract operator [WIP]
Currently the operator extracts a triangulated mesh from the mask and
applies a solidify modifier.
I would like to avoid using a shrinkwrap or duplicating the sculpt to
create the external edge loop. I think it should be possible to do
something similar to the relax brush to shrink the geometry to fit the
external loop within the mask.
===================================================================
M source/blender/editors/object/object_edit.c
M source/blender/editors/object/object_intern.h
M source/blender/editors/object/object_ops.c
===================================================================
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 696cf2e9972..16af8d92b53 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -2029,3 +2029,140 @@ void OBJECT_OT_loop_to_vertex_colors(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+static int paint_mask_extract_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+
+ ID *data;
+ data = ob->data;
+ if (data && ID_IS_LINKED(data)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (ob->type == OB_MESH) {
+ Mesh *mesh = ob->data;
+ Main *bmain = CTX_data_main(C);
+ CustomData *vdata = GET_CD_DATA(mesh, vdata);
+ float *paint_mask = CustomData_get_layer(vdata, CD_PAINT_MASK);
+ if (!paint_mask) {
+ return OPERATOR_CANCELLED;
+ }
+ BKE_mesh_runtime_looptri_recalc(mesh);
+ const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(mesh);
+ MVertTri *verttri = MEM_callocN(sizeof(*verttri) * BKE_mesh_runtime_looptri_len(mesh),
+ "remesh_looptri");
+ BKE_mesh_runtime_verttri_from_looptri(
+ verttri, mesh->mloop, looptri, BKE_mesh_runtime_looptri_len(mesh));
+
+ int totfaces = BKE_mesh_runtime_looptri_len(mesh);
+ unsigned int totverts = mesh->totvert;
+ float *verts = (float *)MEM_calloc_arrayN(totverts * 3, sizeof(float), "remesh_input_verts");
+ unsigned int *faces = (unsigned int *)MEM_calloc_arrayN(
+ totfaces * 3, sizeof(unsigned int), "remesh_intput_faces");
+
+ for (int i = 0; i < totverts; i++) {
+ MVert mvert = mesh->mvert[i];
+ verts[i * 3] = mvert.co[0];
+ verts[i * 3 + 1] = mvert.co[1];
+ verts[i * 3 + 2] = mvert.co[2];
+ }
+
+ int current_valid_face = 0;
+ float mask_threshold = 0.7;
+ for (int i = 0; i < totfaces; i++) {
+ MVertTri vt = verttri[i];
+ if (paint_mask[vt.tri[0]] > mask_threshold && paint_mask[vt.tri[1]] > mask_threshold &&
+ paint_mask[vt.tri[2]] > mask_threshold) {
+ faces[current_valid_face * 3] = vt.tri[0];
+ faces[current_valid_face * 3 + 1] = vt.tri[1];
+ faces[current_valid_face * 3 + 2] = vt.tri[2];
+ current_valid_face++;
+ }
+ }
+
+ Mesh *newMesh = BKE_mesh_new_nomain(mesh->totvert, 0, current_valid_face, 0, 0);
+
+ for (int i = 0; i < mesh->totvert; i++) {
+ float vco[3] = {verts[i * 3], verts[i * 3 + 1], verts[i * 3 + 2]};
+ copy_v3_v3(newMesh->mvert[i].co, vco);
+ }
+
+ for (int i = 0; i < current_valid_face; i++) {
+ newMesh->mface[i].v4 = 0;
+ newMesh->mface[i].v3 = faces[i * 3];
+ newMesh->mface[i].v2 = faces[i * 3 + 1];
+ newMesh->mface[i].v1 = faces[i * 3 + 2];
+ }
+
+ MEM_freeN(faces);
+ MEM_freeN(verts);
+
+ BKE_mesh_calc_edges_tessface(newMesh);
+ BKE_mesh_convert_mfaces_to_mpolys(newMesh);
+ BKE_mesh_calc_normals(newMesh);
+ BKE_mesh_strip_loose_edges(newMesh);
+ BKE_mesh_strip_loose_polysloops(newMesh);
+ BKE_mesh_strip_loose_faces(newMesh);
+
+ const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(newMesh);
+ BMesh *bm;
+ bm = BM_mesh_create(&allocsize,
+ &((struct BMeshCreateParams){
+ .use_toolflags = false,
+ }));
+
+ BM_mesh_bm_from_me(bm,
+ newMesh,
+ (&(struct BMeshFromMeshParams){
+ .calc_face_normal = true,
+ }));
+
+ BMEditMesh *em = BKE_editmesh_create(bm, false);
+ BMVert *v;
+ BMIter iter;
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_set(v, BM_ELEM_TAG, (v->e == NULL));
+ }
+ BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_VERTS);
+ BKE_editmesh_free_derivedmesh(em);
+ BKE_mesh_free(newMesh);
+ newMesh = BKE_mesh_from_bmesh_nomain(bm, (&(struct BMeshToMeshParams){}));
+ ushort local_view_bits = 0;
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d && v3d->localvd) {
+ local_view_bits = v3d->local_view_uuid;
+ }
+ Object *newob = ED_object_add_type(C, OB_MESH, NULL, ob->loc, ob->rot, false, local_view_bits);
+
+ BKE_mesh_nomain_to_mesh(newMesh, newob->data, newob, &CD_MASK_EVERYTHING, true);
+
+ struct Scene *scene = CTX_data_scene(C);
+ if (!ED_object_modifier_add(op->reports, bmain, scene, newob, NULL, eModifierType_Solidify)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, newob);
+ BKE_mesh_batch_cache_dirty_tag(newob->data, BKE_MESH_BATCH_DIRTY_ALL);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&newob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, newob->data);
+ BKE_mesh_free(newMesh);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_paint_mask_extract(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Mask Extract";
+ ot->description = "Create a new solid object from the current paint mask";
+ ot->idname = "OBJECT_OT_paint_mask_extract";
+
+ /* api callbacks */
+ ot->poll = object_mode_set_poll;
+ ot->exec = paint_mask_extract_exec;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 1345d21fd83..1d7f11c187a 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -284,6 +284,8 @@ void OBJECT_OT_remesh(struct wmOperatorType *ot);
void OBJECT_OT_vertex_to_loop_colors(struct wmOperatorType *ot);
void OBJECT_OT_loop_to_vertex_colors(struct wmOperatorType *ot);
+void OBJECT_OT_paint_mask_extract(struct wmOperatorType *ot);
+
void REMESH_OT_csg_add(struct wmOperatorType *ot);
void REMESH_OT_csg_remove(struct wmOperatorType *ot);
void REMESH_OT_csg_move_up(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index cdbc05a5cee..c2425ff792b 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -262,6 +262,8 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_vertex_to_loop_colors);
WM_operatortype_append(OBJECT_OT_loop_to_vertex_colors);
+ WM_operatortype_append(OBJECT_OT_paint_mask_extract);
+
WM_operatortype_append(REMESH_OT_csg_add);
WM_operatortype_append(REMESH_OT_csg_remove);
WM_operatortype_append(REMESH_OT_csg_move_down);
More information about the Bf-blender-cvs
mailing list