diff options
7 files changed, 533 insertions, 150 deletions
diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt index a2eb68a1b71..faed8abb202 100644 --- a/source/blender/editors/transform/CMakeLists.txt +++ b/source/blender/editors/transform/CMakeLists.txt @@ -50,6 +50,7 @@ set(SRC transform_convert_mball.c transform_convert_mesh.c transform_convert_mesh_edge.c + transform_convert_mesh_skin.c transform_convert_mesh_uv.c transform_convert_nla.c transform_convert_node.c diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index dd35d67e1fa..fb365da6b43 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -1078,7 +1078,12 @@ void createTransData(bContext *C, TransInfo *t) initTransDataContainers_FromObjectData(t, ob, NULL, 0); if (t->obedit_type == OB_MESH) { - convert_type = TC_MESH_VERTS; + if (t->mode == TFM_SKIN_RESIZE) { + convert_type = TC_MESH_SKIN; + } + else { + convert_type = TC_MESH_VERTS; + } } else if (ELEM(t->obedit_type, OB_CURVE, OB_SURF)) { convert_type = TC_CURVE_VERTS; @@ -1202,6 +1207,9 @@ void createTransData(bContext *C, TransInfo *t) case TC_MESH_EDGES: createTransEdge(t); break; + case TC_MESH_SKIN: + createTransMeshSkin(t); + break; case TC_MESH_UV: createTransUVs(C, t); break; @@ -1273,9 +1281,9 @@ void createTransData(bContext *C, TransInfo *t) if (ELEM(convert_type, TC_ACTION_DATA, TC_GRAPH_EDIT_DATA)) { /* Distance has already been set. */ } - else if (convert_type == TC_MESH_VERTS) { + else if (ELEM(convert_type, TC_MESH_VERTS, TC_MESH_SKIN)) { if (t->flag & T_PROP_CONNECTED) { - /* Already calculated by editmesh_set_connectivity_distance. */ + /* Already calculated by transform_convert_mesh_connectivity_distance. */ } else { set_prop_dist(t, false); @@ -1536,6 +1544,9 @@ void recalcData(TransInfo *t) case TC_MESH_EDGES: recalcData_mesh(t); break; + case TC_MESH_SKIN: + recalcData_mesh_skin(t); + break; case TC_MESH_UV: recalcData_uv(t); break; diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h index 59fcd016020..be4322b42e2 100644 --- a/source/blender/editors/transform/transform_convert.h +++ b/source/blender/editors/transform/transform_convert.h @@ -25,6 +25,8 @@ #pragma once struct BezTriple; +struct BMEditMesh; +struct BMesh; struct FCurve; struct ListBase; struct Object; @@ -65,6 +67,7 @@ typedef enum eTransConvertType { TC_MBALL_VERTS, TC_MESH_VERTS, TC_MESH_EDGES, + TC_MESH_SKIN, TC_MESH_UV, TC_NLA_DATA, TC_NODE_DATA, @@ -136,6 +139,55 @@ void special_aftertrans_update__mask(bContext *C, TransInfo *t); void createTransMBallVerts(TransInfo *t); /* transform_convert_mesh.c */ +struct TransIslandData { + float (*center)[3]; + float (*axismtx)[3][3]; + int island_tot; + int *island_vert_map; +}; + +struct MirrorDataVert { + int index; + int flag; +}; + +struct TransMirrorData { + struct MirrorDataVert *vert_map; + int mirror_elem_len; +}; + +struct TransMeshDataCrazySpace { + float (*quats)[4]; + float (*defmats)[3][3]; +}; + +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); +void transform_convert_mesh_islanddata_free(struct TransIslandData *island_data); +void transform_convert_mesh_connectivity_distance(struct BMesh *bm, + const float mtx[3][3], + float *dists, + int *index); +void transform_convert_mesh_mirrordata_calc(struct BMEditMesh *em, + const bool use_select, + const bool use_topology, + const bool mirror_axis[3], + struct TransMirrorData *r_mirror_data); +void transform_convert_mesh_mirrordata_free(struct TransMirrorData *mirror_data); +void transform_convert_mesh_crazyspace_detect(TransInfo *t, + struct TransDataContainer *tc, + struct BMEditMesh *em, + struct TransMeshDataCrazySpace *r_crazyspace_data); +void transform_convert_mesh_crazyspace_transdata_set(const float mtx[3][3], + const float smtx[3][3], + const float defmat[3][3], + const float quat[4], + struct TransData *r_td); +void transform_convert_mesh_crazyspace_free(struct TransMeshDataCrazySpace *r_crazyspace_data); + void createTransEditVerts(TransInfo *t); void recalcData_mesh(TransInfo *t); void special_aftertrans_update__mesh(bContext *C, TransInfo *t); @@ -143,6 +195,10 @@ void special_aftertrans_update__mesh(bContext *C, TransInfo *t); /* transform_convert_mesh_edge.c */ void createTransEdge(TransInfo *t); +/* transform_convert_mesh_skin.c */ +void createTransMeshSkin(TransInfo *t); +void recalcData_mesh_skin(TransInfo *t); + /* transform_convert_mesh_uv.c */ void createTransUVs(bContext *C, TransInfo *t); void recalcData_uv(TransInfo *t); diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index 5f41aaa8e50..b3bd6b31879 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -27,8 +27,6 @@ #include "MEM_guardedalloc.h" #include "BLI_alloca.h" -#include "BLI_bitmap.h" -#include "BLI_ghash.h" #include "BLI_linklist_stack.h" #include "BLI_math.h" #include "BLI_memarena.h" @@ -45,12 +43,10 @@ #include "DEG_depsgraph_query.h" #include "transform.h" -#include "transform_mode.h" +#include "transform_orientations.h" #include "transform_snap.h" -/* Own include. */ #include "transform_convert.h" -#include "transform_orientations.h" #define USE_FACE_SUBSTITUTE @@ -59,18 +55,11 @@ * * \{ */ -struct TransIslandData { - float (*center)[3]; - float (*axismtx)[3][3]; - int island_tot; - int *island_vert_map; -}; - -static void editmesh_islands_info_calc(BMEditMesh *em, - const bool calc_single_islands, - const bool calc_island_center, - const bool calc_island_axismtx, - struct TransIslandData *r_island_data) +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) { BMesh *bm = em->bm; char htype; @@ -242,6 +231,19 @@ static void editmesh_islands_info_calc(BMEditMesh *em, r_island_data->island_vert_map = vert_map; } +void transform_convert_mesh_islanddata_free(struct TransIslandData *island_data) +{ + if (island_data->center) { + MEM_freeN(island_data->center); + } + if (island_data->axismtx) { + MEM_freeN(island_data->axismtx); + } + if (island_data->island_vert_map) { + MEM_freeN(island_data->island_vert_map); + } +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -285,10 +287,10 @@ static bool bmesh_test_dist_add(BMVert *v, * \param dists: Store the closest connected distance to selected vertices. * \param index: Optionally store the original index we're measuring the distance to (can be NULL). */ -static void editmesh_set_connectivity_distance(BMesh *bm, - const float mtx[3][3], - float *dists, - int *index) +void transform_convert_mesh_connectivity_distance(struct BMesh *bm, + const float mtx[3][3], + float *dists, + int *index) { BLI_LINKSTACK_DECLARE(queue, BMVert *); @@ -436,16 +438,6 @@ static void editmesh_set_connectivity_distance(BMesh *bm, /* Used for both mirror epsilon and TD_MIRROR_EDGE_ */ #define TRANSFORM_MAXDIST_MIRROR 0.00002f -struct MirrorDataVert { - int index; - int flag; -}; - -struct TransMirrorData { - struct MirrorDataVert *vert_map; - int mirror_elem_len; -}; - static bool is_in_quadrant_v3(const float co[3], const int quadrant[3], const float epsilon) { if (quadrant[0] && ((co[0] * quadrant[0]) < -epsilon)) { @@ -460,11 +452,11 @@ static bool is_in_quadrant_v3(const float co[3], const int quadrant[3], const fl return true; } -static void editmesh_mirror_data_calc(BMEditMesh *em, - const bool use_select, - const bool use_topology, - const bool mirror_axis[3], - struct TransMirrorData *r_mirror_data) +void transform_convert_mesh_mirrordata_calc(struct BMEditMesh *em, + const bool use_select, + const bool use_topology, + const bool mirror_axis[3], + struct TransMirrorData *r_mirror_data) { struct MirrorDataVert *vert_map; @@ -572,6 +564,119 @@ static void editmesh_mirror_data_calc(BMEditMesh *em, r_mirror_data->mirror_elem_len = mirror_elem_len; } +void transform_convert_mesh_mirrordata_free(struct TransMirrorData *mirror_data) +{ + if (mirror_data->vert_map) { + MEM_freeN(mirror_data->vert_map); + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Crazy Space + * + * \{ */ + +/* Detect CrazySpace [tm]. + * Vertices with space affected by quats are marked with #BM_ELEM_TAG */ +void transform_convert_mesh_crazyspace_detect(TransInfo *t, + struct TransDataContainer *tc, + struct BMEditMesh *em, + struct TransMeshDataCrazySpace *r_crazyspace_data) +{ + float(*quats)[4] = NULL; + float(*defmats)[3][3] = NULL; + const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0; + if (BKE_modifiers_get_cage_index(t->scene, tc->obedit, NULL, 1) != -1) { + float(*defcos)[3] = NULL; + int totleft = -1; + if (BKE_modifiers_is_correctable_deformed(t->scene, tc->obedit)) { + BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context)); + + /* Use evaluated state because we need b-bone cache. */ + Scene *scene_eval = (Scene *)DEG_get_evaluated_id(t->depsgraph, &t->scene->id); + Object *obedit_eval = (Object *)DEG_get_evaluated_id(t->depsgraph, &tc->obedit->id); + BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval); + /* check if we can use deform matrices for modifier from the + * start up to stack, they are more accurate than quats */ + totleft = BKE_crazyspace_get_first_deform_matrices_editbmesh( + t->depsgraph, scene_eval, obedit_eval, em_eval, &defmats, &defcos); + } + + /* If we still have more modifiers, also do crazy-space + * correction with \a quats, relative to the coordinates after + * the modifiers that support deform matrices \a defcos. */ + +#if 0 /* TODO, fix crazy-space & extrude so it can be enabled for general use - campbell */ + if ((totleft > 0) || (totleft == -1)) +#else + if (totleft > 0) +#endif + { + float(*mappedcos)[3] = NULL; + mappedcos = BKE_crazyspace_get_mapped_editverts(t->depsgraph, tc->obedit); + quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats"); + BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode); + if (mappedcos) { + MEM_freeN(mappedcos); + } + } + + if (defcos) { + MEM_freeN(defcos); + } + } + r_crazyspace_data->quats = quats; + r_crazyspace_data->defmats = defmats; +} + +void transform_convert_mesh_crazyspace_transdata_set(const float mtx[3][3], + const float smtx[3][3], + const float defmat[3][3], + const float quat[4], + struct TransData *r_td) +{ + /* CrazySpace */ + if (quat || defmat) { + float mat[3][3], qmat[3][3], imat[3][3]; + + /* Use both or either quat and defmat correction. */ + if (quat) { + quat_to_mat3(qmat, quat); + + if (defmat) { + mul_m3_series(mat, defmat, qmat, mtx); + } + else { + mul_m3_m3m3(mat, mtx, qmat); + } + } + else { + mul_m3_m3m3(mat, mtx, defmat); + } + + invert_m3_m3(imat, mat); + + copy_m3_m3(r_td->smtx, imat); + copy_m3_m3(r_td->mtx, mat); + } + else { + copy_m3_m3(r_td->smtx, smtx); + copy_m3_m3(r_td->mtx, mtx); + } +} + +void transform_convert_mesh_crazyspace_free(struct TransMeshDataCrazySpace *r_crazyspace_data) +{ + if (r_crazyspace_data->quats) { + MEM_freeN(r_crazyspace_data->quats); + } + if (r_crazyspace_data->defmats) { + MEM_freeN(r_crazyspace_data->defmats); + } +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -643,19 +748,6 @@ static void VertsToTransData(TransInfo *t, td->val = bweight; td->ival = *bweight; } - else if (t->mode == TFM_SKIN_RESIZE) { - MVertSkin *vs = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MVERT_SKIN); - if (vs) { - /* skin node size */ - td->ext = tx; - copy_v3_v3(tx->isize, vs->radius); - tx->size = vs->radius; - td->val = vs->radius; - } - else { - td->flag |= TD_SKIP; - } - } else if (t->mode == TFM_SHRINKFATTEN) { td->ext = tx; tx->isize[0] = BM_vert_calc_shell_factor_ex(eve, no, BM_ELEM_SELECT); @@ -677,6 +769,7 @@ void createTransEditVerts(TransInfo *t) struct TransIslandData island_data = {NULL}; struct TransMirrorData mirror_data = {NULL}; + struct TransMeshDataCrazySpace crazyspace_data = {NULL}; /** * Quick check if we can transform. @@ -730,7 +823,7 @@ void createTransEditVerts(TransInfo *t) * TODO(Germano): Extend the list to exclude other modes. */ const bool calc_island_axismtx = !ELEM(t->mode, TFM_SHRINKFATTEN); - editmesh_islands_info_calc( + transform_convert_mesh_islands_calc( em, calc_single_islands, calc_island_center, calc_island_axismtx, &island_data); } @@ -748,7 +841,7 @@ void createTransEditVerts(TransInfo *t) if (is_island_center) { dists_index = MEM_mallocN(bm->totvert * sizeof(int), __func__); } - editmesh_set_connectivity_distance(em->bm, mtx, dists, dists_index); + transform_convert_mesh_connectivity_distance(em->bm, mtx, dists, dists_index); } /* Create TransDataMirror. */ @@ -757,7 +850,8 @@ void createTransEditVerts(TransInfo *t) bool use_select = (t->flag & T_PROP_EDIT) == 0; const bool mirror_axis[3] = { tc->use_mirror_axis_x, tc->use_mirror_axis_y, tc->use_mirror_axis_z}; - editmesh_mirror_data_calc(em, use_select, use_topology, mirror_axis, &mirror_data); + transform_convert_mesh_mirrordata_calc( + em, use_select, use_topology, mirror_axis, &mirror_data); if (mirror_data.vert_map) { tc->data_mirror_len = mirror_data.mirror_elem_len; @@ -774,11 +868,14 @@ void createTransEditVerts(TransInfo *t) } } + /* Detect CrazySpace [tm]. */ + transform_convert_mesh_crazyspace_detect(t, tc, em, &crazyspace_data); + /* Create TransData. */ BLI_assert(data_len >= 1); tc->data_len = data_len; tc->data = MEM_callocN(data_len * sizeof(TransData), "TransObData(Mesh EditMode)"); - if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) { + if (t->mode == TFM_SHRINKFATTEN) { /* warning, this is overkill, we only need 2 extra floats, * but this stores loads of extra stuff, for TFM_SHRINKFATTEN its even more overkill * since we may not use the 'alt' transform mode to maintain shell thickness, @@ -787,49 +884,6 @@ void createTransEditVerts(TransInfo *t) "TransObData ext"); } - /* detect CrazySpace [tm] */ - float(*quats)[4] = NULL; - float(*defmats)[3][3] = NULL; - if (BKE_modifiers_get_cage_index(t->scene, tc->obedit, NULL, 1) != -1) { - float(*defcos)[3] = NULL; - int totleft = -1; - if (BKE_modifiers_is_correctable_deformed(t->scene, tc->obedit)) { - BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context)); - - /* Use evaluated state because we need b-bone cache. */ - Scene *scene_eval = (Scene *)DEG_get_evaluated_id(t->depsgraph, &t->scene->id); - Object *obedit_eval = (Object *)DEG_get_evaluated_id(t->depsgraph, &tc->obedit->id); - BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval); - /* check if we can use deform matrices for modifier from the - * start up to stack, they are more accurate than quats */ - totleft = BKE_crazyspace_get_first_deform_matrices_editbmesh( - t->depsgraph, scene_eval, obedit_eval, em_eval, &defmats, &defcos); - } - - /* If we still have more modifiers, also do crazy-space - * correction with \a quats, relative to the coordinates after - * the modifiers that support deform matrices \a defcos. */ - -#if 0 /* TODO, fix crazy-space & extrude so it can be enabled for general use - campbell */ - if ((totleft > 0) || (totleft == -1)) -#else - if (totleft > 0) -#endif - { - float(*mappedcos)[3] = NULL; - mappedcos = BKE_crazyspace_get_mapped_editverts(t->depsgraph, tc->obedit); - quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats"); - BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode); - if (mappedcos) { - MEM_freeN(mappedcos); - } - } - - if (defcos) { - MEM_freeN(defcos); - } - } - int cd_vert_bweight_offset = -1; if (t->mode == TFM_BWEIGHT) { BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_VERT_BWEIGHT); @@ -894,34 +948,14 @@ void createTransEditVerts(TransInfo *t) } /* CrazySpace */ - const bool use_quats = quats && BM_elem_flag_test(eve, BM_ELEM_TAG); - if (use_quats || defmats) { - float mat[3][3], qmat[3][3], imat[3][3]; - - /* Use both or either quat and defmat correction. */ - if (use_quats) { - quat_to_mat3(qmat, quats[BM_elem_index_get(eve)]); - - if (defmats) { - mul_m3_series(mat, defmats[a], qmat, mtx); - } - else { - mul_m3_m3m3(mat, mtx, qmat); - } - } - else { - mul_m3_m3m3(mat, mtx, defmats[a]); - } - - invert_m3_m3(imat, mat); - - copy_m3_m3(tob->smtx, imat); - copy_m3_m3(tob->mtx, mat); - } - else { - copy_m3_m3(tob->smtx, smtx); - copy_m3_m3(tob->mtx, mtx); - } + transform_convert_mesh_crazyspace_transdata_set( + mtx, + smtx, + crazyspace_data.defmats ? crazyspace_data.defmats[a] : NULL, + crazyspace_data.quats && BM_elem_flag_test(eve, BM_ELEM_TAG) ? + crazyspace_data.quats[a] : + NULL, + tob); if (tc->use_mirror_axis_any) { if (tc->use_mirror_axis_x && fabsf(tob->loc[0]) < TRANSFORM_MAXDIST_MIRROR) { @@ -939,24 +973,9 @@ void createTransEditVerts(TransInfo *t) } } - if (island_data.center) { - MEM_freeN(island_data.center); - } - if (island_data.axismtx) { - MEM_freeN(island_data.axismtx); - } - if (island_data.island_vert_map) { - MEM_freeN(island_data.island_vert_map); - } - if (mirror_data.vert_map) { - MEM_freeN(mirror_data.vert_map); - } - if (quats) { - MEM_freeN(quats); - } - if (defmats) { - MEM_freeN(defmats); - } + transform_convert_mesh_islanddata_free(&island_data); + transform_convert_mesh_mirrordata_free(&mirror_data); + transform_convert_mesh_crazyspace_free(&crazyspace_data); if (dists) { MEM_freeN(dists); } @@ -1523,7 +1542,7 @@ static void mesh_customdatacorrect_restore(struct TransInfo *t) * * \{ */ -static void transform_apply_to_mirror(TransInfo *t) +static void mesh_apply_to_mirror(TransInfo *t) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { if (tc->use_mirror_axis_any) { @@ -1570,7 +1589,7 @@ void recalcData_mesh(TransInfo *t) clipMirrorModifier(t); if ((t->flag & T_NO_MIRROR) == 0 && (t->options & CTX_NO_MIRROR) == 0) { - transform_apply_to_mirror(t); + mesh_apply_to_mirror(t); } mesh_customdatacorrect_apply(t, false); diff --git a/source/blender/editors/transform/transform_convert_mesh_skin.c b/source/blender/editors/transform/transform_convert_mesh_skin.c new file mode 100644 index 00000000000..78f9380f383 --- /dev/null +++ b/source/blender/editors/transform/transform_convert_mesh_skin.c @@ -0,0 +1,296 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + */ + +/** \file + * \ingroup edtransform + */ + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_crazyspace.h" +#include "BKE_editmesh.h" +#include "BKE_modifier.h" +#include "BKE_scene.h" + +#include "ED_mesh.h" + +#include "DEG_depsgraph_query.h" + +#include "transform.h" +#include "transform_orientations.h" + +#include "transform_convert.h" + +/* -------------------------------------------------------------------- */ +/** \name Edit Mesh #CD_MVERT_SKIN Transform Creation + * + * \{ */ + +static void mesh_skin_transdata_create(TransInfo *t, + TransDataBasic *td, + BMEditMesh *em, + BMVert *eve, + const struct TransIslandData *island_data, + const int island_index) +{ + BLI_assert(BM_elem_flag_test(eve, BM_ELEM_HIDDEN) == 0); + MVertSkin *vs = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MVERT_SKIN); + if (vs) { + copy_v3_v3(td->iloc, vs->radius); + td->loc = vs->radius; + } + else { + td->flag |= TD_SKIP; + } + + td->flag = 0; + + if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + td->flag |= TD_SELECTED; + } + + td->extra = eve; +} + +void createTransMeshSkin(TransInfo *t) +{ + BLI_assert(t->mode == TFM_SKIN_RESIZE); + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + Mesh *me = tc->obedit->data; + BMesh *bm = em->bm; + BMVert *eve; + BMIter iter; + float mtx[3][3], smtx[3][3]; + int a; + const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0; + + struct TransIslandData island_data = {NULL}; + struct TransMirrorData mirror_data = {NULL}; + struct TransMeshDataCrazySpace crazyspace_data = {NULL}; + + /** + * Quick check if we can transform. + * + * \note ignore modes here, even in edge/face modes, + * transform data is created by selected vertices. + */ + + /* Support other objects using PET to adjust these, unless connected is enabled. */ + if ((!prop_mode || (prop_mode & T_PROP_CONNECTED)) && (bm->totvertsel == 0)) { + continue; + } + + int data_len = 0; + if (prop_mode) { + BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { + if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { + data_len++; + } + } + } + else { + data_len = bm->totvertsel; + } + + if (data_len == 0) { + continue; + } + + const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS); + if (is_island_center) { + /* In this specific case, near-by vertices will need to know + * the island of the nearest connected vertex. */ + const bool calc_single_islands = ((prop_mode & T_PROP_CONNECTED) && + (t->around == V3D_AROUND_LOCAL_ORIGINS) && + (em->selectmode & SCE_SELECT_VERTEX)); + + const bool calc_island_center = false; + const bool calc_island_axismtx = false; + + transform_convert_mesh_islands_calc( + em, calc_single_islands, calc_island_center, calc_island_axismtx, &island_data); + } + + copy_m3_m4(mtx, tc->obedit->obmat); + /* we use a pseudo-inverse so that when one of the axes is scaled to 0, + * matrix inversion still works and we can still moving along the other */ + pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); + + /* Original index of our connected vertex when connected distances are calculated. + * Optional, allocate if needed. */ + int *dists_index = NULL; + float *dists = NULL; + if (prop_mode & T_PROP_CONNECTED) { + dists = MEM_mallocN(bm->totvert * sizeof(float), __func__); + if (is_island_center) { + dists_index = MEM_mallocN(bm->totvert * sizeof(int), __func__); + } + transform_convert_mesh_connectivity_distance(em->bm, mtx, dists, dists_index); + } + + /* Create TransDataMirror. */ + if (tc->use_mirror_axis_any) { + bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; + bool use_select = (t->flag & T_PROP_EDIT) == 0; + const bool mirror_axis[3] = { + tc->use_mirror_axis_x, tc->use_mirror_axis_y, tc->use_mirror_axis_z}; + transform_convert_mesh_mirrordata_calc( + em, use_select, use_topology, mirror_axis, &mirror_data); + + if (mirror_data.vert_map) { + tc->data_mirror_len = mirror_data.mirror_elem_len; + tc->data_mirror = MEM_mallocN(mirror_data.mirror_elem_len * sizeof(*tc->data_mirror), + __func__); + + BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) { + if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + if (mirror_data.vert_map[a].index != -1) { + data_len--; + } + } + } + } + } + + /* Detect CrazySpace [tm]. */ + transform_convert_mesh_crazyspace_detect(t, tc, em, &crazyspace_data); + + /* Create TransData. */ + BLI_assert(data_len >= 1); + tc->data_len = data_len; + tc->data = MEM_callocN(data_len * sizeof(TransData), "TransObData(Mesh EditMode)"); + + TransData *td = tc->data; + TransDataMirror *td_mirror = tc->data_mirror; + BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) { + if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { + continue; + } + + int island_index = -1; + if (island_data.island_vert_map) { + const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a; + island_index = island_data.island_vert_map[connected_index]; + } + + if (mirror_data.vert_map && mirror_data.vert_map[a].index != -1) { + mesh_skin_transdata_create( + t, (TransDataBasic *)td_mirror, em, eve, &island_data, island_index); + + int elem_index = mirror_data.vert_map[a].index; + BMVert *v_src = BM_vert_at_index(bm, elem_index); + MVertSkin *vs = CustomData_bmesh_get(&em->bm->vdata, v_src->head.data, CD_MVERT_SKIN); + + td_mirror->flag |= mirror_data.vert_map[a].flag; + td_mirror->loc_src = vs->radius; + td_mirror++; + } + else if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + mesh_skin_transdata_create(t, (TransDataBasic *)td, em, eve, &island_data, island_index); + + if (t->around == V3D_AROUND_LOCAL_ORIGINS) { + createSpaceNormal(td->axismtx, eve->no); + } + else { + /* Setting normals */ + copy_v3_v3(td->axismtx[2], eve->no); + td->axismtx[0][0] = td->axismtx[0][1] = td->axismtx[0][2] = td->axismtx[1][0] = + td->axismtx[1][1] = td->axismtx[1][2] = 0.0f; + } + + if (prop_mode) { + if (prop_mode & T_PROP_CONNECTED) { + td->dist = dists[a]; + } + else { + td->flag |= TD_NOTCONNECTED; + td->dist = FLT_MAX; + } + } + + /* CrazySpace */ + transform_convert_mesh_crazyspace_transdata_set( + mtx, + smtx, + crazyspace_data.defmats ? crazyspace_data.defmats[a] : NULL, + crazyspace_data.quats && BM_elem_flag_test(eve, BM_ELEM_TAG) ? + crazyspace_data.quats[a] : + NULL, + td); + + td++; + } + } + + transform_convert_mesh_islanddata_free(&island_data); + transform_convert_mesh_mirrordata_free(&mirror_data); + transform_convert_mesh_crazyspace_free(&crazyspace_data); + if (dists) { + MEM_freeN(dists); + } + if (dists_index) { + MEM_freeN(dists_index); + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Recalc Mesh Data + * + * \{ */ + +static void mesh_skin_apply_to_mirror(TransInfo *t) +{ + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + if (tc->use_mirror_axis_any) { + TransDataMirror *td_mirror = tc->data_mirror; + for (int i = 0; i < tc->data_mirror_len; i++, td_mirror++) { + copy_v3_v3(td_mirror->loc, td_mirror->loc_src); + } + } + } +} + +void recalcData_mesh_skin(TransInfo *t) +{ + bool is_canceling = t->state == TRANS_CANCEL; + /* mirror modifier clipping? */ + if (!is_canceling) { + if ((t->flag & T_NO_MIRROR) == 0 && (t->options & CTX_NO_MIRROR) == 0) { + mesh_skin_apply_to_mirror(t); + } + } + + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */ + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + EDBM_mesh_normals_update(em); + BKE_editmesh_looptri_calc(em); + } +} +/** \} */ diff --git a/source/blender/editors/transform/transform_convert_mesh_uv.c b/source/blender/editors/transform/transform_convert_mesh_uv.c index b54c45e2ab2..52394009d28 100644 --- a/source/blender/editors/transform/transform_convert_mesh_uv.c +++ b/source/blender/editors/transform/transform_convert_mesh_uv.c @@ -92,7 +92,7 @@ static void UVsToTransData(const float aspect[2], */ static void uv_set_connectivity_distance(BMesh *bm, float *dists, const float aspect[2]) { - /* Mostly copied from #editmesh_set_connectivity_distance. */ + /* Mostly copied from #transform_convert_mesh_connectivity_distance. */ BLI_LINKSTACK_DECLARE(queue, BMLoop *); /* Any BM_ELEM_TAG'd loop is added to 'queue_next', this makes sure that we don't add things diff --git a/source/blender/editors/transform/transform_mode_skin_resize.c b/source/blender/editors/transform/transform_mode_skin_resize.c index b4c919cbb86..8beacb844b9 100644 --- a/source/blender/editors/transform/transform_mode_skin_resize.c +++ b/source/blender/editors/transform/transform_mode_skin_resize.c @@ -88,8 +88,8 @@ static void applySkinResize(TransInfo *t, const int UNUSED(mval[2])) } mat3_to_size(fsize, tmat); - td->val[0] = td->ext->isize[0] * (1 + (fsize[0] - 1) * td->factor); - td->val[1] = td->ext->isize[1] * (1 + (fsize[1] - 1) * td->factor); + td->loc[0] = td->iloc[0] * (1 + (fsize[0] - 1) * td->factor); + td->loc[1] = td->iloc[1] * (1 + (fsize[1] - 1) * td->factor); } } |