fix for own error in edge-rotate keeping edge customdata - this was crashing when rotating multiple edges.

Now create the rotate edge in advance and copy its customdata (before joining the faces).

This commit also fixes an annoyance where tryangulating faces could create duplicate edges.
This commit is contained in:
2012-03-06 19:29:05 +00:00
parent 31d2ee9bf7
commit d1937de1d2
13 changed files with 65 additions and 75 deletions

View File

@@ -860,8 +860,6 @@ static int disk_is_flagged(BMVert *v, int flag)
* Joins a collected group of faces into one. Only restriction on
* the input data is that the faces must be connected to each other.
*
* \param do_clear Remove the edges and verts shared by faces when joining.
*
* \return The newly created combine BMFace.
*
* \note If a pair of faces share multiple edges,
@@ -870,8 +868,7 @@ static int disk_is_flagged(BMVert *v, int flag)
* \note this is a generic, flexible join faces function,
* almost everything uses this, including #BM_faces_join_pair
*/
BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface,
const short do_del)
BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface)
{
BMFace *f, *newf;
#ifdef USE_BMESH_HOLES
@@ -1025,7 +1022,6 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface,
}
/* delete old geometr */
if (do_del) {
for (i = 0; i < BLI_array_count(deledges); i++) {
BM_edge_kill(bm, deledges[i]);
}
@@ -1033,7 +1029,6 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface,
for (i = 0; i < BLI_array_count(delverts); i++) {
BM_vert_kill(bm, delverts[i]);
}
}
BLI_array_free(edges);
BLI_array_free(deledges);
@@ -1114,7 +1109,8 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2,
#ifdef USE_BMESH_HOLES
ListBase *holes,
#endif
BMEdge *example
BMEdge *example,
const short nodouble
)
{
#ifdef USE_BMESH_HOLES
@@ -1139,7 +1135,7 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2,
}
/* allocate new edge between v1 and v2 */
e = BM_edge_create(bm, v1, v2, example, FALSE);
e = BM_edge_create(bm, v1, v2, example, nodouble);
f2 = bm_face_create__sfme(bm, f);
f1loop = bm_loop_create(bm, v2, e, f, v2loop);

View File

@@ -44,8 +44,7 @@ int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *etarget);
int bmesh_loop_reverse(BMesh *bm, BMFace *f);
BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface,
const short do_del);
BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface);
/* EULER API - For modifying structure */
BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1,
@@ -53,7 +52,8 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1,
#ifdef USE_BMESH_HOLES
ListBase *holes,
#endif
BMEdge *example
BMEdge *example,
const short nodouble
);
BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e);

View File

