new mesh bisect tool, available in the mesh menu.
authorCampbell Barton <ideasman42@gmail.com>
Fri, 23 Aug 2013 11:46:08 +0000 (11:46 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 23 Aug 2013 11:46:08 +0000 (11:46 +0000)
cuts the mesh in half based on the cursor location and the viewport,
optionally supports filling the cut area (with uvs. vcols, etc),
and removing geometry on either side of the cut.

release/scripts/startup/bl_ui/space_view3d.py
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/mesh/mesh_intern.h
source/blender/editors/mesh/mesh_ops.c

index 781ebd32318b04c41d1279888770e144882a6d53..9f4d0f8dcc1bb7946f2a1d4c114f89436df49d65 100644 (file)
@@ -1828,6 +1828,7 @@ class VIEW3D_MT_edit_mesh(Menu):
 
         layout.operator("mesh.symmetrize")
         layout.operator("mesh.symmetry_snap")
+        layout.operator("mesh.bisect")
         layout.operator_menu_enum("mesh.sort_elements", "type", text="Sort Elements...")
 
         layout.separator()
index 877e62a01f4604192f43847b700ec6bc7e1a0729..a6202b01ea454da9dff485846c9d7d1b1f942cf8 100644 (file)
@@ -4435,6 +4435,133 @@ void MESH_OT_convex_hull(wmOperatorType *ot)
 }
 #endif
 
