Commit: d7c762d2f7533a6f77a912f82937e79fb046362e Author: Germano Cavalcante Date: Mon Apr 26 09:35:03 2021 -0300 Branches: master https://developer.blender.org/rBd7c762d2f7533a6f77a912f82937e79fb046362e
Cleanup: Rearrange the functions in 'transform_convert_mesh.c' The creation of `TransCustomData` is best located at the beginning of the file as it is a specific struct of the file and can be used a lot locally. =================================================================== M source/blender/editors/transform/transform_convert_mesh.c =================================================================== diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index 872f3e1385a..59f314f5301 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -48,1530 +48,1551 @@ #include "transform_convert.h" -#define USE_FACE_SUBSTITUTE - /* -------------------------------------------------------------------- */ -/** \name Island Creation +/** \name Container TransCustomData Creation * \{ */ -void transform_convert_mesh_islands_calc(struct BMEditMesh *em, - const bool calc_single_islands, - const bool calc_island_center, - const bool calc_island_axismtx, - struct TransIslandData *r_island_data) -{ - struct TransIslandData data = {NULL}; +struct TransCustomDataMergeGroup { + /** map {BMVert: TransCustomDataLayerVert} */ + struct LinkNode **cd_loop_groups; +}; - BMesh *bm = em->bm; - char htype; - char itype; - int i; +struct TransCustomDataLayer { + BMesh *bm; + struct MemArena *arena; - /* group vars */ - int *groups_array = NULL; - int(*group_index)[2] = NULL; + struct GHash *origfaces; + struct BMesh *bm_origfaces; - bool has_only_single_islands = bm->totedgesel == 0 && bm->totfacesel == 0; - if (has_only_single_islands && !calc_single_islands) { - return; + /* Special handle for multi-resolution. */ + int cd_loop_mdisp_offset; + + /* Optionally merge custom-data groups (this keeps UVs connected for example). */ + struct { + /** map {BMVert: TransDataBasic} */ + struct GHash *origverts; + struct TransCustomDataMergeGroup *data; + int data_len; + /** Array size of 'layer_math_map_len' + * maps #TransCustomDataLayerVert.cd_group index to absolute #CustomData layer index */ + int *customdatalayer_map; + /** Number of math BMLoop layers. */ + int customdatalayer_map_len; + } merge_group; + + bool use_merge_group; +}; + +static void tc_mesh_customdatacorrect_free_fn(struct TransInfo *UNUSED(t), + struct TransDataContainer *UNUSED(tc), + struct TransCustomData *custom_data) +{ + struct TransCustomDataLayer *tcld = custom_data->data; + bmesh_edit_end(tcld->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES); + + if (tcld->bm_origfaces) { + BM_mesh_free(tcld->bm_origfaces); + } + if (tcld->origfaces) { + BLI_ghash_free(tcld->origfaces, NULL, NULL); + } + if (tcld->merge_group.origverts) { + BLI_ghash_free(tcld->merge_group.origverts, NULL, NULL); + } + if (tcld->arena) { + BLI_memarena_free(tcld->arena); + } + if (tcld->merge_group.customdatalayer_map) { + MEM_freeN(tcld->merge_group.customdatalayer_map); } - data.island_vert_map = MEM_mallocN(sizeof(*data.island_vert_map) * bm->totvert, __func__); - /* we shouldn't need this, but with incorrect selection flushing - * its possible we have a selected vertex that's not in a face, - * for now best not crash in that case. */ - copy_vn_i(data.island_vert_map, bm->totvert, -1); + MEM_freeN(tcld); + custom_data->data = NULL; +} - if (!has_only_single_islands) { - if (em->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) { - groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totedgesel, __func__); - data.island_tot = BM_mesh_calc_edge_groups( - bm, groups_array, &group_index, NULL, NULL, BM_ELEM_SELECT); +#define USE_FACE_SUBSTITUTE +#ifdef USE_FACE_SUBSTITUTE +# define FACE_SUBSTITUTE_INDEX INT_MIN - htype = BM_EDGE; - itype = BM_VERTS_OF_EDGE; +/** + * Search for a neighboring face with area and preferably without selected vertex. + * Used to replace area-less faces in custom-data correction. + */ +static BMFace *tc_mesh_customdatacorrect_find_best_face_substitute(BMFace *f) +{ + BMFace *best_face = NULL; + BMLoop *l; + BMIter liter; + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { + BMLoop *l_radial_next = l->radial_next; + BMFace *f_test = l_radial_next->f; + if (f_test == f) { + continue; } - else { /* (bm->selectmode & SCE_SELECT_FACE) */ - groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__); - data.island_tot = BM_mesh_calc_face_groups( - bm, groups_array, &group_index, NULL, NULL, NULL, BM_ELEM_SELECT, BM_VERT); - - htype = BM_FACE; - itype = BM_VERTS_OF_FACE; + if (is_zero_v3(f_test->no)) { + continue; } - BLI_assert(data.island_tot); - if (calc_island_center) { - data.center = MEM_mallocN(sizeof(*data.center) * data.island_tot, __func__); + /* Check the loops edge isn't selected. */ + if (!BM_elem_flag_test(l_radial_next->v, BM_ELEM_SELECT) && + !BM_elem_flag_test(l_radial_next->next->v, BM_ELEM_SELECT)) { + /* Prefer edges with unselected vertices. + * Useful for extrude. */ + best_face = f_test; + break; } - - if (calc_island_axismtx) { - data.axismtx = MEM_mallocN(sizeof(*data.axismtx) * data.island_tot, __func__); + if (best_face == NULL) { + best_face = f_test; } + } + return best_face; +} - BM_mesh_elem_table_ensure(bm, htype); - - void **ele_array; - ele_array = (htype == BM_FACE) ? (void **)bm->ftable : (void **)bm->etable; - - BM_mesh_elem_index_ensure(bm, BM_VERT); - - /* may be an edge OR a face array */ - for (i = 0; i < data.island_tot; i++) { - BMEditSelection ese = {NULL}; - - const int fg_sta = group_index[i][0]; - const int fg_len = group_index[i][1]; - float co[3], no[3], tangent[3]; - int j; +static void tc_mesh_customdatacorrect_face_substitute_set(struct TransCustomDataLayer *tcld, + BMFace *f, + BMFace *f_copy) +{ + BLI_assert(is_zero_v3(f->no)); + BMesh *bm = tcld->bm; + /* It is impossible to calculate the loops weights of a face without area. + * Find a substitute. */ + BMFace *f_substitute = tc_mesh_customdatacorrect_find_best_face_substitute(f); + if (f_substitute) { + /* Copy the custom-data from the substitute face. */ + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BM_loop_interp_from_face(bm, l_iter, f_substitute, false, false); + } while ((l_iter = l_iter->next) != l_first); - zero_v3(co); - zero_v3(no); - zero_v3(tangent); + /* Use the substitute face as the reference during the transformation. */ + BMFace *f_substitute_copy = BM_face_copy(tcld->bm_origfaces, bm, f_substitute, true, true); - ese.htype = htype; + /* Hack: reference substitute face in `f_copy->no`. + * `tcld->origfaces` is already used to restore the initial value. */ + BM_elem_index_set(f_copy, FACE_SUBSTITUTE_INDEX); + *((BMFace **)&f_copy->no[0]) = f_substitute_copy; + } +} - /* loop on each face or edge in this group: - * - assign r_vert_map - * - calculate (co, no) - */ - for (j = 0; j < fg_len; j++) { - ese.ele = ele_array[groups_array[fg_sta + j]]; +static BMFace *tc_mesh_customdatacorrect_face_substitute_get(BMFace *f_copy) +{ + BLI_assert(BM_elem_index_get(f_copy) == FACE_SUBSTITUTE_INDEX); + return *((BMFace **)&f_copy->no[0]); +} - if (data.center) { - float tmp_co[3]; - BM_editselection_center(&ese, tmp_co); - add_v3_v3(co, tmp_co); - } +#endif /* USE_FACE_SUBSTITUTE */ - if (data.axismtx) { - float tmp_no[3], tmp_tangent[3]; - BM_editselection_normal(&ese, tmp_no); - BM_editselection_plane(&ese, tmp_tangent); - add_v3_v3(no, tmp_no); - add_v3_v3(tangent, tmp_tangent); - } +static void tc_mesh_customdatacorrect_init_vert(struct TransCustomDataLayer *tcld, + struct TransDataBasic *td, + const int index) +{ + BMesh *bm = tcld->bm; + BMVert *v = td->extra; + BMIter liter; + int j, l_num; + float *loop_weights; - { - /* setup vertex map */ - BMIter iter; - BMVert *v; + // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) { + BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, v); + l_num = liter.count; + loop_weights = tcld->use_merge_group ? BLI_array_alloca(loop_weights, l_num) : NULL; + for (j = 0; j < l_num; j++) { + BMLoop *l = BM_iter_step(&liter); + BMLoop *l_prev, *l_next; - /* connected edge-verts */ - BM_ITER_ELEM (v, &iter, ese.ele, itype) { - data.island_vert_map[BM_elem_index_get(v)] = i; - } - } + /* Generic custom-data correction. Copy face data. */ + void **val_p; + if (!BLI_ghash_ensure_p(tcld->origfaces, l->f, &val_p)) { + BMFace *f_copy = BM_face_copy(tcld->bm_origfaces, bm, l->f, true, true); + *val_p = f_copy; +#ifdef USE_FACE_SUBSTITUTE + if (is_zero_v3(l->f->no)) { + tc_mesh_customdatacorrect_face_substitute_set(tcld, l->f, f_copy); } +#endif + } - if (data.center) { - mul_v3_v3fl(data.center[i], co, 1.0f / (float)fg_len); + if (tcld->use_merge_group) { + if ((l_prev = BM_loop_find_prev_nodouble(l, l->next, FLT_EPSILON)) && + (l_next = BM_loop_find_next_nodouble(l, l_prev, FLT_EPSILON))) { + loop_weights[j] = angle_v3v3v3(l_prev->v->co, l->v->co, l_next->v->co); } - - if (data.axismtx) { - if (createSpaceNormalTangent(data.axismtx[i], no, tangent)) { - /* pass */ - } - else { - if (normalize_v3(no) != 0.0f) { - axis_dominant_v3_to_m3(data.axismtx[i], no); - invert_m3(data.axismtx[i]); - } - else { - unit_m3(data.axismtx[i]); - } - } + else { + loop_weights[j] = 0.0f; } } - - MEM_freeN(groups_array); - MEM_freeN(group_index); } - /* for PET we need islands of 1 so connected vert @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs