diff options
author | Joseph Eagar <joeedh@gmail.com> | 2011-03-28 04:29:45 +0400 |
---|---|---|
committer | Joseph Eagar <joeedh@gmail.com> | 2011-03-28 04:29:45 +0400 |
commit | 3875461a3349722fcb7c31e444a9c76c02ae314d (patch) | |
tree | 6d7eb69342072f9e6b566d2a1fb44538cb5bf566 | |
parent | fc050837b00a0b24f83900402c04211eaa70693a (diff) |
=bmesh=
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.
-rw-r--r-- | release/scripts/ui/space_view3d.py | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/customdata.c | 3 | ||||
-rw-r--r-- | source/blender/bmesh/bmesh.h | 12 | ||||
-rw-r--r-- | source/blender/bmesh/bmesh_operators.h | 2 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_interp.c | 17 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_mods.c | 4 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_opdefines.c | 1 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_polygon.c | 21 | ||||
-rw-r--r-- | source/blender/bmesh/operators/subdivideop.c | 287 | ||||
-rw-r--r-- | source/blender/bmesh/operators/subdivideop.h | 5 | ||||
-rw-r--r-- | source/blender/editors/mesh/bmesh_tools.c | 42 | ||||
-rw-r--r-- | source/blender/editors/mesh/loopcut.c | 2 |
12 files changed, 276 insertions, 123 deletions
diff --git a/release/scripts/ui/space_view3d.py b/release/scripts/ui/space_view3d.py index 730c442ad25..cb10d6a3570 100644 --- a/release/scripts/ui/space_view3d.py +++ b/release/scripts/ui/space_view3d.py @@ -557,7 +557,7 @@ class VIEW3D_MT_select_edit_curve(bpy.types.Menu): 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" 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("mesh.subdivide", text="Subdivide") - layout.operator("mesh.subdivide", text="Subdivide Smooth").smoothness = 1.0 layout.operator("mesh.merge", text="Merge...") layout.operator("mesh.remove_doubles") layout.operator("mesh.hide", text="Hide") diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 346fb5dd85d..e40275121ae 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -1450,8 +1450,9 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, int size = typeInfo->size * totelem, flag = 0, index = data->totlayer; 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)]; + } if((alloctype == CD_ASSIGN) || (alloctype == CD_REFERENCE)) { newlayerdata = layerdata; diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h index e5c2daaa016..97741854f71 100644 --- a/source/blender/bmesh/bmesh.h +++ b/source/blender/bmesh/bmesh.h @@ -204,6 +204,7 @@ void BM_Edge_UpdateNormals ( BMesh *bm, BMEdge *e ); /*update a vert normal (but not the faces incident on it)*/ void BM_Vert_UpdateNormal ( BMesh *bm, BMVert *v ); +void BM_Vert_UpdateAllNormals ( BMesh *bm, BMVert *v ); 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_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_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_named ( BMesh *bm, CustomData *data, int type, char *name ); -void BM_free_data_layer ( BMesh *em, CustomData *data, int type ); +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_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_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); void BM_SetCDf(struct CustomData *cd, void *element, int type, float val); diff --git a/source/blender/bmesh/bmesh_operators.h b/source/blender/bmesh/bmesh_operators.h index 620d7576141..490e9c849d3 100644 --- a/source/blender/bmesh/bmesh_operators.h +++ b/source/blender/bmesh/bmesh_operators.h @@ -81,7 +81,7 @@ struct EditMesh; void BMOP_DupeFromFlag(struct BMesh *bm, int etypeflag, int flag); void BM_esubdivideflag(struct Object *obedit, BMesh *bm, int flag, float smooth, 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); /*this next one return 1 if they did anything, or zero otherwise. diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index c089c20e3d9..9e1d1fc6176 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -118,7 +118,10 @@ void BM_Data_Facevert_Edgeinterp(BMesh *bm, BMVert *v1, BMVert *UNUSED(v2), BMVe v2loop = (BMLoop*)(l->prev); } - + + if (!v1loop || !v2loop) + return; + src[0] = v1loop->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); } +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) { if (CustomData_has_layer(cd, type)) { diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index f8524f10006..1759d6ae365 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -517,8 +517,8 @@ BMVert *BM_Split_Edge(BMesh *bm, BMVert *v, BMEdge *e, BMEdge **ne, float percen } /*v->nv->v2*/ - BM_Data_Facevert_Edgeinterp(bm,v2, v, nv, e, percent); - BM_Data_Interp_From_Verts(bm, v2, v, nv, percent); + BM_Data_Facevert_Edgeinterp(bm, v2, v, nv, e, percent); + BM_Data_Interp_From_Verts(bm, v, v2, nv, percent); if (CustomData_has_layer(&bm->ldata, CD_MDISPS) && e->l && nv) { int i, j; diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index c949d730d8c..a9fd22a9e2e 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -657,6 +657,7 @@ BMOpDefine def_subdop = { {BMOP_OPSLOT_FLT, "smooth"}, {BMOP_OPSLOT_FLT, "fractal"}, {BMOP_OPSLOT_INT, "beauty"}, + {BMOP_OPSLOT_INT, "seed"}, {BMOP_OPSLOT_MAPPING, "custompatterns"}, {BMOP_OPSLOT_MAPPING, "edgepercents"}, diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 89bbfeac478..8eea93e0223 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -445,7 +445,26 @@ void BM_Vert_UpdateNormal(BMesh *bm, BMVert *v) 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]) diff --git a/source/blender/bmesh/operators/subdivideop.c b/source/blender/bmesh/operators/subdivideop.c index 320381e664c..ca649b86c30 100644 --- a/source/blender/bmesh/operators/subdivideop.c +++ b/source/blender/bmesh/operators/subdivideop.c @@ -86,6 +86,59 @@ NOTE: beauty has been renamed to flag! 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 edge subdivision*/ 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; } /* 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) { 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) { - /* we calculate an offset vector vec1[], to be added to *co */ - 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; + origco = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, params->origkey); + sub_v3_v3v3(vec1, origco, v->co); + + for (i=0; i<totlayer; i++) { + co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, i); + sub_v3_v3(co, vec1); } - if(params->beauty & B_FRACTAL) { - fac= params->fractal*len_v3v3(vsta->co, vend->co); - vec1[0]= fac*(float)(0.5-BLI_drand()); - vec1[1]= fac*(float)(0.5-BLI_drand()); - vec1[2]= fac*(float)(0.5-BLI_drand()); - add_v3_v3v3(co, co, vec1); + for (i=0; i<totlayer; i++) { + co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, i); + + if(params->beauty & B_SMOOTH) { + /* we calculate an offset vector vec1[], to be added to *co */ + 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) { 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, oedge, params, percent2, vsta, vend); + alter_co(bm, ev, oedge, params, percent2, vsta, vend); #if 0 //TODO /* clip if needed by mirror modifier */ @@ -220,7 +300,7 @@ static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge, "edgepercents", edge); else { 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, BMVert *vsta, BMVert *vend) { 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; + temp.v1 = &ov1; + temp.v2 = &ov2; + for(i=0;i<numcuts;i++) { v = subdivideedgenum(bm, eed, &temp, i, params->numcuts, params, &newe, vsta, vend); + BMO_SetFlag(bm, v, SUBD_SPLIT); BMO_SetFlag(bm, eed, 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 && 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 @@ -344,7 +431,7 @@ static void quad_2edge_split_innervert(BMesh *bm, BMFace *UNUSED(face), BMVert * { BMFace *nf; BMVert *v, *lastv; - BMEdge *e, *ne; + BMEdge *e, *ne, olde; int i, numcuts = params->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)], &nf); - v = BM_Split_Edge(bm, e->v1, e, &ne, 0.5f); - connect_smallest_face(bm, lastv, v, &nf); + olde = *e; + 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; } @@ -496,7 +587,7 @@ static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts temp = *e; for (a=0; a<numcuts; a++) { v = subdivideedgenum(bm, e, &temp, a, numcuts, params, &ne, - v1, v2); + v1, v2); if (!v) bmesh_error(); @@ -561,7 +652,7 @@ static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, { BMFace *nf; BMEdge *e, *ne, temp; - BMVert ***lines, *v; + BMVert ***lines, *v, ov1, ov2; void *stackarr[1]; 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]; temp = *e; + ov1 = *verts[a]; + ov2 = *verts[b]; + temp.v1 = &ov1; + temp.v2 = &ov2; for (j=0; j<i; j++) { v = subdivideedgenum(bm, e, &temp, j, i, params, &ne, verts[a], verts[b]); @@ -670,27 +765,27 @@ typedef struct subd_facedata { void esubdivide_exec(BMesh *bmesh, BMOperator *op) { 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; subdparams params; subd_facedata *facedata = NULL; - BLI_array_declare(facedata); - BMLoop *l, **splits = NULL, **loops = NULL; + BMIter viter, fiter, liter; + BMVert *v, **verts = NULL; + BMEdge *edge, **edges = NULL; + BMLoop *nl, *l, **splits = NULL, **loops = NULL; + BMFace *face; BLI_array_declare(splits); BLI_array_declare(loops); + BLI_array_declare(facedata); + BLI_array_declare(edges); + BLI_array_declare(verts); float smooth, fractal; 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); numcuts = BMO_Get_Int(op, "numcuts"); + seed = BMO_Get_Int(op, "seed"); smooth = BMO_Get_Float(op, "smooth"); fractal = BMO_Get_Float(op, "fractal"); beauty = BMO_Get_Int(op, "beauty"); @@ -698,6 +793,8 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op) singleedge = BMO_Get_Int(op, "singleedge"); gridfill = BMO_Get_Int(op, "gridfill"); + BLI_srandom(seed); + patterns[1] = NULL; //straight cut is patterns[1] == NULL switch (cornertype) { @@ -728,6 +825,15 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op) 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*/ BMO_Flag_To_Slot(bmesh, op, "edges", SUBD_SPLIT, BM_EDGE); @@ -735,9 +841,14 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op) params.numcuts = numcuts; params.op = op; params.smooth = smooth; + params.seed = seed; params.fractal = fractal; 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", FACE_CUSTOMFILL); @@ -967,6 +1078,14 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op) pat->connectexec(bmesh, face, verts, ¶ms); } + /*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 (edges) BLI_array_free(edges); if (verts) BLI_array_free(verts); @@ -985,15 +1104,15 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op) /*editmesh-emulating function*/ void BM_esubdivideflag(Object *UNUSED(obedit), BMesh *bm, int flag, float smooth, 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; BMO_InitOpf(bm, &op, "esubd edges=%he smooth=%f fractal=%f " "beauty=%d numcuts=%d quadcornertype=%d singleedge=%d " - "gridfill=%d", + "gridfill=%d seed=%d", flag, smooth, fractal, beauty, numcuts, - cornertype, singleedge, gridfill); + cornertype, singleedge, gridfill, seed); 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); } -#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) { BMOIter siter; BMEdge *e; subdparams params; - + int skey; + params.numcuts = BMO_GetSlot(op, "numcuts")->data.i; 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*/ BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) { bm_subdivide_multicut(bm, e, ¶ms, e->v1, e->v2); @@ -1072,4 +1181,6 @@ void esplit_exec(BMesh *bm, BMOperator *op) BMO_Flag_To_Slot(bm, op, "outsplit", ELE_SPLIT, BM_ALL); + + BM_free_data_layer_n(bm, &bm->vdata, CD_SHAPEKEY, skey); } diff --git a/source/blender/bmesh/operators/subdivideop.h b/source/blender/bmesh/operators/subdivideop.h index 7bb471117d8..966cd90cbde 100644 --- a/source/blender/bmesh/operators/subdivideop.h +++ b/source/blender/bmesh/operators/subdivideop.h @@ -6,7 +6,10 @@ typedef struct subdparams { float smooth; float fractal; int beauty; + int seed; + int origkey; /*shapekey holding displaced vertex coordinates for current geometry*/ BMOperator *op; + float off[3]; } subdparams; typedef void (*subd_pattern_fill_fp)(BMesh *bm, BMFace *face, BMVert **verts, @@ -35,4 +38,4 @@ typedef struct subdpattern { split the edge only? */ -#endif /* _SUBDIVIDEOP_H */
\ No newline at end of file +#endif /* _SUBDIVIDEOP_H */ diff --git a/source/blender/editors/mesh/bmesh_tools.c b/source/blender/editors/mesh/bmesh_tools.c index a34c2d86a50..5b33a6b5d1c 100644 --- a/source/blender/editors/mesh/bmesh_tools.c +++ b/source/blender/editors/mesh/bmesh_tools.c @@ -112,21 +112,24 @@ static int subdivide_exec(bContext *C, wmOperator *op) Object *obedit= CTX_data_edit_object(C); BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; 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")/100; + float fractal= RNA_float_get(op->ptr, "fractal")/2.5; int flag= 0; - if(smooth != 0.0f) - flag |= B_SMOOTH; if(fractal != 0.0f) 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, - smooth, fractal, + 0.0f, fractal, ts->editbutflag|flag, cuts, 0, RNA_enum_get(op->ptr, "quadcorner"), - RNA_boolean_get(op->ptr, "tess_single_edge"), - RNA_boolean_get(op->ptr, "gridfill")); + RNA_boolean_get(op->ptr, "quadtri"), + 1, RNA_int_get(op->ptr, "seed")); DAG_id_tag_update(obedit->data, OB_RECALC_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; /* properties */ - RNA_def_int(ot->srna, "number_cuts", 1, 1, 20, "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); + RNA_def_int(ot->srna, "number_cuts", 1, 1, 50, "Number of Cuts", "", 1, INT_MAX); - /*props */ - 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_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_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", "How to subdivide quad corners (anything other then Straight Cut will prevent ngons)"); + + 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 */ /* 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; BMIter liter; @@ -790,7 +792,7 @@ void EDBM_toggle_select_all(BMEditMesh *em) /* exported for UV */ 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); 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); BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; @@ -1675,7 +1677,7 @@ void EDBM_reveal_mesh(BMEditMesh *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); 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); RegionView3D *r3d = CTX_wm_region_view3d(C); diff --git a/source/blender/editors/mesh/loopcut.c b/source/blender/editors/mesh/loopcut.c index 711177e817b..6cb79039a88 100644 --- a/source/blender/editors/mesh/loopcut.c +++ b/source/blender/editors/mesh/loopcut.c @@ -295,7 +295,7 @@ static void ringsel_finish(bContext *C, wmOperator *op) if (lcd->do_cut) { BM_esubdivideflag(lcd->ob, em->bm, BM_SELECT, 0.0f, 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 */ if (em->selectmode & SCE_SELECT_FACE) { if (em->selectmode == SCE_SELECT_FACE) |