diff options
Diffstat (limited to 'source/blender/bmesh/intern/bmesh_interp.c')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_interp.c | 213 |
1 files changed, 101 insertions, 112 deletions
diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index 6e468bf44f2..f51013c3f1c 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -197,7 +197,7 @@ void BM_face_interp_from_face_ex( if (do_vertex) { CustomData_bmesh_interp(&bm->vdata, blocks_v, w, NULL, f_src->len, l_iter->v->head.data); } - } while (i++, (l_iter = l_iter->next) != l_first); + } while ((void)i++, (l_iter = l_iter->next) != l_first); } void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex) @@ -221,7 +221,7 @@ void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, con mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co); blocks_l[i] = l_iter->head.data; if (do_vertex) blocks_v[i] = l_iter->v->head.data; - } while (i++, (l_iter = l_iter->next) != l_first); + } while ((void)i++, (l_iter = l_iter->next) != l_first); BM_face_interp_from_face_ex(bm, f_dst, f_src, do_vertex, blocks_l, blocks_v, cos_2d, axis_mat); @@ -242,18 +242,25 @@ void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, con * </pre> */ static int compute_mdisp_quad( - BMLoop *l, float v1[3], float v2[3], float v3[3], float v4[3], + const BMLoop *l, const float l_f_center[3], + float v1[3], float v2[3], float v3[3], float v4[3], float e1[3], float e2[3]) { - float cent[3], n[3], p[3]; - - /* computer center */ - BM_face_calc_center_mean(l->f, cent); + float n[3], p[3]; + +#ifndef NDEBUG + { + float cent[3]; + /* computer center */ + BM_face_calc_center_mean(l->f, cent); + BLI_assert(equals_v3v3(cent, l_f_center)); + } +#endif mid_v3_v3v3(p, l->prev->v->co, l->v->co); mid_v3_v3v3(n, l->next->v->co, l->v->co); - copy_v3_v3(v1, cent); + copy_v3_v3(v1, l_f_center); copy_v3_v3(v2, p); copy_v3_v3(v3, l->v->co); copy_v3_v3(v4, n); @@ -264,52 +271,13 @@ static int compute_mdisp_quad( return 1; } -/* funnily enough, I think this is identical to face_to_crn_interp, heh */ -static float quad_coord(const float aa[3], const float bb[3], const float cc[3], const float dd[3], int a1, int a2) -{ - float x, y, z, f1; - float div; - - x = aa[a1] * cc[a2] - cc[a1] * aa[a2]; - y = aa[a1] * dd[a2] + bb[a1] * cc[a2] - cc[a1] * bb[a2] - dd[a1] * aa[a2]; - z = bb[a1] * dd[a2] - dd[a1] * bb[a2]; - - div = 2.0f * (x - y + z); - - if (fabsf(div) > FLT_EPSILON * 10.0f) { - const float f_tmp = sqrtf(y * y - 4.0f * x * z); - - f1 = min_ff(fabsf(( f_tmp - y + 2.0f * z) / div), - fabsf((-f_tmp - y + 2.0f * z) / div)); - - CLAMP_MAX(f1, 1.0f + FLT_EPSILON); - } - else { - f1 = -z / (y - 2 * z); - CLAMP(f1, 0.0f, 1.0f + FLT_EPSILON); - - if (isnan(f1) || f1 > 1.0f || f1 < 0.0f) { - int i; - - for (i = 0; i < 2; i++) { - if (fabsf(aa[i]) < FLT_EPSILON * 100.0f) - return aa[(i + 1) % 2] / fabsf(bb[(i + 1) % 2] - aa[(i + 1) % 2]); - if (fabsf(cc[i]) < FLT_EPSILON * 100.0f) - return cc[(i + 1) % 2] / fabsf(dd[(i + 1) % 2] - cc[(i + 1) % 2]); - } - } - } - - return f1; -} - -static int quad_co( - float *r_x, float *r_y, +static bool quad_co( const float v1[3], const float v2[3], const float v3[3], const float v4[3], - const float p[3], const float n[3]) + const float p[3], const float n[3], + float r_uv[2]) { float projverts[5][3], n2[3]; - float dprojverts[4][3], origin[3] = {0.0f, 0.0f, 0.0f}; + float origin[2] = {0.0f, 0.0f}; int i; /* project points into 2d along normal */ @@ -322,7 +290,7 @@ static int quad_co( normal_quad_v3(n2, projverts[0], projverts[1], projverts[2], projverts[3]); if (dot_v3v3(n, n2) < -FLT_EPSILON) { - return 0; + return false; } /* rotate */ @@ -330,50 +298,45 @@ static int quad_co( /* subtract origin */ for (i = 0; i < 4; i++) { - sub_v3_v3(projverts[i], projverts[4]); + sub_v2_v2(projverts[i], projverts[4]); } - - copy_v3_v3(dprojverts[0], projverts[0]); - copy_v3_v3(dprojverts[1], projverts[1]); - copy_v3_v3(dprojverts[2], projverts[2]); - copy_v3_v3(dprojverts[3], projverts[3]); - if (!isect_point_quad_v2(origin, dprojverts[0], dprojverts[1], dprojverts[2], dprojverts[3])) { - return 0; + if (!isect_point_quad_v2(origin, projverts[0], projverts[1], projverts[2], projverts[3])) { + return false; } - - *r_y = quad_coord(dprojverts[1], dprojverts[0], dprojverts[2], dprojverts[3], 0, 1); - *r_x = quad_coord(dprojverts[2], dprojverts[1], dprojverts[3], dprojverts[0], 0, 1); - return 1; + resolve_quad_uv_v2(r_uv, origin, projverts[0], projverts[3], projverts[2], projverts[1]); + + return true; } static void mdisp_axis_from_quad( float v1[3], float v2[3], float UNUSED(v3[3]), float v4[3], - float axis_x[3], float axis_y[3]) + float r_axis_x[3], float r_axis_y[3]) { - sub_v3_v3v3(axis_x, v4, v1); - sub_v3_v3v3(axis_y, v2, v1); + sub_v3_v3v3(r_axis_x, v4, v1); + sub_v3_v3v3(r_axis_y, v2, v1); - normalize_v3(axis_x); - normalize_v3(axis_y); + normalize_v3(r_axis_x); + normalize_v3(r_axis_y); } /* tl is loop to project onto, l is loop whose internal displacement, co, is being * projected. x and y are location in loop's mdisps grid of point co. */ static bool mdisp_in_mdispquad( - BMLoop *l, BMLoop *tl, float p[3], float *x, float *y, - int res, float axis_x[3], float axis_y[3]) + BMLoop *l_src, BMLoop *l_dst, const float l_dst_f_center[3], + const float p[3], int res, + float r_axis_x[3], float r_axis_y[3], float r_uv[2]) { float v1[3], v2[3], c[3], v3[3], v4[3], e1[3], e2[3]; float eps = FLT_EPSILON * 4000; - if (is_zero_v3(l->v->no)) - BM_vert_normal_update_all(l->v); - if (is_zero_v3(tl->v->no)) - BM_vert_normal_update_all(tl->v); + if (is_zero_v3(l_src->v->no)) + BM_vert_normal_update_all(l_src->v); + if (is_zero_v3(l_dst->v->no)) + BM_vert_normal_update_all(l_dst->v); - compute_mdisp_quad(tl, v1, v2, v3, v4, e1, e2); + compute_mdisp_quad(l_dst, l_dst_f_center, v1, v2, v3, v4, e1, e2); /* expand quad a bit */ cent_quad_v3(c, v1, v2, v3, v4); @@ -385,13 +348,12 @@ static bool mdisp_in_mdispquad( add_v3_v3(v1, c); add_v3_v3(v2, c); add_v3_v3(v3, c); add_v3_v3(v4, c); - if (!quad_co(x, y, v1, v2, v3, v4, p, l->v->no)) + if (!quad_co(v1, v2, v3, v4, p, l_src->v->no, r_uv)) return 0; - *x *= res - 1; - *y *= res - 1; + mul_v2_fl(r_uv, (float)(res - 1)); - mdisp_axis_from_quad(v1, v2, v3, v4, axis_x, axis_y); + mdisp_axis_from_quad(v1, v2, v3, v4, r_axis_x, r_axis_y); return 1; } @@ -439,23 +401,21 @@ static void bm_loop_flip_disp( disp[1] = (mat[0][0] * b[1] - b[0] * mat[1][0]) / d; } -static void bm_loop_interp_mdisps(BMesh *bm, BMLoop *l_dst, const BMFace *f_src) +void BM_loop_interp_multires_ex( + BMesh *UNUSED(bm), BMLoop *l_dst, const BMFace *f_src, + const float f_dst_center[3], const float f_src_center[3], const int cd_loop_mdisp_offset) { - const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); MDisps *md_dst; float d, v1[3], v2[3], v3[3], v4[3] = {0.0f, 0.0f, 0.0f}, e1[3], e2[3]; int ix, res; float axis_x[3], axis_y[3]; - - if (cd_loop_mdisp_offset == -1) - return; /* ignore 2-edged faces */ if (UNLIKELY(l_dst->f->len < 3)) return; md_dst = BM_ELEM_CD_GET_VOID_P(l_dst, cd_loop_mdisp_offset); - compute_mdisp_quad(l_dst, v1, v2, v3, v4, e1, e2); + compute_mdisp_quad(l_dst, f_dst_center, v1, v2, v3, v4, e1, e2); /* if no disps data allocate a new grid, the size of the first grid in f_src. */ if (!md_dst->totdisp) { @@ -484,29 +444,20 @@ static void bm_loop_interp_mdisps(BMesh *bm, BMLoop *l_dst, const BMFace *f_src) BMLoop *l_first; float co1[3], co2[3], co[3]; - copy_v3_v3(co1, e1); - - mul_v3_fl(co1, y); - add_v3_v3(co1, v1); - - copy_v3_v3(co2, e2); - mul_v3_fl(co2, y); - add_v3_v3(co2, v4); - - sub_v3_v3v3(co, co2, co1); - mul_v3_fl(co, x); - add_v3_v3(co, co1); + madd_v3_v3v3fl(co1, v1, e1, y); + madd_v3_v3v3fl(co2, v4, e2, y); + interp_v3_v3v3(co, co1, co2, x); l_iter = l_first = BM_FACE_FIRST_LOOP(f_src); do { - float x2, y2; MDisps *md_src; float src_axis_x[3], src_axis_y[3]; + float uv[2]; md_src = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset); - if (mdisp_in_mdispquad(l_dst, l_iter, co, &x2, &y2, res, src_axis_x, src_axis_y)) { - old_mdisps_bilinear(md_dst->disps[iy * res + ix], md_src->disps, res, (float)x2, (float)y2); + if (mdisp_in_mdispquad(l_dst, l_iter, f_src_center, co, res, src_axis_x, src_axis_y, uv)) { + old_mdisps_bilinear(md_dst->disps[iy * res + ix], md_src->disps, res, uv[0], uv[1]); bm_loop_flip_disp(src_axis_x, src_axis_y, axis_x, axis_y, md_dst->disps[iy * res + ix]); break; @@ -517,6 +468,52 @@ static void bm_loop_interp_mdisps(BMesh *bm, BMLoop *l_dst, const BMFace *f_src) } /** + * project the multires grid in target onto f_src's set of multires grids + */ +void BM_loop_interp_multires(BMesh *bm, BMLoop *l_dst, const BMFace *f_src) +{ + const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); + + if (cd_loop_mdisp_offset != -1) { + float f_dst_center[3]; + float f_src_center[3]; + + BM_face_calc_center_mean(l_dst->f, f_dst_center); + BM_face_calc_center_mean(f_src, f_src_center); + + BM_loop_interp_multires_ex(bm, l_dst, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset); + } +} + +void BM_face_interp_multires_ex( + BMesh *bm, BMFace *f_dst, const BMFace *f_src, + const float f_dst_center[3], const float f_src_center[3], const int cd_loop_mdisp_offset) +{ + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f_dst); + do { + BM_loop_interp_multires_ex( + bm, l_iter, f_src, + f_dst_center, f_src_center, cd_loop_mdisp_offset); + } while ((l_iter = l_iter->next) != l_first); +} + +void BM_face_interp_multires(BMesh *bm, BMFace *f_dst, const BMFace *f_src) +{ + const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); + + if (cd_loop_mdisp_offset != -1) { + float f_dst_center[3]; + float f_src_center[3]; + + BM_face_calc_center_mean(f_dst, f_dst_center); + BM_face_calc_center_mean(f_src, f_src_center); + + BM_face_interp_multires_ex(bm, f_dst, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset); + } +} + +/** * smooths boundaries between multires grids, * including some borders in adjacent faces */ @@ -623,14 +620,6 @@ void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f) } /** - * project the multires grid in target onto f_src's set of multires grids - */ -void BM_loop_interp_multires(BMesh *bm, BMLoop *l_dst, const BMFace *f_src) -{ - bm_loop_interp_mdisps(bm, l_dst, f_src); -} - -/** * projects a single loop, target, onto f_src for customdata interpolation. multires is handled. * if do_vertex is true, target's vert data will also get interpolated. */ @@ -661,7 +650,7 @@ void BM_loop_interp_from_face( if (do_vertex) { vblocks[i] = l_iter->v->head.data; } - } while (i++, (l_iter = l_iter->next) != l_first); + } while ((void)i++, (l_iter = l_iter->next) != l_first); mul_v2_m3v3(co, axis_mat, l_dst->v->co); @@ -673,7 +662,7 @@ void BM_loop_interp_from_face( } if (do_multires) { - bm_loop_interp_mdisps(bm, l_dst, f_src); + BM_loop_interp_multires(bm, l_dst, f_src); } } @@ -698,7 +687,7 @@ void BM_vert_interp_from_face(BMesh *bm, BMVert *v_dst, const BMFace *f_src) do { mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co); blocks[i] = l_iter->v->head.data; - } while (i++, (l_iter = l_iter->next) != l_first); + } while ((void)i++, (l_iter = l_iter->next) != l_first); mul_v2_m3v3(co, axis_mat, v_dst->co); |