Blender V5.0
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
8
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
25namespace blender::ed::transform {
26
27/* -------------------------------------------------------------------- */
30
31static float *mesh_skin_transdata_center(const TransIslandData *island_data,
32 const int island_index,
33 BMVert *eve)
34{
35 if (island_data->center && island_index != -1) {
36 return island_data->center[island_index];
37 }
38 return eve->co;
39}
40
42 BMEditMesh *em,
43 BMVert *eve,
44 const TransIslandData *island_data,
45 const int island_index)
46{
48 MVertSkin *vs = static_cast<MVertSkin *>(
50 td->flag = 0;
51 if (vs) {
52 copy_v3_v3(td->iloc, vs->radius);
53 td->loc = vs->radius;
54 }
55 else {
56 td->flag |= TD_SKIP;
57 }
58
60 td->flag |= TD_SELECTED;
61 }
62
63 copy_v3_v3(td->center, mesh_skin_transdata_center(island_data, island_index, eve));
64 td->extra = eve;
65}
66
67static void createTransMeshSkin(bContext * /*C*/, TransInfo *t)
68{
71 BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
72 Mesh *mesh = static_cast<Mesh *>(tc->obedit->data);
73 BMesh *bm = em->bm;
74 BMVert *eve;
75 BMIter iter;
76 float mtx[3][3], smtx[3][3];
77 int a;
78 const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
79
80 TransIslandData island_data = {nullptr};
81 TransMirrorData mirror_data = {nullptr};
82 TransMeshDataCrazySpace crazyspace_data = {nullptr};
83
90
91 if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) {
92 continue;
93 }
94
95 /* Support other objects using proportional editing to adjust these, unless connected is
96 * enabled. */
97 if ((!prop_mode || (prop_mode & T_PROP_CONNECTED)) && (bm->totvertsel == 0)) {
98 continue;
99 }
100
101 int data_len = 0;
102 if (prop_mode) {
103 BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
105 data_len++;
106 }
107 }
108 }
109 else {
110 data_len = bm->totvertsel;
111 }
112
113 if (data_len == 0) {
114 continue;
115 }
116
117 const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS);
118 if (is_island_center) {
119 /* In this specific case, near-by vertices will need to know
120 * the island of the nearest connected vertex. */
121 const bool calc_single_islands = ((prop_mode & T_PROP_CONNECTED) &&
124
125 const bool calc_island_center = false;
126 const bool calc_island_axismtx = false;
127
129 em, calc_single_islands, calc_island_center, calc_island_axismtx, &island_data);
130 }
131
132 copy_m3_m4(mtx, tc->obedit->object_to_world().ptr());
133 /* We use a pseudo-inverse so that when one of the axes is scaled to 0,
134 * matrix inversion still works and we can still moving along the other. */
136
137 /* Original index of our connected vertex when connected distances are calculated.
138 * Optional, allocate if needed. */
139 int *dists_index = nullptr;
140 float *dists = nullptr;
141 if (prop_mode & T_PROP_CONNECTED) {
142 dists = MEM_malloc_arrayN<float>(bm->totvert, __func__);
143 if (is_island_center) {
144 dists_index = MEM_malloc_arrayN<int>(bm->totvert, __func__);
145 }
146 transform_convert_mesh_connectivity_distance(em->bm, mtx, dists, dists_index);
147 }
148
149 /* Create TransDataMirror. */
150 if (tc->use_mirror_axis_any) {
151 bool use_topology = (mesh->editflag & ME_EDIT_MIRROR_TOPO) != 0;
152 bool use_select = (t->flag & T_PROP_EDIT) == 0;
153 const bool mirror_axis[3] = {
154 bool(tc->use_mirror_axis_x), bool(tc->use_mirror_axis_y), bool(tc->use_mirror_axis_z)};
156 em, use_select, use_topology, mirror_axis, &mirror_data);
157
158 if (mirror_data.vert_map) {
159 tc->data_mirror_len = mirror_data.mirror_elem_len;
160 tc->data_mirror = static_cast<TransDataMirror *>(
161 MEM_callocN(mirror_data.mirror_elem_len * sizeof(*tc->data_mirror), __func__));
162
163 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
164 if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
165 if (mirror_data.vert_map[a].index != -1) {
166 data_len--;
167 }
168 }
169 }
170 }
171 }
172
173 /* Detect CrazySpace [TM]. */
174 transform_convert_mesh_crazyspace_detect(t, tc, em, &crazyspace_data);
175
176 /* Create TransData. */
177 BLI_assert(data_len >= 1);
178 tc->data_len = data_len;
179 tc->data = MEM_calloc_arrayN<TransData>(data_len, "TransObData(Mesh EditMode)");
180
181 TransData *td = tc->data;
182 TransDataMirror *td_mirror = tc->data_mirror;
183 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
185 continue;
186 }
187
188 int island_index = -1;
189 if (island_data.island_vert_map) {
190 const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a;
191 island_index = island_data.island_vert_map[connected_index];
192 }
193
194 if (mirror_data.vert_map && mirror_data.vert_map[a].index != -1) {
196 (TransDataBasic *)td_mirror, em, eve, &island_data, island_index);
197
198 int elem_index = mirror_data.vert_map[a].index;
199 BMVert *v_src = BM_vert_at_index(bm, elem_index);
200 MVertSkin *vs = static_cast<MVertSkin *>(
202
203 td_mirror->flag |= mirror_data.vert_map[a].flag;
204 td_mirror->loc_src = vs->radius;
205 td_mirror++;
206 }
207 else if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
208 mesh_skin_transdata_create((TransDataBasic *)td, em, eve, &island_data, island_index);
209
211 createSpaceNormal(td->axismtx, eve->no);
212 }
213 else {
214 /* Setting normals. */
215 copy_v3_v3(td->axismtx[2], eve->no);
216 td->axismtx[0][0] = td->axismtx[0][1] = td->axismtx[0][2] = td->axismtx[1][0] =
217 td->axismtx[1][1] = td->axismtx[1][2] = 0.0f;
218 }
219
220 if (prop_mode) {
221 if (prop_mode & T_PROP_CONNECTED) {
222 td->dist = dists[a];
223 }
224 else {
225 td->dist = FLT_MAX;
226 }
227 }
228
229 /* CrazySpace. */
231 mtx,
232 smtx,
233 !crazyspace_data.defmats.is_empty() ? crazyspace_data.defmats[a].ptr() : nullptr,
234 crazyspace_data.quats && BM_elem_flag_test(eve, BM_ELEM_TAG) ?
235 crazyspace_data.quats[a] :
236 nullptr,
237 td);
238
239 td++;
240 }
241 }
242
246 if (dists) {
247 MEM_freeN(dists);
248 }
249 if (dists_index) {
250 MEM_freeN(dists_index);
251 }
252 }
253}
254
256
257/* -------------------------------------------------------------------- */
260
262{
264 if (tc->use_mirror_axis_any) {
265 TransDataMirror *td_mirror = tc->data_mirror;
266 for (int i = 0; i < tc->data_mirror_len; i++, td_mirror++) {
267 copy_v3_v3(td_mirror->loc, td_mirror->loc_src);
268 }
269 }
270 }
271}
272
274{
275 bool is_canceling = t->state == TRANS_CANCEL;
276 /* Mirror modifier clipping? */
277 if (!is_canceling) {
278 if (!(t->flag & T_NO_MIRROR)) {
280 }
281 }
282
284 DEG_id_tag_update(static_cast<ID *>(tc->obedit->data), ID_RECALC_GEOMETRY);
285 BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
287 }
288}
289
291
293 /*flags*/ (T_EDIT | T_POINTS),
294 /*create_trans_data*/ createTransMeshSkin,
295 /*recalc_data*/ recalcData_mesh_skin,
296 /*special_aftertrans_update*/ nullptr,
297};
298
299} // namespace blender::ed::transform
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:61
void BKE_editmesh_looptris_and_normals_calc(BMEditMesh *em)
Definition editmesh.cc:95
#define BLI_assert(a)
Definition BLI_assert.h:46
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:1074
@ CD_MVERT_SKIN
@ ME_EDIT_MIRROR_TOPO
@ SCE_SELECT_VERTEX
@ V3D_AROUND_LOCAL_ORIGINS
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
BMesh * bm
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static float * mesh_skin_transdata_center(const TransIslandData *island_data, const int island_index, BMVert *eve)
void transform_convert_mesh_mirrordata_free(TransMirrorData *mirror_data)
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_islanddata_free(TransIslandData *island_data)
void transform_convert_mesh_crazyspace_free(TransMeshDataCrazySpace *r_crazyspace_data)
void transform_convert_mesh_crazyspace_detect(TransInfo *t, TransDataContainer *tc, BMEditMesh *em, TransMeshDataCrazySpace *r_crazyspace_data)
static void mesh_skin_apply_to_mirror(TransInfo *t)
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)
bool createSpaceNormal(float mat[3][3], const float normal[3])
static void createTransMeshSkin(bContext *, TransInfo *t)
static void mesh_skin_transdata_create(TransDataBasic *td, BMEditMesh *em, BMVert *eve, const TransIslandData *island_data, const int island_index)
TransConvertTypeInfo TransConvertType_MeshSkin
void transform_convert_mesh_connectivity_distance(BMesh *bm, const float mtx[3][3], float *dists, int *index)
static void recalcData_mesh_skin(TransInfo *t)
void transform_convert_mesh_islands_calc(BMEditMesh *em, bool calc_single_islands, bool calc_island_center, bool calc_island_axismtx, TransIslandData *r_island_data)
#define FLT_MAX
Definition stdcycles.h:14
short selectmode
void * data
float co[3]
float no[3]
BMHeader head
CustomData vdata
Definition DNA_ID.h:414
i
Definition text_draw.cc:230
#define T_PROP_EDIT_ALL
Definition transform.hh:28
#define FOREACH_TRANS_DATA_CONTAINER(t, th)
Definition transform.hh:42
conversion and adaptation of different datablocks to a common struct.