+
+static int mesh_bisect_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene = CTX_data_scene(C);
+
+       /* both can be NULL, fallbacks values are used */
+       View3D *v3d = CTX_wm_view3d(C);
+       RegionView3D *rv3d = ED_view3d_context_rv3d(C);
+
+       Object *obedit = CTX_data_edit_object(C);
+       BMEditMesh *em = BKE_editmesh_from_object(obedit);
+       BMesh *bm = em->bm;
+       BMOperator bmop;
+       float plane_co[3];
+       float plane_no[3];
+       float imat[4][4];
+
+       const float thresh = RNA_float_get(op->ptr, "threshold");
+       const bool use_fill = RNA_boolean_get(op->ptr, "use_fill");
+       const bool clear_inner = RNA_boolean_get(op->ptr, "clear_inner");
+       const bool clear_outer = RNA_boolean_get(op->ptr, "clear_outer");
+
+       PropertyRNA *prop;
+
+       prop = RNA_struct_find_property(op->ptr, "plane_co");
+       if (RNA_property_is_set(op->ptr, prop)) {
+               RNA_property_float_get_array(op->ptr, prop, plane_co);
+       }
+       else {
+               copy_v3_v3(plane_co, give_cursor(scene, v3d));
+               RNA_property_float_set_array(op->ptr, prop, plane_co);
+       }
+
+       prop = RNA_struct_find_property(op->ptr, "plane_no");
+       if (RNA_property_is_set(op->ptr, prop)) {
+               RNA_property_float_get_array(op->ptr, prop, plane_no);
+       }
+       else {
+               if (rv3d) {
+                       copy_v3_v3(plane_no, rv3d->viewinv[1]);
+               }
+               else {
+                       /* fallback... */
+                       plane_no[0] = plane_no[1] = 0.0f; plane_no[2] = 1.0f;
+               }
+               RNA_property_float_set_array(op->ptr, prop, plane_no);
+       }
+
+       invert_m4_m4(imat, obedit->obmat);
+       mul_m4_v3(imat, plane_co);
+       mul_mat3_m4_v3(imat, plane_no);
+       normalize_v3(plane_no);
+
+       EDBM_op_init(em, &bmop, op,
+                    "bisect_plane geom=%hvef plane_co=%v plane_no=%v dist=%f clear_inner=%b clear_outer=%b",
+                    BM_ELEM_SELECT, plane_co, plane_no, thresh, clear_inner, clear_outer);
+       BMO_op_exec(bm, &bmop);
+
+       if (use_fill) {
+               float normal_fill[3];
+               BMOperator bmop_fill;
+               BMOperator bmop_attr;
+
+               normalize_v3_v3(normal_fill, plane_no);
+               if (clear_outer == true && clear_inner == false) {
+                       negate_v3(normal_fill);
+               }
+
+               /* Fill */
+               BMO_op_initf(
+                       bm, &bmop_fill, op->flag,
+                       "triangle_fill edges=%S normal=%v use_dissolve=%b",
+                       &bmop, "geom_cut.out", normal_fill, true);
+               BMO_op_exec(bm, &bmop_fill);
+
+               /* Copy Attributes */
+               BMO_op_initf(bm, &bmop_attr, op->flag,
+                            "face_attribute_fill faces=%S use_normals=%b use_data=%b",
+                            &bmop_fill, "geom.out", false, true);
+               BMO_op_exec(bm, &bmop_attr);
+               BMO_op_finish(bm, &bmop_attr);
+               BMO_op_finish(bm, &bmop_fill);
+       }
+
+       EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+       BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom_cut.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, true);
+
+       if (!EDBM_op_finish(em, &bmop, op, true)) {
+               return OPERATOR_CANCELLED;
+       }
+       else {
+               EDBM_update_generic(em, true, true);
+               EDBM_selectmode_flush(em);
+               return OPERATOR_FINISHED;
+       }
+}
+
+void MESH_OT_bisect(struct wmOperatorType *ot)
+{
+       PropertyRNA *prop;
+
+       /* identifiers */
+       ot->name = "Bisect";
+       ot->description = "Enforce symmetry (both form and topological) across an axis";
+       ot->idname = "MESH_OT_bisect";
+
+       /* api callbacks */
+       ot->exec = mesh_bisect_exec;
+       ot->poll = ED_operator_editmesh;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+
+       prop = RNA_def_float_vector(ot->srna, "plane_co", 3, NULL, -FLT_MAX, FLT_MAX, "Point", "", -FLT_MAX, FLT_MAX);
+       RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+       prop = RNA_def_float_vector(ot->srna, "plane_no", 3, NULL, -FLT_MAX, FLT_MAX, "Direction", "", -FLT_MAX, FLT_MAX);
+       RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+       RNA_def_boolean(ot->srna, "use_fill", false, "Fill", "Fill in the cut");
+       RNA_def_boolean(ot->srna, "clear_inner", false, "Clear Inner", "Remove geometry behind the plane");
+       RNA_def_boolean(ot->srna, "clear_outer", false, "Clear Outer", "Remove geometry infront of the plane");
+
+       RNA_def_float(ot->srna, "threshold", 0.0001, 0.0, 10.0, "Axis Threshold", "", 0.00001, 0.1);
+
+}
+
 static int mesh_symmetrize_exec(bContext *C, wmOperator *op)
 {
        Object *obedit = CTX_data_edit_object(C);
index 1dcc0e64183e32aace6b36e3bc46221a83b7eb40..be9243dc7ef5975f87f3357c86af7c75e503702c 100644 (file)
@@ -171,6 +171,7 @@ void MESH_OT_edge_split(struct wmOperatorType *ot);
 void MESH_OT_bridge_edge_loops(struct wmOperatorType *ot);
 void MESH_OT_wireframe(struct wmOperatorType *ot);
 void MESH_OT_convex_hull(struct wmOperatorType *ot);
+void MESH_OT_bisect(struct wmOperatorType *ot);
 void MESH_OT_symmetrize(struct wmOperatorType *ot);
 void MESH_OT_symmetry_snap(struct wmOperatorType *ot);
 void MESH_OT_shape_propagate_to_all(struct wmOperatorType *ot);
index b5352fb35f456400ee926314fbb4eba2965b8868..c98ad13acf6c0d39baf0f6397d10378eba5a8064 100644 (file)
@@ -175,6 +175,7 @@ void ED_operatortypes_mesh(void)
        WM_operatortype_append(MESH_OT_convex_hull);
 #endif
 
+       WM_operatortype_append(MESH_OT_bisect);
        WM_operatortype_append(MESH_OT_symmetrize);
        WM_operatortype_append(MESH_OT_symmetry_snap);