169 lines
5.3 KiB
C
169 lines
5.3 KiB
C
/*
|
|
* 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.
|
|
*/
|
|
|
|
/** \file
|
|
* \ingroup bmesh
|
|
*
|
|
* Triangulate.
|
|
*/
|
|
|
|
#include "DNA_modifier_types.h" /* for MOD_TRIANGULATE_NGON_BEAUTY only */
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
#include "BLI_alloca.h"
|
|
#include "BLI_heap.h"
|
|
#include "BLI_linklist.h"
|
|
#include "BLI_memarena.h"
|
|
#include "BLI_utildefines.h"
|
|
|
|
/* only for defines */
|
|
#include "BLI_polyfill_2d.h"
|
|
#include "BLI_polyfill_2d_beautify.h"
|
|
|
|
#include "bmesh.h"
|
|
|
|
#include "bmesh_triangulate.h" /* own include */
|
|
|
|
/**
|
|
* a version of #BM_face_triangulate that maps to #BMOpSlot
|
|
*/
|
|
static void bm_face_triangulate_mapping(BMesh *bm,
|
|
BMFace *face,
|
|
const int quad_method,
|
|
const int ngon_method,
|
|
const bool use_tag,
|
|
BMOperator *op,
|
|
BMOpSlot *slot_facemap_out,
|
|
BMOpSlot *slot_facemap_double_out,
|
|
|
|
MemArena *pf_arena,
|
|
/* use for MOD_TRIANGULATE_NGON_BEAUTY only! */
|
|
struct Heap *pf_heap)
|
|
{
|
|
int faces_array_tot = face->len - 3;
|
|
BMFace **faces_array = BLI_array_alloca(faces_array, faces_array_tot);
|
|
LinkNode *faces_double = NULL;
|
|
BLI_assert(face->len > 3);
|
|
|
|
BM_face_triangulate(bm,
|
|
face,
|
|
faces_array,
|
|
&faces_array_tot,
|
|
NULL,
|
|
NULL,
|
|
&faces_double,
|
|
quad_method,
|
|
ngon_method,
|
|
use_tag,
|
|
pf_arena,
|
|
pf_heap);
|
|
|
|
if (faces_array_tot) {
|
|
int i;
|
|
BMO_slot_map_elem_insert(op, slot_facemap_out, face, face);
|
|
for (i = 0; i < faces_array_tot; i++) {
|
|
BMO_slot_map_elem_insert(op, slot_facemap_out, faces_array[i], face);
|
|
}
|
|
|
|
while (faces_double) {
|
|
LinkNode *next = faces_double->next;
|
|
BMO_slot_map_elem_insert(op, slot_facemap_double_out, faces_double->link, face);
|
|
MEM_freeN(faces_double);
|
|
faces_double = next;
|
|
}
|
|
}
|
|
}
|
|
|
|
void BM_mesh_triangulate(BMesh *bm,
|
|
const int quad_method,
|
|
const int ngon_method,
|
|
const int min_vertices,
|
|
const bool tag_only,
|
|
BMOperator *op,
|
|
BMOpSlot *slot_facemap_out,
|
|
BMOpSlot *slot_facemap_double_out)
|
|
{
|
|
BMIter iter;
|
|
BMFace *face;
|
|
MemArena *pf_arena;
|
|
Heap *pf_heap;
|
|
|
|
pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
|
|
|
|
if (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY) {
|
|
pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
|
|
}
|
|
else {
|
|
pf_heap = NULL;
|
|
}
|
|
|
|
if (slot_facemap_out) {
|
|
/* same as below but call: bm_face_triangulate_mapping() */
|
|
BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) {
|
|
if (face->len >= min_vertices) {
|
|
if (tag_only == false || BM_elem_flag_test(face, BM_ELEM_TAG)) {
|
|
bm_face_triangulate_mapping(bm,
|
|
face,
|
|
quad_method,
|
|
ngon_method,
|
|
tag_only,
|
|
op,
|
|
slot_facemap_out,
|
|
slot_facemap_double_out,
|
|
pf_arena,
|
|
pf_heap);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
LinkNode *faces_double = NULL;
|
|
|
|
BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) {
|
|
if (face->len >= min_vertices) {
|
|
if (tag_only == false || BM_elem_flag_test(face, BM_ELEM_TAG)) {
|
|
BM_face_triangulate(bm,
|
|
face,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&faces_double,
|
|
quad_method,
|
|
ngon_method,
|
|
tag_only,
|
|
pf_arena,
|
|
pf_heap);
|
|
}
|
|
}
|
|
}
|
|
|
|
while (faces_double) {
|
|
LinkNode *next = faces_double->next;
|
|
BM_face_kill(bm, faces_double->link);
|
|
MEM_freeN(faces_double);
|
|
faces_double = next;
|
|
}
|
|
}
|
|
|
|
BLI_memarena_free(pf_arena);
|
|
|
|
if (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY) {
|
|
BLI_heap_free(pf_heap, NULL);
|
|
}
|
|
}
|