fix/workaround [#33281] script goes into not responding
scanfill remove-doubles pass assumes ordered edges (as with curves), otherwise it can hang. workaround this problem by skipping removing-doubles for mesh ngons, since this isnt such a common case as it is with curves and we can just not support it.
This commit is contained in:
parent
ceed3ef640
commit
f9e339ef00
|
@ -487,7 +487,7 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, int flipnormal)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX (obedit && obedit->actcol)?(obedit->actcol-1):0)) { */
|
/* XXX (obedit && obedit->actcol)?(obedit->actcol-1):0)) { */
|
||||||
if (totvert && (tot = BLI_scanfill_calc(&sf_ctx, FALSE))) {
|
if (totvert && (tot = BLI_scanfill_calc(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES))) {
|
||||||
if (tot) {
|
if (tot) {
|
||||||
dlnew = MEM_callocN(sizeof(DispList), "filldisplist");
|
dlnew = MEM_callocN(sizeof(DispList), "filldisplist");
|
||||||
dlnew->type = DL_INDEX3;
|
dlnew->type = DL_INDEX3;
|
||||||
|
|
|
@ -215,7 +215,7 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *tm)
|
||||||
/* complete the loop */
|
/* complete the loop */
|
||||||
BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
|
BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
|
||||||
|
|
||||||
totfilltri = BLI_scanfill_calc_ex(&sf_ctx, FALSE, efa->no);
|
totfilltri = BLI_scanfill_calc_ex(&sf_ctx, 0, efa->no);
|
||||||
BLI_array_grow_items(looptris, totfilltri);
|
BLI_array_grow_items(looptris, totfilltri);
|
||||||
|
|
||||||
for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
|
for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
|
||||||
|
|
|
@ -933,7 +933,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
|
||||||
}
|
}
|
||||||
|
|
||||||
/* main scan-fill */
|
/* main scan-fill */
|
||||||
sf_tri_tot = BLI_scanfill_calc_ex(&sf_ctx, FALSE, zvec);
|
sf_tri_tot = BLI_scanfill_calc_ex(&sf_ctx, 0, zvec);
|
||||||
|
|
||||||
face_array = MEM_mallocN(sizeof(*face_array) * (sf_tri_tot + tot_feather_quads), "maskrast_face_index");
|
face_array = MEM_mallocN(sizeof(*face_array) * (sf_tri_tot + tot_feather_quads), "maskrast_face_index");
|
||||||
face_index = 0;
|
face_index = 0;
|
||||||
|
|
|
@ -2607,7 +2607,7 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
|
||||||
}
|
}
|
||||||
BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert_first);
|
BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert_first);
|
||||||
|
|
||||||
totfilltri = BLI_scanfill_calc(&sf_ctx, FALSE);
|
totfilltri = BLI_scanfill_calc(&sf_ctx, 0);
|
||||||
if (totfilltri) {
|
if (totfilltri) {
|
||||||
BLI_array_grow_items(mface_to_poly_map, totfilltri);
|
BLI_array_grow_items(mface_to_poly_map, totfilltri);
|
||||||
BLI_array_grow_items(mface, totfilltri);
|
BLI_array_grow_items(mface, totfilltri);
|
||||||
|
|
|
@ -94,9 +94,18 @@ typedef struct ScanFillFace {
|
||||||
struct ScanFillVert *BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3]);
|
struct ScanFillVert *BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3]);
|
||||||
struct ScanFillEdge *BLI_scanfill_edge_add(ScanFillContext *sf_ctx, struct ScanFillVert *v1, struct ScanFillVert *v2);
|
struct ScanFillEdge *BLI_scanfill_edge_add(ScanFillContext *sf_ctx, struct ScanFillVert *v1, struct ScanFillVert *v2);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
BLI_SCANFILL_CALC_QUADTRI_FASTPATH = (1 << 0),
|
||||||
|
|
||||||
|
/* note: using BLI_SCANFILL_CALC_REMOVE_DOUBLES
|
||||||
|
* Assumes ordered edges, otherwise we risk an eternal loop
|
||||||
|
* removing double verts. - campbell */
|
||||||
|
BLI_SCANFILL_CALC_REMOVE_DOUBLES = (1 << 1),
|
||||||
|
};
|
||||||
|
|
||||||
int BLI_scanfill_begin(ScanFillContext *sf_ctx);
|
int BLI_scanfill_begin(ScanFillContext *sf_ctx);
|
||||||
int BLI_scanfill_calc(ScanFillContext *sf_ctx, const short do_quad_tri_speedup);
|
int BLI_scanfill_calc(ScanFillContext *sf_ctx, const int flag);
|
||||||
int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const short do_quad_tri_speedup,
|
int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag,
|
||||||
const float nor_proj[3]);
|
const float nor_proj[3]);
|
||||||
void BLI_scanfill_end(ScanFillContext *sf_ctx);
|
void BLI_scanfill_end(ScanFillContext *sf_ctx);
|
||||||
|
|
||||||
|
|
|
@ -503,8 +503,7 @@ static void splitlist(ScanFillContext *sf_ctx, ListBase *tempve, ListBase *tempe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
|
||||||
static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf)
|
|
||||||
{
|
{
|
||||||
ScanFillVertLink *sc = NULL, *sc1;
|
ScanFillVertLink *sc = NULL, *sc1;
|
||||||
ScanFillVert *eve, *v1, *v2, *v3;
|
ScanFillVert *eve, *v1, *v2, *v3;
|
||||||
|
@ -530,26 +529,28 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* STEP 0: remove zero sized edges */
|
/* STEP 0: remove zero sized edges */
|
||||||
eed = sf_ctx->filledgebase.first;
|
if (flag & BLI_SCANFILL_CALC_REMOVE_DOUBLES) {
|
||||||
while (eed) {
|
eed = sf_ctx->filledgebase.first;
|
||||||
if (equals_v2v2(eed->v1->xy, eed->v2->xy)) {
|
while (eed) {
|
||||||
if (eed->v1->f == SF_VERT_ZERO_LEN && eed->v2->f != SF_VERT_ZERO_LEN) {
|
if (equals_v2v2(eed->v1->xy, eed->v2->xy)) {
|
||||||
eed->v2->f = SF_VERT_ZERO_LEN;
|
if (eed->v1->f == SF_VERT_ZERO_LEN && eed->v2->f != SF_VERT_ZERO_LEN) {
|
||||||
eed->v2->tmp.v = eed->v1->tmp.v;
|
eed->v2->f = SF_VERT_ZERO_LEN;
|
||||||
}
|
eed->v2->tmp.v = eed->v1->tmp.v;
|
||||||
else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f != SF_VERT_ZERO_LEN) {
|
}
|
||||||
eed->v1->f = SF_VERT_ZERO_LEN;
|
else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f != SF_VERT_ZERO_LEN) {
|
||||||
eed->v1->tmp.v = eed->v2->tmp.v;
|
eed->v1->f = SF_VERT_ZERO_LEN;
|
||||||
}
|
eed->v1->tmp.v = eed->v2->tmp.v;
|
||||||
else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f == SF_VERT_ZERO_LEN) {
|
}
|
||||||
eed->v1->tmp.v = eed->v2->tmp.v;
|
else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f == SF_VERT_ZERO_LEN) {
|
||||||
}
|
eed->v1->tmp.v = eed->v2->tmp.v;
|
||||||
else {
|
}
|
||||||
eed->v2->f = SF_VERT_ZERO_LEN;
|
else {
|
||||||
eed->v2->tmp.v = eed->v1;
|
eed->v2->f = SF_VERT_ZERO_LEN;
|
||||||
|
eed->v2->tmp.v = eed->v1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
eed = eed->next;
|
||||||
}
|
}
|
||||||
eed = eed->next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* STEP 1: make using FillVert and FillEdge lists a sorted
|
/* STEP 1: make using FillVert and FillEdge lists a sorted
|
||||||
|
@ -572,28 +573,42 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf)
|
||||||
|
|
||||||
qsort(sf_ctx->_scdata, verts, sizeof(ScanFillVertLink), vergscdata);
|
qsort(sf_ctx->_scdata, verts, sizeof(ScanFillVertLink), vergscdata);
|
||||||
|
|
||||||
eed = sf_ctx->filledgebase.first;
|
if (flag & BLI_SCANFILL_CALC_REMOVE_DOUBLES) {
|
||||||
while (eed) {
|
for (eed = sf_ctx->filledgebase.first; eed; eed = nexted) {
|
||||||
nexted = eed->next;
|
nexted = eed->next;
|
||||||
BLI_remlink(&sf_ctx->filledgebase, eed);
|
BLI_remlink(&sf_ctx->filledgebase, eed);
|
||||||
/* This code is for handling zero-length edges that get
|
/* This code is for handling zero-length edges that get
|
||||||
* collapsed in step 0. It was removed for some time to
|
* collapsed in step 0. It was removed for some time to
|
||||||
* fix trunk bug #4544, so if that comes back, this code
|
* fix trunk bug #4544, so if that comes back, this code
|
||||||
* may need some work, or there will have to be a better
|
* may need some work, or there will have to be a better
|
||||||
* fix to #4544. */
|
* fix to #4544.
|
||||||
if (eed->v1->f == SF_VERT_ZERO_LEN) {
|
*
|
||||||
v1 = eed->v1;
|
* warning, this can hang on un-ordered edges, see: [#33281]
|
||||||
while ((eed->v1->f == SF_VERT_ZERO_LEN) && (eed->v1->tmp.v != v1) && (eed->v1 != eed->v1->tmp.v))
|
* for now disable 'BLI_SCANFILL_CALC_REMOVE_DOUBLES' for ngons.
|
||||||
eed->v1 = eed->v1->tmp.v;
|
*/
|
||||||
|
if (eed->v1->f == SF_VERT_ZERO_LEN) {
|
||||||
|
v1 = eed->v1;
|
||||||
|
while ((eed->v1->f == SF_VERT_ZERO_LEN) && (eed->v1->tmp.v != v1) && (eed->v1 != eed->v1->tmp.v))
|
||||||
|
eed->v1 = eed->v1->tmp.v;
|
||||||
|
}
|
||||||
|
if (eed->v2->f == SF_VERT_ZERO_LEN) {
|
||||||
|
v2 = eed->v2;
|
||||||
|
while ((eed->v2->f == SF_VERT_ZERO_LEN) && (eed->v2->tmp.v != v2) && (eed->v2 != eed->v2->tmp.v))
|
||||||
|
eed->v2 = eed->v2->tmp.v;
|
||||||
|
}
|
||||||
|
if (eed->v1 != eed->v2) {
|
||||||
|
addedgetoscanlist(sf_ctx, eed, verts);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (eed->v2->f == SF_VERT_ZERO_LEN) {
|
}
|
||||||
v2 = eed->v2;
|
else {
|
||||||
while ((eed->v2->f == SF_VERT_ZERO_LEN) && (eed->v2->tmp.v != v2) && (eed->v2 != eed->v2->tmp.v))
|
for (eed = sf_ctx->filledgebase.first; eed; eed = nexted) {
|
||||||
eed->v2 = eed->v2->tmp.v;
|
nexted = eed->next;
|
||||||
|
BLI_remlink(&sf_ctx->filledgebase, eed);
|
||||||
|
if (eed->v1 != eed->v2) {
|
||||||
|
addedgetoscanlist(sf_ctx, eed, verts);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (eed->v1 != eed->v2) addedgetoscanlist(sf_ctx, eed, verts);
|
|
||||||
|
|
||||||
eed = nexted;
|
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
sc = scdata;
|
sc = scdata;
|
||||||
|
@ -775,12 +790,12 @@ int BLI_scanfill_begin(ScanFillContext *sf_ctx)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int BLI_scanfill_calc(ScanFillContext *sf_ctx, const short do_quad_tri_speedup)
|
int BLI_scanfill_calc(ScanFillContext *sf_ctx, const int flag)
|
||||||
{
|
{
|
||||||
return BLI_scanfill_calc_ex(sf_ctx, do_quad_tri_speedup, NULL);
|
return BLI_scanfill_calc_ex(sf_ctx, flag, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const short do_quad_tri_speedup, const float nor_proj[3])
|
int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float nor_proj[3])
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* - fill works with its own lists, so create that first (no faces!)
|
* - fill works with its own lists, so create that first (no faces!)
|
||||||
|
@ -810,30 +825,32 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const short do_quad_tri_speedu
|
||||||
a += 1;
|
a += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_quad_tri_speedup && (a == 3)) {
|
if (flag & BLI_SCANFILL_CALC_QUADTRI_FASTPATH) {
|
||||||
eve = sf_ctx->fillvertbase.first;
|
if (a == 3) {
|
||||||
|
eve = sf_ctx->fillvertbase.first;
|
||||||
|
|
||||||
addfillface(sf_ctx, eve, eve->next, eve->next->next);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (do_quad_tri_speedup && (a == 4)) {
|
|
||||||
float vec1[3], vec2[3];
|
|
||||||
|
|
||||||
eve = sf_ctx->fillvertbase.first;
|
|
||||||
/* no need to check 'eve->next->next->next' is valid, already counted */
|
|
||||||
/* use shortest diagonal for quad */
|
|
||||||
sub_v3_v3v3(vec1, eve->co, eve->next->next->co);
|
|
||||||
sub_v3_v3v3(vec2, eve->next->co, eve->next->next->next->co);
|
|
||||||
|
|
||||||
if (dot_v3v3(vec1, vec1) < dot_v3v3(vec2, vec2)) {
|
|
||||||
addfillface(sf_ctx, eve, eve->next, eve->next->next);
|
addfillface(sf_ctx, eve, eve->next, eve->next->next);
|
||||||
addfillface(sf_ctx, eve->next->next, eve->next->next->next, eve);
|
return 1;
|
||||||
}
|
}
|
||||||
else {
|
else if (a == 4) {
|
||||||
addfillface(sf_ctx, eve->next, eve->next->next, eve->next->next->next);
|
float vec1[3], vec2[3];
|
||||||
addfillface(sf_ctx, eve->next->next->next, eve, eve->next);
|
|
||||||
|
eve = sf_ctx->fillvertbase.first;
|
||||||
|
/* no need to check 'eve->next->next->next' is valid, already counted */
|
||||||
|
/* use shortest diagonal for quad */
|
||||||
|
sub_v3_v3v3(vec1, eve->co, eve->next->next->co);
|
||||||
|
sub_v3_v3v3(vec2, eve->next->co, eve->next->next->next->co);
|
||||||
|
|
||||||
|
if (dot_v3v3(vec1, vec1) < dot_v3v3(vec2, vec2)) {
|
||||||
|
addfillface(sf_ctx, eve, eve->next, eve->next->next);
|
||||||
|
addfillface(sf_ctx, eve->next->next, eve->next->next->next, eve);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addfillface(sf_ctx, eve->next, eve->next->next, eve->next->next->next);
|
||||||
|
addfillface(sf_ctx, eve->next->next->next, eve, eve->next);
|
||||||
|
}
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
return 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* first test vertices if they are in edges */
|
/* first test vertices if they are in edges */
|
||||||
|
@ -1091,7 +1108,7 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const short do_quad_tri_speedu
|
||||||
for (a = 0; a < poly; a++) {
|
for (a = 0; a < poly; a++) {
|
||||||
if (pf->edges > 1) {
|
if (pf->edges > 1) {
|
||||||
splitlist(sf_ctx, &tempve, &temped, pf->nr);
|
splitlist(sf_ctx, &tempve, &temped, pf->nr);
|
||||||
totfaces += scanfill(sf_ctx, pf);
|
totfaces += scanfill(sf_ctx, pf, flag);
|
||||||
}
|
}
|
||||||
pf++;
|
pf++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,7 +190,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
|
||||||
/* sf_edge->tmp.p = e; */ /* UNUSED */
|
/* sf_edge->tmp.p = e; */ /* UNUSED */
|
||||||
}
|
}
|
||||||
|
|
||||||
BLI_scanfill_calc(&sf_ctx, FALSE);
|
BLI_scanfill_calc(&sf_ctx, 0);
|
||||||
|
|
||||||
for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
|
for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
|
||||||
BMFace *f = BM_face_create_quad_tri(bm,
|
BMFace *f = BM_face_create_quad_tri(bm,
|
||||||
|
|
|
@ -306,7 +306,7 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh
|
||||||
|
|
||||||
BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
|
BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
|
||||||
|
|
||||||
BLI_scanfill_calc_ex(&sf_ctx, TRUE, efa->no);
|
BLI_scanfill_calc_ex(&sf_ctx, 0, efa->no);
|
||||||
for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
|
for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
|
||||||
int i;
|
int i;
|
||||||
ls[0] = sf_tri->v1->tmp.p;
|
ls[0] = sf_tri->v1->tmp.p;
|
||||||
|
|
|
@ -255,7 +255,7 @@ static void draw_filled_lasso(wmGesture *gt)
|
||||||
if (sf_vert_first) {
|
if (sf_vert_first) {
|
||||||
const float zvec[3] = {0.0f, 0.0f, 1.0f};
|
const float zvec[3] = {0.0f, 0.0f, 1.0f};
|
||||||
BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
|
BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
|
||||||
BLI_scanfill_calc_ex(&sf_ctx, FALSE, zvec);
|
BLI_scanfill_calc_ex(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES, zvec);
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glColor4f(1.0, 1.0, 1.0, 0.05);
|
glColor4f(1.0, 1.0, 1.0, 0.05);
|
||||||
|
|
Loading…
Reference in New Issue