BMesh: add BM_mesh_separate_faces
Fast-path for bmesh split operator which duplicates and deletes. Use when only separating faces, currently used by the intersect tool.
This commit is contained in:
parent
5be8adf8c0
commit
5afe4c787f
@ -152,6 +152,8 @@ set(SRC
|
||||
tools/bmesh_path_region.h
|
||||
tools/bmesh_region_match.c
|
||||
tools/bmesh_region_match.h
|
||||
tools/bmesh_separate.c
|
||||
tools/bmesh_separate.h
|
||||
tools/bmesh_triangulate.c
|
||||
tools/bmesh_triangulate.h
|
||||
tools/bmesh_wireframe.c
|
||||
|
@ -43,6 +43,7 @@ extern "C" {
|
||||
#include "tools/bmesh_path.h"
|
||||
#include "tools/bmesh_path_region.h"
|
||||
#include "tools/bmesh_region_match.h"
|
||||
#include "tools/bmesh_separate.h"
|
||||
#include "tools/bmesh_triangulate.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -378,6 +378,10 @@ void BMO_dupe_from_flag(BMesh *bm, int htype, const char hflag)
|
||||
* BMOP_DUPE_VOUTPUT: Buffer containing pointers to the split mesh vertices
|
||||
* BMOP_DUPE_EOUTPUT: Buffer containing pointers to the split mesh edges
|
||||
* BMOP_DUPE_FOUTPUT: Buffer containing pointers to the split mesh faces
|
||||
*
|
||||
* \note Lower level uses of this operator may want to use #BM_mesh_separate_faces
|
||||
* Since it's faster for the 'use_only_faces' case.
|
||||
*
|
||||
*/
|
||||
void bmo_split_exec(BMesh *bm, BMOperator *op)
|
||||
{
|
||||
|
131
source/blender/bmesh/tools/bmesh_separate.c
Normal file
131
source/blender/bmesh/tools/bmesh_separate.c
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* ***** 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 *****
|
||||
*/
|
||||
|
||||
/** \file blender/bmesh/tools/bmesh_separate.c
|
||||
* \ingroup bmesh
|
||||
*
|
||||
* BMesh separate, disconnects a set of faces from all others,
|
||||
* so they don't share any vertices/edges with other faces.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_buffer.h"
|
||||
|
||||
#include "bmesh.h"
|
||||
#include "intern/bmesh_private.h"
|
||||
#include "bmesh_separate.h" /* own include */
|
||||
|
||||
/**
|
||||
* Split all faces that match `filter_fn`.
|
||||
* \note
|
||||
*/
|
||||
void BM_mesh_separate_faces(
|
||||
BMesh *bm,
|
||||
BMFaceFilterFunc filter_fn, void *user_data)
|
||||
{
|
||||
BMFace **faces_array_all = MEM_mallocN(bm->totface * sizeof(BMFace *), __func__);
|
||||
/*
|
||||
* - Create an array of faces based on 'filter_fn'.
|
||||
* First part of array for match, for non-match.
|
||||
*
|
||||
* - Clear all vertex tags, then tag all vertices from 'faces_b'.
|
||||
*
|
||||
* - Loop over 'faces_a', checking each vertex,
|
||||
* splitting out any which are tagged (and therefor shared).
|
||||
*/
|
||||
|
||||
BMFace *f;
|
||||
BMIter iter;
|
||||
|
||||
unsigned int faces_a_len = 0;
|
||||
unsigned int faces_b_len = 0;
|
||||
{
|
||||
int i_a = 0;
|
||||
int i_b = bm->totface;
|
||||
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
|
||||
faces_array_all[filter_fn(f, user_data) ? i_a++ : --i_b] = f;
|
||||
}
|
||||
faces_a_len = i_a;
|
||||
faces_b_len = bm->totface - i_a;
|
||||
}
|
||||
|
||||
BMFace **faces_a = faces_array_all;
|
||||
BMFace **faces_b = faces_array_all + faces_a_len;
|
||||
|
||||
/* Enable for all */
|
||||
BM_mesh_elem_hflag_enable_all(bm, BM_VERT, BM_ELEM_TAG, false);
|
||||
|
||||
/* Disable vert tag on faces_b */
|
||||
for (unsigned int i = 0; i < faces_b_len; i++) {
|
||||
BMLoop *l_iter, *l_first;
|
||||
l_iter = l_first = BM_FACE_FIRST_LOOP(faces_b[i]);
|
||||
do {
|
||||
BM_elem_flag_disable(l_iter->v, BM_ELEM_TAG);
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
}
|
||||
|
||||
|
||||
BLI_buffer_declare_static(BMLoop **, loop_split, 0, 128);
|
||||
|
||||
/* Check shared verts ('faces_a' tag and disable) */
|
||||
for (unsigned int i = 0; i < faces_a_len; i++) {
|
||||
BMLoop *l_iter, *l_first;
|
||||
l_iter = l_first = BM_FACE_FIRST_LOOP(faces_a[i]);
|
||||
do {
|
||||
if (!BM_elem_flag_test(l_iter->v, BM_ELEM_TAG)) {
|
||||
BMVert *v = l_iter->v;
|
||||
/* Disable, since we may visit this vertex again on other faces */
|
||||
BM_elem_flag_disable(v, BM_ELEM_TAG);
|
||||
|
||||
/* We know the vertex is shared, collect all vertices and split them off. */
|
||||
|
||||
/* Fill 'loop_split' */
|
||||
{
|
||||
BMEdge *e_first, *e_iter;
|
||||
e_iter = e_first = l_iter->e;
|
||||
do {
|
||||
BMLoop *l_radial_first, *l_radial_iter;
|
||||
l_radial_first = l_radial_iter = e_iter->l;
|
||||
do {
|
||||
if (l_radial_iter->v == v) {
|
||||
if (filter_fn(l_radial_iter->f, user_data)) {
|
||||
BLI_buffer_append(&loop_split, BMLoop *, l_radial_iter);
|
||||
}
|
||||
}
|
||||
} while ((l_radial_iter = l_radial_iter->radial_next) != l_radial_first);
|
||||
} while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
|
||||
}
|
||||
|
||||
/* Perform the split */
|
||||
bmesh_urmv_loop_multi(bm, loop_split.data, loop_split.count);
|
||||
|
||||
BLI_buffer_empty(&loop_split);
|
||||
}
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
}
|
||||
|
||||
BLI_buffer_free(&loop_split);
|
||||
|
||||
MEM_freeN(faces_array_all);
|
||||
}
|
32
source/blender/bmesh/tools/bmesh_separate.h
Normal file
32
source/blender/bmesh/tools/bmesh_separate.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* ***** 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_SEPARATE_H__
|
||||
#define __BMESH_SEPARATE_H__
|
||||
|
||||
/** \file blender/bmesh/tools/bmesh_separate.h
|
||||
* \ingroup bmesh
|
||||
*/
|
||||
|
||||
void BM_mesh_separate_faces(
|
||||
BMesh *bm,
|
||||
BMFaceFilterFunc filter_fn, void *user_data);
|
||||
|
||||
#endif /* __BMESH_SEPARATE_H__ */
|
@ -51,6 +51,7 @@
|
||||
#include "mesh_intern.h" /* own include */
|
||||
|
||||
#include "tools/bmesh_intersect.h"
|
||||
#include "tools/bmesh_separate.h"
|
||||
|
||||
|
||||
/* detect isolated holes and fill them */
|
||||
@ -196,13 +197,9 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op)
|
||||
|
||||
if (use_separate_cut) {
|
||||
/* detach selected/un-selected faces */
|
||||
BMOperator bmop;
|
||||
EDBM_op_init(em, &bmop, op, "split geom=%hf use_only_faces=%b", BM_ELEM_SELECT, true);
|
||||
BMO_op_exec(em->bm, &bmop);
|
||||
if (!EDBM_op_finish(em, &bmop, op, true)) {
|
||||
/* should never happen! */
|
||||
BKE_report(op->reports, RPT_ERROR, "Error separating");
|
||||
}
|
||||
BM_mesh_separate_faces(
|
||||
bm,
|
||||
BM_elem_cb_check_hflag_enabled_simple(const BMFace *, BM_ELEM_SELECT));
|
||||
}
|
||||
|
||||
if (has_isect) {
|
||||
|
Loading…
Reference in New Issue
Block a user