@@ -133,7 +133,7 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v)
* increasing valence to four. this may be hackish. . */
BMLoop *loop = e->l;
if (loop->v == v) loop = loop->next;
if (!BM_face_split(bm, loop->f, v, loop->v, NULL, NULL))
if (!BM_face_split(bm, loop->f, v, loop->v, NULL, NULL, FALSE))
return FALSE;
if (!BM_disk_dissolve(bm, v)) {
@@ -153,7 +153,7 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v)
f = e->l->f;
f2 = e->l->radial_next->f;
if (f != f2 && !BM_faces_join_pair(bm, f, f2, e, TRUE)) {
if (f != f2 && !BM_faces_join_pair(bm, f, f2, e)) {
return FALSE;
}
@@ -170,7 +170,7 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v)
f = NULL;
len = bmesh_radial_length(e->l);
if (len == 2 && (e != baseedge) && (e != keepedge)) {
f = BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, TRUE);
f = BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e);
/* return if couldn't join faces in manifold
* conditions */
//!disabled for testing why bad things happen
@@ -200,7 +200,7 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v)
if (f != f2) {
/* join two remaining face */
if (!BM_faces_join_pair(bm, f, f2, e, TRUE)) {
if (!BM_faces_join_pair(bm, f, f2, e)) {
return FALSE;
}
}
@@ -224,8 +224,7 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v)
*
* \return pointer to the combined face
*/
BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e,
const short do_del)
BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
{
BMLoop *l1, *l2;
BMEdge *jed = NULL;
@@ -261,7 +260,7 @@ BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e,
bmesh_loop_reverse(bm, f2);
}
f1 = BM_faces_join(bm, faces, 2, do_del);
f1 = BM_faces_join(bm, faces, 2);
return f1;
}
@@ -292,7 +291,7 @@ BMEdge *BM_verts_connect(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **r_f)
if (v_iter == v2) {
BMLoop *nl;
f_iter = BM_face_split(bm, f_iter, v1, v2, &nl, NULL);
f_iter = BM_face_split(bm, f_iter, v1, v2, &nl, NULL, FALSE);
if (r_f) {
*r_f = f_iter;
@@ -319,12 +318,14 @@ BMEdge *BM_verts_connect(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **r_f)
* \param v1, v2 vertices which define the split edge, must be different
* \param r_l pointer which will receive the BMLoop for the split edge in the new face
* \param example Edge used for attributes of splitting edge, if non-NULL
* \param nodouble Use an existing edge if found
*
* \return Pointer to the newly created face representing one side of the split
* if the split is successful (and the original original face will be the
* other side). NULL if the split fails.
*/
BMFace *BM_face_split(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **r_l, BMEdge *example)
BMFace *BM_face_split(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **r_l,
BMEdge *example, const short nodouble)
{
const int has_mdisp = CustomData_has_layer(&bm->ldata, CD_MDISPS);
BMFace *nf, *of;
@@ -337,9 +338,9 @@ BMFace *BM_face_split(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **r_l
}
#ifdef USE_BMESH_HOLES
nf = bmesh_sfme(bm, f, v1, v2, r_l, NULL, example);
nf = bmesh_sfme(bm, f, v1, v2, r_l, NULL, example, nodouble);
#else
nf = bmesh_sfme(bm, f, v1, v2, r_l, example);
nf = bmesh_sfme(bm, f, v1, v2, r_l, example, nodouble);
#endif
if (nf) {
@@ -408,9 +409,9 @@ BMFace *BM_face_split_n(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, float cos[
r_l = &l_dummy;
#ifdef USE_BMESH_HOLES
nf = bmesh_sfme(bm, f, v1, v2, r_l, NULL, example);
nf = bmesh_sfme(bm, f, v1, v2, r_l, NULL, example, FALSE);
#else
nf = bmesh_sfme(bm, f, v1, v2, r_l, example);
nf = bmesh_sfme(bm, f, v1, v2, r_l, example, FALSE);
#endif
/* bmesh_sfme returns in r_l a Loop for nf going from v1 to v2.
* The radial_next is for f and goes from v2 to v1 */
@@ -522,10 +523,10 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac,
}
if (BLI_array_count(faces) >= 2) {
BMFace *f2 = BM_faces_join(bm, faces, BLI_array_count(faces), TRUE);
BMFace *f2 = BM_faces_join(bm, faces, BLI_array_count(faces));
if (f2) {
BMLoop *nl = NULL;
if (BM_face_split(bm, f2, tv, tv2, &nl, NULL)) {
if (BM_face_split(bm, f2, tv, tv2, &nl, NULL, FALSE)) {
ne = nl->e;
}
}
@@ -995,9 +996,9 @@ int BM_edge_rotate_check_beauty(BMesh *UNUSED(bm), BMEdge *e,
BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const short ccw, const short check_flag)
{
BMVert *v1, *v2;
BMLoop *l1, *l2, *nl;
BMLoop *l1, *l2;
BMFace *f;
BMEdge *e_splice = NULL;
BMEdge *e_new = NULL;
if (!BM_edge_rotate_check(bm, e)) {
return NULL;
@@ -1021,10 +1022,7 @@ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const short ccw, const short check_
}
/* check before applying */
if (check_flag & BM_EDGEROT_CHECK_SPLICE) {
e_splice = BM_edge_exists(v1, v2);
}
else if (check_flag & BM_EDGEROT_CHECK_EXISTS) {
if (check_flag & BM_EDGEROT_CHECK_EXISTS) {
if (BM_edge_exists(v1, v2)) {
return NULL;
}
@@ -1044,8 +1042,12 @@ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const short ccw, const short check_
/* --------------- */
/* Rotate The Edge */
/* first create the new edge, this is so we can copy the customdata from the old one
* if splice if disabled, always add in a new edge even if theres one there. */
e_new = BM_edge_create(bm, v1, v2, e, (check_flag & BM_EDGEROT_CHECK_SPLICE)!=0);
/* don't delete the edge, manually remove the egde after so we can copy its attributes */
f = BM_faces_join_pair(bm, l1->f, l2->f, e, FALSE);
f = BM_faces_join_pair(bm, l1->f, l2->f, NULL);
if (f == NULL) {
return NULL;
@@ -1054,19 +1056,11 @@ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const short ccw, const short check_
/* note, this assumes joining the faces _didnt_ also remove the verts.
* the #BM_edge_rotate_check will ensure this, but its possibly corrupt state or future edits
* break this */
if (!BM_face_split(bm, f, v1, v2, &nl, e))
if (!BM_face_split(bm, f, v1, v2, NULL, NULL, TRUE)) {
return NULL;
/* edge has done its job as an example, now remove */
BM_edge_kill(bm, e);
/* replace existing edge (kill e_splice) */
if (e_splice) {
BM_edge_splice(bm, e_splice, nl->e);
}
return nl->e;
return e_new;
}
/**

View File

@@ -33,14 +33,14 @@ int BM_vert_dissolve(BMesh *bm, BMVert *v);
int BM_disk_dissolve(BMesh *bm, BMVert *v);
BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e,
const short do_del);
BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e);
BMEdge *BM_verts_connect(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **r_f);
BMFace *BM_face_split(BMesh *bm, BMFace *f,
BMVert *v1, BMVert *v2,
BMLoop **r_l, BMEdge *example);
BMLoop **r_l,
BMEdge *example, const short nodouble);
BMFace *BM_face_split_n(BMesh *bm, BMFace *f,
BMVert *v1, BMVert *v2,

View File

@@ -835,7 +835,7 @@ void BM_face_triangulate(BMesh *bm, BMFace *f, float (*projectverts)[3],
/* v = l->v; */ /* UNUSED */
f = BM_face_split(bm, l_iter->f, l_iter->prev->v,
l_iter->next->v,
&newl, NULL);
&newl, NULL, TRUE);
if (UNLIKELY(!f)) {
fprintf(stderr, "%s: triangulator failed to split face! (bmesh internal error)\n", __func__);
@@ -867,7 +867,7 @@ void BM_face_triangulate(BMesh *bm, BMFace *f, float (*projectverts)[3],
while (l_iter->f->len > 3) {
nextloop = l_iter->next->next;
f = BM_face_split(bm, l_iter->f, l_iter->v, nextloop->v,
&newl, NULL);
&newl, NULL, TRUE);
if (!f) {
printf("triangle fan step of triangulator failed.\n");

View File

@@ -103,7 +103,7 @@ void bmo_connectverts_exec(BMesh *bm, BMOperator *op)
}
for (i = 0; i < BLI_array_count(verts) / 2; i++) {
nf = BM_face_split(bm, f, verts[i * 2], verts[i * 2 + 1], &nl, NULL);
nf = BM_face_split(bm, f, verts[i * 2], verts[i * 2 + 1], &nl, NULL, FALSE);
f = nf;
if (!nl || !nf) {

View File

@@ -144,7 +144,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
while (faces[tot])
tot++;
f = BM_faces_join(bm, faces, tot, TRUE);
f = BM_faces_join(bm, faces, tot);
if (!f) {
BMO_error_raise(bm, op, BMERR_DISSOLVEFACES_FAILED,
"Could not create merged face");
@@ -207,7 +207,7 @@ void bmo_dissolve_edgeloop_exec(BMesh *bm, BMOperator *op)
BMO_elem_flag_enable(bm, e->v1, VERT_MARK);
BMO_elem_flag_enable(bm, e->v2, VERT_MARK);
BM_faces_join_pair(bm, fa, fb, e, TRUE);
BM_faces_join_pair(bm, fa, fb, e);
}
}
@@ -260,7 +260,7 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
if (BM_edge_face_pair(e, &fa, &fb)) {
/* join faces */
BM_faces_join_pair(bm, fa, fb, e, TRUE);
BM_faces_join_pair(bm, fa, fb, e);
}
}
@@ -515,7 +515,7 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op)
if (BM_edge_face_angle(bm, e) < angle_limit) {
BMFace *nf = BM_faces_join_pair(bm, e->l->f,
e->l->radial_next->f,
e, TRUE); /* join faces */
e); /* join faces */
/* there may be some errors, we dont mind, just move on */
if (nf == NULL) {

View File

@@ -331,7 +331,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
BM_edge_face_pair(e, &f1, &f2); /* checked above */
BM_faces_join_pair(bm, f1, f2, e, TRUE);
BM_faces_join_pair(bm, f1, f2, e);
}
BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
@@ -363,7 +363,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
continue;
}
BM_faces_join_pair(bm, f1, f2, e, TRUE);
BM_faces_join_pair(bm, f1, f2, e);
}
}

View File

@@ -55,7 +55,7 @@ static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op)
if (split && doub != v2) {
BMLoop *nl;
BMFace *f2 = BM_face_split(bm, f, doub, v2, &nl, NULL);
BMFace *f2 = BM_face_split(bm, f, doub, v2, &nl, NULL, FALSE);
remdoubles_splitface(f, bm, op);
remdoubles_splitface(f2, bm, op);

View File

@@ -85,7 +85,7 @@ static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v1, BMVert *v2, BMFace *
}
if (curf) {
face = BM_face_split(bm, curf, v1, v2, &nl, NULL);
face = BM_face_split(bm, curf, v1, v2, &nl, NULL, FALSE);
if (r_nf) *r_nf = face;
return nl ? nl->e : NULL;
@@ -954,7 +954,7 @@ void bmo_esubd_exec(BMesh *bmesh, BMOperator *op)
for (j = 0; j < BLI_array_count(splits) / 2; j++) {
if (splits[j * 2]) {
/* BMFace *nf = */ /* UNUSED */
BM_face_split(bmesh, face, splits[j * 2]->v, splits[j * 2 + 1]->v, &nl, NULL);
BM_face_split(bmesh, face, splits[j * 2]->v, splits[j * 2 + 1]->v, &nl, NULL, FALSE);
}
}

View File

@@ -544,14 +544,14 @@ static BMLoop *BME_bevel_edge(BMesh *bm, BMLoop *l, float value, int UNUSED(opti
se = l->next->e;
jf = NULL;
if (kl->v == kv) {
BM_face_split(bm, kl->f, kl->prev->v, kl->next->v, &nl, kl->prev->e);
BM_face_split(bm, kl->f, kl->prev->v, kl->next->v, &nl, kl->prev->e, FALSE);
ke = kl->e;
/* BMESH-TODO: jfke doesn't handle customdata */
jf = bmesh_jfke(bm, kl->prev->radial_next->f, kl->f, kl->prev->e);
BM_vert_collapse_edge(bm, ke, kv, FALSE);
}
else {
BM_face_split(bm, kl->f, kl->next->next->v, kl->v, &nl, kl->next->e);
BM_face_split(bm, kl->f, kl->next->next->v, kl->v, &nl, kl->next->e, FALSE);
ke = kl->e;
/* BMESH-TODO: jfke doesn't handle customdata */
jf = bmesh_jfke(bm, kl->next->radial_next->f, kl->f, kl->next->e);
@@ -590,14 +590,14 @@ static BMLoop *BME_bevel_edge(BMesh *bm, BMLoop *l, float value, int UNUSED(opti
se = l->e;
jf = NULL;
if (kl->v == kv) {
BM_face_split(bm, kl->f, kl->prev->v, kl->next->v, &nl, kl->prev->e);
BM_face_split(bm, kl->f, kl->prev->v, kl->next->v, &nl, kl->prev->e, FALSE);
ke = kl->e;
/* BMESH-TODO: jfke doesn't handle customdata */
jf = bmesh_jfke(bm, kl->prev->radial_next->f, kl->f, kl->prev->e);
BM_vert_collapse_edge(bm, ke, kv, FALSE);
}
else {
BM_face_split(bm, kl->f, kl->next->next->v, kl->v, &nl, kl->next->e);
BM_face_split(bm, kl->f, kl->next->next->v, kl->v, &nl, kl->next->e, FALSE);
ke = kl->e;
/* BMESH-TODO: jfke doesn't handle customdata */
jf = bmesh_jfke(bm, kl->next->radial_next->f, kl->f, kl->next->e);
@@ -612,7 +612,7 @@ static BMLoop *BME_bevel_edge(BMesh *bm, BMLoop *l, float value, int UNUSED(opti
}
if (!BMO_elem_flag_test(bm, v1, BME_BEVEL_NONMAN) || !BMO_elem_flag_test(bm, v2, BME_BEVEL_NONMAN)) {
BM_face_split(bm, f, v2, v1, &l, e);
BM_face_split(bm, f, v2, v1, &l, e, FALSE);
BMO_elem_flag_enable(bm, l->e, BME_BEVEL_BEVEL);
l = l->radial_next;
}
@@ -640,7 +640,7 @@ static BMLoop *BME_bevel_vert(BMesh *bm, BMLoop *l, float value, int UNUSED(opti
l = l->next->next;
/* "cut off" this corner */
f = BM_face_split(bm, l->f, v2, v1, NULL, l->e);
f = BM_face_split(bm, l->f, v2, v1, NULL, l->e, FALSE);
return l;
}
@@ -965,7 +965,7 @@ static BMesh *BME_bevel_mesh(BMesh *bm, float value, int UNUSED(res), int option
/* get rid of beveled edge */
BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
if(BMO_elem_flag_test(bm, e, BME_BEVEL_BEVEL) && BMO_elem_flag_test(bm, e, BME_BEVEL_ORIG)) {
BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, TRUE);
BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e);
}
}
@@ -979,9 +979,9 @@ static BMesh *BME_bevel_mesh(BMesh *bm, float value, int UNUSED(res), int option
if(l->v != v) l = l->next;
if(l2->v != v) l2 = l2->next;
if(l->f->len > 3)
BM_face_split(bm, l->f, l->next->v, l->prev->v, &l, l->e); /* clip this corner off */
BM_face_split(bm, l->f, l->next->v, l->prev->v, &l, l->e, FALSE); /* clip this corner off */
if(l2->f->len > 3)
BM_face_split(bm, l2->f, l2->next->v, l2->prev->v, &l, l2->e); /* clip this corner off */
BM_face_split(bm, l2->f, l2->next->v, l2->prev->v, &l, l2->e, FALSE); /* clip this corner off */
curedge = bmesh_disk_edge_next(curedge, v);
} while(curedge != v->e);
BME_Bevel_Dissolve_Disk(bm, v);

View File

@@ -1680,7 +1680,7 @@ static void remerge_faces(knifetool_opdata *kcd)
if (BLI_array_count(faces) > 0) {
idx = BM_elem_index_get(faces[0]);
f2 = BM_faces_join(bm, faces, BLI_array_count(faces), TRUE);
f2 = BM_faces_join(bm, faces, BLI_array_count(faces));
if (f2) {
BMO_elem_flag_enable(bm, f2, FACE_NEW);
BM_elem_index_set(f2, idx); /* set_dirty! */ /* BMESH_TODO, check if this is valid or not */

View File

@@ -363,7 +363,7 @@ static PyObject *bpy_bm_utils_face_split(PyObject *UNUSED(self), PyObject *args)
f_new = BM_face_split(bm, py_face->f,
py_vert_a->v, py_vert_b->v,
&l_new, py_edge_example ? py_edge_example->e : NULL);
&l_new, py_edge_example ? py_edge_example->e : NULL, FALSE); /* BMESH_TODO, make arg */
if (f_new && l_new) {
PyObject *ret = PyTuple_New(2);
@@ -406,7 +406,7 @@ static PyObject *bpy_bm_utils_face_join(PyObject *UNUSED(self), PyObject *value)
/* Go ahead and join the face!
* --------------------------- */
f_new = BM_faces_join(bm, face_array, (int)face_seq_len, TRUE); /* BMESH_TODO, make optional */
f_new = BM_faces_join(bm, face_array, (int)face_seq_len);
if (f_new) {
return BPy_BMFace_CreatePyObject(bm, f_new);