diff options
Diffstat (limited to 'source/blender/bmesh/operators')
-rw-r--r-- | source/blender/bmesh/operators/bmo_connect_pair.c | 2 | ||||
-rw-r--r-- | source/blender/bmesh/operators/bmo_extrude.c | 6 | ||||
-rw-r--r-- | source/blender/bmesh/operators/bmo_inset.c | 9 | ||||
-rw-r--r-- | source/blender/bmesh/operators/bmo_planar_faces.c | 4 | ||||
-rw-r--r-- | source/blender/bmesh/operators/bmo_similar.c | 18 | ||||
-rw-r--r-- | source/blender/bmesh/operators/bmo_subdivide.c | 153 |
6 files changed, 155 insertions, 37 deletions
diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c index ead1c7126e4..12af8902dc5 100644 --- a/source/blender/bmesh/operators/bmo_connect_pair.c +++ b/source/blender/bmesh/operators/bmo_connect_pair.c @@ -215,7 +215,7 @@ static void state_calc_co_pair( interp_v3_v3v3(r_co, co_a, co_b, fac); } -#ifdef DEBUG +#ifndef NDEBUG /** * Ideally we wouldn't need this and for most cases we don't. * But when a face has vertices that are on the boundary more than once this becomes tricky. diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c index 435b9e60949..3eae98b3c46 100644 --- a/source/blender/bmesh/operators/bmo_extrude.c +++ b/source/blender/bmesh/operators/bmo_extrude.c @@ -137,7 +137,7 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op) * This function won't crash if its not but won't work right either. * \a e_b is the new edge. * - * \note The edge this face comes from needs to be from the first and second verts fo the face. + * \note The edge this face comes from needs to be from the first and second verts to the face. * The caller must ensure this else we will copy from the wrong source. */ static void bm_extrude_copy_face_loop_attributes(BMesh *bm, BMFace *f) @@ -728,9 +728,9 @@ static void solidify_add_thickness(BMesh *bm, const float dist) if (BMO_elem_flag_test(bm, f, FACE_MARK)) { /* array for passing verts to angle_poly_v3 */ - float *face_angles = BLI_buffer_resize_data(&face_angles_buf, float, f->len); + float *face_angles = BLI_buffer_reinit_data(&face_angles_buf, float, f->len); /* array for receiving angles from angle_poly_v3 */ - float **verts = BLI_buffer_resize_data(&verts_buf, float *, f->len); + float **verts = BLI_buffer_reinit_data(&verts_buf, float *, f->len); BM_ITER_ELEM_INDEX (l, &loopIter, f, BM_LOOPS_OF_FACE, i) { verts[i] = l->v->co; diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c index 6664bf6dc46..118a19d3082 100644 --- a/source/blender/bmesh/operators/bmo_inset.c +++ b/source/blender/bmesh/operators/bmo_inset.c @@ -208,14 +208,11 @@ static void bm_loop_customdata_merge( */ const void *data_src; - CustomData_data_add( + CustomData_data_mix_value( type, BM_ELEM_CD_GET_VOID_P(l_a_inner_inset, offset), - BM_ELEM_CD_GET_VOID_P(l_b_inner_inset, offset)); - CustomData_data_multiply( - type, - BM_ELEM_CD_GET_VOID_P(l_a_inner_inset, offset), - 0.5f); + BM_ELEM_CD_GET_VOID_P(l_b_inner_inset, offset), + CDT_MIX_MIX, 0.5f); CustomData_data_copy_value( type, BM_ELEM_CD_GET_VOID_P(l_a_inner_inset, offset), diff --git a/source/blender/bmesh/operators/bmo_planar_faces.c b/source/blender/bmesh/operators/bmo_planar_faces.c index 4e3ac58a813..2856d3d18a6 100644 --- a/source/blender/bmesh/operators/bmo_planar_faces.c +++ b/source/blender/bmesh/operators/bmo_planar_faces.c @@ -21,7 +21,7 @@ /** \file blender/bmesh/operators/bmo_planar_faces.c * \ingroup bmesh * - * Iternatively flatten 4+ sided faces. + * Iteratively flatten 4+ sided faces. */ #include "MEM_guardedalloc.h" @@ -117,7 +117,7 @@ void bmo_planar_faces_exec(BMesh *bm, BMOperator *op) } va = *va_p; - closest_to_plane_v3(co, plane, l_iter->v->co); + closest_to_plane_normalized_v3(co, plane, l_iter->v->co); va->co_tot += 1; interp_v3_v3v3(va->co, va->co, co, 1.0f / (float)va->co_tot); diff --git a/source/blender/bmesh/operators/bmo_similar.c b/source/blender/bmesh/operators/bmo_similar.c index 5f8438919df..708d57a7a08 100644 --- a/source/blender/bmesh/operators/bmo_similar.c +++ b/source/blender/bmesh/operators/bmo_similar.c @@ -102,7 +102,6 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) float angle = 0.0f; SimSel_FaceExt *f_ext = NULL; int *indices = NULL; - float t_no[3]; /* temporary normal */ const int type = BMO_slot_int_get(op->slots_in, "type"); const float thresh = BMO_slot_float_get(op->slots_in, "thresh"); const float thresh_radians = thresh * (float)M_PI; @@ -158,12 +157,8 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) /* compute the center of the polygon */ BM_face_calc_center_mean(f_ext[i].f, f_ext[i].c); - /* normalize the polygon normal */ - copy_v3_v3(t_no, f_ext[i].f->no); - normalize_v3(t_no); - /* compute the plane distance */ - f_ext[i].d = dot_v3v3(t_no, f_ext[i].c); + f_ext[i].d = dot_v3v3(f_ext[i].f->no, f_ext[i].c); break; case SIMFACE_AREA: @@ -212,16 +207,23 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) break; case SIMFACE_COPLANAR: + { + float sign = 1.0f; angle = angle_normalized_v3v3(fs->no, fm->no); /* angle -> 0 */ + /* allow for normal pointing in either direction (just check the plane) */ + if (angle > (float)M_PI * 0.5f) { + angle = (float)M_PI - angle; + sign = -1.0f; + } if (angle <= thresh_radians) { /* and dot product difference -> 0 */ - delta_fl = f_ext[i].d - f_ext[indices[idx]].d; + delta_fl = f_ext[i].d - (f_ext[indices[idx]].d * sign); if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) { BMO_elem_flag_enable(bm, fm, FACE_MARK); cont = false; } } break; - + } case SIMFACE_AREA: delta_fl = f_ext[i].area - f_ext[indices[idx]].area; if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) { diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index 45e3c8d193d..38fa2cfdcc8 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -163,6 +163,85 @@ static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v_a, BMVert *v_b, BMFace return NULL; } + +/** + * Specialized slerp that uses a sphere defined by each points normal. + */ +static void interp_slerp_co_no_v3( + const float co_a[3], const float no_a[3], + const float co_b[3], const float no_b[3], + const float no_dir[3], /* caller already knows, avoid normalize */ + float fac, + float r_co[3]) +{ + /* center of the sphere defined by both normals */ + float center[3]; + + BLI_assert(len_squared_v3v3(no_a, no_b) != 0); + + /* calculate sphere 'center' */ + { + /* use point on plane to */ + float plane_a[4], plane_b[4], plane_c[4]; + float no_mid[3], no_ortho[3]; + /* pass this as an arg instead */ +#if 0 + float no_dir[3]; +#endif + + float v_a_no_ortho[3], v_b_no_ortho[3]; + + add_v3_v3v3(no_mid, no_a, no_b); + normalize_v3(no_mid); + +#if 0 + sub_v3_v3v3(no_dir, co_a, co_b); + normalize_v3(no_dir); +#endif + + /* axis of slerp */ + cross_v3_v3v3(no_ortho, no_mid, no_dir); + normalize_v3(no_ortho); + + /* create planes */ + cross_v3_v3v3(v_a_no_ortho, no_ortho, no_a); + cross_v3_v3v3(v_b_no_ortho, no_ortho, no_b); + project_v3_plane(v_a_no_ortho, no_ortho, v_a_no_ortho); + project_v3_plane(v_b_no_ortho, no_ortho, v_b_no_ortho); + + plane_from_point_normal_v3(plane_a, co_a, v_a_no_ortho); + plane_from_point_normal_v3(plane_b, co_b, v_b_no_ortho); + plane_from_point_normal_v3(plane_c, co_b, no_ortho); + + /* find the sphere center from 3 planes */ + if (isect_plane_plane_plane_v3(plane_a, plane_b, plane_c, center)) { + /* pass */ + } + else { + mid_v3_v3v3(center, co_a, co_b); + } + } + + /* calculate the final output 'r_co' */ + { + float ofs_a[3], ofs_b[3], ofs_slerp[3]; + float dist_a, dist_b; + + sub_v3_v3v3(ofs_a, co_a, center); + sub_v3_v3v3(ofs_b, co_b, center); + + dist_a = normalize_v3(ofs_a); + dist_b = normalize_v3(ofs_b); + + if (interp_v3_v3v3_slerp(ofs_slerp, ofs_a, ofs_b, fac)) { + madd_v3_v3v3fl(r_co, center, ofs_slerp, interpf(dist_b, dist_a, fac)); + } + else { + interp_v3_v3v3(r_co, co_a, co_b, fac); + } + } +} + /* calculates offset for co, based on fractal, sphere or smooth settings */ static void alter_co( BMVert *v, BMEdge *UNUSED(e_orig), @@ -179,32 +258,72 @@ static void alter_co( mul_v3_fl(co, params->smooth); } else if (params->use_smooth) { - /* we calculate an offset vector vec1[], to be added to *co */ - float dir[3], tvec[3]; - float fac, len, val; + /* calculating twice and blending gives smoother results, + * removing visible seams. */ +#define USE_SPHERE_DUAL_BLEND - sub_v3_v3v3(dir, v_a->co, v_b->co); - len = (float)M_SQRT1_2 * normalize_v3(dir); + const float eps_unit_vec = 1e-5f; + float smooth; + float no_dir[3]; - /* cosine angle */ - fac = dot_v3v3(dir, v_a->no); - mul_v3_v3fl(tvec, v_a->no, fac); +#ifdef USE_SPHERE_DUAL_BLEND + float no_reflect[3], co_a[3], co_b[3]; +#endif - /* cosine angle */ - fac = -dot_v3v3(dir, v_b->no); - madd_v3_v3fl(tvec, v_b->no, fac); + sub_v3_v3v3(no_dir, v_a->co, v_b->co); + normalize_v3(no_dir); - /* falloff for multi subdivide */ - val = fabsf(1.0f - 2.0f * fabsf(0.5f - perc)); - val = bmesh_subd_falloff_calc(params->smooth_falloff, val); +#ifndef USE_SPHERE_DUAL_BLEND + if (len_squared_v3v3(v_a->no, v_b->no) < eps_unit_vec) { + interp_v3_v3v3(co, v_a->co, v_b->co, perc); + } + else { + interp_slerp_co_no_v3(v_a->co, v_a->no, v_b->co, v_b->no, no_dir, perc, co); + } +#else + /* sphere-a */ + reflect_v3_v3v3(no_reflect, v_a->no, no_dir); + if (len_squared_v3v3(v_a->no, no_reflect) < eps_unit_vec) { + interp_v3_v3v3(co_a, v_a->co, v_b->co, perc); + } + else { + interp_slerp_co_no_v3(v_a->co, v_a->no, v_b->co, no_reflect, no_dir, perc, co_a); + } + + /* sphere-b */ + reflect_v3_v3v3(no_reflect, v_b->no, no_dir); + if (len_squared_v3v3(v_b->no, no_reflect) < eps_unit_vec) { + interp_v3_v3v3(co_b, v_a->co, v_b->co, perc); + } + else { + interp_slerp_co_no_v3(v_a->co, no_reflect, v_b->co, v_b->no, no_dir, perc, co_b); + } + + /* blend both spheres */ + interp_v3_v3v3(co, co_a, co_b, perc); +#endif /* USE_SPHERE_DUAL_BLEND */ + + /* apply falloff */ + if (params->smooth_falloff == SUBD_FALLOFF_LIN) { + smooth = 1.0f; + } + else { + smooth = fabsf(1.0f - 2.0f * fabsf(0.5f - perc)); + smooth = 1.0f + bmesh_subd_falloff_calc(params->smooth_falloff, smooth); + } if (params->use_smooth_even) { - val *= shell_v3v3_mid_normalized_to_dist(v_a->no, v_b->no); + smooth *= shell_v3v3_mid_normalized_to_dist(v_a->no, v_b->no); } - mul_v3_fl(tvec, params->smooth * val * len); + smooth *= params->smooth; + if (smooth != 1.0f) { + float co_flat[3]; + interp_v3_v3v3(co_flat, v_a->co, v_b->co, perc); + interp_v3_v3v3(co, co_flat, co, smooth); + } - add_v3_v3(co, tvec); +#undef USE_SPHERE_DUAL_BLEND } if (params->use_fractal) { |