Improved edge subdivide.  The last tool panel
is a bit clearer, with a "quad/tri" checkbox
(that, in addition to turning on the old 
 singe-edge-triangluation feature also 
 automatically switches cornervert to Inner Vert
 if it is Straight, to avoid producing ngons).
 
I also rewrote fractal to be more likes its name, and
 removed the "smoothness" parameter (which never
 worked, anyway, even in trunk).  Also removed the
 grid fill paramter, it wasn't all that useful.
This commit is contained in:
Joseph Eagar 2011-03-28 00:29:45 +00:00
parent fc050837b0
commit 3875461a33
12 changed files with 276 additions and 123 deletions

@ -557,7 +557,7 @@ class VIEW3D_MT_select_edit_curve(bpy.types.Menu):
layout.operator("curve.select_less") layout.operator("curve.select_less")
class VIEW3D_MT_select_edit_surface(bpy.types.Menu): class sVIEW3D_MT_select_edit_surface(bpy.types.Menu):
bl_label = "Select" bl_label = "Select"
def draw(self, context): def draw(self, context):
@ -1366,7 +1366,6 @@ class VIEW3D_MT_edit_mesh_specials(bpy.types.Menu):
layout.operator_context = 'INVOKE_REGION_WIN' layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("mesh.subdivide", text="Subdivide") layout.operator("mesh.subdivide", text="Subdivide")
layout.operator("mesh.subdivide", text="Subdivide Smooth").smoothness = 1.0
layout.operator("mesh.merge", text="Merge...") layout.operator("mesh.merge", text="Merge...")
layout.operator("mesh.remove_doubles") layout.operator("mesh.remove_doubles")
layout.operator("mesh.hide", text="Hide") layout.operator("mesh.hide", text="Hide")

