Fix T84376: Skin Resize(Ctrl + A) does not work in Symmetry

Since the `TransData` converted from vertices is the same used for other
transform modes (Move, Rotate, Resize), the logic used for mirroring
focused only on the position of the vertices.

The solution here is to create a specific `TansData` for `CD_MVERT_SKIN`.
This commit is contained in:
Germano Cavalcante 2021-01-04 17:36:51 -03:00
parent 8c80299fc4
commit 54ee410914
Notes: blender-bot 2023-02-13 22:20:49 +01:00
Referenced by commit c63442d2f2, Fix T84673: Skin resize operator always using object origin as pivot
Referenced by commit f41de6dc46, Fix T84404: Crash when using Skin Resize in mesh without Skin modifier
Referenced by issue #84673, Skin resize operator is always using object origin as pivot point
Referenced by issue #84404, In edit mode, when one vertice is selected, then by typing "CTRL+A",  this causes the program Blender to totally disappear.
Referenced by issue #84376, Skin Resize(Ctrl + A) does not work in Symmetry
7 changed files with 533 additions and 150 deletions

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);
}
}
/** \} */

View File

@ -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

View File

@ -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);
}
}