2011-03-17 22:59:54 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
2011-05-09 04:06:48 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2011-03-17 22:59:54 +00:00
|
|
|
#include "BLI_ghash.h"
|
|
|
|
|
#include "BLI_memarena.h"
|
|
|
|
|
#include "BLI_array.h"
|
|
|
|
|
#include "BLI_math.h"
|
|
|
|
|
#include "BLI_array.h"
|
|
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
|
#include "BLI_smallhash.h"
|
|
|
|
|
|
|
|
|
|
#include "bmesh.h"
|
|
|
|
|
#include "bmesh_operators_private.h"
|
|
|
|
|
|
|
|
|
|
#define BEVEL_FLAG 1
|
|
|
|
|
#define BEVEL_DEL 2
|
|
|
|
|
#define FACE_NEW 4
|
|
|
|
|
#define EDGE_OLD 8
|
|
|
|
|
#define FACE_OLD 16
|
|
|
|
|
#define FACE_DONE 32
|
|
|
|
|
#define VERT_OLD 64
|
|
|
|
|
#define FACE_SPAN 128
|
|
|
|
|
#define FACE_HOLE 256
|
|
|
|
|
|
|
|
|
|
typedef struct LoopTag {
|
|
|
|
|
BMVert *newv;
|
|
|
|
|
} LoopTag;
|
|
|
|
|
|
|
|
|
|
typedef struct EdgeTag {
|
|
|
|
|
BMVert *newv1, *newv2;
|
|
|
|
|
} EdgeTag;
|
|
|
|
|
|
2011-12-12 22:25:28 +00:00
|
|
|
static void calc_corner_co(BMesh *bm, BMLoop *l, const float fac, float r_co[3])
|
2011-03-17 22:59:54 +00:00
|
|
|
{
|
2011-12-12 22:25:28 +00:00
|
|
|
float no[3], l_vec_prev[3], l_vec_next[3], l_co_prev[3], l_co[3], l_co_next[3];
|
|
|
|
|
int is_concave;
|
2011-04-15 07:08:36 +00:00
|
|
|
|
|
|
|
|
if (l->f->len > 2) {
|
2011-12-12 22:25:28 +00:00
|
|
|
copy_v3_v3(l_co_prev, l->prev->v->co);
|
|
|
|
|
copy_v3_v3(l_co, l->v->co);
|
|
|
|
|
copy_v3_v3(l_co_next, l->next->v->co);
|
2011-12-12 09:09:01 +00:00
|
|
|
|
|
|
|
|
/*calculate normal*/
|
2011-12-12 22:25:28 +00:00
|
|
|
sub_v3_v3v3(l_vec_prev, l_co_prev, l_co);
|
|
|
|
|
sub_v3_v3v3(l_vec_next, l_co_next, l_co);
|
2011-12-12 09:09:01 +00:00
|
|
|
|
2011-12-12 22:25:28 +00:00
|
|
|
cross_v3_v3v3(no, l_vec_prev, l_vec_next);
|
|
|
|
|
is_concave= dot_v3v3(no, l->f->no) > 0.0f;
|
2011-12-12 09:09:01 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2011-04-15 07:08:36 +00:00
|
|
|
BMIter iter;
|
|
|
|
|
BMLoop *l2;
|
|
|
|
|
float up[3] = {0.0f, 0.0f, 1.0f};
|
2011-12-12 22:25:28 +00:00
|
|
|
|
|
|
|
|
copy_v3_v3(l_co_prev, l->prev->v->co);
|
|
|
|
|
copy_v3_v3(l_co, l->v->co);
|
2011-04-15 07:08:36 +00:00
|
|
|
|
|
|
|
|
BM_ITER(l2, &iter, bm, BM_LOOPS_OF_VERT, l->v) {
|
2011-04-16 13:00:41 +00:00
|
|
|
if (l2->f != l->f) {
|
2011-12-12 22:25:28 +00:00
|
|
|
copy_v3_v3(l_co_next, BM_OtherEdgeVert(l2->e, l2->next->v)->co);
|
2011-04-15 07:08:36 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-12 22:25:28 +00:00
|
|
|
sub_v3_v3v3(l_vec_prev, l_co_prev, l_co);
|
|
|
|
|
sub_v3_v3v3(l_vec_next, l_co_next, l_co);
|
2011-03-17 22:59:54 +00:00
|
|
|
|
2011-12-12 22:25:28 +00:00
|
|
|
cross_v3_v3v3(no, l_vec_prev, l_vec_next);
|
2011-08-20 20:19:58 +00:00
|
|
|
if (dot_v3v3(no, no) == 0.0f) {
|
2011-04-15 07:08:36 +00:00
|
|
|
no[0] = no[1] = 0.0f; no[2] = -1.0f;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-12 22:25:28 +00:00
|
|
|
is_concave = dot_v3v3(no, up) < 0.0f;
|
2011-03-17 22:59:54 +00:00
|
|
|
}
|
2011-12-12 09:09:01 +00:00
|
|
|
|
2011-12-12 09:28:46 +00:00
|
|
|
if (1) {
|
|
|
|
|
/*simple percentage method */
|
2011-04-15 07:08:36 +00:00
|
|
|
|
2011-12-12 09:28:46 +00:00
|
|
|
|
|
|
|
|
/* not strictly necessary, balance vectors
|
|
|
|
|
* so the longer edge doesn't skew the result,
|
2011-12-12 23:58:05 +00:00
|
|
|
* gives nicer, move even output */
|
2011-12-12 22:25:28 +00:00
|
|
|
float medium= (normalize_v3(l_vec_prev) + normalize_v3(l_vec_next)) / 2.0f;
|
|
|
|
|
mul_v3_fl(l_vec_prev, medium);
|
|
|
|
|
mul_v3_fl(l_vec_next, medium);
|
2011-12-12 09:28:46 +00:00
|
|
|
/* done */
|
|
|
|
|
|
|
|
|
|
|
2011-12-12 22:25:28 +00:00
|
|
|
add_v3_v3(l_vec_prev, l_vec_next);
|
|
|
|
|
mul_v3_fl(l_vec_prev, fac * 0.5);
|
2011-12-12 09:28:46 +00:00
|
|
|
|
2011-12-12 22:25:28 +00:00
|
|
|
if (is_concave)
|
|
|
|
|
negate_v3(l_vec_prev);
|
2011-12-12 09:28:46 +00:00
|
|
|
|
2011-12-12 22:25:28 +00:00
|
|
|
add_v3_v3v3(r_co, l_vec_prev, l->v->co);
|
2011-12-12 09:28:46 +00:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* distance based */
|
|
|
|
|
float tvec[3];
|
|
|
|
|
float dist;
|
|
|
|
|
|
2011-12-12 22:25:28 +00:00
|
|
|
normalize_v3(l_vec_prev);
|
|
|
|
|
normalize_v3(l_vec_next);
|
2011-12-12 09:28:46 +00:00
|
|
|
|
|
|
|
|
/* get the medium normalized direction */
|
2011-12-12 22:25:28 +00:00
|
|
|
add_v3_v3v3(tvec, l_vec_prev,l_vec_next);
|
2011-12-12 09:28:46 +00:00
|
|
|
normalize_v3(tvec);
|
|
|
|
|
|
|
|
|
|
/* for angle calculation */
|
2011-12-12 22:25:28 +00:00
|
|
|
negate_v3(l_vec_next);
|
2011-12-12 09:28:46 +00:00
|
|
|
|
2011-12-12 22:25:28 +00:00
|
|
|
dist= shell_angle_to_dist(angle_normalized_v3v3(l_vec_prev, l_vec_next) * 0.5);
|
2011-12-12 09:28:46 +00:00
|
|
|
|
|
|
|
|
mul_v3_fl(tvec, fac * dist);
|
|
|
|
|
|
2011-12-12 22:25:28 +00:00
|
|
|
if (is_concave)
|
2011-12-12 09:28:46 +00:00
|
|
|
negate_v3(tvec);
|
|
|
|
|
|
2011-12-12 22:25:28 +00:00
|
|
|
add_v3_v3v3(r_co, tvec, l->v->co);
|
2011-12-12 09:28:46 +00:00
|
|
|
|
|
|
|
|
}
|
2011-03-17 22:59:54 +00:00
|
|
|
}
|
|
|
|
|
|
2011-05-13 10:59:30 +00:00
|
|
|
#define ETAG_SET(e, v, nv) (v) == (e)->v1 ? (etags[BM_GetIndex((e))].newv1 = (nv)) : (etags[BM_GetIndex((e))].newv2 = (nv))
|
|
|
|
|
#define ETAG_GET(e, v) ((v) == (e)->v1 ? (etags[BM_GetIndex((e))].newv1) : (etags[BM_GetIndex((e))].newv2))
|
2011-03-17 22:59:54 +00:00
|
|
|
|
|
|
|
|
void bmesh_bevel_exec(BMesh *bm, BMOperator *op)
|
|
|
|
|
{
|
|
|
|
|
BMOIter siter;
|
|
|
|
|
BMIter iter;
|
|
|
|
|
BMEdge *e;
|
|
|
|
|
BMVert *v;
|
2011-04-15 07:08:36 +00:00
|
|
|
BMFace **faces = NULL, *f;
|
2011-03-17 22:59:54 +00:00
|
|
|
LoopTag *tags=NULL, *tag;
|
2011-10-13 04:58:34 +00:00
|
|
|
EdgeTag *etags = NULL;
|
2011-03-17 22:59:54 +00:00
|
|
|
BMVert **verts = NULL;
|
|
|
|
|
BMEdge **edges = NULL;
|
|
|
|
|
BLI_array_declare(faces);
|
|
|
|
|
BLI_array_declare(tags);
|
|
|
|
|
BLI_array_declare(etags);
|
|
|
|
|
BLI_array_declare(verts);
|
|
|
|
|
BLI_array_declare(edges);
|
|
|
|
|
SmallHash hash;
|
|
|
|
|
float fac = BMO_Get_Float(op, "percent");
|
2011-04-16 13:00:41 +00:00
|
|
|
int i, li, has_elens, HasMDisps = CustomData_has_layer(&bm->ldata, CD_MDISPS);
|
|
|
|
|
|
|
|
|
|
has_elens = CustomData_has_layer(&bm->edata, CD_PROP_FLT) && BMO_Get_Int(op, "uselengths");
|
|
|
|
|
if (has_elens) {
|
|
|
|
|
li = BMO_Get_Int(op, "lengthlayer");
|
|
|
|
|
}
|
2011-03-17 22:59:54 +00:00
|
|
|
|
|
|
|
|
BLI_smallhash_init(&hash);
|
|
|
|
|
|
|
|
|
|
BMO_ITER(e, &siter, bm, op, "geom", BM_EDGE) {
|
|
|
|
|
BMO_SetFlag(bm, e, BEVEL_FLAG|BEVEL_DEL);
|
|
|
|
|
BMO_SetFlag(bm, e->v1, BEVEL_FLAG|BEVEL_DEL);
|
|
|
|
|
BMO_SetFlag(bm, e->v2, BEVEL_FLAG|BEVEL_DEL);
|
|
|
|
|
|
|
|
|
|
if (BM_Edge_FaceCount(e) < 2) {
|
|
|
|
|
BMO_ClearFlag(bm, e, BEVEL_DEL);
|
|
|
|
|
BMO_ClearFlag(bm, e->v1, BEVEL_DEL);
|
|
|
|
|
BMO_ClearFlag(bm, e->v2, BEVEL_DEL);
|
|
|
|
|
}
|
2011-04-15 07:08:36 +00:00
|
|
|
#if 0
|
|
|
|
|
if (BM_Edge_FaceCount(e) == 0) {
|
|
|
|
|
BMVert *verts[2] = {e->v1, e->v2};
|
|
|
|
|
BMEdge *edges[2] = {e, BM_Make_Edge(bm, e->v1, e->v2, e, 0)};
|
|
|
|
|
|
|
|
|
|
BMO_SetFlag(bm, edges[1], BEVEL_FLAG);
|
2011-10-13 04:58:34 +00:00
|
|
|
BM_Make_Face(bm, verts, edges, 2, 0);
|
2011-04-15 07:08:36 +00:00
|
|
|
}
|
|
|
|
|
#endif
|
2011-03-17 22:59:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
|
|
|
|
|
BMO_SetFlag(bm, v, VERT_OLD);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
//a bit of cleaner code that, alas, doens't work.
|
|
|
|
|
/*build edge tags*/
|
|
|
|
|
BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
|
|
|
|
|
if (BMO_TestFlag(bm, e->v1, BEVEL_FLAG) || BMO_TestFlag(bm, e->v2, BEVEL_FLAG)) {
|
|
|
|
|
BMIter liter;
|
|
|
|
|
BMLoop *l;
|
|
|
|
|
|
|
|
|
|
if (!BMO_TestFlag(bm, e, EDGE_OLD)) {
|
2011-11-28 05:56:00 +00:00
|
|
|
BM_SetIndex(e, BLI_array_count(etags)); /* set_dirty! */
|
2011-03-17 22:59:54 +00:00
|
|
|
BLI_array_growone(etags);
|
|
|
|
|
|
|
|
|
|
BMO_SetFlag(bm, e, EDGE_OLD);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BM_ITER(l, &liter, bm, BM_LOOPS_OF_EDGE, e) {
|
|
|
|
|
BMLoop *l2;
|
|
|
|
|
BMIter liter2;
|
|
|
|
|
|
|
|
|
|
if (BMO_TestFlag(bm, l->f, BEVEL_FLAG))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
BM_ITER(l2, &liter2, bm, BM_LOOPS_OF_FACE, l->f) {
|
2011-12-13 05:20:02 +00:00
|
|
|
BM_SetIndex(l2, BLI_array_count(tags)); /* set_loop */
|
2011-03-17 22:59:54 +00:00
|
|
|
BLI_array_growone(tags);
|
|
|
|
|
|
|
|
|
|
if (!BMO_TestFlag(bm, l2->e, EDGE_OLD)) {
|
2011-11-28 05:56:00 +00:00
|
|
|
BM_SetIndex(l2->e, BLI_array_count(etags)); /* set_dirty! */
|
2011-03-17 22:59:54 +00:00
|
|
|
BLI_array_growone(etags);
|
|
|
|
|
|
|
|
|
|
BMO_SetFlag(bm, l2->e, EDGE_OLD);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BMO_SetFlag(bm, l->f, BEVEL_FLAG);
|
|
|
|
|
BLI_array_append(faces, l->f);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2011-11-28 05:56:00 +00:00
|
|
|
BM_SetIndex(e, -1); /* set_dirty! */
|
2011-03-17 22:59:54 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/*create and assign looptag structures*/
|
|
|
|
|
BMO_ITER(e, &siter, bm, op, "geom", BM_EDGE) {
|
|
|
|
|
BMLoop *l;
|
|
|
|
|
BMIter liter;
|
|
|
|
|
|
|
|
|
|
BMO_SetFlag(bm, e->v1, BEVEL_FLAG|BEVEL_DEL);
|
|
|
|
|
BMO_SetFlag(bm, e->v2, BEVEL_FLAG|BEVEL_DEL);
|
|
|
|
|
|
|
|
|
|
if (BM_Edge_FaceCount(e) < 2) {
|
|
|
|
|
BMO_ClearFlag(bm, e, BEVEL_DEL);
|
|
|
|
|
BMO_ClearFlag(bm, e->v1, BEVEL_DEL);
|
|
|
|
|
BMO_ClearFlag(bm, e->v2, BEVEL_DEL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!BLI_smallhash_haskey(&hash, (intptr_t)e)) {
|
|
|
|
|
BLI_array_growone(etags);
|
2011-11-28 05:56:00 +00:00
|
|
|
BM_SetIndex(e, BLI_array_count(etags)-1); /* set_dirty! */
|
2011-03-17 22:59:54 +00:00
|
|
|
BLI_smallhash_insert(&hash, (intptr_t)e, NULL);
|
|
|
|
|
BMO_SetFlag(bm, e, EDGE_OLD);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*find all faces surrounding e->v1 and, e->v2*/
|
|
|
|
|
for (i=0; i<2; i++) {
|
|
|
|
|
BM_ITER(l, &liter, bm, BM_LOOPS_OF_VERT, i?e->v2:e->v1) {
|
|
|
|
|
BMLoop *l2;
|
|
|
|
|
BMIter liter2;
|
|
|
|
|
|
|
|
|
|
/*see if we've already processed this loop's face*/
|
|
|
|
|
if (BLI_smallhash_haskey(&hash, (intptr_t)l->f))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/*create tags for all loops in l->f*/
|
|
|
|
|
BM_ITER(l2, &liter2, bm, BM_LOOPS_OF_FACE, l->f) {
|
|
|
|
|
BLI_array_growone(tags);
|
2011-11-28 06:49:16 +00:00
|
|
|
BM_SetIndex(l2, BLI_array_count(tags)-1); /* set_loop */
|
2011-03-17 22:59:54 +00:00
|
|
|
|
|
|
|
|
if (!BLI_smallhash_haskey(&hash, (intptr_t)l2->e)) {
|
|
|
|
|
BLI_array_growone(etags);
|
2011-11-28 05:56:00 +00:00
|
|
|
BM_SetIndex(l2->e, BLI_array_count(etags)-1); /* set_dirty! */
|
2011-03-17 22:59:54 +00:00
|
|
|
BLI_smallhash_insert(&hash, (intptr_t)l2->e, NULL);
|
|
|
|
|
BMO_SetFlag(bm, l2->e, EDGE_OLD);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLI_smallhash_insert(&hash, (intptr_t)l->f, NULL);
|
|
|
|
|
BMO_SetFlag(bm, l->f, BEVEL_FLAG);
|
|
|
|
|
BLI_array_append(faces, l->f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-28 06:49:16 +00:00
|
|
|
bm->elem_index_dirty |= BM_EDGE;
|
2011-12-04 00:44:09 +00:00
|
|
|
|
2011-03-17 22:59:54 +00:00
|
|
|
BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
|
|
|
|
|
BMIter eiter;
|
|
|
|
|
|
|
|
|
|
if (!BMO_TestFlag(bm, v, BEVEL_FLAG))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
|
|
|
|
|
if (!BMO_TestFlag(bm, e, BEVEL_FLAG) && !ETAG_GET(e, v)) {
|
|
|
|
|
BMVert *v2;
|
|
|
|
|
float co[3];
|
|
|
|
|
|
|
|
|
|
v2 = BM_OtherEdgeVert(e, v);
|
|
|
|
|
sub_v3_v3v3(co, v2->co, v->co);
|
2011-04-16 13:00:41 +00:00
|
|
|
if (has_elens) {
|
|
|
|
|
float elen = *(float*)CustomData_bmesh_get_n(&bm->edata, e->head.data, CD_PROP_FLT, li);
|
|
|
|
|
|
|
|
|
|
normalize_v3(co);
|
|
|
|
|
mul_v3_fl(co, elen);
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-17 22:59:54 +00:00
|
|
|
mul_v3_fl(co, fac);
|
|
|
|
|
add_v3_v3(co, v->co);
|
|
|
|
|
|
|
|
|
|
v2 = BM_Make_Vert(bm, co, v);
|
|
|
|
|
ETAG_SET(e, v, v2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i=0; i<BLI_array_count(faces); i++) {
|
|
|
|
|
BMLoop *l;
|
|
|
|
|
BMIter liter;
|
|
|
|
|
|
|
|
|
|
BMO_SetFlag(bm, faces[i], FACE_OLD);
|
|
|
|
|
|
|
|
|
|
BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, faces[i]) {
|
|
|
|
|
float co[3];
|
|
|
|
|
|
|
|
|
|
if (BMO_TestFlag(bm, l->e, BEVEL_FLAG)) {
|
|
|
|
|
if (BMO_TestFlag(bm, l->prev->e, BEVEL_FLAG))
|
|
|
|
|
{
|
2011-05-13 10:49:26 +00:00
|
|
|
tag = tags + BM_GetIndex(l);
|
2011-12-12 22:25:28 +00:00
|
|
|
calc_corner_co(bm, l, fac, co);
|
2011-03-17 22:59:54 +00:00
|
|
|
tag->newv = BM_Make_Vert(bm, co, l->v);
|
|
|
|
|
} else {
|
2011-05-13 10:49:26 +00:00
|
|
|
tag = tags + BM_GetIndex(l);
|
2011-03-17 22:59:54 +00:00
|
|
|
tag->newv = ETAG_GET(l->prev->e, l->v);
|
|
|
|
|
|
|
|
|
|
if (!tag->newv) {
|
|
|
|
|
sub_v3_v3v3(co, l->prev->v->co, l->v->co);
|
2011-04-16 13:00:41 +00:00
|
|
|
if (has_elens) {
|
|
|
|
|
float elen = *(float*)CustomData_bmesh_get_n(&bm->edata, l->prev->e->head.data, CD_PROP_FLT, li);
|
|
|
|
|
|
|
|
|
|
normalize_v3(co);
|
|
|
|
|
mul_v3_fl(co, elen);
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-17 22:59:54 +00:00
|
|
|
mul_v3_fl(co, fac);
|
|
|
|
|
add_v3_v3(co, l->v->co);
|
|
|
|
|
|
|
|
|
|
tag->newv = BM_Make_Vert(bm, co, l->v);
|
|
|
|
|
|
|
|
|
|
ETAG_SET(l->prev->e, l->v, tag->newv);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (BMO_TestFlag(bm, l->v, BEVEL_FLAG)) {
|
2011-05-13 10:49:26 +00:00
|
|
|
tag = tags + BM_GetIndex(l);
|
2011-03-17 22:59:54 +00:00
|
|
|
tag->newv = ETAG_GET(l->e, l->v);
|
|
|
|
|
|
|
|
|
|
if (!tag->newv) {
|
|
|
|
|
sub_v3_v3v3(co, l->next->v->co, l->v->co);
|
2011-04-16 13:00:41 +00:00
|
|
|
if (has_elens) {
|
|
|
|
|
float elen = *(float*)CustomData_bmesh_get_n(&bm->edata, l->e->head.data, CD_PROP_FLT, li);
|
|
|
|
|
|
|
|
|
|
normalize_v3(co);
|
|
|
|
|
mul_v3_fl(co, elen);
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-17 22:59:54 +00:00
|
|
|
mul_v3_fl(co, fac);
|
|
|
|
|
add_v3_v3(co, l->v->co);
|
|
|
|
|
|
2011-05-13 10:49:26 +00:00
|
|
|
tag = tags + BM_GetIndex(l);
|
2011-03-17 22:59:54 +00:00
|
|
|
tag->newv = BM_Make_Vert(bm, co, l->v);
|
|
|
|
|
|
|
|
|
|
ETAG_SET(l->e, l->v, tag->newv);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2011-05-13 10:49:26 +00:00
|
|
|
tag = tags + BM_GetIndex(l);
|
2011-03-17 22:59:54 +00:00
|
|
|
tag->newv = l->v;
|
|
|
|
|
BMO_ClearFlag(bm, l->v, BEVEL_DEL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-13 04:58:34 +00:00
|
|
|
/*create new faces inset from original faces*/
|
2011-03-17 22:59:54 +00:00
|
|
|
for (i=0; i<BLI_array_count(faces); i++) {
|
|
|
|
|
BMLoop *l;
|
|
|
|
|
BMIter liter;
|
|
|
|
|
BMFace *f;
|
2011-04-16 13:00:41 +00:00
|
|
|
BMVert *lastv=NULL, *firstv=NULL;
|
|
|
|
|
|
2011-03-17 22:59:54 +00:00
|
|
|
BMO_SetFlag(bm, faces[i], BEVEL_DEL);
|
|
|
|
|
|
|
|
|
|
BLI_array_empty(verts);
|
|
|
|
|
BLI_array_empty(edges);
|
|
|
|
|
|
|
|
|
|
BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, faces[i]) {
|
|
|
|
|
BMVert *v2;
|
|
|
|
|
|
2011-05-13 10:49:26 +00:00
|
|
|
tag = tags + BM_GetIndex(l);
|
2011-03-17 22:59:54 +00:00
|
|
|
BLI_array_append(verts, tag->newv);
|
|
|
|
|
|
2011-04-16 13:00:41 +00:00
|
|
|
if (!firstv)
|
|
|
|
|
firstv = tag->newv;
|
|
|
|
|
|
|
|
|
|
if (lastv) {
|
|
|
|
|
e = BM_Make_Edge(bm, lastv, tag->newv, l->e, 1);
|
|
|
|
|
BM_Copy_Attributes(bm, bm, l->prev->e, e);
|
|
|
|
|
BLI_array_append(edges, e);
|
|
|
|
|
}
|
|
|
|
|
lastv=tag->newv;
|
|
|
|
|
|
2011-10-13 04:58:34 +00:00
|
|
|
v2 = ETAG_GET(l->e, l->next->v);
|
2011-03-17 22:59:54 +00:00
|
|
|
|
2011-05-13 10:49:26 +00:00
|
|
|
tag = tags + BM_GetIndex(l->next);
|
2011-03-17 22:59:54 +00:00
|
|
|
if (!BMO_TestFlag(bm, l->e, BEVEL_FLAG) && v2 && v2 != tag->newv) {
|
|
|
|
|
BLI_array_append(verts, v2);
|
2011-04-15 07:08:36 +00:00
|
|
|
|
2011-04-16 13:00:41 +00:00
|
|
|
e = BM_Make_Edge(bm, lastv, v2, l->e, 1);
|
|
|
|
|
BM_Copy_Attributes(bm, bm, l->e, e);
|
|
|
|
|
|
2011-04-15 07:08:36 +00:00
|
|
|
BLI_array_append(edges, e);
|
2011-04-16 13:00:41 +00:00
|
|
|
lastv = v2;
|
2011-04-15 07:08:36 +00:00
|
|
|
}
|
2011-03-17 22:59:54 +00:00
|
|
|
}
|
|
|
|
|
|
2011-04-16 13:00:41 +00:00
|
|
|
e = BM_Make_Edge(bm, firstv, lastv, bm_firstfaceloop(faces[i])->e, 1);
|
2011-05-12 17:47:26 +00:00
|
|
|
if (bm_firstfaceloop(faces[i])->prev->e != e)
|
|
|
|
|
BM_Copy_Attributes(bm, bm, bm_firstfaceloop(faces[i])->prev->e, e);
|
2011-04-16 13:00:41 +00:00
|
|
|
BLI_array_append(edges, e);
|
|
|
|
|
|
2011-10-13 04:58:34 +00:00
|
|
|
f = BM_Make_Ngon(bm, verts[0], verts[1], edges, BLI_array_count(edges), 0);
|
2011-03-17 22:59:54 +00:00
|
|
|
if (!f) {
|
2011-11-24 23:09:55 +00:00
|
|
|
printf("%s: could not make face!\n", __func__);
|
2011-03-17 22:59:54 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BMO_SetFlag(bm, f, FACE_NEW);
|
2011-04-16 13:00:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i=0; i<BLI_array_count(faces); i++) {
|
|
|
|
|
BMLoop *l;
|
|
|
|
|
BMIter liter;
|
|
|
|
|
int j;
|
2011-03-17 22:59:54 +00:00
|
|
|
|
|
|
|
|
/*create quad spans between split edges*/
|
|
|
|
|
BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, faces[i]) {
|
|
|
|
|
BMVert *v1=NULL, *v2=NULL, *v3=NULL, *v4=NULL;
|
|
|
|
|
|
|
|
|
|
if (!BMO_TestFlag(bm, l->e, BEVEL_FLAG))
|
|
|
|
|
continue;
|
|
|
|
|
|
2011-05-13 10:49:26 +00:00
|
|
|
v1 = tags[BM_GetIndex(l)].newv;
|
|
|
|
|
v2 = tags[BM_GetIndex(l->next)].newv;
|
2011-03-17 22:59:54 +00:00
|
|
|
if (l->radial_next != l) {
|
2011-05-13 10:49:26 +00:00
|
|
|
v3 = tags[BM_GetIndex(l->radial_next)].newv;
|
2011-03-17 22:59:54 +00:00
|
|
|
if (l->radial_next->next->v == l->next->v) {
|
|
|
|
|
v4 = v3;
|
2011-05-13 10:49:26 +00:00
|
|
|
v3 = tags[BM_GetIndex(l->radial_next->next)].newv;
|
2011-03-17 22:59:54 +00:00
|
|
|
} else {
|
2011-05-13 10:49:26 +00:00
|
|
|
v4 = tags[BM_GetIndex(l->radial_next->next)].newv;
|
2011-03-17 22:59:54 +00:00
|
|
|
}
|
|
|
|
|
} else {
|
2011-10-13 04:58:34 +00:00
|
|
|
/*the loop is on a boundary*/
|
2011-03-17 22:59:54 +00:00
|
|
|
v3 = l->next->v;
|
|
|
|
|
v4 = l->v;
|
|
|
|
|
|
|
|
|
|
for (j=0; j<2; j++) {
|
|
|
|
|
BMIter eiter;
|
|
|
|
|
BMVert *v = j ? v4 : v3;
|
|
|
|
|
|
|
|
|
|
BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
|
|
|
|
|
if (!BM_Vert_In_Edge(e, v3) || !BM_Vert_In_Edge(e, v4))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (!BMO_TestFlag(bm, e, BEVEL_FLAG) && BMO_TestFlag(bm, e, EDGE_OLD)) {
|
|
|
|
|
BMVert *vv;
|
|
|
|
|
|
|
|
|
|
vv = ETAG_GET(e, v);
|
|
|
|
|
if (!vv || BMO_TestFlag(bm, vv, BEVEL_FLAG))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (j)
|
|
|
|
|
v1 = vv;
|
|
|
|
|
else
|
|
|
|
|
v2 = vv;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BMO_ClearFlag(bm, v3, BEVEL_DEL);
|
|
|
|
|
BMO_ClearFlag(bm, v4, BEVEL_DEL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (v1 != v2 && v2 != v3 && v3 != v4) {
|
|
|
|
|
BMIter liter2;
|
2011-04-16 13:00:41 +00:00
|
|
|
BMLoop *l2, *l3;
|
2011-05-13 13:17:30 +00:00
|
|
|
BMEdge *e1, *e2;
|
2011-04-16 13:00:41 +00:00
|
|
|
float d1, d2, *d3;
|
2011-03-17 22:59:54 +00:00
|
|
|
|
|
|
|
|
f = BM_Make_QuadTri(bm, v4, v3, v2, v1, l->f, 1);
|
2011-04-15 23:42:43 +00:00
|
|
|
|
|
|
|
|
e1 = BM_Edge_Exist(v4, v3);
|
|
|
|
|
e2 = BM_Edge_Exist(v2, v1);
|
|
|
|
|
BM_Copy_Attributes(bm, bm, l->e, e1);
|
|
|
|
|
BM_Copy_Attributes(bm, bm, l->e, e2);
|
2011-04-16 13:00:41 +00:00
|
|
|
|
|
|
|
|
/*set edge lengths of cross edges as the average of the cross edges they're based on*/
|
|
|
|
|
if (has_elens) {
|
2011-09-07 06:49:20 +00:00
|
|
|
#if 0 /* angle happens not to be used. why? - not sure it just isnt - campbell. leave this in incase we need to use it later */
|
2011-04-16 13:00:41 +00:00
|
|
|
float ang;
|
2011-09-07 06:49:20 +00:00
|
|
|
#endif
|
2011-04-16 13:00:41 +00:00
|
|
|
e1 = BM_Edge_Exist(v1, v4);
|
|
|
|
|
e2 = BM_Edge_Exist(v2, v3);
|
|
|
|
|
|
|
|
|
|
if (l->radial_next->v == l->v) {
|
|
|
|
|
l2 = l->radial_next->prev;
|
|
|
|
|
l3 = l->radial_next->next;
|
|
|
|
|
} else {
|
|
|
|
|
l2 = l->radial_next->next;
|
|
|
|
|
l3 = l->radial_next->prev;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
d3 = CustomData_bmesh_get_n(&bm->edata, e1->head.data, CD_PROP_FLT, li);
|
|
|
|
|
d1 = *(float*)CustomData_bmesh_get_n(&bm->edata, l->prev->e->head.data, CD_PROP_FLT, li);
|
|
|
|
|
d2 = *(float*)CustomData_bmesh_get_n(&bm->edata, l2->e->head.data, CD_PROP_FLT, li);
|
2011-09-07 06:49:20 +00:00
|
|
|
#if 0
|
2011-04-16 13:00:41 +00:00
|
|
|
ang = angle_v3v3v3(l->prev->v->co, l->v->co, BM_OtherEdgeVert(l2->e, l->v)->co);
|
2011-09-07 06:49:20 +00:00
|
|
|
#endif
|
2011-08-20 20:19:58 +00:00
|
|
|
*d3 = (d1+d2)*0.5f;
|
2011-04-16 13:00:41 +00:00
|
|
|
|
|
|
|
|
d3 = CustomData_bmesh_get_n(&bm->edata, e2->head.data, CD_PROP_FLT, li);
|
|
|
|
|
d1 = *(float*)CustomData_bmesh_get_n(&bm->edata, l->next->e->head.data, CD_PROP_FLT, li);
|
|
|
|
|
d2 = *(float*)CustomData_bmesh_get_n(&bm->edata, l3->e->head.data, CD_PROP_FLT, li);
|
2011-09-07 06:49:20 +00:00
|
|
|
#if 0
|
2011-04-16 13:00:41 +00:00
|
|
|
ang = angle_v3v3v3(BM_OtherEdgeVert(l->next->e, l->next->v)->co, l->next->v->co, BM_OtherEdgeVert(l3->e, l->next->v)->co);
|
2011-09-07 06:49:20 +00:00
|
|
|
#endif
|
2011-08-20 20:19:58 +00:00
|
|
|
*d3 = (d1+d2)*0.5f;
|
2011-04-16 13:00:41 +00:00
|
|
|
}
|
2011-04-15 23:42:43 +00:00
|
|
|
|
2011-03-17 22:59:54 +00:00
|
|
|
if (!f) {
|
2011-09-24 12:13:13 +00:00
|
|
|
fprintf(stderr, "%s: face index out of range! (bmesh internal error)\n", __func__);
|
2011-03-17 22:59:54 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BMO_SetFlag(bm, f, FACE_NEW|FACE_SPAN);
|
|
|
|
|
|
|
|
|
|
/*un-tag edges in f for deletion*/
|
|
|
|
|
BM_ITER(l2, &liter2, bm, BM_LOOPS_OF_FACE, f) {
|
|
|
|
|
BMO_ClearFlag(bm, l2->e, BEVEL_DEL);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
f = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*fill in holes at vertices*/
|
|
|
|
|
BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
|
|
|
|
|
BMIter eiter;
|
|
|
|
|
BMVert *vv, *vstart=NULL, *lastv=NULL;
|
|
|
|
|
SmallHash tmphash;
|
|
|
|
|
int rad, insorig=0, err=0;
|
2011-12-04 00:44:09 +00:00
|
|
|
|
2011-03-17 22:59:54 +00:00
|
|
|
BLI_smallhash_init(&tmphash);
|
2011-12-04 00:44:09 +00:00
|
|
|
|
2011-03-17 22:59:54 +00:00
|
|
|
if (!BMO_TestFlag(bm, v, BEVEL_FLAG))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
BLI_array_empty(verts);
|
|
|
|
|
BLI_array_empty(edges);
|
|
|
|
|
|
|
|
|
|
BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
|
|
|
|
|
BMIter liter;
|
|
|
|
|
BMVert *v1=NULL, *v2=NULL;
|
|
|
|
|
BMLoop *l;
|
|
|
|
|
|
|
|
|
|
if (BM_Edge_FaceCount(e) < 2)
|
|
|
|
|
insorig = 1;
|
|
|
|
|
|
2011-12-04 00:44:09 +00:00
|
|
|
if (BM_GetIndex(e) == -1)
|
|
|
|
|
continue;
|
|
|
|
|
|
2011-03-17 22:59:54 +00:00
|
|
|
rad = 0;
|
|
|
|
|
BM_ITER(l, &liter, bm, BM_LOOPS_OF_EDGE, e) {
|
|
|
|
|
if (!BMO_TestFlag(bm, l->f, FACE_OLD))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
rad++;
|
|
|
|
|
|
|
|
|
|
if (l->v == v)
|
2011-05-13 10:49:26 +00:00
|
|
|
tag = tags + BM_GetIndex(l);
|
2011-03-17 22:59:54 +00:00
|
|
|
else
|
2011-05-13 10:49:26 +00:00
|
|
|
tag = tags + BM_GetIndex(l->next);
|
2011-03-17 22:59:54 +00:00
|
|
|
|
|
|
|
|
if (!v1)
|
|
|
|
|
v1 = tag->newv;
|
2011-09-12 15:13:31 +00:00
|
|
|
else if (!v2)
|
2011-03-17 22:59:54 +00:00
|
|
|
v2 = tag->newv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rad < 2)
|
|
|
|
|
insorig = 1;
|
|
|
|
|
|
|
|
|
|
if (!v1)
|
|
|
|
|
v1 = ETAG_GET(e, v);
|
|
|
|
|
if (!v2 || v1 == v2)
|
|
|
|
|
v2 = ETAG_GET(e, v);
|
|
|
|
|
|
|
|
|
|
if (v1) {
|
|
|
|
|
if (!BLI_smallhash_haskey(&tmphash, (intptr_t)v1)) {
|
|
|
|
|
BLI_array_append(verts, v1);
|
|
|
|
|
BLI_smallhash_insert(&tmphash, (intptr_t)v1, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (v2 && v1 != v2 && !BLI_smallhash_haskey(&tmphash, (intptr_t)v2)) {
|
|
|
|
|
BLI_array_append(verts, v2);
|
|
|
|
|
BLI_smallhash_insert(&tmphash, (intptr_t)v2, NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!BLI_array_count(verts))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (insorig) {
|
|
|
|
|
BLI_array_append(verts, v);
|
|
|
|
|
BLI_smallhash_insert(&tmphash, (intptr_t)v, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*find edges that exist between vertices in verts. this is basically
|
2011-10-13 04:58:34 +00:00
|
|
|
a topological walk of the edges connecting them.*/
|
2011-03-17 22:59:54 +00:00
|
|
|
vstart = vstart ? vstart : verts[0];
|
|
|
|
|
vv = vstart;
|
|
|
|
|
do {
|
|
|
|
|
BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, vv) {
|
|
|
|
|
BMVert *vv2 = BM_OtherEdgeVert(e, vv);
|
|
|
|
|
|
|
|
|
|
if (vv2 != lastv && BLI_smallhash_haskey(&tmphash, (intptr_t)vv2)) {
|
|
|
|
|
/*if we've go over the same vert twice, break out of outer loop*/
|
|
|
|
|
if (BLI_smallhash_lookup(&tmphash, (intptr_t)vv2) != NULL) {
|
|
|
|
|
e = NULL;
|
|
|
|
|
err = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*use self pointer as tag*/
|
|
|
|
|
BLI_smallhash_remove(&tmphash, (intptr_t)vv2);
|
|
|
|
|
BLI_smallhash_insert(&tmphash, (intptr_t)vv2, vv2);
|
|
|
|
|
|
|
|
|
|
lastv = vv;
|
|
|
|
|
BLI_array_append(edges, e);
|
|
|
|
|
vv = vv2;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (e == NULL)
|
|
|
|
|
break;
|
|
|
|
|
} while (vv != vstart);
|
|
|
|
|
|
|
|
|
|
if (err)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/*there may not be a complete loop of edges, so start again and make
|
2011-10-13 04:58:34 +00:00
|
|
|
final edge afterwards. in this case, the previous loop worked to
|
|
|
|
|
find one of the two edges at the extremes.*/
|
2011-03-17 22:59:54 +00:00
|
|
|
if (vv != vstart) {
|
|
|
|
|
/*undo previous tagging*/
|
|
|
|
|
for (i=0; i<BLI_array_count(verts); i++) {
|
|
|
|
|
BLI_smallhash_remove(&tmphash, (intptr_t)verts[i]);
|
|
|
|
|
BLI_smallhash_insert(&tmphash, (intptr_t)verts[i], NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vstart = vv;
|
|
|
|
|
lastv = NULL;
|
|
|
|
|
BLI_array_empty(edges);
|
|
|
|
|
do {
|
|
|
|
|
BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, vv) {
|
|
|
|
|
BMVert *vv2 = BM_OtherEdgeVert(e, vv);
|
|
|
|
|
|
|
|
|
|
if (vv2 != lastv && BLI_smallhash_haskey(&tmphash, (intptr_t)vv2)) {
|
|
|
|
|
/*if we've go over the same vert twice, break out of outer loop*/
|
|
|
|
|
if (BLI_smallhash_lookup(&tmphash, (intptr_t)vv2) != NULL) {
|
|
|
|
|
e = NULL;
|
|
|
|
|
err = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*use self pointer as tag*/
|
|
|
|
|
BLI_smallhash_remove(&tmphash, (intptr_t)vv2);
|
|
|
|
|
BLI_smallhash_insert(&tmphash, (intptr_t)vv2, vv2);
|
|
|
|
|
|
|
|
|
|
lastv = vv;
|
|
|
|
|
BLI_array_append(edges, e);
|
|
|
|
|
vv = vv2;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (e == NULL)
|
|
|
|
|
break;
|
|
|
|
|
} while (vv != vstart);
|
|
|
|
|
|
|
|
|
|
if (!err) {
|
|
|
|
|
e = BM_Make_Edge(bm, vv, vstart, NULL, 1);
|
|
|
|
|
BLI_array_append(edges, e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (err)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (BLI_array_count(edges) >= 3) {
|
|
|
|
|
BMFace *f;
|
|
|
|
|
|
2011-04-13 03:56:14 +00:00
|
|
|
if (BM_Face_Exists(bm, verts, BLI_array_count(verts), &f))
|
|
|
|
|
continue;
|
|
|
|
|
|
2011-03-17 22:59:54 +00:00
|
|
|
f = BM_Make_Ngon(bm, lastv, vstart, edges, BLI_array_count(edges), 0);
|
|
|
|
|
if (!f) {
|
2011-09-24 12:13:13 +00:00
|
|
|
fprintf(stderr, "%s: in bevel vert fill! (bmesh internal error)\n", __func__);
|
|
|
|
|
} else {
|
2011-03-17 22:59:54 +00:00
|
|
|
BMO_SetFlag(bm, f, FACE_NEW|FACE_HOLE);
|
2011-09-24 12:13:13 +00:00
|
|
|
}
|
2011-03-17 22:59:54 +00:00
|
|
|
}
|
|
|
|
|
BLI_smallhash_release(&tmphash);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*copy over customdata*/
|
|
|
|
|
for (i=0; i<BLI_array_count(faces); i++) {
|
|
|
|
|
BMLoop *l;
|
|
|
|
|
BMIter liter;
|
|
|
|
|
BMFace *f = faces[i];
|
|
|
|
|
|
|
|
|
|
BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
|
|
|
|
|
BMLoop *l2;
|
|
|
|
|
BMIter liter2;
|
|
|
|
|
|
2011-05-13 10:49:26 +00:00
|
|
|
tag = tags + BM_GetIndex(l);
|
2011-03-17 22:59:54 +00:00
|
|
|
if (!tag->newv)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
BM_ITER(l2, &liter2, bm, BM_LOOPS_OF_VERT, tag->newv) {
|
|
|
|
|
if (!BMO_TestFlag(bm, l2->f, FACE_NEW) || (l2->v != tag->newv && l2->v != l->v))
|
|
|
|
|
continue;
|
|
|
|
|
|
2011-03-27 02:56:41 +00:00
|
|
|
if (tag->newv != l->v || HasMDisps) {
|
2011-03-17 22:59:54 +00:00
|
|
|
BM_Copy_Attributes(bm, bm, l->f, l2->f);
|
2011-04-13 21:48:16 +00:00
|
|
|
BM_loop_interp_from_face(bm, l2, l->f, 1, 1);
|
2011-03-17 22:59:54 +00:00
|
|
|
} else {
|
|
|
|
|
BM_Copy_Attributes(bm, bm, l->f, l2->f);
|
|
|
|
|
BM_Copy_Attributes(bm, bm, l, l2);
|
|
|
|
|
}
|
2011-03-27 02:56:41 +00:00
|
|
|
|
|
|
|
|
if (HasMDisps) {
|
|
|
|
|
BMLoop *l3;
|
|
|
|
|
BMIter liter3;
|
|
|
|
|
|
|
|
|
|
BM_ITER(l3, &liter3, bm, BM_LOOPS_OF_FACE, l2->f) {
|
|
|
|
|
BM_loop_interp_multires(bm, l3, l->f);
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-03-17 22:59:54 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*handle vertices along boundary edges*/
|
|
|
|
|
BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
|
|
|
|
|
if (BMO_TestFlag(bm, v, VERT_OLD) && BMO_TestFlag(bm, v, BEVEL_FLAG) && !BMO_TestFlag(bm, v, BEVEL_DEL)) {
|
|
|
|
|
BMLoop *l;
|
|
|
|
|
BMLoop *lorig=NULL;
|
|
|
|
|
BMIter liter;
|
|
|
|
|
|
|
|
|
|
BM_ITER(l, &liter, bm, BM_LOOPS_OF_VERT, v) {
|
2011-03-20 16:30:39 +00:00
|
|
|
// BMIter liter2;
|
|
|
|
|
// BMLoop *l2 = l->v == v ? l : l->next, *l3;
|
2011-03-17 22:59:54 +00:00
|
|
|
|
|
|
|
|
if (BMO_TestFlag(bm, l->f, FACE_OLD)) {
|
|
|
|
|
lorig = l;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!lorig)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
BM_ITER(l, &liter, bm, BM_LOOPS_OF_VERT, v) {
|
2011-03-27 02:56:41 +00:00
|
|
|
BMLoop *l2 = l->v == v ? l : l->next;
|
2011-03-17 22:59:54 +00:00
|
|
|
|
|
|
|
|
BM_Copy_Attributes(bm, bm, lorig->f, l2->f);
|
|
|
|
|
BM_Copy_Attributes(bm, bm, lorig, l2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-04-15 07:08:36 +00:00
|
|
|
#if 0
|
2011-10-13 04:58:34 +00:00
|
|
|
/*clean up any remaining 2-edged faces*/
|
2011-04-15 07:08:36 +00:00
|
|
|
BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
|
|
|
|
|
if (f->len == 2) {
|
|
|
|
|
BMFace *faces[2] = {f, bm_firstfaceloop(f)->radial_next->f};
|
|
|
|
|
|
|
|
|
|
if (faces[0] == faces[1])
|
|
|
|
|
BM_Kill_Face(bm, f);
|
|
|
|
|
else
|
|
|
|
|
BM_Join_Faces(bm, faces, 2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2011-03-17 22:59:54 +00:00
|
|
|
BMO_CallOpf(bm, "del geom=%fv context=%i", BEVEL_DEL, DEL_VERTS);
|
|
|
|
|
|
|
|
|
|
/*clean up any edges that might not get properly deleted*/
|
|
|
|
|
BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
|
|
|
|
|
if (BMO_TestFlag(bm, e, EDGE_OLD) && !e->l)
|
|
|
|
|
BMO_SetFlag(bm, e, BEVEL_DEL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BMO_CallOpf(bm, "del geom=%fe context=%i", BEVEL_DEL, DEL_EDGES);
|
|
|
|
|
BMO_CallOpf(bm, "del geom=%ff context=%i", BEVEL_DEL, DEL_FACES);
|
|
|
|
|
|
|
|
|
|
BLI_smallhash_release(&hash);
|
|
|
|
|
BLI_array_free(tags);
|
|
|
|
|
BLI_array_free(etags);
|
|
|
|
|
BLI_array_free(verts);
|
|
|
|
|
BLI_array_free(edges);
|
|
|
|
|
BLI_array_free(faces);
|
|
|
|
|
|
|
|
|
|
BMO_Flag_To_Slot(bm, op, "face_spans", FACE_SPAN, BM_FACE);
|
|
|
|
|
BMO_Flag_To_Slot(bm, op, "face_holes", FACE_HOLE, BM_FACE);
|
|
|
|
|
}
|