@ -1450,8 +1450,9 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
int size = typeInfo->size * totelem, flag = 0, index = data->totlayer; int size = typeInfo->size * totelem, flag = 0, index = data->totlayer;
void *newlayerdata; void *newlayerdata;
if (!typeInfo->defaultname && CustomData_has_layer(data, type)) if (!typeInfo->defaultname && CustomData_has_layer(data, type)) {
return &data->layers[CustomData_get_layer_index(data, type)]; return &data->layers[CustomData_get_layer_index(data, type)];
}
if((alloctype == CD_ASSIGN) || (alloctype == CD_REFERENCE)) { if((alloctype == CD_ASSIGN) || (alloctype == CD_REFERENCE)) {
newlayerdata = layerdata; newlayerdata = layerdata;

@ -204,6 +204,7 @@ void BM_Edge_UpdateNormals ( BMesh *bm, BMEdge *e );
/*update a vert normal (but not the faces incident on it)*/ /*update a vert normal (but not the faces incident on it)*/
void BM_Vert_UpdateNormal ( BMesh *bm, BMVert *v ); void BM_Vert_UpdateNormal ( BMesh *bm, BMVert *v );
void BM_Vert_UpdateAllNormals ( BMesh *bm, BMVert *v );
void BM_flip_normal ( BMesh *bm, BMFace *f ); void BM_flip_normal ( BMesh *bm, BMFace *f );
@ -232,11 +233,12 @@ void BM_multires_smooth_bounds(BMesh *bm, BMFace *f);
void BM_loop_interp_multires(BMesh *bm, BMLoop *target, BMFace *source); void BM_loop_interp_multires(BMesh *bm, BMLoop *target, BMFace *source);
void BM_vert_interp_from_face(BMesh *bm, BMVert *v, BMFace *source); void BM_vert_interp_from_face(BMesh *bm, BMVert *v, BMFace *source);
void BM_Data_Interp_From_Verts ( struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMVert *v, float fac ); void BM_Data_Interp_From_Verts (struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMVert *v, float fac );
void BM_Data_Facevert_Edgeinterp ( struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMVert *v, struct BMEdge *e1, float fac ); void BM_Data_Facevert_Edgeinterp (struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMVert *v, struct BMEdge *e1, float fac );
void BM_add_data_layer ( BMesh *em, CustomData *data, int type ); void BM_add_data_layer (BMesh *em, CustomData *data, int type );
void BM_add_data_layer_named ( BMesh *bm, CustomData *data, int type, char *name ); void BM_add_data_layer_named (BMesh *bm, CustomData *data, int type, char *name );
void BM_free_data_layer ( BMesh *em, CustomData *data, int type ); void BM_free_data_layer (BMesh *em, CustomData *data, int type );
void BM_free_data_layer_n(BMesh *bm, CustomData *data, int type, int n);
float BM_GetCDf(struct CustomData *cd, void *element, int type); float BM_GetCDf(struct CustomData *cd, void *element, int type);
void BM_SetCDf(struct CustomData *cd, void *element, int type, float val); void BM_SetCDf(struct CustomData *cd, void *element, int type, float val);

@ -81,7 +81,7 @@ struct EditMesh;
void BMOP_DupeFromFlag(struct BMesh *bm, int etypeflag, int flag); void BMOP_DupeFromFlag(struct BMesh *bm, int etypeflag, int flag);
void BM_esubdivideflag(struct Object *obedit, BMesh *bm, int flag, float smooth, void BM_esubdivideflag(struct Object *obedit, BMesh *bm, int flag, float smooth,
float fractal, int beauty, int numcuts, int seltype, float fractal, int beauty, int numcuts, int seltype,
int cornertype, int singleedge, int gridfill); int cornertype, int singleedge, int gridfill, int seed);
void BM_extrudefaceflag(BMesh *bm, int flag); void BM_extrudefaceflag(BMesh *bm, int flag);
/*this next one return 1 if they did anything, or zero otherwise. /*this next one return 1 if they did anything, or zero otherwise.

@ -118,7 +118,10 @@ void BM_Data_Facevert_Edgeinterp(BMesh *bm, BMVert *v1, BMVert *UNUSED(v2), BMVe
v2loop = (BMLoop*)(l->prev); v2loop = (BMLoop*)(l->prev);
} }
if (!v1loop || !v2loop)
return;
src[0] = v1loop->head.data; src[0] = v1loop->head.data;
src[1] = v2loop->head.data; src[1] = v2loop->head.data;
@ -719,6 +722,18 @@ void BM_free_data_layer(BMesh *bm, CustomData *data, int type)
if (olddata.layers) MEM_freeN(olddata.layers); if (olddata.layers) MEM_freeN(olddata.layers);
} }
void BM_free_data_layer_n(BMesh *bm, CustomData *data, int type, int n)
{
CustomData olddata;
olddata= *data;
olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL;
CustomData_free_layer(data, type, 0, CustomData_get_layer_index_n(data, type, n));
update_data_blocks(bm, &olddata, data);
if (olddata.layers) MEM_freeN(olddata.layers);
}
float BM_GetCDf(CustomData *cd, void *element, int type) float BM_GetCDf(CustomData *cd, void *element, int type)
{ {
if (CustomData_has_layer(cd, type)) { if (CustomData_has_layer(cd, type)) {

@ -517,8 +517,8 @@ BMVert *BM_Split_Edge(BMesh *bm, BMVert *v, BMEdge *e, BMEdge **ne, float percen
} }
/*v->nv->v2*/ /*v->nv->v2*/
BM_Data_Facevert_Edgeinterp(bm,v2, v, nv, e, percent); BM_Data_Facevert_Edgeinterp(bm, v2, v, nv, e, percent);
BM_Data_Interp_From_Verts(bm, v2, v, nv, percent); BM_Data_Interp_From_Verts(bm, v, v2, nv, percent);
if (CustomData_has_layer(&bm->ldata, CD_MDISPS) && e->l && nv) { if (CustomData_has_layer(&bm->ldata, CD_MDISPS) && e->l && nv) {
int i, j; int i, j;

@ -657,6 +657,7 @@ BMOpDefine def_subdop = {
{BMOP_OPSLOT_FLT, "smooth"}, {BMOP_OPSLOT_FLT, "smooth"},
{BMOP_OPSLOT_FLT, "fractal"}, {BMOP_OPSLOT_FLT, "fractal"},
{BMOP_OPSLOT_INT, "beauty"}, {BMOP_OPSLOT_INT, "beauty"},
{BMOP_OPSLOT_INT, "seed"},
{BMOP_OPSLOT_MAPPING, "custompatterns"}, {BMOP_OPSLOT_MAPPING, "custompatterns"},
{BMOP_OPSLOT_MAPPING, "edgepercents"}, {BMOP_OPSLOT_MAPPING, "edgepercents"},

@ -445,7 +445,26 @@ void BM_Vert_UpdateNormal(BMesh *bm, BMVert *v)
if (!len) return; if (!len) return;
mul_v3_fl(v->no, 1.0f/(int)len); mul_v3_fl(v->no, 1.0f/(float)len);
}
void BM_Vert_UpdateAllNormals(BMesh *bm, BMVert *v)
{
BMIter iter;
BMFace *f;
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++) {
BM_Face_UpdateNormal(bm, f);
add_v3_v3v3(v->no, f->no, v->no);
}
if (!len) return;
mul_v3_fl(v->no, 1.0f/(float)len);
} }
void bmesh_update_face_normal(BMesh *bm, BMFace *f, float (*projectverts)[3]) void bmesh_update_face_normal(BMesh *bm, BMFace *f, float (*projectverts)[3])

@ -86,6 +86,59 @@ NOTE: beauty has been renamed to flag!
split the edge only? split the edge only?
*/ */
#if 0 //misc. code, maps a parametric coordinate to a fractal line
float lastrnd[3], vec2[3] = {0.0f, 0.0f, 0.0f};
int seed = BLI_rand();
int d, i, j, dp, lvl, wid;
float df;
BLI_srandom(seed);
wid = (params->numcuts+2);
dp = perc*wid;
wid /= 2;
d = lvl = 0;
while (1) {
if (d > dp) {
d -= wid;
} else if (d < dp) {
d += wid;
} else {
break;
}
wid = MAX2((wid/2), 1);
lvl++;
}
zero_v3(vec1);
df = 1.0f;
for (i=0; i<lvl; i++, df /= 4.0f) {
int tot = (1<<i);
lastrnd[0] = BLI_drand()-0.5f;
lastrnd[1] = BLI_drand()-0.5f;
lastrnd[2] = BLI_drand()-0.5f;
for (j=0; j<tot; j++) {
float a, b, rnd[3], rnd2[3];
rnd[0] = BLI_drand()-0.5f;
rnd[1] = BLI_drand()-0.5f;
rnd[2] = BLI_drand()-0.5f;
a = (float)j*(float)((float)params->numcuts/(float)tot);
b = (float)(j+1)*(float)((float)params->numcuts/(float)tot);
if (d >= a && d <= b) {
interp_v3_v3v3(rnd2, lastrnd, rnd, (((float)d)-a)/(b-a));
mul_v3_fl(rnd2, df);
add_v3_v3(vec1, rnd2);
}
copy_v3_v3(lastrnd, rnd);
}
}
#endif
/*connects face with smallest len, which I think should always be correct for /*connects face with smallest len, which I think should always be correct for
edge subdivision*/ edge subdivision*/
BMEdge *connect_smallest_face(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf) { BMEdge *connect_smallest_face(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf) {
@ -115,59 +168,88 @@ BMEdge *connect_smallest_face(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf) {
return NULL; return NULL;
} }
/* calculates offset for co, based on fractal, sphere or smooth settings */ /* calculates offset for co, based on fractal, sphere or smooth settings */
static void alter_co(float *co, BMEdge *UNUSED(edge), subdparams *params, float perc, static void alter_co(BMesh *bm, BMVert *v, BMEdge *origed, subdparams *params, float perc,
BMVert *vsta, BMVert *vend) BMVert *vsta, BMVert *vend)
{ {
float vec1[3], fac; float vec1[3], fac;
float *co=NULL, *origco=NULL;
int i, totlayer = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY);
BM_Vert_UpdateAllNormals(bm, v);
if(params->beauty & B_SMOOTH) { origco = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, params->origkey);
/* we calculate an offset vector vec1[], to be added to *co */ sub_v3_v3v3(vec1, origco, v->co);
float len, fac, nor[3], nor1[3], nor2[3], smooth=params->smooth;
for (i=0; i<totlayer; i++) {
sub_v3_v3v3(nor, vsta->co, vend->co); co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, i);
len= 0.5f*normalize_v3(nor); sub_v3_v3(co, vec1);
copy_v3_v3(nor1, vsta->no);
copy_v3_v3(nor2, vend->no);
/* cosine angle */
fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ;
vec1[0]= fac*nor1[0];
vec1[1]= fac*nor1[1];
vec1[2]= fac*nor1[2];
/* cosine angle */
fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ;
vec1[0]+= fac*nor2[0];
vec1[1]+= fac*nor2[1];
vec1[2]+= fac*nor2[2];
/* falloff for multi subdivide */
smooth *= sqrt(fabs(1.0f - 2.0f*fabs(perc)));
vec1[0]*= smooth*len;
vec1[1]*= smooth*len;
vec1[2]*= smooth*len;
co[0] += vec1[0];
co[1] += vec1[1];
co[2] += vec1[2];
}
else if(params->beauty & B_SPHERE) { /* subdivide sphere */
normalize_v3(co);
co[0]*= params->smooth;
co[1]*= params->smooth;
co[2]*= params->smooth;
} }
if(params->beauty & B_FRACTAL) { for (i=0; i<totlayer; i++) {
fac= params->fractal*len_v3v3(vsta->co, vend->co); co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, i);
vec1[0]= fac*(float)(0.5-BLI_drand());
vec1[1]= fac*(float)(0.5-BLI_drand()); if(params->beauty & B_SMOOTH) {
vec1[2]= fac*(float)(0.5-BLI_drand()); /* we calculate an offset vector vec1[], to be added to *co */
add_v3_v3v3(co, co, vec1); float len, fac, nor[3], nor1[3], nor2[3], smooth=params->smooth;
sub_v3_v3v3(nor, vsta->co, vend->co);
len= 0.5f*normalize_v3(nor);
copy_v3_v3(nor1, vsta->no);
copy_v3_v3(nor2, vend->no);
/* cosine angle */
fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ;
vec1[0]= fac*nor1[0];
vec1[1]= fac*nor1[1];
vec1[2]= fac*nor1[2];
/* cosine angle */
fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ;
vec1[0]+= fac*nor2[0];
vec1[1]+= fac*nor2[1];
vec1[2]+= fac*nor2[2];
/* falloff for multi subdivide */
smooth *= sqrt(fabs(1.0f - 2.0f*fabs(perc)));
vec1[0]*= smooth*len;
vec1[1]*= smooth*len;
vec1[2]*= smooth*len;
co[0] += vec1[0];
co[1] += vec1[1];
co[2] += vec1[2];
}
else if(params->beauty & B_SPHERE) { /* subdivide sphere */
normalize_v3(co);
co[0]*= params->smooth;
co[1]*= params->smooth;
co[2]*= params->smooth;
}
if(params->beauty & B_FRACTAL) {
float len = len_v3v3(vsta->co, vend->co);
float vec2[3] = {0.0f, 0.0f, 0.0f}, co2[3];
fac= params->fractal*len;
add_v3_v3(vec2, vsta->no);
add_v3_v3(vec2, vend->no);
mul_v3_fl(vec2, 0.5f);
add_v3_v3v3(co2, v->co, params->off);
vec1[0] = fac*(BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 1)-0.5f);
vec1[1] = fac*(BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 1)-0.5f);
vec1[2] = fac*(BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 1)-0.5f);
mul_v3_v3(vec2, vec1);
/*add displacement*/
add_v3_v3v3(co, co, vec2);
}
} }
} }
@ -180,15 +262,13 @@ static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge,BMEdge *oedge,
BMEdge **out,BMVert *vsta,BMVert *vend) BMEdge **out,BMVert *vsta,BMVert *vend)
{ {
BMVert *ev; BMVert *ev;
// float co[3];
ev = BM_Split_Edge(bm, edge->v1, edge, out, percent); ev = BM_Split_Edge(bm, edge->v1, edge, out, percent);
BM_Vert_UpdateNormal(bm, ev);
BMO_SetFlag(bm, ev, ELE_INNER); BMO_SetFlag(bm, ev, ELE_INNER);
/* offset for smooth or sphere or fractal */ /* offset for smooth or sphere or fractal */
alter_co(ev->co, oedge, params, percent2, vsta, vend); alter_co(bm, ev, oedge, params, percent2, vsta, vend);
#if 0 //TODO #if 0 //TODO
/* clip if needed by mirror modifier */ /* clip if needed by mirror modifier */
@ -220,7 +300,7 @@ static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge,
"edgepercents", edge); "edgepercents", edge);
else { else {
percent= 1.0f/(float)(totpoint+1-curpoint); percent= 1.0f/(float)(totpoint+1-curpoint);
percent2 = (float)curpoint / (float)(totpoint + 1); percent2 = (float)(curpoint+1) / (float)(totpoint+1);
} }
@ -232,12 +312,16 @@ static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge,
static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, subdparams *params, static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, subdparams *params,
BMVert *vsta, BMVert *vend) { BMVert *vsta, BMVert *vend) {
BMEdge *eed = edge, *newe, temp = *edge; BMEdge *eed = edge, *newe, temp = *edge;
BMVert *v; BMVert *v, ov1=*edge->v1, ov2=*edge->v2, *v1=edge->v1, *v2=edge->v2;
int i, numcuts = params->numcuts; int i, numcuts = params->numcuts;
temp.v1 = &ov1;
temp.v2 = &ov2;
for(i=0;i<numcuts;i++) { for(i=0;i<numcuts;i++) {
v = subdivideedgenum(bm, eed, &temp, i, params->numcuts, params, v = subdivideedgenum(bm, eed, &temp, i, params->numcuts, params,
&newe, vsta, vend); &newe, vsta, vend);
BMO_SetFlag(bm, v, SUBD_SPLIT); BMO_SetFlag(bm, v, SUBD_SPLIT);
BMO_SetFlag(bm, eed, SUBD_SPLIT); BMO_SetFlag(bm, eed, SUBD_SPLIT);
BMO_SetFlag(bm, newe, SUBD_SPLIT); BMO_SetFlag(bm, newe, SUBD_SPLIT);
@ -250,6 +334,9 @@ static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, subdparams *params,
if (v->e) CHECK_ELEMENT(bm, v->e); if (v->e) CHECK_ELEMENT(bm, v->e);
if (v->e && v->e->l) CHECK_ELEMENT(bm, v->e->l->f); if (v->e && v->e->l) CHECK_ELEMENT(bm, v->e->l->f);
} }
alter_co(bm, v1, &temp, params, 0, &ov1, &ov2);
alter_co(bm, v2, &temp, params, 1.0, &ov1, &ov2);
} }
/*note: the patterns are rotated as necassary to /*note: the patterns are rotated as necassary to
@ -344,7 +431,7 @@ static void quad_2edge_split_innervert(BMesh *bm, BMFace *UNUSED(face), BMVert *
{ {
BMFace *nf; BMFace *nf;
BMVert *v, *lastv; BMVert *v, *lastv;
BMEdge *e, *ne; BMEdge *e, *ne, olde;
int i, numcuts = params->numcuts; int i, numcuts = params->numcuts;
lastv = verts[numcuts]; lastv = verts[numcuts];
@ -353,8 +440,12 @@ static void quad_2edge_split_innervert(BMesh *bm, BMFace *UNUSED(face), BMVert *
e = connect_smallest_face(bm, verts[i], verts[numcuts+(numcuts-i)], e = connect_smallest_face(bm, verts[i], verts[numcuts+(numcuts-i)],
&nf); &nf);
v = BM_Split_Edge(bm, e->v1, e, &ne, 0.5f); olde = *e;
connect_smallest_face(bm, lastv, v, &nf); v = bm_subdivide_edge_addvert(bm, e, &olde, params, 0.5f, 0.5f, &ne, e->v1, e->v2);
if (i != numcuts-1)
connect_smallest_face(bm, lastv, v, &nf);
lastv = v; lastv = v;
} }
@ -496,7 +587,7 @@ static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts
temp = *e; temp = *e;
for (a=0; a<numcuts; a++) { for (a=0; a<numcuts; a++) {
v = subdivideedgenum(bm, e, &temp, a, numcuts, params, &ne, v = subdivideedgenum(bm, e, &temp, a, numcuts, params, &ne,
v1, v2); v1, v2);
if (!v) if (!v)
bmesh_error(); bmesh_error();
@ -561,7 +652,7 @@ static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
{ {
BMFace *nf; BMFace *nf;
BMEdge *e, *ne, temp; BMEdge *e, *ne, temp;
BMVert ***lines, *v; BMVert ***lines, *v, ov1, ov2;
void *stackarr[1]; void *stackarr[1];
int i, j, a, b, numcuts = params->numcuts; int i, j, a, b, numcuts = params->numcuts;
@ -594,6 +685,10 @@ static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
lines[i+1][1+i] = verts[b]; lines[i+1][1+i] = verts[b];
temp = *e; temp = *e;
ov1 = *verts[a];
ov2 = *verts[b];
temp.v1 = &ov1;
temp.v2 = &ov2;
for (j=0; j<i; j++) { for (j=0; j<i; j++) {
v = subdivideedgenum(bm, e, &temp, j, i, params, &ne, v = subdivideedgenum(bm, e, &temp, j, i, params, &ne,
verts[a], verts[b]); verts[a], verts[b]);
@ -670,27 +765,27 @@ typedef struct subd_facedata {
void esubdivide_exec(BMesh *bmesh, BMOperator *op) void esubdivide_exec(BMesh *bmesh, BMOperator *op)
{ {
BMOpSlot *einput; BMOpSlot *einput;
BMEdge *edge, **edges = NULL;
BLI_array_declare(edges);
BMFace *face;
BMLoop *nl;
BMVert **verts = NULL;
BLI_array_declare(verts);
BMIter fiter, liter;
subdpattern *pat; subdpattern *pat;
subdparams params; subdparams params;
subd_facedata *facedata = NULL; subd_facedata *facedata = NULL;
BLI_array_declare(facedata); BMIter viter, fiter, liter;
BMLoop *l, **splits = NULL, **loops = NULL; BMVert *v, **verts = NULL;
BMEdge *edge, **edges = NULL;
BMLoop *nl, *l, **splits = NULL, **loops = NULL;
BMFace *face;
BLI_array_declare(splits); BLI_array_declare(splits);
BLI_array_declare(loops); BLI_array_declare(loops);
BLI_array_declare(facedata);
BLI_array_declare(edges);
BLI_array_declare(verts);
float smooth, fractal; float smooth, fractal;
int beauty, cornertype, singleedge, gridfill; int beauty, cornertype, singleedge, gridfill;
int i, j, matched, a, b, numcuts, totesel; int skey, seed, i, j, matched, a, b, numcuts, totesel;
BMO_Flag_Buffer(bmesh, op, "edges", SUBD_SPLIT, BM_EDGE); BMO_Flag_Buffer(bmesh, op, "edges", SUBD_SPLIT, BM_EDGE);
numcuts = BMO_Get_Int(op, "numcuts"); numcuts = BMO_Get_Int(op, "numcuts");
seed = BMO_Get_Int(op, "seed");
smooth = BMO_Get_Float(op, "smooth"); smooth = BMO_Get_Float(op, "smooth");
fractal = BMO_Get_Float(op, "fractal"); fractal = BMO_Get_Float(op, "fractal");
beauty = BMO_Get_Int(op, "beauty"); beauty = BMO_Get_Int(op, "beauty");
@ -698,6 +793,8 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
singleedge = BMO_Get_Int(op, "singleedge"); singleedge = BMO_Get_Int(op, "singleedge");
gridfill = BMO_Get_Int(op, "gridfill"); gridfill = BMO_Get_Int(op, "gridfill");
BLI_srandom(seed);
patterns[1] = NULL; patterns[1] = NULL;
//straight cut is patterns[1] == NULL //straight cut is patterns[1] == NULL
switch (cornertype) { switch (cornertype) {
@ -728,6 +825,15 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
patterns[5] = NULL; patterns[5] = NULL;
} }
/*add a temporary shapekey layer to store displacements on current geometry*/
BM_add_data_layer(bmesh, &bmesh->vdata, CD_SHAPEKEY);
skey = CustomData_number_of_layers(&bmesh->vdata, CD_SHAPEKEY)-1;
BM_ITER(v, &viter, bmesh, BM_VERTS_OF_MESH, NULL) {
float *co = CustomData_bmesh_get_n(&bmesh->vdata, v->head.data, CD_SHAPEKEY, skey);
copy_v3_v3(co, v->co);
}
/*first go through and tag edges*/ /*first go through and tag edges*/
BMO_Flag_To_Slot(bmesh, op, "edges", BMO_Flag_To_Slot(bmesh, op, "edges",
SUBD_SPLIT, BM_EDGE); SUBD_SPLIT, BM_EDGE);
@ -735,9 +841,14 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
params.numcuts = numcuts; params.numcuts = numcuts;
params.op = op; params.op = op;
params.smooth = smooth; params.smooth = smooth;
params.seed = seed;
params.fractal = fractal; params.fractal = fractal;
params.beauty = beauty; params.beauty = beauty;
params.origkey = skey;
params.off[0] = BLI_drand()*200.0f;
params.off[1] = BLI_drand()*200.0f;
params.off[2] = BLI_drand()*200.0f;
BMO_Mapping_To_Flag(bmesh, op, "custompatterns", BMO_Mapping_To_Flag(bmesh, op, "custompatterns",
FACE_CUSTOMFILL); FACE_CUSTOMFILL);
@ -967,6 +1078,14 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
pat->connectexec(bmesh, face, verts, &params); pat->connectexec(bmesh, face, verts, &params);
} }
/*copy original-geometry displacements to current coordinates*/
BM_ITER(v, &viter, bmesh, BM_VERTS_OF_MESH, NULL) {
float *co = CustomData_bmesh_get_n(&bmesh->vdata, v->head.data, CD_SHAPEKEY, skey);
copy_v3_v3(v->co, co);
}
BM_free_data_layer_n(bmesh, &bmesh->vdata, CD_SHAPEKEY, skey);
if (facedata) BLI_array_free(facedata); if (facedata) BLI_array_free(facedata);
if (edges) BLI_array_free(edges); if (edges) BLI_array_free(edges);
if (verts) BLI_array_free(verts); if (verts) BLI_array_free(verts);
@ -985,15 +1104,15 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
/*editmesh-emulating function*/ /*editmesh-emulating function*/
void BM_esubdivideflag(Object *UNUSED(obedit), BMesh *bm, int flag, float smooth, void BM_esubdivideflag(Object *UNUSED(obedit), BMesh *bm, int flag, float smooth,
float fractal, int beauty, int numcuts, float fractal, int beauty, int numcuts,
int seltype, int cornertype, int singleedge, int gridfill) int seltype, int cornertype, int singleedge, int gridfill, int seed)
{ {
BMOperator op; BMOperator op;
BMO_InitOpf(bm, &op, "esubd edges=%he smooth=%f fractal=%f " BMO_InitOpf(bm, &op, "esubd edges=%he smooth=%f fractal=%f "
"beauty=%d numcuts=%d quadcornertype=%d singleedge=%d " "beauty=%d numcuts=%d quadcornertype=%d singleedge=%d "
"gridfill=%d", "gridfill=%d seed=%d",
flag, smooth, fractal, beauty, numcuts, flag, smooth, fractal, beauty, numcuts,
cornertype, singleedge, gridfill); cornertype, singleedge, gridfill, seed);
BMO_Exec_Op(bm, &op); BMO_Exec_Op(bm, &op);
@ -1040,31 +1159,21 @@ void BM_esubdivideflag(Object *UNUSED(obedit), BMesh *bm, int flag, float smooth
BMO_Finish_Op(bm, &op); BMO_Finish_Op(bm, &op);
} }
#if 0
void BM_esubdivideflag_conv(Object *obedit,EditMesh *em,int selflag, float rad,
int flag, int numcuts, int seltype) {
BMesh *bm = editmesh_to_bmesh(em);
EditMesh *em2;
BM_esubdivideflag(obedit, bm, selflag, rad, flag, numcuts, seltype);
em2 = bmesh_to_editmesh(bm);
free_editMesh(em);
*em = *em2;
MEM_freeN(em2);
BM_Free_Mesh(bm);
}
#endif
void esplit_exec(BMesh *bm, BMOperator *op) void esplit_exec(BMesh *bm, BMOperator *op)
{ {
BMOIter siter; BMOIter siter;
BMEdge *e; BMEdge *e;
subdparams params; subdparams params;
int skey;
params.numcuts = BMO_GetSlot(op, "numcuts")->data.i; params.numcuts = BMO_GetSlot(op, "numcuts")->data.i;
params.op = op; params.op = op;
BM_add_data_layer(bm, &bm->vdata, CD_SHAPEKEY);
skey = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY)-1;
params.origkey = skey;
/*go through and split edges*/ /*go through and split edges*/
BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) { BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
bm_subdivide_multicut(bm, e, &params, e->v1, e->v2); bm_subdivide_multicut(bm, e, &params, e->v1, e->v2);
@ -1072,4 +1181,6 @@ void esplit_exec(BMesh *bm, BMOperator *op)
BMO_Flag_To_Slot(bm, op, "outsplit", BMO_Flag_To_Slot(bm, op, "outsplit",
ELE_SPLIT, BM_ALL); ELE_SPLIT, BM_ALL);
BM_free_data_layer_n(bm, &bm->vdata, CD_SHAPEKEY, skey);
} }

