Blender  V2.93
transform_convert_mesh.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_alloca.h"
30 #include "BLI_linklist_stack.h"
31 #include "BLI_math.h"
32 #include "BLI_memarena.h"
33 
34 #include "BKE_context.h"
35 #include "BKE_crazyspace.h"
36 #include "BKE_editmesh.h"
37 #include "BKE_mesh.h"
38 #include "BKE_modifier.h"
39 #include "BKE_scene.h"
40 
41 #include "ED_mesh.h"
42 
43 #include "DEG_depsgraph_query.h"
44 
45 #include "transform.h"
46 #include "transform_orientations.h"
47 #include "transform_snap.h"
48 
49 #include "transform_convert.h"
50 
51 #define USE_FACE_SUBSTITUTE
52 
53 /* -------------------------------------------------------------------- */
58  const bool calc_single_islands,
59  const bool calc_island_center,
60  const bool calc_island_axismtx,
61  struct TransIslandData *r_island_data)
62 {
63  struct TransIslandData data = {NULL};
64 
65  BMesh *bm = em->bm;
66  char htype;
67  char itype;
68  int i;
69 
70  /* group vars */
71  int *groups_array = NULL;
72  int(*group_index)[2] = NULL;
73 
74  bool has_only_single_islands = bm->totedgesel == 0 && bm->totfacesel == 0;
75  if (has_only_single_islands && !calc_single_islands) {
76  return;
77  }
78 
79  data.island_vert_map = MEM_mallocN(sizeof(*data.island_vert_map) * bm->totvert, __func__);
80  /* we shouldn't need this, but with incorrect selection flushing
81  * its possible we have a selected vertex that's not in a face,
82  * for now best not crash in that case. */
83  copy_vn_i(data.island_vert_map, bm->totvert, -1);
84 
85  if (!has_only_single_islands) {
87  groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totedgesel, __func__);
88  data.island_tot = BM_mesh_calc_edge_groups(
89  bm, groups_array, &group_index, NULL, NULL, BM_ELEM_SELECT);
90 
91  htype = BM_EDGE;
93  }
94  else { /* (bm->selectmode & SCE_SELECT_FACE) */
95  groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__);
96  data.island_tot = BM_mesh_calc_face_groups(
97  bm, groups_array, &group_index, NULL, NULL, NULL, BM_ELEM_SELECT, BM_VERT);
98 
99  htype = BM_FACE;
101  }
102 
103  BLI_assert(data.island_tot);
104  if (calc_island_center) {
105  data.center = MEM_mallocN(sizeof(*data.center) * data.island_tot, __func__);
106  }
107 
108  if (calc_island_axismtx) {
109  data.axismtx = MEM_mallocN(sizeof(*data.axismtx) * data.island_tot, __func__);
110  }
111 
113 
114  void **ele_array;
115  ele_array = (htype == BM_FACE) ? (void **)bm->ftable : (void **)bm->etable;
116 
118 
119  /* may be an edge OR a face array */
120  for (i = 0; i < data.island_tot; i++) {
121  BMEditSelection ese = {NULL};
122 
123  const int fg_sta = group_index[i][0];
124  const int fg_len = group_index[i][1];
125  float co[3], no[3], tangent[3];
126  int j;
127 
128  zero_v3(co);
129  zero_v3(no);
130  zero_v3(tangent);
131 
132  ese.htype = htype;
133 
134  /* loop on each face or edge in this group:
135  * - assign r_vert_map
136  * - calculate (co, no)
137  */
138  for (j = 0; j < fg_len; j++) {
139  ese.ele = ele_array[groups_array[fg_sta + j]];
140 
141  if (data.center) {
142  float tmp_co[3];
143  BM_editselection_center(&ese, tmp_co);
144  add_v3_v3(co, tmp_co);
145  }
146 
147  if (data.axismtx) {
148  float tmp_no[3], tmp_tangent[3];
149  BM_editselection_normal(&ese, tmp_no);
150  BM_editselection_plane(&ese, tmp_tangent);
151  add_v3_v3(no, tmp_no);
152  add_v3_v3(tangent, tmp_tangent);
153  }
154 
155  {
156  /* setup vertex map */
157  BMIter iter;
158  BMVert *v;
159 
160  /* connected edge-verts */
161  BM_ITER_ELEM (v, &iter, ese.ele, itype) {
162  data.island_vert_map[BM_elem_index_get(v)] = i;
163  }
164  }
165  }
166 
167  if (data.center) {
168  mul_v3_v3fl(data.center[i], co, 1.0f / (float)fg_len);
169  }
170 
171  if (data.axismtx) {
172  if (createSpaceNormalTangent(data.axismtx[i], no, tangent)) {
173  /* pass */
174  }
175  else {
176  if (normalize_v3(no) != 0.0f) {
177  axis_dominant_v3_to_m3(data.axismtx[i], no);
178  invert_m3(data.axismtx[i]);
179  }
180  else {
181  unit_m3(data.axismtx[i]);
182  }
183  }
184  }
185  }
186 
187  MEM_freeN(groups_array);
188  MEM_freeN(group_index);
189  }
190 
191  /* for PET we need islands of 1 so connected vertices can use it with V3D_AROUND_LOCAL_ORIGINS */
192  if (calc_single_islands) {
193  BMIter viter;
194  BMVert *v;
195  int group_tot_single = 0;
196 
197  BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
198  if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (data.island_vert_map[i] == -1)) {
199  group_tot_single += 1;
200  }
201  }
202 
203  if (group_tot_single != 0) {
204  if (calc_island_center) {
205  data.center = MEM_reallocN(data.center,
206  sizeof(*data.center) * (data.island_tot + group_tot_single));
207  }
208  if (calc_island_axismtx) {
209  data.axismtx = MEM_reallocN(data.axismtx,
210  sizeof(*data.axismtx) * (data.island_tot + group_tot_single));
211  }
212 
213  BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
214  if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (data.island_vert_map[i] == -1)) {
215  data.island_vert_map[i] = data.island_tot;
216  if (data.center) {
217  copy_v3_v3(data.center[data.island_tot], v->co);
218  }
219  if (data.axismtx) {
220  if (is_zero_v3(v->no) == false) {
221  axis_dominant_v3_to_m3(data.axismtx[data.island_tot], v->no);
222  invert_m3(data.axismtx[data.island_tot]);
223  }
224  else {
225  unit_m3(data.axismtx[data.island_tot]);
226  }
227  }
228 
229  data.island_tot += 1;
230  }
231  }
232  }
233  }
234 
235  *r_island_data = data;
236 }
237 
239 {
240  if (island_data->center) {
241  MEM_freeN(island_data->center);
242  }
243  if (island_data->axismtx) {
244  MEM_freeN(island_data->axismtx);
245  }
246  if (island_data->island_vert_map) {
247  MEM_freeN(island_data->island_vert_map);
248  }
249 }
250 
253 /* -------------------------------------------------------------------- */
257 /* Propagate distance from v1 and v2 to v0. */
258 static bool bmesh_test_dist_add(BMVert *v0,
259  BMVert *v1,
260  BMVert *v2,
261  float *dists,
262  /* optionally track original index */
263  int *index,
264  const float mtx[3][3])
265 {
266  if ((BM_elem_flag_test(v0, BM_ELEM_SELECT) == 0) &&
267  (BM_elem_flag_test(v0, BM_ELEM_HIDDEN) == 0)) {
268  const int i0 = BM_elem_index_get(v0);
269  const int i1 = BM_elem_index_get(v1);
270 
271  BLI_assert(dists[i1] != FLT_MAX);
272  if (dists[i0] <= dists[i1]) {
273  return false;
274  }
275 
276  float dist0;
277 
278  if (v2) {
279  /* Distance across triangle. */
280  const int i2 = BM_elem_index_get(v2);
281  BLI_assert(dists[i2] != FLT_MAX);
282  if (dists[i0] <= dists[i2]) {
283  return false;
284  }
285 
286  float vm0[3], vm1[3], vm2[3];
287  mul_v3_m3v3(vm0, mtx, v0->co);
288  mul_v3_m3v3(vm1, mtx, v1->co);
289  mul_v3_m3v3(vm2, mtx, v2->co);
290 
291  dist0 = geodesic_distance_propagate_across_triangle(vm0, vm1, vm2, dists[i1], dists[i2]);
292  }
293  else {
294  /* Distance along edge. */
295  float vec[3];
296  sub_v3_v3v3(vec, v1->co, v0->co);
297  mul_m3_v3(mtx, vec);
298 
299  dist0 = dists[i1] + len_v3(vec);
300  }
301 
302  if (dist0 < dists[i0]) {
303  dists[i0] = dist0;
304  if (index != NULL) {
305  index[i0] = index[i1];
306  }
307  return true;
308  }
309  }
310 
311  return false;
312 }
313 
314 static bool bmesh_test_loose_edge(BMEdge *edge)
315 {
316  /* Actual loose edge. */
317  if (edge->l == NULL) {
318  return true;
319  }
320 
321  /* Loose edge due to hidden adjacent faces. */
322  BMIter iter;
323  BMFace *face;
324  BM_ITER_ELEM (face, &iter, edge, BM_FACES_OF_EDGE) {
325  if (BM_elem_flag_test(face, BM_ELEM_HIDDEN) == 0) {
326  return false;
327  }
328  }
329  return true;
330 }
331 
338  const float mtx[3][3],
339  float *dists,
340  int *index)
341 {
343 
344  /* any BM_ELEM_TAG'd edge is in 'queue_next', so we don't add in twice */
345  const int tag_queued = BM_ELEM_TAG;
346  const int tag_loose = BM_ELEM_TAG_ALT;
347 
348  BLI_LINKSTACK_DECLARE(queue_next, BMEdge *);
349 
351  BLI_LINKSTACK_INIT(queue_next);
352 
353  {
354  /* Set indexes and initial distances for selected vertices. */
355  BMIter viter;
356  BMVert *v;
357  int i;
358 
359  BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
360  float dist;
361  BM_elem_index_set(v, i); /* set_inline */
362 
364  dist = FLT_MAX;
365  if (index != NULL) {
366  index[i] = i;
367  }
368  }
369  else {
370  dist = 0.0f;
371  if (index != NULL) {
372  index[i] = i;
373  }
374  }
375 
376  dists[i] = dist;
377  }
379  }
380 
381  {
382  /* Add edges with at least one selected vertex to the queue. */
383  BMIter eiter;
384  BMEdge *e;
385 
386  BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
387 
388  /* Always clear to satisfy the assert, also predictable to leave in cleared state. */
389  BM_elem_flag_disable(e, tag_queued);
390 
392  continue;
393  }
394 
395  BMVert *v1 = e->v1;
396  BMVert *v2 = e->v2;
397  int i1 = BM_elem_index_get(v1);
398  int i2 = BM_elem_index_get(v2);
399 
400  if (dists[i1] != FLT_MAX || dists[i2] != FLT_MAX) {
402  }
404  }
405  }
406 
407  do {
408  BMEdge *e;
409 
410  while ((e = BLI_LINKSTACK_POP(queue))) {
411  BMVert *v1 = e->v1;
412  BMVert *v2 = e->v2;
413  int i1 = BM_elem_index_get(v1);
414  int i2 = BM_elem_index_get(v2);
415 
416  if (BM_elem_flag_test(e, tag_loose) || (dists[i1] == FLT_MAX || dists[i2] == FLT_MAX)) {
417  /* Propagate along edge from vertex with smallest to largest distance. */
418  if (dists[i1] > dists[i2]) {
419  SWAP(int, i1, i2);
420  SWAP(BMVert *, v1, v2);
421  }
422 
423  if (bmesh_test_dist_add(v2, v1, NULL, dists, index, mtx)) {
424  /* Add adjacent loose edges to the queue, or all edges if this is a loose edge.
425  * Other edges are handled by propagation across edges below. */
426  BMEdge *e_other;
427  BMIter eiter;
428  BM_ITER_ELEM (e_other, &eiter, v2, BM_EDGES_OF_VERT) {
429  if (e_other != e && BM_elem_flag_test(e_other, tag_queued) == 0 &&
430  !BM_elem_flag_test(e_other, BM_ELEM_HIDDEN) &&
431  (BM_elem_flag_test(e, tag_loose) || BM_elem_flag_test(e_other, tag_loose))) {
432  BM_elem_flag_enable(e_other, tag_queued);
433  BLI_LINKSTACK_PUSH(queue_next, e_other);
434  }
435  }
436  }
437  }
438 
439  if (!BM_elem_flag_test(e, tag_loose)) {
440  /* Propagate across edge to vertices in adjacent faces. */
441  BMLoop *l;
442  BMIter liter;
443  BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) {
445  continue;
446  }
447  /* Don't check hidden edges or vertices in this loop
448  * since any hidden edge causes the face to be hidden too. */
449  for (BMLoop *l_other = l->next->next; l_other != l; l_other = l_other->next) {
450  BMVert *v_other = l_other->v;
451  BLI_assert(!ELEM(v_other, v1, v2));
452 
453  if (bmesh_test_dist_add(v_other, v1, v2, dists, index, mtx)) {
454  /* Add adjacent edges to the queue, if they are ready to propagate across/along.
455  * Always propagate along loose edges, and for other edges only propagate across
456  * if both vertices have a known distances. */
457  BMEdge *e_other;
458  BMIter eiter;
459  BM_ITER_ELEM (e_other, &eiter, v_other, BM_EDGES_OF_VERT) {
460  if (e_other != e && BM_elem_flag_test(e_other, tag_queued) == 0 &&
461  !BM_elem_flag_test(e_other, BM_ELEM_HIDDEN) &&
462  (BM_elem_flag_test(e_other, tag_loose) ||
463  dists[BM_elem_index_get(BM_edge_other_vert(e_other, v_other))] != FLT_MAX)) {
464  BM_elem_flag_enable(e_other, tag_queued);
465  BLI_LINKSTACK_PUSH(queue_next, e_other);
466  }
467  }
468  }
469  }
470  }
471  }
472  }
473 
474  /* Clear for the next loop. */
475  for (LinkNode *lnk = queue_next; lnk; lnk = lnk->next) {
476  BMEdge *e_link = lnk->link;
477 
478  BM_elem_flag_disable(e_link, tag_queued);
479  }
480 
481  BLI_LINKSTACK_SWAP(queue, queue_next);
482 
483  /* None should be tagged now since 'queue_next' is empty. */
484  BLI_assert(BM_iter_mesh_count_flag(BM_EDGES_OF_MESH, bm, tag_queued, true) == 0);
485  } while (BLI_LINKSTACK_SIZE(queue));
486 
488  BLI_LINKSTACK_FREE(queue_next);
489 }
490 
493 /* -------------------------------------------------------------------- */
497 /* Used for both mirror epsilon and TD_MIRROR_EDGE_ */
498 #define TRANSFORM_MAXDIST_MIRROR 0.00002f
499 
500 static bool is_in_quadrant_v3(const float co[3], const int quadrant[3], const float epsilon)
501 {
502  if (quadrant[0] && ((co[0] * quadrant[0]) < -epsilon)) {
503  return false;
504  }
505  if (quadrant[1] && ((co[1] * quadrant[1]) < -epsilon)) {
506  return false;
507  }
508  if (quadrant[2] && ((co[2] * quadrant[2]) < -epsilon)) {
509  return false;
510  }
511  return true;
512 }
513 
515  const bool use_select,
516  const bool use_topology,
517  const bool mirror_axis[3],
518  struct TransMirrorData *r_mirror_data)
519 {
520  struct MirrorDataVert *vert_map;
521 
522  BMesh *bm = em->bm;
523  BMVert *eve;
524  BMIter iter;
525  int i, flag, totvert = bm->totvert;
526 
527  vert_map = MEM_callocN(totvert * sizeof(*vert_map), __func__);
528 
529  float select_sum[3] = {0};
530  BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
531  vert_map[i] = (struct MirrorDataVert){-1, 0};
532  if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
533  continue;
534  }
535  if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
536  add_v3_v3(select_sum, eve->co);
537  }
538  }
539 
540  /* Tag only elements that will be transformed within the quadrant. */
541  int quadrant[3];
542  for (int a = 0; a < 3; a++) {
543  if (mirror_axis[a]) {
544  quadrant[a] = select_sum[a] >= 0.0f ? 1 : -1;
545  }
546  else {
547  quadrant[a] = 0;
548  }
549  }
550 
551  uint mirror_elem_len = 0;
552  int *index[3] = {NULL, NULL, NULL};
553  bool is_single_mirror_axis = (mirror_axis[0] + mirror_axis[1] + mirror_axis[2]) == 1;
554  bool test_selected_only = use_select && is_single_mirror_axis;
555  for (int a = 0; a < 3; a++) {
556  if (!mirror_axis[a]) {
557  continue;
558  }
559 
560  index[a] = MEM_mallocN(totvert * sizeof(*index[a]), __func__);
562  em, a, false, test_selected_only, true, use_topology, TRANSFORM_MAXDIST_MIRROR, index[a]);
563 
564  flag = TD_MIRROR_X << a;
565  BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
566  int i_mirr = index[a][i];
567  if (i_mirr < 0) {
568  continue;
569  }
570  if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
571  continue;
572  }
573  if (use_select && !BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
574  continue;
575  }
576  if (!is_in_quadrant_v3(eve->co, quadrant, TRANSFORM_MAXDIST_MIRROR)) {
577  continue;
578  }
579  if (vert_map[i_mirr].flag != 0) {
580  /* One mirror per element.
581  * It can happen when vertices occupy the same position. */
582  continue;
583  }
584 
585  vert_map[i_mirr] = (struct MirrorDataVert){i, flag};
586  mirror_elem_len++;
587  }
588  }
589 
590  if (!mirror_elem_len) {
591  MEM_freeN(vert_map);
592  vert_map = NULL;
593  }
594  else if (!is_single_mirror_axis) {
595  /* Adjustment for elements that are mirrors of mirrored elements. */
596  for (int a = 0; a < 3; a++) {
597  if (!mirror_axis[a]) {
598  continue;
599  }
600 
601  flag = TD_MIRROR_X << a;
602  for (i = 0; i < totvert; i++) {
603  int i_mirr = index[a][i];
604  if (i_mirr < 0) {
605  continue;
606  }
607  if (vert_map[i].index != -1 && !(vert_map[i].flag & flag)) {
608  if (vert_map[i_mirr].index == -1) {
609  mirror_elem_len++;
610  }
611  vert_map[i_mirr].index = vert_map[i].index;
612  vert_map[i_mirr].flag |= vert_map[i].flag | flag;
613  }
614  }
615  }
616  }
617 
618  MEM_SAFE_FREE(index[0]);
619  MEM_SAFE_FREE(index[1]);
620  MEM_SAFE_FREE(index[2]);
621 
622  r_mirror_data->vert_map = vert_map;
623  r_mirror_data->mirror_elem_len = mirror_elem_len;
624 }
625 
627 {
628  if (mirror_data->vert_map) {
629  MEM_freeN(mirror_data->vert_map);
630  }
631 }
632 
635 /* -------------------------------------------------------------------- */
639 /* Detect CrazySpace [tm].
640  * Vertices with space affected by quats are marked with #BM_ELEM_TAG */
642  struct TransDataContainer *tc,
643  struct BMEditMesh *em,
644  struct TransMeshDataCrazySpace *r_crazyspace_data)
645 {
646  float(*quats)[4] = NULL;
647  float(*defmats)[3][3] = NULL;
648  const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
649  if (BKE_modifiers_get_cage_index(t->scene, tc->obedit, NULL, 1) != -1) {
650  float(*defcos)[3] = NULL;
651  int totleft = -1;
653  BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context));
654 
655  /* Use evaluated state because we need b-bone cache. */
656  Scene *scene_eval = (Scene *)DEG_get_evaluated_id(t->depsgraph, &t->scene->id);
657  Object *obedit_eval = (Object *)DEG_get_evaluated_id(t->depsgraph, &tc->obedit->id);
658  BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval);
659  /* check if we can use deform matrices for modifier from the
660  * start up to stack, they are more accurate than quats */
662  t->depsgraph, scene_eval, obedit_eval, em_eval, &defmats, &defcos);
663  }
664 
665  /* If we still have more modifiers, also do crazy-space
666  * correction with \a quats, relative to the coordinates after
667  * the modifiers that support deform matrices \a defcos. */
668 
669 #if 0 /* TODO, fix crazy-space & extrude so it can be enabled for general use - campbell */
670  if ((totleft > 0) || (totleft == -1))
671 #else
672  if (totleft > 0)
673 #endif
674  {
675  float(*mappedcos)[3] = NULL;
676  mappedcos = BKE_crazyspace_get_mapped_editverts(t->depsgraph, tc->obedit);
677  quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats");
678  BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode);
679  if (mappedcos) {
680  MEM_freeN(mappedcos);
681  }
682  }
683 
684  if (defcos) {
685  MEM_freeN(defcos);
686  }
687  }
688  r_crazyspace_data->quats = quats;
689  r_crazyspace_data->defmats = defmats;
690 }
691 
693  const float smtx[3][3],
694  const float defmat[3][3],
695  const float quat[4],
696  struct TransData *r_td)
697 {
698  /* CrazySpace */
699  if (quat || defmat) {
700  float mat[3][3], qmat[3][3], imat[3][3];
701 
702  /* Use both or either quat and defmat correction. */
703  if (quat) {
704  quat_to_mat3(qmat, quat);
705 
706  if (defmat) {
707  mul_m3_series(mat, defmat, qmat, mtx);
708  }
709  else {
710  mul_m3_m3m3(mat, mtx, qmat);
711  }
712  }
713  else {
714  mul_m3_m3m3(mat, mtx, defmat);
715  }
716 
717  invert_m3_m3(imat, mat);
718 
719  copy_m3_m3(r_td->smtx, imat);
720  copy_m3_m3(r_td->mtx, mat);
721  }
722  else {
723  copy_m3_m3(r_td->smtx, smtx);
724  copy_m3_m3(r_td->mtx, mtx);
725  }
726 }
727 
729 {
730  if (r_crazyspace_data->quats) {
731  MEM_freeN(r_crazyspace_data->quats);
732  }
733  if (r_crazyspace_data->defmats) {
734  MEM_freeN(r_crazyspace_data->defmats);
735  }
736 }
737 
740 /* -------------------------------------------------------------------- */
744 static void transdata_center_get(const struct TransIslandData *island_data,
745  const int island_index,
746  const float iloc[3],
747  float r_center[3])
748 {
749  if (island_data->center && island_index != -1) {
750  copy_v3_v3(r_center, island_data->center[island_index]);
751  }
752  else {
753  copy_v3_v3(r_center, iloc);
754  }
755 }
756 
757 /* way to overwrite what data is edited with transform */
759  TransData *td,
760  TransDataExtension *tx,
761  BMEditMesh *em,
762  BMVert *eve,
763  float *bweight,
764  const struct TransIslandData *island_data,
765  const int island_index)
766 {
767  float *no, _no[3];
769 
770  td->flag = 0;
771  // if (key)
772  // td->loc = key->co;
773  // else
774  td->loc = eve->co;
775  copy_v3_v3(td->iloc, td->loc);
776 
777  if ((t->mode == TFM_SHRINKFATTEN) && (em->selectmode & SCE_SELECT_FACE) &&
779  (BM_vert_calc_normal_ex(eve, BM_ELEM_SELECT, _no))) {
780  no = _no;
781  }
782  else {
783  no = eve->no;
784  }
785 
786  transdata_center_get(island_data, island_index, td->iloc, td->center);
787 
788  if ((island_index != -1) && island_data->axismtx) {
789  copy_m3_m3(td->axismtx, island_data->axismtx[island_index]);
790  }
791  else if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
792  createSpaceNormal(td->axismtx, no);
793  }
794  else {
795  /* Setting normals */
796  copy_v3_v3(td->axismtx[2], no);
797  td->axismtx[0][0] = td->axismtx[0][1] = td->axismtx[0][2] = td->axismtx[1][0] =
798  td->axismtx[1][1] = td->axismtx[1][2] = 0.0f;
799  }
800 
801  td->ext = NULL;
802  td->val = NULL;
803  td->extra = eve;
804  if (t->mode == TFM_BWEIGHT) {
805  td->val = bweight;
806  td->ival = *bweight;
807  }
808  else if (t->mode == TFM_SHRINKFATTEN) {
809  td->ext = tx;
811  }
812 }
813 
815 {
817  TransDataExtension *tx = NULL;
818  BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
819  Mesh *me = tc->obedit->data;
820  BMesh *bm = em->bm;
821  BMVert *eve;
822  BMIter iter;
823  float mtx[3][3], smtx[3][3];
824  int a;
825  const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
826 
827  struct TransIslandData island_data = {NULL};
828  struct TransMirrorData mirror_data = {NULL};
829  struct TransMeshDataCrazySpace crazyspace_data = {NULL};
830 
838  /* Support other objects using PET to adjust these, unless connected is enabled. */
839  if ((!prop_mode || (prop_mode & T_PROP_CONNECTED)) && (bm->totvertsel == 0)) {
840  continue;
841  }
842 
843  int data_len = 0;
844  if (prop_mode) {
845  BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
846  if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
847  data_len++;
848  }
849  }
850  }
851  else {
852  data_len = bm->totvertsel;
853  }
854 
855  if (data_len == 0) {
856  continue;
857  }
858 
859  /* Snap rotation along normal needs a common axis for whole islands,
860  * otherwise one get random crazy results, see T59104.
861  * However, we do not want to use the island center for the pivot/translation reference. */
862  const bool is_snap_rotate = ((t->mode == TFM_TRANSLATION) &&
863  /* There is not guarantee that snapping
864  * is initialized yet at this point... */
866  (t->settings->snap_flag & SCE_SNAP_ROTATE) != 0) &&
867  (t->around != V3D_AROUND_LOCAL_ORIGINS));
868 
869  /* Even for translation this is needed because of island-orientation, see: T51651. */
870  const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) || is_snap_rotate;
871  if (is_island_center) {
872  /* In this specific case, near-by vertices will need to know
873  * the island of the nearest connected vertex. */
874  const bool calc_single_islands = ((prop_mode & T_PROP_CONNECTED) &&
875  (t->around == V3D_AROUND_LOCAL_ORIGINS) &&
876  (em->selectmode & SCE_SELECT_VERTEX));
877 
878  const bool calc_island_center = !is_snap_rotate;
879  /* The island axismtx is only necessary in some modes.
880  * TODO(Germano): Extend the list to exclude other modes. */
881  const bool calc_island_axismtx = !ELEM(t->mode, TFM_SHRINKFATTEN);
882 
884  em, calc_single_islands, calc_island_center, calc_island_axismtx, &island_data);
885  }
886 
887  copy_m3_m4(mtx, tc->obedit->obmat);
888  /* we use a pseudo-inverse so that when one of the axes is scaled to 0,
889  * matrix inversion still works and we can still moving along the other */
891 
892  /* Original index of our connected vertex when connected distances are calculated.
893  * Optional, allocate if needed. */
894  int *dists_index = NULL;
895  float *dists = NULL;
896  if (prop_mode & T_PROP_CONNECTED) {
897  dists = MEM_mallocN(bm->totvert * sizeof(float), __func__);
898  if (is_island_center) {
899  dists_index = MEM_mallocN(bm->totvert * sizeof(int), __func__);
900  }
901  transform_convert_mesh_connectivity_distance(em->bm, mtx, dists, dists_index);
902  }
903 
904  /* Create TransDataMirror. */
905  if (tc->use_mirror_axis_any) {
906  bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
907  bool use_select = (t->flag & T_PROP_EDIT) == 0;
908  const bool mirror_axis[3] = {
909  tc->use_mirror_axis_x, tc->use_mirror_axis_y, tc->use_mirror_axis_z};
911  em, use_select, use_topology, mirror_axis, &mirror_data);
912 
913  if (mirror_data.vert_map) {
914  tc->data_mirror_len = mirror_data.mirror_elem_len;
915  tc->data_mirror = MEM_mallocN(mirror_data.mirror_elem_len * sizeof(*tc->data_mirror),
916  __func__);
917 
918  BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
919  if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
920  if (mirror_data.vert_map[a].index != -1) {
921  data_len--;
922  }
923  }
924  }
925  }
926  }
927 
928  /* Detect CrazySpace [tm]. */
929  transform_convert_mesh_crazyspace_detect(t, tc, em, &crazyspace_data);
930 
931  /* Create TransData. */
932  BLI_assert(data_len >= 1);
933  tc->data_len = data_len;
934  tc->data = MEM_callocN(data_len * sizeof(TransData), "TransObData(Mesh EditMode)");
935  if (t->mode == TFM_SHRINKFATTEN) {
936  /* warning, this is overkill, we only need 2 extra floats,
937  * but this stores loads of extra stuff, for TFM_SHRINKFATTEN its even more overkill
938  * since we may not use the 'alt' transform mode to maintain shell thickness,
939  * but with generic transform code its hard to lazy init vars */
940  tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension),
941  "TransObData ext");
942  }
943 
944  int cd_vert_bweight_offset = -1;
945  if (t->mode == TFM_BWEIGHT) {
947  cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
948  }
949 
950  TransData *tob = tc->data;
951  TransDataMirror *td_mirror = tc->data_mirror;
952  BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
953  if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
954  continue;
955  }
956 
957  int island_index = -1;
958  if (island_data.island_vert_map) {
959  const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a;
960  island_index = island_data.island_vert_map[connected_index];
961  }
962 
963  if (mirror_data.vert_map && mirror_data.vert_map[a].index != -1) {
964  int elem_index = mirror_data.vert_map[a].index;
965  BMVert *v_src = BM_vert_at_index(bm, elem_index);
966 
967  if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
968  mirror_data.vert_map[a].flag |= TD_SELECTED;
969  }
970 
971  td_mirror->extra = eve;
972  td_mirror->loc = eve->co;
973  copy_v3_v3(td_mirror->iloc, eve->co);
974  td_mirror->flag = mirror_data.vert_map[a].flag;
975  td_mirror->loc_src = v_src->co;
976  transdata_center_get(&island_data, island_index, td_mirror->iloc, td_mirror->center);
977 
978  td_mirror++;
979  }
980  else if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
981  float *bweight = (cd_vert_bweight_offset != -1) ?
982  BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) :
983  NULL;
984 
985  /* Do not use the island center in case we are using islands
986  * only to get axis for snap/rotate to normal... */
987  VertsToTransData(t, tob, tx, em, eve, bweight, &island_data, island_index);
988  if (tx) {
989  tx++;
990  }
991 
992  /* selected */
993  if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
994  tob->flag |= TD_SELECTED;
995  }
996 
997  if (prop_mode) {
998  if (prop_mode & T_PROP_CONNECTED) {
999  tob->dist = dists[a];
1000  }
1001  else {
1002  tob->flag |= TD_NOTCONNECTED;
1003  tob->dist = FLT_MAX;
1004  }
1005  }
1006 
1007  /* CrazySpace */
1009  mtx,
1010  smtx,
1011  crazyspace_data.defmats ? crazyspace_data.defmats[a] : NULL,
1012  crazyspace_data.quats && BM_elem_flag_test(eve, BM_ELEM_TAG) ?
1013  crazyspace_data.quats[a] :
1014  NULL,
1015  tob);
1016 
1017  if (tc->use_mirror_axis_any) {
1018  if (tc->use_mirror_axis_x && fabsf(tob->loc[0]) < TRANSFORM_MAXDIST_MIRROR) {
1019  tob->flag |= TD_MIRROR_EDGE_X;
1020  }
1021  if (tc->use_mirror_axis_y && fabsf(tob->loc[1]) < TRANSFORM_MAXDIST_MIRROR) {
1022  tob->flag |= TD_MIRROR_EDGE_Y;
1023  }
1024  if (tc->use_mirror_axis_z && fabsf(tob->loc[2]) < TRANSFORM_MAXDIST_MIRROR) {
1025  tob->flag |= TD_MIRROR_EDGE_Z;
1026  }
1027  }
1028 
1029  tob++;
1030  }
1031  }
1032 
1035  transform_convert_mesh_crazyspace_free(&crazyspace_data);
1036  if (dists) {
1037  MEM_freeN(dists);
1038  }
1039  if (dists_index) {
1040  MEM_freeN(dists_index);
1041  }
1042  }
1043 }
1044 
1047 /* -------------------------------------------------------------------- */
1054 };
1055 
1058  struct MemArena *arena;
1059 
1060  struct GHash *origfaces;
1062 
1063  /* Special handle for multi-resolution. */
1065 
1066  /* Optionally merge custom-data groups (this keeps UVs connected for example). */
1067  struct {
1069  struct GHash *origverts;
1078 
1080 };
1081 
1083  struct TransDataContainer *UNUSED(tc),
1084  struct TransCustomData *custom_data)
1085 {
1086  struct TransCustomDataLayer *tcld = custom_data->data;
1088 
1089  if (tcld->bm_origfaces) {
1090  BM_mesh_free(tcld->bm_origfaces);
1091  }
1092  if (tcld->origfaces) {
1093  BLI_ghash_free(tcld->origfaces, NULL, NULL);
1094  }
1095  if (tcld->merge_group.origverts) {
1097  }
1098  if (tcld->arena) {
1099  BLI_memarena_free(tcld->arena);
1100  }
1101  if (tcld->merge_group.customdatalayer_map) {
1103  }
1104 
1105  MEM_freeN(tcld);
1106  custom_data->data = NULL;
1107 }
1108 
1109 #ifdef USE_FACE_SUBSTITUTE
1110 
1111 # define FACE_SUBSTITUTE_INDEX INT_MIN
1112 
1118 {
1119  BMFace *best_face = NULL;
1120  BMLoop *l;
1121  BMIter liter;
1122  BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
1123  BMLoop *l_radial_next = l->radial_next;
1124  BMFace *f_test = l_radial_next->f;
1125  if (f_test == f) {
1126  continue;
1127  }
1128  if (is_zero_v3(f_test->no)) {
1129  continue;
1130  }
1131 
1132  /* Check the loops edge isn't selected. */
1133  if (!BM_elem_flag_test(l_radial_next->v, BM_ELEM_SELECT) &&
1134  !BM_elem_flag_test(l_radial_next->next->v, BM_ELEM_SELECT)) {
1135  /* Prefer edges with unselected vertices.
1136  * Useful for extrude. */
1137  best_face = f_test;
1138  break;
1139  }
1140  if (best_face == NULL) {
1141  best_face = f_test;
1142  }
1143  }
1144  return best_face;
1145 }
1146 
1148  BMFace *f,
1149  BMFace *f_copy)
1150 {
1151  BLI_assert(is_zero_v3(f->no));
1152  BMesh *bm = tcld->bm;
1153  /* It is impossible to calculate the loops weights of a face without area.
1154  * Find a substitute. */
1156  if (f_substitute) {
1157  /* Copy the custom-data from the substitute face. */
1158  BMLoop *l_iter, *l_first;
1159  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
1160  do {
1161  BM_loop_interp_from_face(bm, l_iter, f_substitute, false, false);
1162  } while ((l_iter = l_iter->next) != l_first);
1163 
1164  /* Use the substitute face as the reference during the transformation. */
1165  BMFace *f_substitute_copy = BM_face_copy(tcld->bm_origfaces, bm, f_substitute, true, true);
1166 
1167  /* Hack: reference substitute face in `f_copy->no`.
1168  * `tcld->origfaces` is already used to restore the initial value. */
1170  *((BMFace **)&f_copy->no[0]) = f_substitute_copy;
1171  }
1172 }
1173 
1175 {
1177  return *((BMFace **)&f_copy->no[0]);
1178 }
1179 
1180 #endif /* USE_FACE_SUBSTITUTE */
1181 
1183  struct TransDataBasic *td,
1184  const int index)
1185 {
1186  BMesh *bm = tcld->bm;
1187  BMVert *v = td->extra;
1188  BMIter liter;
1189  int j, l_num;
1190  float *loop_weights;
1191 
1192  // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) {
1193  BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, v);
1194  l_num = liter.count;
1195  loop_weights = tcld->use_merge_group ? BLI_array_alloca(loop_weights, l_num) : NULL;
1196  for (j = 0; j < l_num; j++) {
1197  BMLoop *l = BM_iter_step(&liter);
1198  BMLoop *l_prev, *l_next;
1199 
1200  /* Generic custom-data correction. Copy face data. */
1201  void **val_p;
1202  if (!BLI_ghash_ensure_p(tcld->origfaces, l->f, &val_p)) {
1203  BMFace *f_copy = BM_face_copy(tcld->bm_origfaces, bm, l->f, true, true);
1204  *val_p = f_copy;
1205 #ifdef USE_FACE_SUBSTITUTE
1206  if (is_zero_v3(l->f->no)) {
1208  }
1209 #endif
1210  }
1211 
1212  if (tcld->use_merge_group) {
1213  if ((l_prev = BM_loop_find_prev_nodouble(l, l->next, FLT_EPSILON)) &&
1214  (l_next = BM_loop_find_next_nodouble(l, l_prev, FLT_EPSILON))) {
1215  loop_weights[j] = angle_v3v3v3(l_prev->v->co, l->v->co, l_next->v->co);
1216  }
1217  else {
1218  loop_weights[j] = 0.0f;
1219  }
1220  }
1221  }
1222 
1223  if (tcld->use_merge_group) {
1224  /* Store cd_loop_groups. */
1225  struct TransCustomDataMergeGroup *merge_data = &tcld->merge_group.data[index];
1226  if (l_num != 0) {
1227  merge_data->cd_loop_groups = BLI_memarena_alloc(
1228  tcld->arena, tcld->merge_group.customdatalayer_map_len * sizeof(void *));
1229  for (j = 0; j < tcld->merge_group.customdatalayer_map_len; j++) {
1230  const int layer_nr = tcld->merge_group.customdatalayer_map[j];
1232  bm, v, layer_nr, loop_weights, tcld->arena);
1233  }
1234  }
1235  else {
1236  merge_data->cd_loop_groups = NULL;
1237  }
1238 
1240  }
1241 }
1242 
1244  struct TransCustomDataLayer *tcld)
1245 {
1246  BMesh *bm = tcld->bm;
1247 
1248  struct GHash *origfaces = BLI_ghash_ptr_new(__func__);
1249  struct BMesh *bm_origfaces = BM_mesh_create(&bm_mesh_allocsize_default,
1250  &((struct BMeshCreateParams){
1251  .use_toolflags = false,
1252  }));
1253 
1254  /* We need to have matching loop custom-data. */
1256 
1257  tcld->origfaces = origfaces;
1258  tcld->bm_origfaces = bm_origfaces;
1259 
1262 }
1263 
1265  struct TransCustomDataLayer *tcld)
1266 {
1267  BMesh *bm = tcld->bm;
1269 
1270  /* TODO: We don't need `layer_math_map` when there are no loops linked
1271  * to one of the sliding vertices. */
1272 
1273  /* Over allocate, only 'math' layers are indexed. */
1274  int *customdatalayer_map = MEM_mallocN(sizeof(int) * bm->ldata.totlayer, __func__);
1275  int layer_math_map_len = 0;
1276  for (int i = 0; i < bm->ldata.totlayer; i++) {
1277  if (CustomData_layer_has_math(&bm->ldata, i)) {
1278  customdatalayer_map[layer_math_map_len++] = i;
1279  }
1280  }
1281  BLI_assert(layer_math_map_len != 0);
1282 
1283  tcld->merge_group.data_len = tc->data_len + tc->data_mirror_len;
1284  tcld->merge_group.customdatalayer_map = customdatalayer_map;
1285  tcld->merge_group.customdatalayer_map_len = layer_math_map_len;
1288  tcld->arena, tcld->merge_group.data_len * sizeof(*tcld->merge_group.data));
1289 }
1290 
1292  const bool use_merge_group)
1293 {
1294  if (tc->custom.type.data) {
1295  /* The custom-data correction has been initiated before.
1296  * Free since some modes have different settings. */
1298  }
1299 
1301  BMesh *bm = em->bm;
1302 
1303  if (bm->shapenr > 1) {
1304  /* Don't do this at all for non-basis shape keys, too easy to
1305  * accidentally break uv maps or vertex colors then */
1306  /* create copies of faces for custom-data projection. */
1307  return;
1308  }
1310  /* There is no custom-data to correct. */
1311  return;
1312  }
1313 
1314  struct TransCustomDataLayer *tcld = MEM_callocN(sizeof(*tcld), __func__);
1315  tcld->bm = bm;
1316  tcld->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
1317 
1318  /* Init `cd_loop_mdisp_offset` to -1 to avoid problems with a valid index. */
1319  tcld->cd_loop_mdisp_offset = -1;
1321 
1323 
1324  if (tcld->use_merge_group) {
1326  }
1327 
1328  {
1329  /* Setup Verts. */
1330  int i = 0;
1331 
1332  TransData *tob = tc->data;
1333  for (int j = tc->data_len; j--; tob++, i++) {
1335  }
1336 
1337  TransDataMirror *td_mirror = tc->data_mirror;
1338  for (int j = tc->data_mirror_len; j--; td_mirror++, i++) {
1339  mesh_customdatacorrect_init_vert(tcld, (TransDataBasic *)td_mirror, i);
1340  }
1341  }
1342 
1343  tc->custom.type.data = tcld;
1345 }
1346 
1348 {
1349  bool use_merge_group = false;
1350  if (ELEM(t->mode, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
1351  if (!(t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT_SLIDE)) {
1352  /* No custom-data correction. */
1353  return;
1354  }
1355  use_merge_group = true;
1356  }
1357  else if (ELEM(t->mode,
1359  TFM_ROTATION,
1360  TFM_RESIZE,
1361  TFM_TOSPHERE,
1362  TFM_SHEAR,
1363  TFM_BEND,
1365  TFM_TRACKBALL,
1366  TFM_PUSHPULL,
1367  TFM_ALIGN)) {
1368  {
1369  if (!(t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
1370  /* No custom-data correction. */
1371  return;
1372  }
1373  use_merge_group = (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT_KEEP_CONNECTED) != 0;
1374  }
1375  }
1376  else {
1377  return;
1378  }
1379 
1382  }
1383 }
1384 
1388 static const float *trans_vert_orig_co_get(struct TransCustomDataLayer *tcld, BMVert *v)
1389 {
1391  return td ? td->iloc : v->co;
1392 }
1393 
1395  struct TransDataBasic *td,
1396  struct TransCustomDataMergeGroup *merge_data,
1397  bool do_loop_mdisps)
1398 {
1399  BMesh *bm = tcld->bm;
1400  BMVert *v = td->extra;
1401  const float *co_orig_3d = td->iloc;
1402 
1403  BMIter liter;
1404  int j, l_num;
1405  float *loop_weights;
1406  const bool is_moved = (len_squared_v3v3(v->co, co_orig_3d) > FLT_EPSILON);
1407  const bool do_loop_weight = is_moved && tcld->merge_group.customdatalayer_map_len;
1408  const float *v_proj_axis = v->no;
1409  /* original (l->prev, l, l->next) projections for each loop ('l' remains unchanged) */
1410  float v_proj[3][3];
1411 
1412  if (do_loop_weight) {
1413  project_plane_normalized_v3_v3v3(v_proj[1], co_orig_3d, v_proj_axis);
1414  }
1415 
1416  // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT)
1417  BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, v);
1418  l_num = liter.count;
1419  loop_weights = do_loop_weight ? BLI_array_alloca(loop_weights, l_num) : NULL;
1420  for (j = 0; j < l_num; j++) {
1421  BMFace *f_copy; /* the copy of 'f' */
1422  BMLoop *l = BM_iter_step(&liter);
1423 
1424  f_copy = BLI_ghash_lookup(tcld->origfaces, l->f);
1425 
1426 #ifdef USE_FACE_SUBSTITUTE
1427  /* In some faces it is not possible to calculate interpolation,
1428  * so we use a substitute. */
1429  if (BM_elem_index_get(f_copy) == FACE_SUBSTITUTE_INDEX) {
1431  }
1432 #endif
1433 
1434  /* only loop data, no vertex data since that contains shape keys,
1435  * and we do not want to mess up other shape keys */
1436  BM_loop_interp_from_face(bm, l, f_copy, false, false);
1437 
1438  /* weight the loop */
1439  if (do_loop_weight) {
1440  const float eps = 1.0e-8f;
1441  const BMLoop *l_prev = l->prev;
1442  const BMLoop *l_next = l->next;
1443  const float *co_prev = trans_vert_orig_co_get(tcld, l_prev->v);
1444  const float *co_next = trans_vert_orig_co_get(tcld, l_next->v);
1445  bool co_prev_ok;
1446  bool co_next_ok;
1447 
1448  /* In the unlikely case that we're next to a zero length edge -
1449  * walk around the to the next.
1450  *
1451  * Since we only need to check if the vertex is in this corner,
1452  * its not important _which_ loop - as long as its not overlapping
1453  * 'sv->co_orig_3d', see: T45096. */
1454  project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
1455  while (UNLIKELY(((co_prev_ok = (len_squared_v3v3(v_proj[1], v_proj[0]) > eps)) == false) &&
1456  ((l_prev = l_prev->prev) != l->next))) {
1457  co_prev = trans_vert_orig_co_get(tcld, l_prev->v);
1458  project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
1459  }
1460  project_plane_normalized_v3_v3v3(v_proj[2], co_next, v_proj_axis);
1461  while (UNLIKELY(((co_next_ok = (len_squared_v3v3(v_proj[1], v_proj[2]) > eps)) == false) &&
1462  ((l_next = l_next->next) != l->prev))) {
1463  co_next = trans_vert_orig_co_get(tcld, l_next->v);
1464  project_plane_normalized_v3_v3v3(v_proj[2], co_next, v_proj_axis);
1465  }
1466 
1467  if (co_prev_ok && co_next_ok) {
1468  const float dist = dist_signed_squared_to_corner_v3v3v3(
1469  v->co, UNPACK3(v_proj), v_proj_axis);
1470 
1471  loop_weights[j] = (dist >= 0.0f) ? 1.0f : ((dist <= -eps) ? 0.0f : (1.0f + (dist / eps)));
1472  if (UNLIKELY(!isfinite(loop_weights[j]))) {
1473  loop_weights[j] = 0.0f;
1474  }
1475  }
1476  else {
1477  loop_weights[j] = 0.0f;
1478  }
1479  }
1480  }
1481 
1482  if (tcld->use_merge_group) {
1483  struct LinkNode **cd_loop_groups = merge_data->cd_loop_groups;
1484  if (tcld->merge_group.customdatalayer_map_len && cd_loop_groups) {
1485  if (do_loop_weight) {
1486  for (j = 0; j < tcld->merge_group.customdatalayer_map_len; j++) {
1488  bm, cd_loop_groups[j], tcld->merge_group.customdatalayer_map[j], loop_weights);
1489  }
1490  }
1491  else {
1492  for (j = 0; j < tcld->merge_group.customdatalayer_map_len; j++) {
1494  bm, cd_loop_groups[j], tcld->merge_group.customdatalayer_map[j]);
1495  }
1496  }
1497  }
1498  }
1499 
1500  /* Special handling for multires
1501  *
1502  * Interpolate from every other loop (not ideal)
1503  * However values will only be taken from loops which overlap other mdisps.
1504  */
1505  const bool update_loop_mdisps = is_moved && do_loop_mdisps && (tcld->cd_loop_mdisp_offset != -1);
1506  if (update_loop_mdisps) {
1507  float(*faces_center)[3] = BLI_array_alloca(faces_center, l_num);
1508  BMLoop *l;
1509 
1510  BM_ITER_ELEM_INDEX (l, &liter, v, BM_LOOPS_OF_VERT, j) {
1511  BM_face_calc_center_median(l->f, faces_center[j]);
1512  }
1513 
1514  BM_ITER_ELEM_INDEX (l, &liter, v, BM_LOOPS_OF_VERT, j) {
1515  BMFace *f_copy = BLI_ghash_lookup(tcld->origfaces, l->f);
1516  float f_copy_center[3];
1517  BMIter liter_other;
1518  BMLoop *l_other;
1519  int j_other;
1520 
1521  BM_face_calc_center_median(f_copy, f_copy_center);
1522 
1523  BM_ITER_ELEM_INDEX (l_other, &liter_other, v, BM_LOOPS_OF_VERT, j_other) {
1525  l_other->f,
1526  f_copy,
1527  faces_center[j_other],
1528  f_copy_center,
1529  tcld->cd_loop_mdisp_offset);
1530  }
1531  }
1532  }
1533 }
1534 
1535 static void mesh_customdatacorrect_apply(TransInfo *t, bool is_final)
1536 {
1538  if (!tc->custom.type.data) {
1539  continue;
1540  }
1541  struct TransCustomDataLayer *tcld = tc->custom.type.data;
1542  const bool use_merge_group = tcld->use_merge_group;
1543 
1544  struct TransCustomDataMergeGroup *merge_data = tcld->merge_group.data;
1545  TransData *tob = tc->data;
1546  for (int i = tc->data_len; i--; tob++) {
1547  mesh_customdatacorrect_apply_vert(tcld, (TransDataBasic *)tob, merge_data, is_final);
1548 
1549  if (use_merge_group) {
1550  merge_data++;
1551  }
1552  }
1553 
1554  TransDataMirror *td_mirror = tc->data_mirror;
1555  for (int i = tc->data_mirror_len; i--; td_mirror++) {
1556  mesh_customdatacorrect_apply_vert(tcld, (TransDataBasic *)td_mirror, merge_data, is_final);
1557 
1558  if (use_merge_group) {
1559  merge_data++;
1560  }
1561  }
1562  }
1563 }
1564 
1566 {
1568  struct TransCustomDataLayer *tcld = tc->custom.type.data;
1569  if (!tcld) {
1570  continue;
1571  }
1572 
1573  BMesh *bm = tcld->bm;
1574  BMesh *bm_copy = tcld->bm_origfaces;
1575 
1576  GHashIterator gh_iter;
1577  GHASH_ITER (gh_iter, tcld->origfaces) {
1578  BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
1579  BMFace *f_copy = BLI_ghashIterator_getValue(&gh_iter);
1580  BLI_assert(f->len == f_copy->len);
1581 
1582  BMLoop *l_iter, *l_first, *l_copy;
1583  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
1584  l_copy = BM_FACE_FIRST_LOOP(f_copy);
1585  do {
1586  /* TODO: Restore only the elements that transform. */
1587  BM_elem_attrs_copy(bm_copy, bm, l_copy, l_iter);
1588  l_copy = l_copy->next;
1589  } while ((l_iter = l_iter->next) != l_first);
1590  }
1591  }
1592 }
1593 
1596 /* -------------------------------------------------------------------- */
1601 {
1603  if (tc->use_mirror_axis_any) {
1604  int i;
1605  TransData *td;
1606  for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
1607  if (td->flag & (TD_MIRROR_EDGE_X | TD_MIRROR_EDGE_Y | TD_MIRROR_EDGE_Z)) {
1608  if (td->flag & TD_MIRROR_EDGE_X) {
1609  td->loc[0] = 0.0f;
1610  }
1611  if (td->flag & TD_MIRROR_EDGE_Y) {
1612  td->loc[1] = 0.0f;
1613  }
1614  if (td->flag & TD_MIRROR_EDGE_Z) {
1615  td->loc[2] = 0.0f;
1616  }
1617  }
1618  }
1619 
1620  TransDataMirror *td_mirror = tc->data_mirror;
1621  for (i = 0; i < tc->data_mirror_len; i++, td_mirror++) {
1622  copy_v3_v3(td_mirror->loc, td_mirror->loc_src);
1623  if (td_mirror->flag & TD_MIRROR_X) {
1624  td_mirror->loc[0] *= -1;
1625  }
1626  if (td_mirror->flag & TD_MIRROR_Y) {
1627  td_mirror->loc[1] *= -1;
1628  }
1629  if (td_mirror->flag & TD_MIRROR_Z) {
1630  td_mirror->loc[2] *= -1;
1631  }
1632  }
1633  }
1634  }
1635 }
1636 
1638 {
1639  bool is_canceling = t->state == TRANS_CANCEL;
1640  /* mirror modifier clipping? */
1641  if (!is_canceling) {
1642  /* apply clipping after so we never project past the clip plane T25423. */
1643  applyProject(t);
1645 
1646  if ((t->flag & T_NO_MIRROR) == 0 && (t->options & CTX_NO_MIRROR) == 0) {
1648  }
1649 
1651  }
1652  else {
1654  }
1655 
1657  DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
1658  BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
1661  }
1662 }
1665 /* -------------------------------------------------------------------- */
1670 {
1671  const bool is_canceling = (t->state == TRANS_CANCEL);
1672  const bool use_automerge = !is_canceling && (t->flag & (T_AUTOMERGE | T_AUTOSPLIT)) != 0;
1673 
1674  if (!is_canceling && ELEM(t->mode, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
1675  /* NOTE(joeedh): Handle multi-res re-projection,
1676  * done on transform completion since it's really slow. */
1678  }
1679 
1680  if (use_automerge) {
1682  BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
1683  BMesh *bm = em->bm;
1684  char hflag;
1685  bool has_face_sel = (bm->totfacesel != 0);
1686 
1687  if (tc->use_mirror_axis_any) {
1688  /* Rather than adjusting the selection (which the user would notice)
1689  * tag all mirrored verts, then auto-merge those. */
1691 
1692  TransDataMirror *td_mirror = tc->data_mirror;
1693  for (int i = tc->data_mirror_len; i--; td_mirror++) {
1694  BM_elem_flag_enable((BMVert *)td_mirror->extra, BM_ELEM_TAG);
1695  }
1696 
1697  hflag = BM_ELEM_SELECT | BM_ELEM_TAG;
1698  }
1699  else {
1700  hflag = BM_ELEM_SELECT;
1701  }
1702 
1703  if (t->flag & T_AUTOSPLIT) {
1705  tc->obedit, true, true, true, hflag, t->scene->toolsettings->doublimit);
1706  }
1707  else {
1708  EDBM_automerge(tc->obedit, true, hflag, t->scene->toolsettings->doublimit);
1709  }
1710 
1711  /* Special case, this is needed or faces won't re-select.
1712  * Flush selected edges to faces. */
1713  if (has_face_sel && (em->selectmode == SCE_SELECT_FACE)) {
1715  }
1716  }
1717  }
1718 
1720  /* table needs to be created for each edit command, since vertices can move etc */
1722  /* TODO(campbell): xform: We need support for many mirror objects at once! */
1723  break;
1724  }
1725 }
typedef float(TangentPoint)[2]
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
void BKE_crazyspace_set_quats_editmesh(struct BMEditMesh *em, float(*origcos)[3], float(*mappedcos)[3], float(*quats)[4], const bool use_select)
Definition: crazyspace.c:130
int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgraph, struct Scene *, struct Object *, struct BMEditMesh *em, float(**deformmats)[3][3], float(**deformcos)[3])
Definition: crazyspace.c:250
float(* BKE_crazyspace_get_mapped_editverts(struct Depsgraph *depsgraph, struct Object *obedit))[3]
Definition: crazyspace.c:102
bool CustomData_has_math(const struct CustomData *data)
Definition: customdata.c:3843
bool CustomData_has_layer(const struct CustomData *data, int type)
bool CustomData_layer_has_math(const struct CustomData *data, int layer_n)
Definition: customdata.c:3820
int CustomData_get_offset(const struct CustomData *data, 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
struct Mesh * BKE_mesh_from_object(struct Object *ob)
Definition: mesh.c:1271
bool BKE_modifiers_is_correctable_deformed(const struct Scene *scene, struct Object *ob)
int BKE_modifiers_get_cage_index(const struct Scene *scene, struct Object *ob, int *r_lastPossibleCageIndex, bool is_virtual)
void BKE_scene_graph_evaluated_ensure(struct Depsgraph *depsgraph, struct Main *bmain)
Definition: scene.c:2718
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:36
#define BLI_assert(a)
Definition: BLI_assert.h:58
BLI_INLINE void * BLI_ghashIterator_getKey(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:146
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:150
#define GHASH_ITER(gh_iter_, ghash_)
Definition: BLI_ghash.h:169
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:756
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:1008
GHash * BLI_ghash_ptr_new_ex(const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:851
void * BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:803
void axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3])
Normal to x,y matrix.
Definition: math_geom.c:3752
float geodesic_distance_propagate_across_triangle(const float v0[3], const float v1[3], const float v2[3], const float dist1, const float dist2)
Definition: math_geom.c:6264
float dist_signed_squared_to_corner_v3v3v3(const float p[3], const float v1[3], const float v2[3], const float v3[3], const float axis_ref[3])
Definition: math_geom.c:543
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:930
void copy_m3_m3(float m1[3][3], const float m2[3][3])
Definition: math_matrix.c:89
void unit_m3(float m[3][3])
Definition: math_matrix.c:58
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:105
#define PSEUDOINVERSE_EPSILON
bool invert_m3_m3(float R[3][3], const float A[3][3])
Definition: math_matrix.c:1161
bool invert_m3(float R[3][3])
Definition: math_matrix.c:1152
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
Definition: math_matrix.c:901
#define mul_m3_series(...)
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
Definition: math_matrix.c:391
void pseudoinverse_m3_m3(float Ainv[3][3], const float A[3][3], float epsilon)
Definition: math_matrix.c:3228
void quat_to_mat3(float mat[3][3], const float q[4])
void copy_vn_i(int *array_tar, const int size, const int val)
Definition: math_vector.c:1374
MINLINE float normalize_v3(float r[3])
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE bool is_zero_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
void project_plane_normalized_v3_v3v3(float out[3], const float p[3], const float v_plane[3])
Definition: math_vector.c:757
MINLINE void zero_v3(float r[3])
float angle_v3v3v3(const float a[3], const float b[3], const float c[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:417
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:109
#define BLI_MEMARENA_STD_BUFSIZE
Definition: BLI_memarena.h:36
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
Definition: BLI_memarena.c:131
struct MemArena * BLI_memarena_new(const size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2) ATTR_MALLOC
Definition: BLI_memarena.c:79
unsigned int uint
Definition: BLI_sys_types.h:83
#define SWAP(type, a, b)
#define UNUSED(x)
#define UNPACK3(a)
#define UNLIKELY(x)
#define ELEM(...)
void DEG_id_tag_update(struct ID *id, int flag)
struct ID * DEG_get_evaluated_id(const struct Depsgraph *depsgraph, struct ID *id)
@ CD_BWEIGHT
@ ME_CDFLAG_VERT_BWEIGHT
@ ME_EDIT_MIRROR_TOPO
#define SCE_SELECT_FACE
#define UVCALC_TRANSFORM_CORRECT_SLIDE
#define SCE_SELECT_VERTEX
#define UVCALC_TRANSFORM_CORRECT_KEEP_CONNECTED
#define UVCALC_TRANSFORM_CORRECT
#define SCE_SNAP_ROTATE
#define SCE_SELECT_EDGE
@ V3D_AROUND_LOCAL_ORIGINS
void EDBM_selectmode_flush_ex(struct BMEditMesh *em, const short selectmode)
void EDBM_automerge_and_split(struct Object *ob, const bool split_edges, const bool split_faces, const bool update, const char hflag, const float dist)
void EDBM_automerge(struct Object *ob, bool update, const char hflag, const float dist)
void EDBM_verts_mirror_cache_begin_ex(struct BMEditMesh *em, const int axis, const bool use_self, const bool use_select, const bool respecthide, const bool use_topology, float maxdist, int *r_index)
void ED_mesh_mirror_spatial_table_end(struct Object *ob)
void EDBM_mesh_normals_update(struct BMEditMesh *em)
@ TFM_RESIZE
Definition: ED_transform.h:48
@ TFM_EDGE_SLIDE
Definition: ED_transform.h:74
@ TFM_SHEAR
Definition: ED_transform.h:51
@ TFM_SHRINKFATTEN
Definition: ED_transform.h:53
@ TFM_VERT_SLIDE
Definition: ED_transform.h:75
@ TFM_BEND
Definition: ED_transform.h:52
@ TFM_ROTATION
Definition: ED_transform.h:47
@ TFM_BWEIGHT
Definition: ED_transform.h:72
@ TFM_ALIGN
Definition: ED_transform.h:73
@ TFM_TOSPHERE
Definition: ED_transform.h:50
@ TFM_TRANSLATION
Definition: ED_transform.h:46
@ TFM_PUSHPULL
Definition: ED_transform.h:56
@ TFM_TRACKBALL
Definition: ED_transform.h:55
_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 i1
_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
_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 v1
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define MEM_reallocN(vmemh, len)
#define C
Definition: RandGen.cpp:39
@ BM_LOOP
Definition: bmesh_class.h:385
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
@ BM_ELEM_HIDDEN
Definition: bmesh_class.h:472
@ BM_ELEM_SELECT
Definition: bmesh_class.h:471
@ BM_ELEM_TAG
Definition: bmesh_class.h:484
@ BM_ELEM_TAG_ALT
Definition: bmesh_class.h:489
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:553
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:530
void BM_elem_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const void *ele_src, void *ele_dst)
void BM_mesh_copy_init_customdata_all_layers(BMesh *bm_dst, BMesh *bm_src, const char htype, const BMAllocTemplate *allocsize)
BMFace * BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f, const bool copy_verts, const bool copy_edges)
Definition: bmesh_core.c:303
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:124
#define BM_elem_flag_disable(ele, hflag)
Definition: bmesh_inline.h:29
#define BM_elem_flag_set(ele, hflag, val)
Definition: bmesh_inline.h:30
#define BM_elem_index_set(ele, index)
Definition: bmesh_inline.h:125
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:26
#define BM_elem_flag_enable(ele, hflag)
Definition: bmesh_inline.h:28
LinkNode * BM_vert_loop_groups_data_layer_create(BMesh *bm, BMVert *v, const int layer_n, const float *loop_weights, MemArena *arena)
void BM_face_interp_multires_ex(BMesh *bm, BMFace *f_dst, const BMFace *f_src, const float f_dst_center[3], const float f_src_center[3], const int cd_loop_mdisp_offset)
Definition: bmesh_interp.c:591
void BM_vert_loop_groups_data_layer_merge(BMesh *bm, LinkNode *groups, const int layer_n)
void BM_vert_loop_groups_data_layer_merge_weights(BMesh *bm, LinkNode *groups, const int layer_n, const float *loop_weights)
void BM_loop_interp_from_face(BMesh *bm, BMLoop *l_dst, const BMFace *f_src, const bool do_vertex, const bool do_multires)
Definition: bmesh_interp.c:737
int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const bool value)
Mesh Iter Flag Count.
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_FACES_OF_EDGE
@ BM_EDGES_OF_MESH
@ BM_VERTS_OF_MESH
@ BM_VERTS_OF_EDGE
@ BM_VERTS_OF_FACE
@ BM_LOOPS_OF_VERT
@ BM_LOOPS_OF_EDGE
@ BM_EDGES_OF_VERT
@ BM_LOOPS_OF_FACE
#define BM_ITER_ELEM_INDEX(ele, iter, data, itype, indexvar)
BLI_INLINE bool BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *data)
Iterator Init.
ATTR_WARN_UNUSED_RESULT BMesh const char itype
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_editselection_center(BMEditSelection *ese, float r_center[3])
void BM_editselection_plane(BMEditSelection *ese, float r_plane[3])
void BM_editselection_normal(BMEditSelection *ese, float r_normal[3])
void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag, const bool respecthide)
const BMAllocTemplate bm_mesh_allocsize_default
Definition: bmesh_mesh.c:46
void BM_mesh_free(BMesh *bm)
BMesh Free Mesh.
Definition: bmesh_mesh.c:307
BMesh * BM_mesh_create(const BMAllocTemplate *allocsize, const struct BMeshCreateParams *params)
BMesh Make Mesh.
Definition: bmesh_mesh.c:157
void bmesh_edit_begin(BMesh *UNUSED(bm), BMOpTypeFlag UNUSED(type_flag))
BMesh Begin Edit.
Definition: bmesh_mesh.c:1975
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.c:2276
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.c:2152
void bmesh_edit_end(BMesh *bm, BMOpTypeFlag type_flag)
BMesh End Edit.
Definition: bmesh_mesh.c:1998
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
Definition: bmesh_mesh.h:98
void BM_mesh_cd_flag_ensure(BMesh *bm, Mesh *mesh, const char cd_flag)
@ BMO_OPTYPE_FLAG_UNTAN_MULTIRES
bool BM_vert_calc_normal_ex(const BMVert *v, const char hflag, float r_no[3])
void BM_face_calc_center_median(const BMFace *f, float r_cent[3])
BMLoop * BM_loop_find_next_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq)
Definition: bmesh_query.c:1492
int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int(**r_group_index)[2], BMLoopFilterFunc filter_fn, BMLoopPairFilterFunc filter_pair_fn, void *user_data, const char hflag_test, const char htype_step)
Definition: bmesh_query.c:2611
float BM_vert_calc_shell_factor_ex(const BMVert *v, const float no[3], const char hflag)
Definition: bmesh_query.c:1870
BMLoop * BM_loop_find_prev_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq)
Definition: bmesh_query.c:1472
int BM_mesh_calc_edge_groups(BMesh *bm, int *r_groups_array, int(**r_group_index)[2], BMVertFilterFunc filter_fn, void *user_data, const char hflag_test)
Definition: bmesh_query.c:2775
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define fabsf(x)
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
bool isfinite(uchar)
Definition: image.cpp:44
static unsigned a[3]
Definition: RandGen.cpp:92
ThreadQueue * queue
all scheduled work for the cpu
static double epsilon
const btScalar eps
Definition: poly34.cpp:11
struct BMLoop * l
Definition: bmesh_class.h:140
short selectmode
Definition: BKE_editmesh.h:72
struct BMesh * bm
Definition: BKE_editmesh.h:52
int len
Definition: bmesh_class.h:279
float no[3]
Definition: bmesh_class.h:280
struct BMVert * v
Definition: bmesh_class.h:165
struct BMLoop * radial_next
Definition: bmesh_class.h:216
struct BMLoop * prev
Definition: bmesh_class.h:245
struct BMFace * f
Definition: bmesh_class.h:183
struct BMLoop * next
Definition: bmesh_class.h:245
float co[3]
Definition: bmesh_class.h:99
float no[3]
Definition: bmesh_class.h:100
int totvert
Definition: bmesh_class.h:297
BMEdge ** etable
Definition: bmesh_class.h:322
int totfacesel
Definition: bmesh_class.h:298
int shapenr
Definition: bmesh_class.h:353
char elem_index_dirty
Definition: bmesh_class.h:305
CustomData vdata
Definition: bmesh_class.h:337
int totvertsel
Definition: bmesh_class.h:298
int totedgesel
Definition: bmesh_class.h:298
CustomData ldata
Definition: bmesh_class.h:337
BMFace ** ftable
Definition: bmesh_class.h:323
struct LinkNode * next
Definition: BLI_linklist.h:39
char editflag
TransCustomData type
Definition: transform.h:428
struct TransCustomDataMergeGroup * data
struct TransCustomDataLayer::@575 merge_group
void(* free_cb)(struct TransInfo *, struct TransDataContainer *tc, struct TransCustomData *custom_data)
Definition: transform.h:405
TransCustomDataContainer custom
Definition: transform.h:501
struct Object * obedit
Definition: transform.h:461
TransData * data
Definition: transform.h:448
TransDataMirror * data_mirror
Definition: transform.h:454
float smtx[3][3]
float axismtx[3][3]
float mtx[3][3]
TransDataExtension * ext
float * val
float(* axismtx)[3][3]
struct MirrorDataVert * vert_map
@ CTX_NO_MIRROR
Definition: transform.h:91
@ T_PROP_EDIT_ALL
Definition: transform.h:114
@ T_AUTOSPLIT
Definition: transform.h:152
@ T_PROP_CONNECTED
Definition: transform.h:112
@ T_AUTOMERGE
Definition: transform.h:150
@ 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
void clipMirrorModifier(TransInfo *t)
conversion and adaptation of different datablocks to a common struct.
void transform_convert_mesh_islanddata_free(struct TransIslandData *island_data)
static void mesh_customdatacorrect_apply_vert(struct TransCustomDataLayer *tcld, struct TransDataBasic *td, struct TransCustomDataMergeGroup *merge_data, bool do_loop_mdisps)
static const float * trans_vert_orig_co_get(struct TransCustomDataLayer *tcld, BMVert *v)
static BMFace * mesh_customdatacorrect_find_best_face_substitute(BMFace *f)
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)
static void mesh_customdatacorrect_restore(struct TransInfo *t)
#define FACE_SUBSTITUTE_INDEX
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)
static void mesh_customdatacorrect_face_substitute_set(struct TransCustomDataLayer *tcld, BMFace *f, BMFace *f_copy)
static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx, BMEditMesh *em, BMVert *eve, float *bweight, const struct TransIslandData *island_data, const int island_index)
static void mesh_customdatacorrect_init_vert(struct TransCustomDataLayer *tcld, struct TransDataBasic *td, const int index)
static void mesh_apply_to_mirror(TransInfo *t)
#define TRANSFORM_MAXDIST_MIRROR
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)
static void mesh_customdatacorrect_init_container(TransDataContainer *tc, const bool use_merge_group)
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)
static void mesh_customdatacorrect_free_cb(struct TransInfo *UNUSED(t), struct TransDataContainer *UNUSED(tc), struct TransCustomData *custom_data)
void recalcData_mesh(TransInfo *t)
void mesh_customdatacorrect_init(TransInfo *t)
static void transdata_center_get(const struct TransIslandData *island_data, const int island_index, const float iloc[3], float r_center[3])
static void mesh_customdatacorrect_apply(TransInfo *t, bool is_final)
void transform_convert_mesh_mirrordata_free(struct TransMirrorData *mirror_data)
static bool bmesh_test_loose_edge(BMEdge *edge)
static bool bmesh_test_dist_add(BMVert *v0, BMVert *v1, BMVert *v2, float *dists, int *index, const float mtx[3][3])
void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
static void mesh_customdatacorrect_init_container_generic(TransDataContainer *UNUSED(tc), struct TransCustomDataLayer *tcld)
void transform_convert_mesh_connectivity_distance(struct BMesh *bm, const float mtx[3][3], float *dists, int *index)
static bool is_in_quadrant_v3(const float co[3], const int quadrant[3], const float epsilon)
void createTransEditVerts(TransInfo *t)
static void mesh_customdatacorrect_init_container_merge_group(TransDataContainer *tc, struct TransCustomDataLayer *tcld)
static BMFace * mesh_customdatacorrect_face_substitute_get(BMFace *f_copy)
@ TD_MIRROR_EDGE_Y
@ TD_MIRROR_Z
@ TD_MIRROR_EDGE_Z
@ TD_MIRROR_X
@ TD_NOTCONNECTED
@ TD_MIRROR_Y
@ TD_MIRROR_EDGE_X
@ TD_SELECTED
bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const float tangent[3])
bool createSpaceNormal(float mat[3][3], const float normal[3])
bool usingSnappingNormal(const TransInfo *t)
void applyProject(TransInfo *t)