Blender  V3.3
transform_convert_mesh_skin.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include "DNA_mesh_types.h"
9 #include "DNA_meshdata_types.h"
10 
11 #include "MEM_guardedalloc.h"
12 
13 #include "BLI_math.h"
14 
15 #include "BKE_context.h"
16 #include "BKE_crazyspace.h"
17 #include "BKE_editmesh.h"
18 #include "BKE_modifier.h"
19 #include "BKE_scene.h"
20 
21 #include "ED_mesh.h"
22 
23 #include "DEG_depsgraph_query.h"
24 
25 #include "transform.h"
26 #include "transform_orientations.h"
27 
28 #include "transform_convert.h"
29 
30 /* -------------------------------------------------------------------- */
34 static float *tc_mesh_skin_transdata_center(const struct TransIslandData *island_data,
35  const int island_index,
36  BMVert *eve)
37 {
38  if (island_data->center && island_index != -1) {
39  return island_data->center[island_index];
40  }
41  return eve->co;
42 }
43 
45  BMEditMesh *em,
46  BMVert *eve,
47  const struct TransIslandData *island_data,
48  const int island_index)
49 {
52  td->flag = 0;
53  if (vs) {
54  copy_v3_v3(td->iloc, vs->radius);
55  td->loc = vs->radius;
56  }
57  else {
58  td->flag |= TD_SKIP;
59  }
60 
62  td->flag |= TD_SELECTED;
63  }
64 
65  copy_v3_v3(td->center, tc_mesh_skin_transdata_center(island_data, island_index, eve));
66  td->extra = eve;
67 }
68 
70 {
71  BLI_assert(t->mode == TFM_SKIN_RESIZE);
73  BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
74  Mesh *me = tc->obedit->data;
75  BMesh *bm = em->bm;
76  BMVert *eve;
77  BMIter iter;
78  float mtx[3][3], smtx[3][3];
79  int a;
80  const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
81 
82  struct TransIslandData island_data = {NULL};
83  struct TransMirrorData mirror_data = {NULL};
84  struct TransMeshDataCrazySpace crazyspace_data = {NULL};
85 
94  continue;
95  }
96 
97  /* Support other objects using PET to adjust these, unless connected is enabled. */
98  if ((!prop_mode || (prop_mode & T_PROP_CONNECTED)) && (bm->totvertsel == 0)) {
99  continue;
100  }
101 
102  int data_len = 0;
103  if (prop_mode) {
104  BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
105  if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
106  data_len++;
107  }
108  }
109  }
110  else {
111  data_len = bm->totvertsel;
112  }
113 
114  if (data_len == 0) {
115  continue;
116  }
117 
118  const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS);
119  if (is_island_center) {
120  /* In this specific case, near-by vertices will need to know
121  * the island of the nearest connected vertex. */
122  const bool calc_single_islands = ((prop_mode & T_PROP_CONNECTED) &&
123  (t->around == V3D_AROUND_LOCAL_ORIGINS) &&
124  (em->selectmode & SCE_SELECT_VERTEX));
125 
126  const bool calc_island_center = false;
127  const bool calc_island_axismtx = false;
128 
130  em, calc_single_islands, calc_island_center, calc_island_axismtx, &island_data);
131  }
132 
133  copy_m3_m4(mtx, tc->obedit->obmat);
134  /* we use a pseudo-inverse so that when one of the axes is scaled to 0,
135  * matrix inversion still works and we can still moving along the other */
137 
138  /* Original index of our connected vertex when connected distances are calculated.
139  * Optional, allocate if needed. */
140  int *dists_index = NULL;
141  float *dists = NULL;
142  if (prop_mode & T_PROP_CONNECTED) {
143  dists = MEM_mallocN(bm->totvert * sizeof(float), __func__);
144  if (is_island_center) {
145  dists_index = MEM_mallocN(bm->totvert * sizeof(int), __func__);
146  }
147  transform_convert_mesh_connectivity_distance(em->bm, mtx, dists, dists_index);
148  }
149 
150  /* Create TransDataMirror. */
151  if (tc->use_mirror_axis_any) {
152  bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
153  bool use_select = (t->flag & T_PROP_EDIT) == 0;
154  const bool mirror_axis[3] = {
155  tc->use_mirror_axis_x, tc->use_mirror_axis_y, tc->use_mirror_axis_z};
157  em, use_select, use_topology, mirror_axis, &mirror_data);
158 
159  if (mirror_data.vert_map) {
160  tc->data_mirror_len = mirror_data.mirror_elem_len;
161  tc->data_mirror = MEM_mallocN(mirror_data.mirror_elem_len * sizeof(*tc->data_mirror),
162  __func__);
163 
164  BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
165  if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
166  if (mirror_data.vert_map[a].index != -1) {
167  data_len--;
168  }
169  }
170  }
171  }
172  }
173 
174  /* Detect CrazySpace [tm]. */
175  transform_convert_mesh_crazyspace_detect(t, tc, em, &crazyspace_data);
176 
177  /* Create TransData. */
178  BLI_assert(data_len >= 1);
179  tc->data_len = data_len;
180  tc->data = MEM_callocN(data_len * sizeof(TransData), "TransObData(Mesh EditMode)");
181 
182  TransData *td = tc->data;
183  TransDataMirror *td_mirror = tc->data_mirror;
184  BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
185  if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
186  continue;
187  }
188 
189  int island_index = -1;
190  if (island_data.island_vert_map) {
191  const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a;
192  island_index = island_data.island_vert_map[connected_index];
193  }
194 
195  if (mirror_data.vert_map && mirror_data.vert_map[a].index != -1) {
197  (TransDataBasic *)td_mirror, em, eve, &island_data, island_index);
198 
199  int elem_index = mirror_data.vert_map[a].index;
200  BMVert *v_src = BM_vert_at_index(bm, elem_index);
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  tc_mesh_skin_transdata_create((TransDataBasic *)td, em, eve, &island_data, island_index);
209 
210  if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
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->flag |= TD_NOTCONNECTED;
226  td->dist = FLT_MAX;
227  }
228  }
229 
230  /* CrazySpace */
232  mtx,
233  smtx,
234  crazyspace_data.defmats ? crazyspace_data.defmats[a] : NULL,
235  crazyspace_data.quats && BM_elem_flag_test(eve, BM_ELEM_TAG) ?
236  crazyspace_data.quats[a] :
237  NULL,
238  td);
239 
240  td++;
241  }
242  }
243 
246  transform_convert_mesh_crazyspace_free(&crazyspace_data);
247  if (dists) {
248  MEM_freeN(dists);
249  }
250  if (dists_index) {
251  MEM_freeN(dists_index);
252  }
253  }
254 }
255 
258 /* -------------------------------------------------------------------- */
263 {
265  if (tc->use_mirror_axis_any) {
266  TransDataMirror *td_mirror = tc->data_mirror;
267  for (int i = 0; i < tc->data_mirror_len; i++, td_mirror++) {
268  copy_v3_v3(td_mirror->loc, td_mirror->loc_src);
269  }
270  }
271  }
272 }
273 
275 {
276  bool is_canceling = t->state == TRANS_CANCEL;
277  /* mirror modifier clipping? */
278  if (!is_canceling) {
279  if (!(t->flag & T_NO_MIRROR)) {
281  }
282  }
283 
285  DEG_id_tag_update(tc->obedit->data, ID_RECALC_GEOMETRY);
286  BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
288  }
289 }
290 
294  /* flags */ (T_EDIT | T_POINTS),
295  /* createTransData */ createTransMeshSkin,
296  /* recalcData */ recalcData_mesh_skin,
297  /* special_aftertrans_update */ NULL,
298 };
bool CustomData_has_layer(const struct CustomData *data, int type)
void * CustomData_bmesh_get(const struct CustomData *data, void *block, int type)
void BKE_editmesh_looptri_and_normals_calc(BMEditMesh *em)
Definition: editmesh.c:135
BMEditMesh * BKE_editmesh_from_object(struct Object *ob)
Return the BMEditMesh for a given object.
Definition: editmesh.c:58
#define BLI_assert(a)
Definition: BLI_assert.h:46
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:87
#define PSEUDOINVERSE_EPSILON
void pseudoinverse_m3_m3(float Ainv[3][3], const float A[3][3], float epsilon)
Definition: math_matrix.c:3107
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define UNUSED(x)
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
@ CD_MVERT_SKIN
@ ME_EDIT_MIRROR_TOPO
#define SCE_SELECT_VERTEX
@ V3D_AROUND_LOCAL_ORIGINS
@ TFM_SKIN_RESIZE
Definition: ED_transform.h:33
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:25
@ BM_ELEM_HIDDEN
Definition: bmesh_class.h:472
@ BM_ELEM_SELECT
Definition: bmesh_class.h:471
@ BM_ELEM_TAG
Definition: bmesh_class.h:484
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:12
#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)
Definition: bmesh_mesh.h:103
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
static unsigned a[3]
Definition: RandGen.cpp:78
#define FOREACH_TRANS_DATA_CONTAINER(t, th)
short selectmode
Definition: BKE_editmesh.h:52
struct BMesh * bm
Definition: BKE_editmesh.h:40
void * data
Definition: bmesh_class.h:51
float co[3]
Definition: bmesh_class.h:87
float no[3]
Definition: bmesh_class.h:88
BMHeader head
Definition: bmesh_class.h:85
int totvert
Definition: bmesh_class.h:297
CustomData vdata
Definition: bmesh_class.h:337
int totvertsel
Definition: bmesh_class.h:298
char editflag
struct MirrorDataVert * vert_map
conversion and adaptation of different datablocks to a common struct.
void transform_convert_mesh_islanddata_free(struct TransIslandData *island_data)
void transform_convert_mesh_mirrordata_calc(struct BMEditMesh *em, bool use_select, bool use_topology, const bool mirror_axis[3], struct TransMirrorData *r_mirror_data)
void transform_convert_mesh_islands_calc(struct BMEditMesh *em, bool calc_single_islands, bool calc_island_center, bool calc_island_axismtx, struct TransIslandData *r_island_data)
void transform_convert_mesh_crazyspace_free(struct TransMeshDataCrazySpace *r_crazyspace_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_mirrordata_free(struct TransMirrorData *mirror_data)
void transform_convert_mesh_connectivity_distance(struct BMesh *bm, const float mtx[3][3], float *dists, int *index)
static void createTransMeshSkin(bContext *UNUSED(C), TransInfo *t)
static void recalcData_mesh_skin(TransInfo *t)
TransConvertTypeInfo TransConvertType_MeshSkin
static float * tc_mesh_skin_transdata_center(const struct TransIslandData *island_data, const int island_index, BMVert *eve)
static void tc_mesh_skin_transdata_create(TransDataBasic *td, BMEditMesh *em, BMVert *eve, const struct TransIslandData *island_data, const int island_index)
static void tc_mesh_skin_apply_to_mirror(TransInfo *t)
@ TD_NOTCONNECTED
@ TD_SELECTED
@ TD_SKIP
bool createSpaceNormal(float mat[3][3], const float normal[3])