fix for problem with edge slide where it would stop shapekey modifier from being applied (because of added vertices),

now, instead of making hidden copies of faces, the faces are copied into a temp bmesh.

also remove a hash that was being created and not used (old code).
This commit is contained in:
Campbell Barton
2013-07-11 04:24:36 +00:00
parent b36999b2f7
commit 7fec23ae0a
8 changed files with 78 additions and 119 deletions

View File

@@ -890,6 +890,24 @@ static BMFace *bm_mesh_copy_new_face(BMesh *bm_new, BMesh *bm_old,
return f_new;
}
void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const BMAllocTemplate *allocsize)
{
if (allocsize == NULL) {
allocsize = &bm_mesh_allocsize_default;
}
CustomData_copy(&bm_src->vdata, &bm_dst->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
CustomData_copy(&bm_src->edata, &bm_dst->edata, CD_MASK_BMESH, CD_CALLOC, 0);
CustomData_copy(&bm_src->ldata, &bm_dst->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
CustomData_copy(&bm_src->pdata, &bm_dst->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
CustomData_bmesh_init_pool(&bm_dst->vdata, allocsize->totvert, BM_VERT);
CustomData_bmesh_init_pool(&bm_dst->edata, allocsize->totedge, BM_EDGE);
CustomData_bmesh_init_pool(&bm_dst->ldata, allocsize->totloop, BM_LOOP);
CustomData_bmesh_init_pool(&bm_dst->pdata, allocsize->totface, BM_FACE);
}
BMesh *BM_mesh_copy(BMesh *bm_old)
{
BMesh *bm_new;
@@ -908,15 +926,7 @@ BMesh *BM_mesh_copy(BMesh *bm_old)
/* allocate a bmesh */
bm_new = BM_mesh_create(&allocsize);
CustomData_copy(&bm_old->vdata, &bm_new->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
CustomData_copy(&bm_old->edata, &bm_new->edata, CD_MASK_BMESH, CD_CALLOC, 0);
CustomData_copy(&bm_old->ldata, &bm_new->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
CustomData_copy(&bm_old->pdata, &bm_new->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
CustomData_bmesh_init_pool(&bm_new->vdata, allocsize.totvert, BM_VERT);
CustomData_bmesh_init_pool(&bm_new->edata, allocsize.totedge, BM_EDGE);
CustomData_bmesh_init_pool(&bm_new->ldata, allocsize.totloop, BM_LOOP);
CustomData_bmesh_init_pool(&bm_new->pdata, allocsize.totface, BM_FACE);
BM_mesh_copy_init_customdata(bm_new, bm_old, &allocsize);
vtable = MEM_mallocN(sizeof(BMVert *) * bm_old->totvert, "BM_mesh_copy vtable");
etable = MEM_mallocN(sizeof(BMEdge *) * bm_old->totedge, "BM_mesh_copy etable");

View File

@@ -27,6 +27,8 @@
* \ingroup bmesh
*/
struct BMAllocTemplate;
BMFace *BM_face_create_quad_tri_v(BMesh *bm,
BMVert **verts, int len,
const BMFace *example, const bool no_double);
@@ -50,6 +52,7 @@ void BMO_remove_tagged_context(BMesh *bm, const short oflag, const int type);
void BM_elem_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, const void *source, void *target);
void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const struct BMAllocTemplate *allocsize);
BMesh *BM_mesh_copy(BMesh *bm_old);
char BM_face_flag_from_mflag(const char mflag);

View File

@@ -210,7 +210,7 @@ static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge
return l;
}
BMFace *BM_face_copy(BMesh *bm, BMFace *f,
BMFace *BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f,
const bool copy_verts, const bool copy_edges)
{
BMVert **verts = BLI_array_alloca(verts, f->len);
@@ -221,11 +221,13 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f,
BMFace *f_copy;
int i;
BLI_assert((bm_dst == bm_src) || (copy_verts && copy_edges));
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
i = 0;
do {
if (copy_verts) {
verts[i] = BM_vert_create(bm, l_iter->v->co, l_iter->v, 0);
verts[i] = BM_vert_create(bm_dst, l_iter->v->co, l_iter->v, 0);
}
else {
verts[i] = l_iter->v;
@@ -248,7 +250,7 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f,
v1 = verts[(i + 1) % f->len];
}
edges[i] = BM_edge_create(bm, v1, v2, l_iter->e, 0);
edges[i] = BM_edge_create(bm_dst, v1, v2, l_iter->e, 0);
}
else {
edges[i] = l_iter->e;
@@ -256,14 +258,14 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f,
i++;
} while ((l_iter = l_iter->next) != l_first);
f_copy = BM_face_create(bm, verts, edges, f->len, BM_CREATE_SKIP_CD);
f_copy = BM_face_create(bm_dst, verts, edges, f->len, BM_CREATE_SKIP_CD);
BM_elem_attrs_copy(bm, bm, f, f_copy);
BM_elem_attrs_copy(bm_src, bm_dst, f, f_copy);
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
l_copy = BM_FACE_FIRST_LOOP(f_copy);
do {
BM_elem_attrs_copy(bm, bm, l_iter, l_copy);
BM_elem_attrs_copy(bm_src, bm_dst, l_iter, l_copy);
l_copy = l_copy->next;
} while ((l_iter = l_iter->next) != l_first);

View File

@@ -27,7 +27,7 @@
* \ingroup bmesh
*/
BMFace *BM_face_copy(BMesh *bm, BMFace *f,
BMFace *BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f,
const bool copy_verts, const bool copy_edges);
typedef enum eBMCreateFlag {

View File

@@ -345,7 +345,7 @@ BMFace *BM_face_split(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **r_l
/* do we have a multires layer? */
if (has_mdisp) {
f_tmp = BM_face_copy(bm, f, false, false);
f_tmp = BM_face_copy(bm, bm, f, false, false);
}
#ifdef USE_BMESH_HOLES
@@ -414,7 +414,7 @@ BMFace *BM_face_split_n(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, float cos[
BLI_assert(v1 != v2);
f_tmp = BM_face_copy(bm, f, true, true);
f_tmp = BM_face_copy(bm, bm, f, true, true);
if (!r_l)
r_l = &l_dummy;
@@ -662,7 +662,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float perce
/* flag existing faces so we can differentiate oldfaces from new faces */
for (i = 0; i < BLI_array_count(oldfaces); i++) {
BM_ELEM_API_FLAG_ENABLE(oldfaces[i], _FLAG_OVERLAP);
oldfaces[i] = BM_face_copy(bm, oldfaces[i], true, true);
oldfaces[i] = BM_face_copy(bm, bm, oldfaces[i], true, true);
BM_ELEM_API_FLAG_DISABLE(oldfaces[i], _FLAG_OVERLAP);
}
}

View File

@@ -59,7 +59,6 @@
#include "BLI_string.h"
#include "BLI_ghash.h"
#include "BLI_linklist.h"
#include "BLI_smallhash.h"
#include "BKE_nla.h"
#include "BKE_bmesh.h"
@@ -4995,8 +4994,7 @@ static bool createEdgeSlideVerts(TransInfo *t)
TransDataEdgeSlideVert *sv_array;
int sv_tot;
BMBVHTree *btree;
/* BMVert -> sv_array index */
SmallHash table;
int *sv_table; /* BMVert -> sv_array index */
EdgeSlideData *sld = MEM_callocN(sizeof(*sld), "sld");
View3D *v3d = NULL;
RegionView3D *rv3d = NULL;
@@ -5036,14 +5034,7 @@ static bool createEdgeSlideVerts(TransInfo *t)
else {
ED_view3d_ob_project_mat_get(rv3d, t->obedit, projectMat);
}
BLI_smallhash_init(&sld->vhash);
BLI_smallhash_init(&table);
if (sld->use_origfaces) {
BLI_smallhash_init(&sld->origfaces);
}
/*ensure valid selection*/
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
@@ -5077,20 +5068,26 @@ static bool createEdgeSlideVerts(TransInfo *t)
}
}
sv_table = MEM_mallocN(sizeof(*sv_table) * bm->totvert, __func__);
j = 0;
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
BM_elem_flag_enable(v, BM_ELEM_TAG);
BLI_smallhash_insert(&table, (uintptr_t)v, SET_INT_IN_POINTER(j));
sv_table[i] = j;
j += 1;
}
else {
BM_elem_flag_disable(v, BM_ELEM_TAG);
sv_table[i] = -1;
}
BM_elem_index_set(v, i); /* set_inline */
}
bm->elem_index_dirty &= ~BM_VERT;
if (!j) {
MEM_freeN(sld);
MEM_freeN(sv_table);
return false;
}
@@ -5187,9 +5184,9 @@ static bool createEdgeSlideVerts(TransInfo *t)
BMEdge *e_prev;
/* XXX, 'sv' will initialize multiple times, this is suspicious. see [#34024] */
BLI_assert(BLI_smallhash_haskey(&table, (uintptr_t)v) != false);
BLI_assert(v != NULL);
sv = sv_array + GET_INT_FROM_POINTER(BLI_smallhash_lookup(&table, (uintptr_t)v));
BLI_assert(sv_table[BM_elem_index_get(v)] != -1);
sv = &sv_array[sv_table[BM_elem_index_get(v)]];
sv->v = v;
copy_v3_v3(sv->v_co_orig, v->co);
sv->loop_nr = loop_nr;
@@ -5213,9 +5210,9 @@ static bool createEdgeSlideVerts(TransInfo *t)
e = get_other_edge(v, e);
if (!e) {
BLI_assert(BLI_smallhash_haskey(&table, (uintptr_t)v) != false);
BLI_assert(v != NULL);
sv = sv_array + GET_INT_FROM_POINTER(BLI_smallhash_lookup(&table, (uintptr_t)v));
BLI_assert(sv_table[BM_elem_index_get(v)] != -1);
sv = &sv_array[sv_table[BM_elem_index_get(v)]];
sv->v = v;
copy_v3_v3(sv->v_co_orig, v->co);
sv->loop_nr = loop_nr;
@@ -5282,7 +5279,6 @@ static bool createEdgeSlideVerts(TransInfo *t)
loop_nr++;
}
/* use for visibility checks */
use_btree_disp = (v3d && t->obedit->dt > OB_WIRE && v3d->drawtype > OB_WIRE);
@@ -5330,8 +5326,8 @@ static bool createEdgeSlideVerts(TransInfo *t)
continue;
}
BLI_assert(BLI_smallhash_haskey(&table, (uintptr_t)v) != false);
j = GET_INT_FROM_POINTER(BLI_smallhash_lookup(&table, (uintptr_t)v));
BLI_assert(sv_table[BM_elem_index_get(v)] != -1);
j = sv_table[BM_elem_index_get(v)];
if (sv_array[j].v_b) {
ED_view3d_project_float_v3_m4(ar, sv_array[j].v_b->co, sco_b, projectMat);
@@ -5378,36 +5374,29 @@ static bool createEdgeSlideVerts(TransInfo *t)
bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
if (sld->use_origfaces) {
sld->origfaces = BLI_ghash_ptr_new(__func__);
sld->bm_origfaces = BM_mesh_create(&bm_mesh_allocsize_default);
/* we need to have matching customdata */
BM_mesh_copy_init_customdata(sld->bm_origfaces, bm, NULL);
}
/*create copies of faces for customdata projection*/
sv_array = sld->sv;
for (i = 0; i < sld->totsv; i++, sv_array++) {
BMIter fiter, liter;
BMIter fiter;
BMFace *f;
BMLoop *l;
if (sld->use_origfaces) {
BM_ITER_ELEM (f, &fiter, sv_array->v, BM_FACES_OF_VERT) {
if (!BLI_smallhash_haskey(&sld->origfaces, (uintptr_t)f)) {
BMFace *copyf = BM_face_copy(bm, f, true, true);
BM_face_select_set(bm, copyf, false);
BM_elem_flag_enable(copyf, BM_ELEM_HIDDEN);
BM_ITER_ELEM (l, &liter, copyf, BM_LOOPS_OF_FACE) {
BM_vert_select_set(bm, l->v, false);
BM_elem_flag_enable(l->v, BM_ELEM_HIDDEN);
BM_edge_select_set(bm, l->e, false);
BM_elem_flag_enable(l->e, BM_ELEM_HIDDEN);
}
BLI_smallhash_insert(&sld->origfaces, (uintptr_t)f, copyf);
if (!BLI_ghash_haskey(sld->origfaces, f)) {
BMFace *f_copy = BM_face_copy(sld->bm_origfaces, bm, f, true, true);
BLI_ghash_insert(sld->origfaces, f, f_copy);
}
}
}
BLI_smallhash_insert(&sld->vhash, (uintptr_t)sv_array->v, sv_array);
/* switch a/b if loop direction is different from global direction */
l_nr = sv_array->loop_nr;
if (dot_v3v3(loop_dir[l_nr], mval_dir) < 0.0f) {
@@ -5419,9 +5408,8 @@ static bool createEdgeSlideVerts(TransInfo *t)
if (rv3d)
calcNonProportionalEdgeSlide(t, sld, mval);
sld->origfaces_init = true;
sld->em = em;
/*zero out start*/
zero_v2(mval_start);
@@ -5439,18 +5427,13 @@ static bool createEdgeSlideVerts(TransInfo *t)
t->customData = sld;
BLI_smallhash_release(&table);
MEM_freeN(sv_table);
if (btree) {
BKE_bmbvh_free(btree);
}
MEM_freeN(loop_dir);
MEM_freeN(loop_maxdist);
if (sld->use_origfaces) {
/* arrays are dirty from copying faces: EDBM_index_arrays_free */
EDBM_update_generic(em, false, true);
}
return true;
}
@@ -5472,15 +5455,8 @@ void projectEdgeSlideData(TransInfo *t, bool is_final)
BM_ITER_ELEM (l, &fiter, sv->v, BM_LOOPS_OF_VERT) {
BMFace *f_copy; /* the copy of 'f' */
BMFace *f_copy_flip; /* the copy of 'f' or detect if we need to flip to the shorter side. */
bool is_sel, is_hide;
/* the face attributes of the copied face will get
* copied over, so its necessary to save the selection
* and hidden state*/
is_sel = BM_elem_flag_test(l->f, BM_ELEM_SELECT) != 0;
is_hide = BM_elem_flag_test(l->f, BM_ELEM_HIDDEN) != 0;
f_copy = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)l->f);
f_copy = BLI_ghash_lookup(sld->origfaces, l->f);
/* project onto copied projection face */
f_copy_flip = f_copy;
@@ -5494,12 +5470,12 @@ void projectEdgeSlideData(TransInfo *t, bool is_final)
if (sld->perc < 0.0f) {
if (BM_vert_in_face(l_ed_sel->radial_next->f, sv->v_b)) {
f_copy_flip = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)l_ed_sel->radial_next->f);
f_copy_flip = BLI_ghash_lookup(sld->origfaces, l_ed_sel->radial_next->f);
}
}
else if (sld->perc > 0.0f) {
if (BM_vert_in_face(l_ed_sel->radial_next->f, sv->v_a)) {
f_copy_flip = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)l_ed_sel->radial_next->f);
f_copy_flip = BLI_ghash_lookup(sld->origfaces, l_ed_sel->radial_next->f);
}
}
@@ -5585,7 +5561,7 @@ void projectEdgeSlideData(TransInfo *t, bool is_final)
l_adj = l;
}
f_copy_flip = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)l_adj->f);
f_copy_flip = BLI_ghash_lookup(sld->origfaces, l_adj->f);
}
}
}
@@ -5602,37 +5578,24 @@ void projectEdgeSlideData(TransInfo *t, bool is_final)
}
/* make sure face-attributes are correct (e.g. MTexPoly) */
BM_elem_attrs_copy(em->bm, em->bm, f_copy, l->f);
/* restore selection and hidden flags */
BM_face_select_set(em->bm, l->f, is_sel);
if (!is_hide) {
/* this check is a workaround for bug, see note - [#30735],
* without this edge can be hidden and selected */
BM_elem_hide_set(em->bm, l->f, is_hide);
}
BM_elem_attrs_copy(sld->bm_origfaces, em->bm, f_copy, l->f);
}
}
}
void freeEdgeSlideTempFaces(EdgeSlideData *sld)
{
if (sld->origfaces_init && sld->use_origfaces) {
SmallHashIter hiter;
BMFace *copyf;
copyf = BLI_smallhash_iternew(&sld->origfaces, &hiter, NULL);
for (; copyf; copyf = BLI_smallhash_iternext(&hiter, NULL)) {
BM_face_verts_kill(sld->em->bm, copyf);
if (sld->use_origfaces) {
if (sld->bm_origfaces) {
BM_mesh_free(sld->bm_origfaces);
sld->bm_origfaces = NULL;
}
BLI_smallhash_release(&sld->origfaces);
/* arrays are dirty from removing faces: EDBM_index_arrays_free */
EDBM_update_generic(sld->em, FALSE, TRUE);
if (sld->origfaces) {
BLI_ghash_free(sld->origfaces, NULL, NULL);
sld->origfaces = NULL;
}
}
sld->origfaces_init = false;
}
@@ -5640,30 +5603,12 @@ void freeEdgeSlideVerts(TransInfo *t)
{
EdgeSlideData *sld = t->customData;
#if 0 /*BMESH_TODO*/
if (me->drawflag & ME_DRAWEXTRA_EDGELEN) {
TransDataEdgeSlideVert *sv;
LinkNode *look = sld->vertlist;
GHash *vertgh = sld->vhash;
while (look) {
sv = BLI_ghash_lookup(vertgh, (EditVert *)look->link);
if (sv != NULL) {
sv->v_a->f &= !SELECT;
sv->v_b->f &= !SELECT;
}
look = look->next;
}
}
#endif
if (!sld)
return;
freeEdgeSlideTempFaces(sld);
bmesh_edit_end(sld->em->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
BLI_smallhash_release(&sld->vhash);
MEM_freeN(sld->sv);
MEM_freeN(sld);

View File

@@ -201,15 +201,14 @@ typedef struct EdgeSlideData {
TransDataEdgeSlideVert *sv;
int totsv;
struct SmallHash vhash;
struct SmallHash origfaces;
struct GHash *origfaces;
int mval_start[2], mval_end[2];
struct BMEditMesh *em;
/* flag that is set when origfaces is initialized */
bool use_origfaces;
bool origfaces_init;
struct BMesh *bm_origfaces;
float perc;

View File

@@ -1616,7 +1616,7 @@ static PyObject *bpy_bmface_copy(BPy_BMFace *self, PyObject *args, PyObject *kw)
return NULL;
}
f_cpy = BM_face_copy(bm, self->f, do_verts, do_edges);
f_cpy = BM_face_copy(bm, bm, self->f, do_verts, do_edges);
if (f_cpy) {
return BPy_BMFace_CreatePyObject(bm, f_cpy);