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