edge subdivide ops now use bmesh code, rather then just the test bmesh op. also, got bmesh edge subdivide's smooth subdivide mode to work (fractal already worked I think, not sure).

This commit is contained in:
Joseph Eagar
2009-03-16 14:15:18 +00:00
parent aa4915fdcf
commit b1de007e50
11 changed files with 104 additions and 54 deletions

View File

@@ -119,6 +119,11 @@ enum {
BMOP_TRIANG_FACEIN, /*faces*/
BMOP_TRIANG_NEW_EDGES, /*edgeout*/
BMOP_TRIANG_NEW_FACES, /*faceout*/
/*facemap, maps new faces to old one. since triangulator
uses only split face, the original ngon face is still there,
though it's just another triangle now.*/
BMOP_TRIANG_FACEMAP,
BMOP_TRIANG_TOTSLOT,
};
@@ -187,6 +192,9 @@ struct EditMesh;
void BMOP_DupeFromFlag(struct BMesh *bm, int etypeflag, int flag);
void BM_esubdivideflag(struct Object *obedit, struct BMesh *bm, int selflag, float rad,
int flag, int numcuts, int seltype);
void BM_esubdivideflag_conv(struct Object *obedit, struct EditMesh *em,
int selflag, float rad, int flag, int numcuts,
int seltype);
void BM_extrudefaceflag(BMesh *bm, int flag);
/*this next one return 1 if they did anything, or zero otherwise.

View File

@@ -52,7 +52,8 @@ BMOpDefine def_triangop = {
"triangulate",
{{BMOP_OPSLOT_ELEMENT_BUF, "faces"},
{BMOP_OPSLOT_ELEMENT_BUF, "edgeout"},
{BMOP_OPSLOT_ELEMENT_BUF, "faceout"}},
{BMOP_OPSLOT_ELEMENT_BUF, "faceout"},
{BMOP_OPSLOT_MAPPING, "facemap"}},
triangulate_exec,
BMOP_TRIANG_TOTSLOT,
0

View File

@@ -351,17 +351,18 @@ void BM_Vert_UpdateNormal(BMesh *bm, BMVert *v)
{
BMIter iter;
BMFace *f;
float norm[3] = {0.0f, 0.0f, 0.0f};
int len=0;
v->no[0] = v->no[1] = v->no[2] = 0.0f;
f = BMIter_New(&iter, bm, BM_FACES_OF_VERT, v);
for (; f; f=BMIter_Step(&iter), len++) {
VecAddf(norm, f->no, norm);
VecAddf(v->no, f->no, v->no);
}
if (!len) return;
VecMulf(norm, 1.0f/(int)len);
VecMulf(v->no, 1.0f/(int)len);
}
void bmesh_update_face_normal(BMesh *bm, BMFace *f, float (*projectverts)[3])
@@ -429,11 +430,11 @@ int linecrosses(double *v1, double *v2, double *v3, double *v4)
return (w1 == w2) && (w3 == w4);*/
w1 = testedgesidef(v1, v3, v2);
w2 = testedgesidef(v2, v4, v1);
w3 = !testedgesidef(v1, v2, v3);
w4 = testedgesidef(v3, v2, v4);
w5 = !testedgesidef(v3, v1, v4);
w1 = testedgeside(v1, v3, v2);
w2 = testedgeside(v2, v4, v1);
w3 = !testedgeside(v1, v2, v3);
w4 = testedgeside(v3, v2, v4);
w5 = !testedgeside(v3, v1, v4);
return w1 == w2 && w2 == w3 && w3 == w4 && w4==w5;
}
@@ -552,17 +553,17 @@ static BMLoop *find_ear(BMesh *bm, BMFace *f, float (*verts)[3],
* triangles (angles less than
* 90 degrees). If the triangulator
* has bits left over (or cannot
* triangulate at all) it uses an
* arbitrary triangulation.
*
* TODO:
* -Modify this to try and find ears that will not create a non-manifold face after conversion back to editmesh
* triangulate at all) it uses a
* simple fan triangulation
*
* newfaces, if non-null, must be an array of BMFace pointers,
* with a length equal to f->len. it will be filled with the new
* triangles, and will be NULL-terminated.
*/
void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3],
int newedgeflag, int newfaceflag)
int newedgeflag, int newfaceflag, BMFace **newfaces)
{
int i, done, nvert;
int i, done, nvert, nf_i = 0;
BMLoop *l, *newl, *nextloop;
BMVert *v;
@@ -607,6 +608,8 @@ void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3],
BMO_SetFlag(bm, newl->e, newedgeflag);
BMO_SetFlag(bm, f, newfaceflag);
if (newfaces) newfaces[nf_i++] = f;
/*l = f->loopbase;
do {
@@ -627,14 +630,22 @@ void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3],
&newl, NULL);
if (!f) {
printf("triangle fan step of triangulator failed.\n");
/*NULL-terminate*/
if (newfaces) newfaces[nf_i] = NULL;
return;
}
if (newfaces) newfaces[nf_i++] = f;
BMO_SetFlag(bm, newl->e, newedgeflag);
BMO_SetFlag(bm, f, newfaceflag);
l = nextloop;
}
}
/*NULL-terminate*/
if (newfaces) newfaces[nf_i] = NULL;
}
/*each pair of loops defines a new edge, a split. this function goes

View File

@@ -66,8 +66,10 @@ int bmesh_test_sysflag(struct BMHeader *element, int flag);
/*Polygon Utilities ? FIXME... where do these each go?*/
/*newedgeflag sets a flag layer flag, obviously not the header flag.*/
void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3], int newedgeflag, int newfaceflag);
void bmesh_update_face_normal(struct BMesh *bm, struct BMFace *f, float (*projectverts)[3]);
void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3],
int newedgeflag, int newfaceflag, BMFace **newfaces);
void bmesh_update_face_normal(struct BMesh *bm, struct BMFace *f,
float (*projectverts)[3]);
void compute_poly_plane(float (*verts)[3], int nverts);
void poly_rotate_plane(float normal[3], float (*verts)[3], int nverts);
void bmesh_flip_normal(struct BMesh *bm, struct BMFace *f);

