Blender  V2.93
transform_convert_mesh_skin.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19 
24 #include "DNA_mesh_types.h"
25 #include "DNA_meshdata_types.h"
26 
27 #include "MEM_guardedalloc.h"
28 
29 #include "BLI_math.h"
30 
31 #include "BKE_context.h"
32 #include "BKE_crazyspace.h"
33 #include "BKE_editmesh.h"
34 #include "BKE_modifier.h"
35 #include "BKE_scene.h"
36 
37 #include "ED_mesh.h"
38 
39 #include "DEG_depsgraph_query.h"
40 
41 #include "transform.h"
42 #include "transform_orientations.h"
43 
44 #include "transform_convert.h"
45 
46 /* -------------------------------------------------------------------- */
50 static float *mesh_skin_transdata_center(const struct TransIslandData *island_data,
51  const int island_index,
52  BMVert *eve)
53 {
54  if (island_data->center && island_index != -1) {
55  return island_data->center[island_index];
56  }
57  return eve->co;
58 }
59 
61  BMEditMesh *em,
62  BMVert *eve,
63  const struct TransIslandData *island_data,
64  const int island_index)
65 {
68  td->flag = 0;
69  if (vs) {
70  copy_v3_v3(td->iloc, vs->radius);
71  td->loc = vs->radius;
72  }
73  else {
74  td->flag |= TD_SKIP;
75  }
76 
78  td->flag |= TD_SELECTED;
79  }
80 
81  copy_v3_v3(td->center, mesh_skin_transdata_center(island_data, island_index, eve));
82  td->extra = eve;
83 }
84 
86 {
87  BLI_assert(t->mode == TFM_SKIN_RESIZE);
89  BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
90  Mesh *me = tc->obedit->data;
91  BMesh *bm = em->bm;
92  BMVert *eve;
93  BMIter iter;
94  float mtx[3][3], smtx[3][3];
95  int a;
96  const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
97 
98  struct TransIslandData island_data = {NULL};
99  struct TransMirrorData mirror_data = {NULL};
100  struct TransMeshDataCrazySpace crazyspace_data = {NULL};
101 
110  continue;
111  }
112 
113  /* Support other objects using PET to adjust these, unless connected is enabled. */
114  if ((!prop_mode || (prop_mode & T_PROP_CONNECTED)) && (bm->totvertsel == 0)) {
115  continue;
116  }
117 
118  int data_len = 0;
119  if (prop_mode) {
120  BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
121  if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
122  data_len++;
123  }
124  }
125  }
126  else {
127  data_len = bm->totvertsel;
128  }
129 
130  if (data_len == 0) {
131  continue;
132  }
133 
134  const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS);
135  if (is_island_center) {
136  /* In this specific case, near-by vertices will need to know
137  * the island of the nearest connected vertex. */
138  const bool calc_single_islands = ((prop_mode & T_PROP_CONNECTED) &&
139  (t->around == V3D_AROUND_LOCAL_ORIGINS) &&
140  (em->selectmode & SCE_SELECT_VERTEX));
141 
142  const bool calc_island_center = false;
143  const bool calc_island_axismtx = false;
144 
146  em, calc_single_islands, calc_island_center, calc_island_axismtx, &island_data);
147  }
148 
149  copy_m3_m4(mtx, tc->obedit->obmat);
150  /* we use a pseudo-inverse so that when one of the axes is scaled to 0,
151  * matrix inversion still works and we can still moving along the other */
153 
154  /* Original index of our connected vertex when connected distances are calculated.
155  * Optional, allocate if needed. */
156  int *dists_index = NULL;
157  float *dists = NULL;
158  if (prop_mode & T_PROP_CONNECTED) {
159  dists = MEM_mallocN(bm->totvert * sizeof(float), __func__);
160  if (is_island_center) {
161  dists_index = MEM_mallocN(bm->totvert * sizeof(int), __func__);
162  }
163  transform_convert_mesh_connectivity_distance(em->bm, mtx, dists, dists_index);
164  }
165 
166  /* Create TransDataMirror. */
167  if (tc->use_mirror_axis_any) {
168  bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
169  bool use_select = (t->flag & T_PROP_EDIT) == 0;
170  const bool mirror_axis[3] = {
171  tc->use_mirror_axis_x, tc->use_mirror_axis_y, tc->use_mirror_axis_z};
173  em, use_select, use_topology, mirror_axis, &mirror_data);
174 
175  if (mirror_data.vert_map) {
176  tc->data_mirror_len = mirror_data.mirror_elem_len;
177  tc->data_mirror = MEM_mallocN(mirror_data.mirror_elem_len * sizeof(*tc->data_mirror),
178  __func__);
179 
180  BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
181  if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
182  if (mirror_data.vert_map[a].index != -1) {
183  data_len--;
184  }
185  }
186  }
187  }
188  }
189 
190  /* Detect CrazySpace [tm]. */
191  transform_convert_mesh_crazyspace_detect(t, tc, em, &crazyspace_data);
192 
193  /* Create TransData. */
194  BLI_assert(data_len >= 1);
195  tc->data_len = data_len;
196  tc->data = MEM_callocN(data_len * sizeof(TransData), "TransObData(Mesh EditMode)");
197 
198  TransData *td = tc->data;
199  TransDataMirror *td_mirror = tc->data_mirror;
200  BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
201  if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
202  continue;
203  }
204 
205  int island_index = -1;
206  if (island_data.island_vert_map) {
207  const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a;
208  island_index = island_data.island_vert_map[connected_index];
209  }
210 
211  if (mirror_data.vert_map && mirror_data.vert_map[a].index != -1) {
213  (TransDataBasic *)td_mirror, em, eve, &island_data, island_index);
214 
215  int elem_index = mirror_data.vert_map[a].index;
216  BMVert *v_src = BM_vert_at_index(bm, elem_index);
218 
219  td_mirror->flag |= mirror_data.vert_map[a].flag;
220  td_mirror->loc_src = vs->radius;
221  td_mirror++;
222  }
223  else if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
224  mesh_skin_transdata_create((TransDataBasic *)td, em, eve, &island_data, island_index);
225 
226  if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
227  createSpaceNormal(td->axismtx, eve->no);
228  }
229  else {
230  /* Setting normals */
231  copy_v3_v3(td->axismtx[2], eve->no);
232  td->axismtx[0][0] = td->axismtx[0][1] = td->axismtx[0][2] = td->axismtx[1][0] =
233  td->axismtx[1][1] = td->axismtx[1][2] = 0.0f;
234  }
235 
236  if (prop_mode) {
237  if (prop_mode & T_PROP_CONNECTED) {
238  td->dist = dists[a];
239  }
240  else {
241  td->flag |= TD_NOTCONNECTED;
242  td->dist = FLT_MAX;
243  }
244  }
245 
246  /* CrazySpace */
248  mtx,
249  smtx,
250  crazyspace_data.defmats ? crazyspace_data.defmats[a] : NULL,
251  crazyspace_data.quats && BM_elem_flag_test(eve, BM_ELEM_TAG) ?
252  crazyspace_data.quats[a] :
253  NULL,
254  td);
255 
256  td++;
257  }
258  }
259 
262  transform_convert_mesh_crazyspace_free(&crazyspace_data);
263  if (dists) {
264  MEM_freeN(dists);
265  }
266  if (dists_index) {
267  MEM_freeN(dists_index);
268  }
269  }
270 }
271 
274 /* -------------------------------------------------------------------- */
279 {
281  if (tc->use_mirror_axis_any) {
282  TransDataMirror *td_mirror = tc->data_mirror;
283  for (int i = 0; i < tc->data_mirror_len; i++, td_mirror++) {
284  copy_v3_v3(td_mirror->loc, td_mirror->loc_src);
285  }
286  }
287  }
288 }
289 
291 {
292  bool is_canceling = t->state == TRANS_CANCEL;
293  /* mirror modifier clipping? */
294  if (!is_canceling) {
295  if ((t->flag & T_NO_MIRROR) == 0 && (t->options & CTX_NO_MIRROR) == 0) {
297  }
298  }
299 
301  DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
302  BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
305  }
306 }
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_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:85
#define BLI_assert(a)
Definition: BLI_assert.h:58
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:105
#define PSEUDOINVERSE_EPSILON
void pseudoinverse_m3_m3(float Ainv[3][3], const float A[3][3], float epsilon)
Definition: math_matrix.c:3228
MINLINE void copy_v3_v3(float r[3], const float a[3])
void DEG_id_tag_update(struct ID *id, int flag)
@ CD_MVERT_SKIN
@ ME_EDIT_MIRROR_TOPO
#define SCE_SELECT_VERTEX
@ V3D_AROUND_LOCAL_ORIGINS
void EDBM_mesh_normals_update(struct BMEditMesh *em)
@ TFM_SKIN_RESIZE
Definition: ED_transform.h:49
_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.
@ 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:26
#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:98
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static unsigned a[3]
Definition: RandGen.cpp:92
short selectmode
Definition: BKE_editmesh.h:72
struct BMesh * bm
Definition: BKE_editmesh.h:52
void * data
Definition: bmesh_class.h:63
float co[3]
Definition: bmesh_class.h:99
float no[3]
Definition: bmesh_class.h:100
BMHeader head
Definition: bmesh_class.h:97
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
@ CTX_NO_MIRROR
Definition: transform.h:91
@ T_PROP_EDIT_ALL
Definition: transform.h:114
@ T_PROP_CONNECTED
Definition: transform.h:112
@ T_NO_MIRROR
Definition: transform.h:125
@ T_PROP_EDIT
Definition: transform.h:111
@ TRANS_CANCEL
Definition: transform.h:193
#define FOREACH_TRANS_DATA_CONTAINER(t, th)
Definition: transform.h:813
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, const bool use_select, const bool use_topology, const bool mirror_axis[3], struct TransMirrorData *r_mirror_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_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_mirrordata_free(struct TransMirrorData *mirror_data)
void transform_convert_mesh_connectivity_distance(struct BMesh *bm, const float mtx[3][3], float *dists, int *index)
void recalcData_mesh_skin(TransInfo *t)
static float * mesh_skin_transdata_center(const struct TransIslandData *island_data, const int island_index, BMVert *eve)
static void mesh_skin_transdata_create(TransDataBasic *td, BMEditMesh *em, BMVert *eve, const struct TransIslandData *island_data, const int island_index)
static void mesh_skin_apply_to_mirror(TransInfo *t)
void createTransMeshSkin(TransInfo *t)
@ TD_NOTCONNECTED
@ TD_SELECTED
@ TD_SKIP
bool createSpaceNormal(float mat[3][3], const float normal[3])