Blender V4.3
transform_convert_mesh_skin.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "DNA_mesh_types.h"
10#include "DNA_meshdata_types.h"
11
12#include "MEM_guardedalloc.h"
13
14#include "BLI_math_matrix.h"
15#include "BLI_math_vector.h"
16
17#include "BKE_context.hh"
18#include "BKE_editmesh.hh"
19
20#include "transform.hh"
22
23#include "transform_convert.hh"
24
25/* -------------------------------------------------------------------- */
29static float *mesh_skin_transdata_center(const TransIslandData *island_data,
30 const int island_index,
31 BMVert *eve)
32{
33 if (island_data->center && island_index != -1) {
34 return island_data->center[island_index];
35 }
36 return eve->co;
37}
38
40 BMEditMesh *em,
41 BMVert *eve,
42 const TransIslandData *island_data,
43 const int island_index)
44{
46 MVertSkin *vs = static_cast<MVertSkin *>(
48 td->flag = 0;
49 if (vs) {
50 copy_v3_v3(td->iloc, vs->radius);
51 td->loc = vs->radius;
52 }
53 else {
54 td->flag |= TD_SKIP;
55 }
56
58 td->flag |= TD_SELECTED;
59 }
60
61 copy_v3_v3(td->center, mesh_skin_transdata_center(island_data, island_index, eve));
62 td->extra = eve;
63}
64
65static void createTransMeshSkin(bContext * /*C*/, TransInfo *t)
66{
69 BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
70 Mesh *mesh = static_cast<Mesh *>(tc->obedit->data);
71 BMesh *bm = em->bm;
72 BMVert *eve;
73 BMIter iter;
74 float mtx[3][3], smtx[3][3];
75 int a;
76 const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
77
78 TransIslandData island_data = {nullptr};
79 TransMirrorData mirror_data = {nullptr};
80 TransMeshDataCrazySpace crazyspace_data = {nullptr};
81
90 continue;
91 }
92
93 /* Support other objects using proportional editing to adjust these, unless connected is
94 * enabled. */
95 if ((!prop_mode || (prop_mode & T_PROP_CONNECTED)) && (bm->totvertsel == 0)) {
96 continue;
97 }
98
99 int data_len = 0;
100 if (prop_mode) {
101 BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
103 data_len++;
104 }
105 }
106 }
107 else {
108 data_len = bm->totvertsel;
109 }
110
111 if (data_len == 0) {
112 continue;
113 }
114
115 const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS);
116 if (is_island_center) {
117 /* In this specific case, near-by vertices will need to know
118 * the island of the nearest connected vertex. */
119 const bool calc_single_islands = ((prop_mode & T_PROP_CONNECTED) &&
122
123 const bool calc_island_center = false;
124 const bool calc_island_axismtx = false;
125
127 em, calc_single_islands, calc_island_center, calc_island_axismtx, &island_data);
128 }
129
130 copy_m3_m4(mtx, tc->obedit->object_to_world().ptr());
131 /* We use a pseudo-inverse so that when one of the axes is scaled to 0,
132 * matrix inversion still works and we can still moving along the other. */
134
135 /* Original index of our connected vertex when connected distances are calculated.
136 * Optional, allocate if needed. */
137 int *dists_index = nullptr;
138 float *dists = nullptr;
139 if (prop_mode & T_PROP_CONNECTED) {
140 dists = static_cast<float *>(MEM_mallocN(bm->totvert * sizeof(float), __func__));
141 if (is_island_center) {
142 dists_index = static_cast<int *>(MEM_mallocN(bm->totvert * sizeof(int), __func__));
143 }
144 transform_convert_mesh_connectivity_distance(em->bm, mtx, dists, dists_index);
145 }
146
147 /* Create TransDataMirror. */
148 if (tc->use_mirror_axis_any) {
149 bool use_topology = (mesh->editflag & ME_EDIT_MIRROR_TOPO) != 0;
150 bool use_select = (t->flag & T_PROP_EDIT) == 0;
151 const bool mirror_axis[3] = {
152 bool(tc->use_mirror_axis_x), bool(tc->use_mirror_axis_y), bool(tc->use_mirror_axis_z)};
154 em, use_select, use_topology, mirror_axis, &mirror_data);
155
156 if (mirror_data.vert_map) {
157 tc->data_mirror_len = mirror_data.mirror_elem_len;
158 tc->data_mirror = static_cast<TransDataMirror *>(
159 MEM_callocN(mirror_data.mirror_elem_len * sizeof(*tc->data_mirror), __func__));
160
161 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
162 if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
163 if (mirror_data.vert_map[a].index != -1) {
164 data_len--;
165 }
166 }
167 }
168 }
169 }
170
171 /* Detect CrazySpace [tm]. */
172 transform_convert_mesh_crazyspace_detect(t, tc, em, &crazyspace_data);
173
174 /* Create TransData. */
175 BLI_assert(data_len >= 1);
176 tc->data_len = data_len;
177 tc->data = static_cast<TransData *>(
178 MEM_callocN(data_len * sizeof(TransData), "TransObData(Mesh EditMode)"));
179
180 TransData *td = tc->data;
181 TransDataMirror *td_mirror = tc->data_mirror;
182 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
184 continue;
185 }
186
187 int island_index = -1;
188 if (island_data.island_vert_map) {
189 const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a;
190 island_index = island_data.island_vert_map[connected_index];
191 }
192
193 if (mirror_data.vert_map && mirror_data.vert_map[a].index != -1) {
195 (TransDataBasic *)td_mirror, em, eve, &island_data, island_index);
196
197 int elem_index = mirror_data.vert_map[a].index;
198 BMVert *v_src = BM_vert_at_index(bm, elem_index);
199 MVertSkin *vs = static_cast<MVertSkin *>(
201
202 td_mirror->flag |= mirror_data.vert_map[a].flag;
203 td_mirror->loc_src = vs->radius;
204 td_mirror++;
205 }
206 else if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
207 mesh_skin_transdata_create((TransDataBasic *)td, em, eve, &island_data, island_index);
208
210 createSpaceNormal(td->axismtx, eve->no);
211 }
212 else {
213 /* Setting normals. */
214 copy_v3_v3(td->axismtx[2], eve->no);
215 td->axismtx[0][0] = td->axismtx[0][1] = td->axismtx[0][2] = td->axismtx[1][0] =
216 td->axismtx[1][1] = td->axismtx[1][2] = 0.0f;
217 }
218
219 if (prop_mode) {
220 if (prop_mode & T_PROP_CONNECTED) {
221 td->dist = dists[a];
222 }
223 else {
224 td->dist = FLT_MAX;
225 }
226 }
227
228 /* CrazySpace. */
230 mtx,
231 smtx,
232 !crazyspace_data.defmats.is_empty() ? crazyspace_data.defmats[a].ptr() : nullptr,
233 crazyspace_data.quats && BM_elem_flag_test(eve, BM_ELEM_TAG) ?
234 crazyspace_data.quats[a] :
235 nullptr,
236 td);
237
238 td++;
239 }
240 }
241
245 if (dists) {
246 MEM_freeN(dists);
247 }
248 if (dists_index) {
249 MEM_freeN(dists_index);
250 }
251 }
252}
253
256/* -------------------------------------------------------------------- */
261{
263 if (tc->use_mirror_axis_any) {
264 TransDataMirror *td_mirror = tc->data_mirror;
265 for (int i = 0; i < tc->data_mirror_len; i++, td_mirror++) {
266 copy_v3_v3(td_mirror->loc, td_mirror->loc_src);
267 }
268 }
269 }
270}
271
273{
274 bool is_canceling = t->state == TRANS_CANCEL;
275 /* Mirror modifier clipping? */
276 if (!is_canceling) {
277 if (!(t->flag & T_NO_MIRROR)) {
279 }
280 }
281
283 DEG_id_tag_update(static_cast<ID *>(tc->obedit->data), ID_RECALC_GEOMETRY);
284 BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
286 }
287}
288
292 /*flags*/ (T_EDIT | T_POINTS),
293 /*create_trans_data*/ createTransMeshSkin,
294 /*recalc_data*/ recalcData_mesh_skin,
295 /*special_aftertrans_update*/ nullptr,
296};
void * CustomData_bmesh_get(const CustomData *data, void *block, eCustomDataType type)
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
Definition editmesh.cc:63
void BKE_editmesh_looptris_and_normals_calc(BMEditMesh *em)
Definition editmesh.cc:83
#define BLI_assert(a)
Definition BLI_assert.h:50
void pseudoinverse_m3_m3(float inverse[3][3], const float mat[3][3], float epsilon)
void copy_m3_m4(float m1[3][3], const float m2[4][4])
#define PSEUDOINVERSE_EPSILON
MINLINE void copy_v3_v3(float r[3], const float a[3])
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
@ CD_MVERT_SKIN
@ ME_EDIT_MIRROR_TOPO
@ SCE_SELECT_VERTEX
@ V3D_AROUND_LOCAL_ORIGINS
@ TFM_SKIN_RESIZE
Read Guarded memory(de)allocation.
@ BM_ELEM_HIDDEN
@ BM_ELEM_SELECT
@ BM_ELEM_TAG
#define BM_elem_flag_test(ele, hflag)
#define BM_ITER_MESH(ele, iter, bm, itype)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_VERTS_OF_MESH
ATTR_WARN_UNUSED_RESULT BMesh * bm
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
#define FLT_MAX
Definition stdcycles.h:14
short selectmode
void * data
float co[3]
float no[3]
BMHeader head
int totvert
CustomData vdata
int totvertsel
Definition DNA_ID.h:413
eTfmMode mode
Definition transform.hh:517
short around
Definition transform.hh:580
eTState state
Definition transform.hh:527
eTFlag flag
Definition transform.hh:523
blender::Array< blender::float3x3, 0 > defmats
MirrorDataVert * vert_map
@ T_PROP_CONNECTED
Definition transform.hh:99
@ T_NO_MIRROR
Definition transform.hh:111
@ T_PROP_EDIT
Definition transform.hh:98
@ T_POINTS
Definition transform.hh:93
@ T_EDIT
Definition transform.hh:91
@ TRANS_CANCEL
Definition transform.hh:210
#define T_PROP_EDIT_ALL
Definition transform.hh:157
#define FOREACH_TRANS_DATA_CONTAINER(t, th)
Definition transform.hh:854
conversion and adaptation of different datablocks to a common struct.
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], TransData *r_td)
void transform_convert_mesh_mirrordata_calc(BMEditMesh *em, bool use_select, bool use_topology, const bool mirror_axis[3], TransMirrorData *r_mirror_data)
void transform_convert_mesh_islands_calc(BMEditMesh *em, bool calc_single_islands, bool calc_island_center, bool calc_island_axismtx, TransIslandData *r_island_data)
void transform_convert_mesh_crazyspace_detect(TransInfo *t, TransDataContainer *tc, BMEditMesh *em, TransMeshDataCrazySpace *r_crazyspace_data)
void transform_convert_mesh_connectivity_distance(BMesh *bm, const float mtx[3][3], float *dists, int *index)
void transform_convert_mesh_mirrordata_free(TransMirrorData *mirror_data)
void transform_convert_mesh_islanddata_free(TransIslandData *island_data)
void transform_convert_mesh_crazyspace_free(TransMeshDataCrazySpace *r_crazyspace_data)
static void mesh_skin_transdata_create(TransDataBasic *td, BMEditMesh *em, BMVert *eve, const TransIslandData *island_data, const int island_index)
static void recalcData_mesh_skin(TransInfo *t)
TransConvertTypeInfo TransConvertType_MeshSkin
static void createTransMeshSkin(bContext *, TransInfo *t)
static float * mesh_skin_transdata_center(const TransIslandData *island_data, const int island_index, BMVert *eve)
static void mesh_skin_apply_to_mirror(TransInfo *t)
@ TD_SELECTED
@ TD_SKIP
bool createSpaceNormal(float mat[3][3], const float normal[3])