split dissolve_disk into dissolve_vert dissolve_disk as agreed. also made dissolve vert bmop use the error api, and put in some code to report it to the user in the xkey ui code. I'm not sure how this should work; I don't think we can have utility code in bmesh/ for reporting errors to the user, so it'll have to go in editors/mesh somewhere.

This commit is contained in:
Joseph Eagar 2009-03-01 06:23:22 +00:00
parent e65eca86ac
commit 8be2a86ce1
8 changed files with 111 additions and 52 deletions

@ -195,7 +195,12 @@ void BM_Collapse_Vert(struct BMesh *bm, struct BMEdge *ke, struct BMVert *kv, fl
struct BMVert *BM_Split_Edge(struct BMesh *bm, struct BMVert *v, struct BMEdge *e, struct BMEdge **ne, float percent, int calcnorm);
struct BMVert *BM_Split_Edge_Multi(struct BMesh *bm, struct BMEdge *e, int numcuts);
BMEdge *BM_Connect_Verts(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf);
void BM_Dissolve_Disk(BMesh *bm, BMVert *v);
/*dissolves vert surrounded by faces*/
int BM_Dissolve_Disk(BMesh *bm, BMVert *v);
/*dissolves vert, in more situations then BM_Dissolve_Disk.*/
int BM_Dissolve_Vert(BMesh *bm, BMVert *v);
/*Interpolation*/
void BM_Data_Interp_From_Verts(struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMVert *v, float fac);

@ -40,19 +40,45 @@
*
*/
#if 1
void BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
BMFace *f, *f2;
BMEdge *e, *keepedge=NULL, *baseedge=NULL;
BMLoop *loop;
int done, len;
int BM_Dissolve_Vert(BMesh *bm, BMVert *v) {
BMIter iter;
BMEdge *e;
int len=0;
if (!v) return 0;
e = BMIter_New(&iter, bm, BM_EDGES_OF_VERT, v);
for (; e; e=BMIter_Step(&iter)) {
len++;
}
if (len == 1) {
bmesh_ke(bm, v->edge);
bmesh_kv(bm, v);
return 1;
}
if(BM_Nonmanifold_Vert(bm, v)) {
if (!v->edge) bmesh_kv(bm, v);
else if (!v->edge->loop) {
bmesh_ke(bm, v->edge);
bmesh_kv(bm, v);
}
return;
} else return 0;
return 1;
}
return BM_Dissolve_Disk(bm, v);
}
int BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
BMFace *f, *f2;
BMEdge *e, *keepedge=NULL, *baseedge=NULL;
BMLoop *loop;
int done, len;
if(BM_Nonmanifold_Vert(bm, v)) {
return 0;
}
if(v->edge){
@ -88,9 +114,6 @@ void BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
/*collapse the vertex*/
BM_Collapse_Vert(bm, v->edge, v, 1.0, 0);
BM_Join_Faces(bm, f, f2, NULL, 0, 0);
} else if (len == 1) {
bmesh_ke(bm, v->edge);
bmesh_kv(bm, v);
}
if(keepedge){
@ -106,7 +129,7 @@ void BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
/*return if couldn't join faces in manifold
conditions.*/
//!disabled for testing why bad things happen
if (!f) return;
if (!f) return 0;
}
if(f){
@ -126,6 +149,8 @@ void BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
/*join two remaining faces*/
BM_Join_Faces(bm, f, f2, NULL, 0, 0);
}
return 1;
}
#else
void BM_Dissolve_Disk(BMesh *bm, BMVert *v){

@ -800,6 +800,7 @@ void BMO_RaiseError(BMesh *bm, BMOperator *owner, int errcode, char *msg)
bmop_error *err = MEM_callocN(sizeof(bmop_error), "bmop_error");
err->errorcode = errcode;
if (!msg) msg = bmop_error_messages[errcode];
err->msg = msg;
err->op = owner;
@ -825,7 +826,7 @@ int BMO_PopError(BMesh *bm, char **msg, BMOperator **op)
if (errorcode) {
bmop_error *err = bm->errorstack.first;
BLI_remlink(&bm->errorstack, &bm->errorstack.first);
BLI_remlink(&bm->errorstack, bm->errorstack.first);
MEM_freeN(err);
}

@ -339,11 +339,10 @@ int linecrosses(float *v1, float *v2, float *v3, float *v4)
return w1 == w2 && w2 == w3 && w3 == w4 && w4==w5;
}
int goodline(float (*projectverts)[3], int v1i, int v2i, int nvert)
int goodline(float (*projectverts)[3], int v1i, int v2i, int nvert, float *outv)
{
/*the hardcoded stuff here, 200000, 0.999, and 1.0001 may be problems
/*the hardcoded stuff here, 0.999 and 1.0001, may be problems
in the future, not sure. - joeedh*/
static float outv[3] = {2000.0f, 2000.0f, 0.0f};
float v1[3], v2[3], p[3], vv1[3], vv2[3], mid[3], a[3], b[3];
int i = 0, lcount=0;
@ -398,7 +397,7 @@ int goodline(float (*projectverts)[3], int v1i, int v2i, int nvert)
*
*/
static BMLoop *find_ear(BMFace *f, float (*verts)[3], int nvert)
static BMLoop *find_ear(BMFace *f, float (*verts)[3], int nvert, float *outv)
{
BMVert *v1, *v2, *v3;
BMLoop *bestear = NULL, *l;
@ -415,12 +414,13 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], int nvert)
if (BM_Edge_Exist(v1, v3)) isear = 0;
if (isear && !goodline(verts, v1->head.eflag2, v3->head.eflag2, nvert)) isear = 0;
if (isear && !goodline(verts, v1->head.eflag2, v3->head.eflag2,
nvert, outv)) isear = 0;
if(isear){
angle = VecAngle3(verts[v1->head.eflag2], verts[v2->head.eflag2], verts[v3->head.eflag2]);
if(!bestear || ABS(angle-40.0) < bestangle){
if(!bestear || ABS(angle-40.0f) < bestangle){
bestear = l;
bestangle = ABS(40.0-angle);
bestangle = ABS(40.0f-angle);
}
}
l = (BMLoop*)(l->head.next);
@ -450,6 +450,7 @@ void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3], int new
{
int i, done, nvert;
BMLoop *l, *newl, *nextloop;
float outv[3] = {-1.0e30f, -1.0e30f, -1.0e30f};
/*copy vertex coordinates to vertspace array*/
i = 0;
@ -458,9 +459,15 @@ void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3], int new
VECCOPY(projectverts[i], l->v->co);
l->v->head.eflag2 = i; /*warning, abuse! never duplicate in tools code! never you hear?*/ /*actually, get rid of this completely, use a new structure for this....*/
i++;
outv[0] = MAX2(outv[0], l->v->co[0])+1.0f;
outv[1] = MAX2(outv[1], l->v->co[1])+1.0f;
outv[2] = MAX2(outv[2], l->v->co[2])+1.0f;
l = (BMLoop*)(l->head.next);
}while(l != f->loopbase);
//bmesh_update_face_normal(bm, f, projectverts);
compute_poly_normal(f->no, projectverts, f->len);
@ -472,7 +479,7 @@ void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3], int new
done = 0;
while(!done && f->len > 3){
done = 1;
l = find_ear(f, projectverts, nvert);
l = find_ear(f, projectverts, nvert, outv);
if(l) {
done = 0;
f = bmesh_sfme(bm, f, ((BMLoop*)(l->head.prev))->v, ((BMLoop*)(l->head.next))->v, &newl);

@ -259,8 +259,23 @@ static void fuse_fgon(BMesh *bm, BMFace *f)
static BM_fgonconvert(BMesh *bm, EditMesh *em, int numCol, int numTex)
{
EditFace *efa;
BMFace *f;
BMIter iter;
struct fgonsort *sortblock, *sb, *sb1;
int a, b, amount=0;
/*
for (efa=em->faces.first; efa; efa=efa->next) {
f = editface_to_BMFace(bm, em, efa, numCol, numTex);
}
for (f=bm->polys.first; f; f=f->head.next) {
fuse_fgon(bm, f);
}
return;*/
EM_fgon_flags(em);
/*zero out efa->tmp, we store fgon index here*/
for(efa = em->faces.first; efa; efa = efa->next){

@ -85,7 +85,11 @@ void dissolveverts_exec(BMesh *bm, BMOperator *op)
len = 0;
for (v=BMIter_New(&iter, bm, BM_VERTS, NULL); v; v=BMIter_Step(&iter)) {
if (BMO_TestFlag(bm, v, VERT_MARK)) {
BM_Dissolve_Disk(bm, v);
if (!BM_Dissolve_Vert(bm, v)) {
BMO_RaiseError(bm, op,
BMERR_DISSOLVEDISK_FAILED, NULL);
return;
}
found = 1;
len++;
}

@ -33,6 +33,8 @@ void extrude_edge_context_exec(BMesh *bm, BMOperator *op)
#if 1
for (e=BMIter_New(&iter, bm, BM_EDGES, NULL);e;e=BMIter_Step(&iter)) {
if (!BMO_TestFlag(bm, e, EXT_INPUT)) continue;
found = 0;
f = BMIter_New(&fiter, bm, BM_FACES_OF_EDGE, e);
for (rlen=0; f; f=BMIter_Step(&fiter), rlen++) {

@ -1102,15 +1102,30 @@ static void erase_vertices(EditMesh *em, ListBase *l)
}
}
void delete_mesh(Object *obedit, EditMesh *em, wmOperator *op, int event)
/* Note, these values must match delete_mesh() event values */
static EnumPropertyItem prop_mesh_delete_types[] = {
{10,"VERT", "Vertices", ""},
{1, "EDGE", "Edges", ""},
{2, "FACE", "Faces", ""},
{3, "ALL", "All", ""},
{4, "EDGE_FACE","Edges & Faces", ""},
{5, "ONLY_FACE","Only Faces", ""},
{6, "EDGE_LOOP","Edge Loop", ""},
{7, "COLLAPSE","Collapse", ""},
{0, NULL, NULL, NULL}
};
static int delete_mesh_exec(bContext *C, wmOperator *op)
{
Object *obedit= CTX_data_edit_object(C);
EditMesh *em= ((Mesh *)obedit->data)->edit_mesh;
EditFace *efa, *nextvl;
EditVert *eve,*nextve;
EditEdge *eed,*nexted;
int count;
char *str="Erase";
int event = RNA_enum_get(op->ptr, "type");
if(event<1) return;
if(event==10 ) {
@ -1121,19 +1136,27 @@ void delete_mesh(Object *obedit, EditMesh *em, wmOperator *op, int event)
}
else if(event==7) {
BMesh *bm = editmesh_to_bmesh(em);
BMOperator op;
BMOperator bmop;
EditMesh *em2;
char *errmsg;
BMO_Init_Op(&op, BMOP_DISSOLVE_VERTS);
BMO_HeaderFlag_To_Slot(bm, &op, BMOP_DISVERTS_VERTIN,
BMO_Init_Op(&bmop, BMOP_DISSOLVE_VERTS);
BMO_HeaderFlag_To_Slot(bm, &bmop, BMOP_DISVERTS_VERTIN,
BM_SELECT, BM_VERT);
BMO_Exec_Op(bm, &op);
BMO_Exec_Op(bm, &bmop);
BMO_Finish_Op(bm, &op);
BMO_Finish_Op(bm, &bmop);
if (BMO_GetError(bm, &errmsg, NULL)) {
BKE_report(op->reports, RPT_ERROR, errmsg);
BMO_ClearStack(bm);
return OPERATOR_CANCELLED;
}
em2 = bmesh_to_editmesh(bm);
set_editMesh(em, em2);
MEM_freeN(em2);
BM_Free_Mesh(bm);
}
else if(event==6) {
if(!EdgeLoopDelete(em, op))
@ -1254,29 +1277,6 @@ void delete_mesh(Object *obedit, EditMesh *em, wmOperator *op, int event)
EM_fgon_flags(em); // redo flags and indices for fgons
// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
}
/* Note, these values must match delete_mesh() event values */
static EnumPropertyItem prop_mesh_delete_types[] = {
{10,"VERT", "Vertices", ""},
{1, "EDGE", "Edges", ""},
{2, "FACE", "Faces", ""},
{3, "ALL", "All", ""},
{4, "EDGE_FACE","Edges & Faces", ""},
{5, "ONLY_FACE","Only Faces", ""},
{6, "EDGE_LOOP","Edge Loop", ""},
{7, "COLLAPSE","Collapse", ""},
{0, NULL, NULL, NULL}
};
static int delete_mesh_exec(bContext *C, wmOperator *op)
{
Object *obedit= CTX_data_edit_object(C);
EditMesh *em= ((Mesh *)obedit->data)->edit_mesh;
delete_mesh(obedit,em, op,RNA_enum_get(op->ptr, "type"));
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
return OPERATOR_FINISHED;