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