From f75d6c4a8f47de096077ae4dc7c3b4e4ccff4043 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 3 Nov 2015 18:28:13 +1100 Subject: BMesh: add BM_loop_interp_multires_ex which takes cached vars Avoid recalculating face centers (for each loop) when interpolating multires. --- source/blender/bmesh/intern/bmesh_core.c | 13 +++- source/blender/bmesh/intern/bmesh_interp.c | 115 +++++++++++++++-------------- source/blender/bmesh/intern/bmesh_interp.h | 6 +- source/blender/bmesh/intern/bmesh_mods.c | 41 ++++++---- 4 files changed, 103 insertions(+), 72 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 858d91027ba..dfa78f611c4 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -1107,6 +1107,7 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del) BMVert *v1 = NULL, *v2 = NULL; const char *err = NULL; int i, tote = 0; + const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); if (UNLIKELY(!totface)) { BMESH_ASSERT(0); @@ -1237,11 +1238,19 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del) BM_ELEM_API_FLAG_DISABLE(f_new, _FLAG_JF); /* handle multi-res data */ - if (CustomData_has_layer(&bm->ldata, CD_MDISPS)) { + if (cd_loop_mdisp_offset != -1) { + float f_center[3]; + float (*faces_center)[3] = BLI_array_alloca(faces_center, totface); + + BM_face_calc_center_mean(f_new, f_center); + for (i = 0; i < totface; i++) { + BM_face_calc_center_mean(faces[i], faces_center[i]); + } + l_iter = l_first = BM_FACE_FIRST_LOOP(f_new); do { for (i = 0; i < totface; i++) { - BM_loop_interp_multires(bm, l_iter, faces[i]); + BM_loop_interp_multires_ex(bm, l_iter, faces[i], f_center, faces_center[i], cd_loop_mdisp_offset); } } while ((l_iter = l_iter->next) != l_first); } diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index 6e468bf44f2..d74e5de6dd8 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -242,18 +242,25 @@ void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, con * */ 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); @@ -304,9 +311,9 @@ static float quad_coord(const float aa[3], const float bb[3], const float cc[3], } static int quad_co( - float *r_x, float *r_y, 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}; @@ -342,38 +349,39 @@ static int quad_co( return 0; } - *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); + r_uv[0] = quad_coord(dprojverts[2], dprojverts[1], dprojverts[3], dprojverts[0], 0, 1); + r_uv[1] = quad_coord(dprojverts[1], dprojverts[0], dprojverts[2], dprojverts[3], 0, 1); return 1; } 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 +393,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 +446,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 +489,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; @@ -516,6 +512,21 @@ 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); + 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); +} + /** * smooths boundaries between multires grids, * including some borders in adjacent faces @@ -622,14 +633,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. @@ -673,7 +676,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); } } diff --git a/source/blender/bmesh/intern/bmesh_interp.h b/source/blender/bmesh/intern/bmesh_interp.h index 969e92f37db..a08a0c90b77 100644 --- a/source/blender/bmesh/intern/bmesh_interp.h +++ b/source/blender/bmesh/intern/bmesh_interp.h @@ -30,7 +30,11 @@ struct LinkNode; struct MemArena; -void BM_loop_interp_multires(BMesh *bm, BMLoop *l_dst, const BMFace *f_src); +void BM_loop_interp_multires_ex( + BMesh *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); +void BM_loop_interp_multires( + BMesh *bm, BMLoop *l_dst, const BMFace *f_src); void BM_vert_interp_from_face(BMesh *bm, BMVert *v_dst, const BMFace *f_src); void BM_data_interp_from_verts(BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v_dst, const float fac); diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 13c43fabdb0..3bf97ef024a 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -282,7 +282,7 @@ BMFace *BM_face_split( BMLoop **r_l, BMEdge *example, const bool no_double) { - const bool has_mdisp = CustomData_has_layer(&bm->ldata, CD_MDISPS); + const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); BMFace *f_new, *f_tmp; BLI_assert(l_a != l_b); @@ -300,7 +300,7 @@ BMFace *BM_face_split( } /* do we have a multires layer? */ - if (has_mdisp) { + if (cd_loop_mdisp_offset != -1) { f_tmp = BM_face_copy(bm, bm, f, false, false); } @@ -312,18 +312,24 @@ BMFace *BM_face_split( if (f_new) { /* handle multires update */ - if (has_mdisp) { + if (cd_loop_mdisp_offset != -1) { BMLoop *l_iter; BMLoop *l_first; + float f_dst_center[3]; + float f_src_center[3]; + BM_face_calc_center_mean(f_tmp, f_src_center); + + BM_face_calc_center_mean(f, f_dst_center); l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { - BM_loop_interp_multires(bm, l_iter, f_tmp); + BM_loop_interp_multires_ex(bm, l_iter, f_tmp, f_dst_center, f_src_center, cd_loop_mdisp_offset); } while ((l_iter = l_iter->next) != l_first); + BM_face_calc_center_mean(f_new, f_dst_center); l_iter = l_first = BM_FACE_FIRST_LOOP(f_new); do { - BM_loop_interp_multires(bm, l_iter, f_tmp); + BM_loop_interp_multires_ex(bm, l_iter, f_tmp, f_dst_center, f_src_center, cd_loop_mdisp_offset); } while ((l_iter = l_iter->next) != l_first); #if 0 @@ -334,7 +340,7 @@ BMFace *BM_face_split( } } - if (has_mdisp) { + if (cd_loop_mdisp_offset != -1) { BM_face_kill(bm, f_tmp); } @@ -1167,7 +1173,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac) BMFace **oldfaces = NULL; BMEdge *e_dummy; BLI_array_staticdeclare(oldfaces, 32); - const bool do_mdisp = (e->l && CustomData_has_layer(&bm->ldata, CD_MDISPS)); + const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); BLI_assert(BM_vert_in_edge(e, v) == true); @@ -1177,7 +1183,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac) } /* do we have a multi-res layer? */ - if (do_mdisp) { + if (cd_loop_mdisp_offset != -1) { BMLoop *l; int i; @@ -1212,12 +1218,16 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac) BM_data_interp_face_vert_edge(bm, v_other, v, v_new, e, fac); BM_data_interp_from_verts(bm, v, v_other, v_new, fac); - if (do_mdisp) { + if (cd_loop_mdisp_offset != -1) { int i, j; /* interpolate new/changed loop data from copied old faces */ - for (j = 0; j < 2; j++) { - for (i = 0; i < BLI_array_count(oldfaces); i++) { + for (i = 0; i < BLI_array_count(oldfaces); i++) { + float f_center_old[3]; + + BM_face_calc_center_mean(oldfaces[i], f_center_old); + + for (j = 0; j < 2; j++) { BMEdge *e1 = j ? *r_e : e; BMLoop *l, *l2; @@ -1227,15 +1237,20 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac) BMESH_ASSERT(0); break; } - + do { /* check this is an old face */ if (BM_ELEM_API_FLAG_TEST(l->f, _FLAG_OVERLAP)) { BMLoop *l2_first; + float f_center[3]; + + BM_face_calc_center_mean(l->f, f_center); l2 = l2_first = BM_FACE_FIRST_LOOP(l->f); do { - BM_loop_interp_multires(bm, l2, oldfaces[i]); + BM_loop_interp_multires_ex( + bm, l2, oldfaces[i], + f_center, f_center_old, cd_loop_mdisp_offset); } while ((l2 = l2->next) != l2_first); } l = l->radial_next; -- cgit v1.2.3