Blender  V3.3
transform_convert_mesh_vert_cdata.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_cdata_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  BMVert *eve,
46  float *weight,
47  const struct TransIslandData *island_data,
48  const int island_index)
49 {
51 
52  td->loc = weight;
53  td->iloc[0] = *weight;
54 
56  td->flag |= TD_SELECTED;
57  }
58 
59  copy_v3_v3(td->center, tc_mesh_cdata_transdata_center(island_data, island_index, eve));
60  td->extra = eve;
61 }
62 
64 {
67  BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
68  Mesh *me = tc->obedit->data;
69  BMesh *bm = em->bm;
70  BMVert *eve;
71  BMIter iter;
72  float mtx[3][3], smtx[3][3];
73  int a;
74  const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
75 
76  struct TransIslandData island_data = {NULL};
77  struct TransMirrorData mirror_data = {NULL};
78  struct TransMeshDataCrazySpace crazyspace_data = {NULL};
79 
80  /* Support other objects using PET to adjust these, unless connected is enabled. */
81  if ((!prop_mode || (prop_mode & T_PROP_CONNECTED)) && (bm->totvertsel == 0)) {
82  continue;
83  }
84 
85  int cd_offset = -1;
86  if (t->mode == TFM_BWEIGHT) {
88  cd_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
89  }
90  else {
92  cd_offset = CustomData_get_offset(&bm->vdata, CD_CREASE);
93  }
94 
95  if (cd_offset == -1) {
96  continue;
97  }
98 
99  int data_len = 0;
100  if (prop_mode) {
101  BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
102  if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
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) &&
120  (t->around == V3D_AROUND_LOCAL_ORIGINS) &&
121  (em->selectmode & SCE_SELECT_VERTEX));
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->obmat);
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 = NULL;
138  float *dists = NULL;
139  if (prop_mode & T_PROP_CONNECTED) {
140  dists = MEM_mallocN(bm->totvert * sizeof(float), __func__);
141  if (is_island_center) {
142  dists_index = 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 = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
150  bool use_select = (t->flag & T_PROP_EDIT) == 0;
151  const bool mirror_axis[3] = {
152  tc->use_mirror_axis_x, tc->use_mirror_axis_y, 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 = MEM_mallocN(mirror_data.mirror_elem_len * sizeof(*tc->data_mirror),
159  __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 = MEM_callocN(data_len * sizeof(TransData), "TransObData(Mesh EditMode)");
178 
179  TransData *td = tc->data;
180  TransDataMirror *td_mirror = tc->data_mirror;
181  BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
182  if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
183  continue;
184  }
185 
186  int island_index = -1;
187  if (island_data.island_vert_map) {
188  const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a;
189  island_index = island_data.island_vert_map[connected_index];
190  }
191 
192  float *weight = BM_ELEM_CD_GET_VOID_P(eve, cd_offset);
193  if (mirror_data.vert_map && mirror_data.vert_map[a].index != -1) {
195  (TransDataBasic *)td_mirror, eve, weight, &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 
200  td_mirror->flag |= mirror_data.vert_map[a].flag;
201  td_mirror->loc_src = BM_ELEM_CD_GET_VOID_P(v_src, cd_offset);
202  td_mirror++;
203  }
204  else if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
206  (TransDataBasic *)td, eve, weight, &island_data, island_index);
207 
208  if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
209  createSpaceNormal(td->axismtx, eve->no);
210  }
211  else {
212  /* Setting normals */
213  copy_v3_v3(td->axismtx[2], eve->no);
214  td->axismtx[0][0] = td->axismtx[0][1] = td->axismtx[0][2] = td->axismtx[1][0] =
215  td->axismtx[1][1] = td->axismtx[1][2] = 0.0f;
216  }
217 
218  if (prop_mode) {
219  if (prop_mode & T_PROP_CONNECTED) {
220  td->dist = dists[a];
221  }
222  else {
223  td->flag |= TD_NOTCONNECTED;
224  td->dist = FLT_MAX;
225  }
226  }
227 
228  /* CrazySpace */
230  mtx,
231  smtx,
232  crazyspace_data.defmats ? crazyspace_data.defmats[a] : NULL,
233  crazyspace_data.quats && BM_elem_flag_test(eve, BM_ELEM_TAG) ?
234  crazyspace_data.quats[a] :
235  NULL,
236  td);
237 
238  td++;
239  }
240  }
241 
244  transform_convert_mesh_crazyspace_free(&crazyspace_data);
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  td_mirror->loc[0] = td_mirror->loc_src[0];
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(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  /* createTransData */ createTransMeshVertCData,
294  /* recalcData */ recalcData_mesh_cdata,
295  /* special_aftertrans_update */ NULL,
296 };
int CustomData_get_offset(const struct CustomData *data, 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)
#define ELEM(...)
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
@ CD_BWEIGHT
@ ME_EDIT_MIRROR_TOPO
@ ME_CDFLAG_VERT_CREASE
@ ME_CDFLAG_VERT_BWEIGHT
#define SCE_SELECT_VERTEX
@ V3D_AROUND_LOCAL_ORIGINS
@ TFM_VERT_CREASE
Definition: ED_transform.h:42
@ TFM_BWEIGHT
Definition: ED_transform.h:57
_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_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:541
#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 BM_mesh_cd_flag_ensure(BMesh *bm, Mesh *mesh, const char cd_flag)
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
float co[3]
Definition: bmesh_class.h:87
float no[3]
Definition: bmesh_class.h:88
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 createTransMeshVertCData(bContext *UNUSED(C), TransInfo *t)
TransConvertTypeInfo TransConvertType_MeshVertCData
static float * tc_mesh_cdata_transdata_center(const struct TransIslandData *island_data, const int island_index, BMVert *eve)
static void tc_mesh_cdata_transdata_create(TransDataBasic *td, BMVert *eve, float *weight, const struct TransIslandData *island_data, const int island_index)
static void tc_mesh_cdata_apply_to_mirror(TransInfo *t)
static void recalcData_mesh_cdata(TransInfo *t)
@ TD_NOTCONNECTED
@ TD_SELECTED
bool createSpaceNormal(float mat[3][3], const float normal[3])