BMesh: intersect tool
Modeling tool to cut intersections into geometry (like boolean, without calculating inside/outside). Faces are split along intersections, leaving new edges selected. Access from Face menu.
This commit is contained in:
parent
4795b61c1b
commit
b9ebf44139
|
@ -2266,6 +2266,7 @@ class VIEW3D_MT_edit_mesh_faces(Menu):
|
|||
layout.operator("mesh.inset")
|
||||
layout.operator("mesh.bevel").vertex_only = False
|
||||
layout.operator("mesh.solidify")
|
||||
layout.operator("mesh.intersect")
|
||||
layout.operator("mesh.wireframe")
|
||||
|
||||
layout.separator()
|
||||
|
|
|
@ -136,6 +136,8 @@ set(SRC
|
|||
tools/bmesh_edgenet.h
|
||||
tools/bmesh_edgesplit.c
|
||||
tools/bmesh_edgesplit.h
|
||||
tools/bmesh_intersect.c
|
||||
tools/bmesh_intersect.h
|
||||
tools/bmesh_path.c
|
||||
tools/bmesh_path.h
|
||||
tools/bmesh_triangulate.c
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef __BMESH_INTERSECT_H__
|
||||
#define __BMESH_INTERSECT_H__
|
||||
|
||||
/** \file blender/bmesh/tools/bmesh_intersect.h
|
||||
* \ingroup bmesh
|
||||
*/
|
||||
|
||||
bool BM_mesh_intersect(
|
||||
BMesh *bm,
|
||||
struct BMLoop *(*looptris)[3], const int looptris_tot,
|
||||
int (*test_fn)(BMFace *f, void *user_data), void *user_data,
|
||||
const bool use_self, const bool use_separate,
|
||||
const float eps);
|
||||
|
||||
#endif /* __BMESH_INTERSECT_H__ */
|
|
@ -32,8 +32,11 @@
|
|||
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_editmesh.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
@ -45,6 +48,129 @@
|
|||
|
||||
#include "mesh_intern.h" /* own include */
|
||||
|
||||
#include "tools/bmesh_intersect.h"
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Cut intersections into geometry */
|
||||
|
||||
/**
|
||||
* Compare selected with its self.
|
||||
*/
|
||||
static int bm_face_isect_self(BMFace *f, void *UNUSED(user_data))
|
||||
{
|
||||
if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare selected/unselected.
|
||||
*/
|
||||
static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data))
|
||||
{
|
||||
if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
return -1;
|
||||
}
|
||||
else if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
enum {
|
||||
ISECT_SEL = 0,
|
||||
ISECT_SEL_UNSEL = 1,
|
||||
};
|
||||
|
||||
static EnumPropertyItem isect_mode_items[] = {
|
||||
{ISECT_SEL, "SELECT", 0, "Self Intersect",
|
||||
"Self intersect selected faces"},
|
||||
{ISECT_SEL_UNSEL, "SELECT_UNSELECT", 0, "Select/Unselected",
|
||||
"Intersect selected with unselected faces"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
static int edbm_intersect_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *obedit = CTX_data_edit_object(C);
|
||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||
BMesh *bm = em->bm;
|
||||
const int mode = RNA_enum_get(op->ptr, "mode");
|
||||
int (*test_fn)(BMFace *, void *);
|
||||
bool use_separate = RNA_boolean_get(op->ptr, "use_separate");
|
||||
const float eps = RNA_float_get(op->ptr, "threshold");
|
||||
bool use_self;
|
||||
bool has_isect;
|
||||
|
||||
switch (mode) {
|
||||
case ISECT_SEL:
|
||||
test_fn = bm_face_isect_self;
|
||||
use_self = true;
|
||||
break;
|
||||
default: /* ISECT_SEL_UNSEL */
|
||||
test_fn = bm_face_isect_pair;
|
||||
use_self = false;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
has_isect = BM_mesh_intersect(
|
||||
bm,
|
||||
em->looptris, em->tottri,
|
||||
test_fn, NULL,
|
||||
use_self, use_separate,
|
||||
eps);
|
||||
|
||||
|
||||
if (has_isect) {
|
||||
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
|
||||
|
||||
if (em->bm->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
|
||||
BMIter iter;
|
||||
BMEdge *e;
|
||||
|
||||
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
|
||||
if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
|
||||
BM_edge_select_set(bm, e, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EDBM_mesh_normals_update(em);
|
||||
EDBM_update_generic(em, true, true);
|
||||
}
|
||||
else {
|
||||
BKE_report(op->reports, RPT_WARNING, "No intersections found");
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void MESH_OT_intersect(struct wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Intersect";
|
||||
ot->description = "Cut an intersection into faces";
|
||||
ot->idname = "MESH_OT_intersect";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = edbm_intersect_exec;
|
||||
ot->poll = ED_operator_editmesh;
|
||||
|
||||
/* props */
|
||||
RNA_def_enum(ot->srna, "mode", isect_mode_items, ISECT_SEL_UNSEL, "Source", "");
|
||||
RNA_def_boolean(ot->srna, "use_separate", true, "Separate", "");
|
||||
RNA_def_float(ot->srna, "threshold", 0.000001f, 0.0, 0.01, "Merge threshold", "", 0.0, 0.001);
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -113,6 +113,7 @@ void MESH_OT_screw(struct wmOperatorType *ot);
|
|||
void MESH_OT_inset(struct wmOperatorType *ot);
|
||||
|
||||
/* *** editmesh_intersect.c *** */
|
||||
void MESH_OT_intersect(struct wmOperatorType *ot);
|
||||
void MESH_OT_face_split_by_edges(struct wmOperatorType *ot);
|
||||
|
||||
|
||||
|
|
|
@ -170,6 +170,7 @@ void ED_operatortypes_mesh(void)
|
|||
|
||||
WM_operatortype_append(MESH_OT_bridge_edge_loops);
|
||||
WM_operatortype_append(MESH_OT_inset);
|
||||
WM_operatortype_append(MESH_OT_intersect);
|
||||
WM_operatortype_append(MESH_OT_face_split_by_edges);
|
||||
WM_operatortype_append(MESH_OT_poke);
|
||||
WM_operatortype_append(MESH_OT_wireframe);
|
||||
|
|
Loading…
Reference in New Issue