View File

@@ -140,18 +140,21 @@ static void alter_co(float *co, BMEdge *edge, subdparams *params, float perc,
/* assumes in the edge is the correct interpolated vertices already */
/* percent defines the interpolation, rad and flag are for special options */
/* results in new vertex with correct coordinate, vertex normal and weight group info */
static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge,
subdparams *params, float percent,
static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge,BMEdge *oedge,
subdparams *params, float percent,
float percent2,
BMEdge **out,BMVert *vsta,BMVert *vend)
{
BMVert *ev;
// float co[3];
ev = BM_Split_Edge(bm, edge->v1, edge, out, percent);
BM_Vert_UpdateNormal(bm, ev);
BMO_SetFlag(bm, ev, ELE_INNER);
/* offset for smooth or sphere or fractal */
alter_co(ev->co, edge, params, percent, vsta, vend);
alter_co(ev->co, oedge, params, percent2, vsta, vend);
#if 0 //TODO
/* clip if needed by mirror modifier */
@@ -171,34 +174,35 @@ static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge,
return ev;
}
static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge,
static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge,
int curpoint, int totpoint, subdparams *params,
BMEdge **newe, BMVert *vsta, BMVert *vend)
{
BMVert *ev;
float percent;
float percent, percent2 = 0.0f;
if (BMO_TestFlag(bm, edge, EDGE_PERCENT) && totpoint == 1)
percent = BMO_Get_MapFloat(bm, params->op,
BMOP_ESUBDIVIDE_PERCENT_EDGEMAP, edge);
else {
percent= 1.0f/(float)(totpoint+1-curpoint);
percent2 = (float)curpoint / (float)(totpoint + 1);
}
ev= bm_subdivide_edge_addvert(bm, edge, params, percent,
newe, vsta, vend);
ev= bm_subdivide_edge_addvert(bm, edge, oedge, params, percent,
percent2, newe, vsta, vend);
return ev;
}
static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, subdparams *params,
BMVert *vsta, BMVert *vend) {
BMEdge *eed = edge, *newe;
BMEdge *eed = edge, *newe, temp = *edge;
BMVert *v;
int i, numcuts = params->numcuts;
for(i=0;i<numcuts;i++) {
v = subdivideedgenum(bm, eed, i, params->numcuts, params,
v = subdivideedgenum(bm, eed, &temp, i, params->numcuts, params,
&newe, vsta, vend);
BMO_SetFlag(bm, v, SUBD_SPLIT);
BMO_SetFlag(bm, eed, SUBD_SPLIT);
@@ -371,7 +375,7 @@ static void q_4edge_split(BMesh *bm, BMFace *face, BMVert **verts,
{
BMFace *nf;
BMVert *v, *v1, *v2;
BMEdge *e, *ne;
BMEdge *e, *ne, temp;
BMVert **lines;
int numcuts = params->numcuts;
int i, j, a, b, s=numcuts+2, totv=numcuts*4+4;
@@ -406,9 +410,10 @@ static void q_4edge_split(BMesh *bm, BMFace *face, BMVert **verts,
v1 = lines[(i+1)*s] = verts[a];
v2 = lines[(i+1)*s + s-1] = verts[b];
temp = *e;
for (a=0; a<numcuts; a++) {
v = subdivideedgenum(bm, e, a, numcuts, params, &ne,
v = subdivideedgenum(bm, e, &temp, a, numcuts, params, &ne,
v1, v2);
BMO_SetFlag(bm, ne, ELE_INNER);
lines[(i+1)*s+a+1] = v;
@@ -496,7 +501,7 @@ static void t_3edge_split(BMesh *bm, BMFace *face, BMVert **verts,
subdparams *params)
{
BMFace *nf;
BMEdge *e, *ne;
BMEdge *e, *ne, temp;
BMVert ***lines, *v;
void *stackarr[1];
int i, j, a, b, numcuts = params->numcuts;
@@ -528,9 +533,10 @@ static void t_3edge_split(BMesh *bm, BMFace *face, BMVert **verts,
lines[i+1][0] = verts[a];
lines[i+1][1+i] = verts[b];
temp = *e;
for (j=0; j<i; j++) {
v = subdivideedgenum(bm, e, j, i, params, &ne,
v = subdivideedgenum(bm, e, &temp, j, i, params, &ne,
verts[a], verts[b]);
lines[i+1][j+1] = v;

View File

@@ -13,33 +13,42 @@
#define EDGE_NEW 1
#define FACE_NEW 1
void triangulate_exec(BMesh *bmesh, BMOperator *op)
void triangulate_exec(BMesh *bm, BMOperator *op)
{
BMOpSlot *finput;
BMFace *face;
BMOIter siter;
BMFace *face, **newfaces = NULL;
V_DECLARE(newfaces);
float (*projectverts)[3] = NULL;
V_DECLARE(projectverts);
int i, lastlen=0, count = 0;
finput = BMO_GetSlot(op, BMOP_ESUBDIVIDE_EDGES);
for (i=0; i<finput->len; i++) {
face = ((BMFace**)finput->data.p)[i];
face = BMO_IterNew(&siter, bm, op, BMOP_TRIANG_FACEIN);
for (; face; face=BMO_IterStep(&siter)) {
if (lastlen < face->len) {
V_RESET(projectverts);
V_RESET(newfaces);
for (lastlen=0; lastlen<face->len; lastlen++) {
V_GROW(projectverts);
V_GROW(projectverts);
V_GROW(projectverts);
V_GROW(newfaces);
}
}
BM_Triangulate_Face(bmesh, face, projectverts, EDGE_NEW, FACE_NEW);
BM_Triangulate_Face(bm, face, projectverts, EDGE_NEW,
FACE_NEW, newfaces);
BMO_Insert_MapPointer(bm, op, BMOP_TRIANG_FACEMAP,
face, face);
for (i=0; newfaces[i]; i++) {
BMO_Insert_MapPointer(bm, op, BMOP_TRIANG_FACEMAP,
newfaces[i], face);
}
}
BMO_Flag_To_Slot(bmesh, op, BMOP_TRIANG_NEW_EDGES, EDGE_NEW, BM_EDGE);
BMO_Flag_To_Slot(bmesh, op, BMOP_TRIANG_NEW_FACES, FACE_NEW, BM_FACE);
BMO_Flag_To_Slot(bm, op, BMOP_TRIANG_NEW_EDGES, EDGE_NEW, BM_EDGE);
BMO_Flag_To_Slot(bm, op, BMOP_TRIANG_NEW_FACES, FACE_NEW, BM_FACE);
V_FREE(projectverts);
}

View File

@@ -1675,6 +1675,7 @@ typedef struct UndoMesh {
EditVertC *verts;
EditEdgeC *edges;
EditFaceC *faces;
EditFaceC *act_face;
EditSelectionC *selected;
int totvert, totedge, totface, totsel;
short selectmode;
@@ -1785,6 +1786,8 @@ static void *editMesh_to_undoMesh(void *emv)
CustomData_from_em_block(&em->fdata, &um->fdata, efa->data, a);
}
if (em->act_face) um->act_face = um->faces + em->act_face->tmp.l;
a = 0;
for(ese=em->selected.first; ese; ese=ese->next, esec++){
esec->type = ese->type;
@@ -1872,7 +1875,9 @@ static void undoMesh_to_editMesh(void *umv, void *emv)
efa->f= efac->f;
efa->h= efac->h;
efa->fgonf= efac->fgonf;
if (efac == um->act_face) em->act_face = efa;
CustomData_to_em_block(&um->fdata, &em->fdata, a, &efa->data);
}
@@ -1896,6 +1901,10 @@ static void undoMesh_to_editMesh(void *umv, void *emv)
EM_free_index_arrays();
}
EM_nvertices_selected(em);
EM_nedges_selected(em);
EM_nfaces_selected(em);
// XXX retopo_free_paint();
// em->retopo_paint_data= retopo_paint_data_copy(um->retopo_paint_data);
// scene->toolsettings->retopo_mode= um->retopo_mode;

View File

@@ -3257,8 +3257,10 @@ static int bmesh_test_exec(bContext *C, wmOperator *op)
bm = editmesh_to_bmesh(em);
#if 1 /*edge subdivide test*/
//BM_esubdivideflag(obedit, bm, SELECT, 0.292f*5.0, B_SMOOTH, G.rt==0?1:G.rt, 0);
BM_esubdivideflag(obedit, bm, SELECT, 0, 0, G.rt==0?1:G.rt, SUBDIV_SELECT_INNER);
//esubdivideflag(obedit, em, 1, -(RNA_float_get(op->ptr, "random_factor")/100), scene->toolsettings->editbutflag, RNA_int_get(op->ptr, "number_cuts"), 0);
BM_esubdivideflag(obedit, bm, SELECT, -0.05f, 0, G.rt==0?1:G.rt, 0);
//BM_esubdivideflag(obedit, bm, SELECT, 0, 0, G.rt==0?1:G.rt, SUBDIV_SELECT_INNER);
#endif

View File

@@ -2188,7 +2188,7 @@ static void fill_quad_quadruple(EditMesh *em, EditFace *efa, struct GHash *gh, i
for(i=1;i<=numcuts;i++) {
/* we create a fake edge for the next loop */
temp.v2 = innerverts[i][0] = verts[1][i];
temp.v2 = innerverts[i][0] = verts[1][i];
temp.v1 = innerverts[i][numcuts+1] = verts[3][i];
for(j=1;j<=numcuts;j++) {
@@ -6439,7 +6439,7 @@ static int subdivide_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
EditMesh *em= ((Mesh *)obedit->data)->edit_mesh;
esubdivideflag(obedit, em, 1, 0.0, scene->toolsettings->editbutflag, 1, 0);
BM_esubdivideflag_conv(obedit, em, 1, 0.0, scene->toolsettings->editbutflag, 1, 0);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
@@ -6466,7 +6466,7 @@ static int subdivide_multi_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
EditMesh *em= ((Mesh *)obedit->data)->edit_mesh;
esubdivideflag(obedit, em, 1, 0.0, scene->toolsettings->editbutflag, RNA_int_get(op->ptr,"number_cuts"), 0);
BM_esubdivideflag_conv(obedit, em, 1, 0.0, scene->toolsettings->editbutflag, RNA_int_get(op->ptr,"number_cuts"), 0);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
@@ -6496,7 +6496,7 @@ static int subdivide_multi_fractal_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
EditMesh *em= ((Mesh *)obedit->data)->edit_mesh;
esubdivideflag(obedit, em, 1, -(RNA_float_get(op->ptr, "random_factor")/100), scene->toolsettings->editbutflag, RNA_int_get(op->ptr, "number_cuts"), 0);
BM_esubdivideflag_conv(obedit, em, 1, -(RNA_float_get(op->ptr, "random_factor")/100), scene->toolsettings->editbutflag, RNA_int_get(op->ptr, "number_cuts"), 0);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
@@ -6527,7 +6527,7 @@ static int subdivide_smooth_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
EditMesh *em= ((Mesh *)obedit->data)->edit_mesh;
esubdivideflag(obedit, em, 1, 0.292f*RNA_float_get(op->ptr, "smoothness"), scene->toolsettings->editbutflag | B_SMOOTH, 1, 0);
BM_esubdivideflag_conv(obedit, em, 1, 0.292f*RNA_float_get(op->ptr, "smoothness"), scene->toolsettings->editbutflag | B_SMOOTH, 1, 0);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);

View File

@@ -1569,7 +1569,7 @@ static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *dra
unsigned char *col;
if (efa->h==0) {
if (efa == data->efa_act) {
if (efa == data->efa_act || efa->flag & ME_DRAW_ACT) {
glColor4ubv(data->cols[2]);
return 2; /* stipple */
} else {

View File

@@ -216,7 +216,9 @@ typedef struct PartialVisibility {
/* flag (mface) */
#define ME_SMOOTH 1
#define ME_FACE_SEL 2
/* flag ME_HIDE==16 is used here too */
/* flag ME_HIDE==16 is used here too */
#define ME_DRAW_ACT 4
/* mselect->type */
#define ME_VSEl 0
#define ME_ESEl 1