@ -6,7 +6,10 @@ typedef struct subdparams {
float smooth; float smooth;
float fractal; float fractal;
int beauty; int beauty;
int seed;
int origkey; /*shapekey holding displaced vertex coordinates for current geometry*/
BMOperator *op; BMOperator *op;
float off[3];
} subdparams; } subdparams;
typedef void (*subd_pattern_fill_fp)(BMesh *bm, BMFace *face, BMVert **verts, typedef void (*subd_pattern_fill_fp)(BMesh *bm, BMFace *face, BMVert **verts,
@ -35,4 +38,4 @@ typedef struct subdpattern {
split the edge only? split the edge only?
*/ */
#endif /* _SUBDIVIDEOP_H */ #endif /* _SUBDIVIDEOP_H */

@ -112,21 +112,24 @@ static int subdivide_exec(bContext *C, wmOperator *op)
Object *obedit= CTX_data_edit_object(C); Object *obedit= CTX_data_edit_object(C);
BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
int cuts= RNA_int_get(op->ptr,"number_cuts"); int cuts= RNA_int_get(op->ptr,"number_cuts");
float smooth= 0.292f*RNA_float_get(op->ptr, "smoothness"); float fractal= RNA_float_get(op->ptr, "fractal")/2.5;
float fractal= RNA_float_get(op->ptr, "fractal")/100;
int flag= 0; int flag= 0;
if(smooth != 0.0f)
flag |= B_SMOOTH;
if(fractal != 0.0f) if(fractal != 0.0f)
flag |= B_FRACTAL; flag |= B_FRACTAL;
if (RNA_boolean_get(op->ptr, "quadtri") &&
RNA_enum_get(op->ptr, "quadcorner") == SUBD_STRAIGHT_CUT)
{
RNA_enum_set(op->ptr, "quadcorner", SUBD_INNERVERT);
}
BM_esubdivideflag(obedit, em->bm, BM_SELECT, BM_esubdivideflag(obedit, em->bm, BM_SELECT,
smooth, fractal, 0.0f, fractal,
ts->editbutflag|flag, ts->editbutflag|flag,
cuts, 0, RNA_enum_get(op->ptr, "quadcorner"), cuts, 0, RNA_enum_get(op->ptr, "quadcorner"),
RNA_boolean_get(op->ptr, "tess_single_edge"), RNA_boolean_get(op->ptr, "quadtri"),
RNA_boolean_get(op->ptr, "gridfill")); 1, RNA_int_get(op->ptr, "seed"));
DAG_id_tag_update(obedit->data, OB_RECALC_DATA); DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
@ -158,19 +161,18 @@ void MESH_OT_subdivide(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
/* properties */ /* properties */
RNA_def_int(ot->srna, "number_cuts", 1, 1, 20, "Number of Cuts", "", 1, INT_MAX); RNA_def_int(ot->srna, "number_cuts", 1, 1, 50, "Number of Cuts", "", 1, INT_MAX);
RNA_def_float(ot->srna, "fractal", 0.0, 0.0f, FLT_MAX, "Fractal", "Fractal randomness factor.", 0.0f, 1000.0f);
RNA_def_float(ot->srna, "smoothness", 0.0f, 0.0f, 1000.0f, "Smoothness", "Smoothness factor.", 0.0f, FLT_MAX);
/*props */ RNA_def_boolean(ot->srna, "quadtri", 0, "Quad/Tri Mode", "Tries to prevent ngons");
RNA_def_enum(ot->srna, "quadcorner", prop_mesh_cornervert_types, SUBD_STRAIGHT_CUT, "Quad Corner Type", "Method used for subdividing two adjacent edges in a quad"); RNA_def_enum(ot->srna, "quadcorner", prop_mesh_cornervert_types, SUBD_STRAIGHT_CUT, "Quad Corner Type", "How to subdivide quad corners (anything other then Straight Cut will prevent ngons)");
RNA_def_boolean(ot->srna, "tess_single_edge", 0, "Tesselate Single Edge", "Adds triangles to single edges belonging to triangles or quads");
RNA_def_boolean(ot->srna, "gridfill", 1, "Grid Fill", "Fill Fully Selected Triangles and Quads With A Grid"); RNA_def_float(ot->srna, "fractal", 0.0, 0.0f, FLT_MAX, "Fractal", "Fractal randomness factor.", 0.0f, 1000.0f);
RNA_def_int(ot->srna, "seed", 0, 0, 10000, "Random Seed", "Seed for the random number generator", 0, 50);
} }
/* individual face extrude */ /* individual face extrude */
/* will use vertex normals for extrusion directions, so *nor is unaffected */ /* will use vertex normals for extrusion directions, so *nor is unaffected */
short EDBM_Extrude_face_indiv(BMEditMesh *em, wmOperator *op, short flag, float *nor) short EDBM_Extrude_face_indiv(BMEditMesh *em, wmOperator *op, short flag, float *UNUSED(nor))
{ {
BMOIter siter; BMOIter siter;
BMIter liter; BMIter liter;
@ -790,7 +792,7 @@ void EDBM_toggle_select_all(BMEditMesh *em) /* exported for UV */
EDBM_set_flag_all(em, SELECT); EDBM_set_flag_all(em, SELECT);
} }
static int toggle_select_all_exec(bContext *C, wmOperator *op) static int toggle_select_all_exec(bContext *C, wmOperator *UNUSED(op))
{ {
Object *obedit= CTX_data_edit_object(C); Object *obedit= CTX_data_edit_object(C);
BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
@ -1240,7 +1242,7 @@ void MESH_OT_mark_sharp(wmOperatorType *ot)
} }
static int editbmesh_vert_connect(bContext *C, wmOperator *op) static int editbmesh_vert_connect(bContext *C, wmOperator *UNUSED(op))
{ {
Object *obedit= CTX_data_edit_object(C); Object *obedit= CTX_data_edit_object(C);
BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
@ -1675,7 +1677,7 @@ void EDBM_reveal_mesh(BMEditMesh *em)
EDBM_selectmode_flush(em); EDBM_selectmode_flush(em);
} }
static int reveal_mesh_exec(bContext *C, wmOperator *op) static int reveal_mesh_exec(bContext *C, wmOperator *UNUSED(op))
{ {
Object *obedit= CTX_data_edit_object(C); Object *obedit= CTX_data_edit_object(C);
BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh; BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh;
@ -1804,7 +1806,7 @@ void MESH_OT_vertices_smooth(wmOperatorType *ot)
} }
static int bm_test_exec(bContext *C, wmOperator *op) static int bm_test_exec(bContext *C, wmOperator *UNUSED(op))
{ {
Object *obedit= CTX_data_edit_object(C); Object *obedit= CTX_data_edit_object(C);
RegionView3D *r3d = CTX_wm_region_view3d(C); RegionView3D *r3d = CTX_wm_region_view3d(C);

@ -295,7 +295,7 @@ static void ringsel_finish(bContext *C, wmOperator *op)
if (lcd->do_cut) { if (lcd->do_cut) {
BM_esubdivideflag(lcd->ob, em->bm, BM_SELECT, 0.0f, BM_esubdivideflag(lcd->ob, em->bm, BM_SELECT, 0.0f,
0.0f, 0, cuts, SUBDIV_SELECT_LOOPCUT, 0.0f, 0, cuts, SUBDIV_SELECT_LOOPCUT,
SUBD_PATH, 0, 0); SUBD_PATH, 0, 0, 0);
/* force edge slide to edge select mode in in face select mode */ /* force edge slide to edge select mode in in face select mode */
if (em->selectmode & SCE_SELECT_FACE) { if (em->selectmode & SCE_SELECT_FACE) {
if (em->selectmode == SCE_SELECT_FACE) if (em->selectmode == SCE_SELECT_FACE)