Blender V5.0
mask_evaluate.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2012 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include <algorithm> /* For `min/max`. */
12#include <cstring>
13
14#include "MEM_guardedalloc.h"
15
16#include "BLI_listbase.h"
17#include "BLI_math_geom.h"
18#include "BLI_math_matrix.h"
19#include "BLI_math_vector.h"
20#include "BLI_utildefines.h"
21
22#include "DNA_mask_types.h"
23
24#include "BKE_curve.hh"
25#include "BKE_mask.h"
26
27#include "DEG_depsgraph.hh"
29
30int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height)
31{
32 float max_segment = 0.01f;
33 int i, resol = 1;
34
35 if (width != 0 && height != 0) {
36 max_segment = 1.0f / float(max_ii(width, height));
37 }
38
39 for (i = 0; i < spline->tot_point; i++) {
40 MaskSplinePoint *point = &spline->points[i];
41 BezTriple *bezt_curr, *bezt_next;
42 float a, b, c, len;
43 int cur_resol;
44
45 bezt_curr = &point->bezt;
46 bezt_next = BKE_mask_spline_point_next_bezt(spline, spline->points, point);
47
48 if (bezt_next == nullptr) {
49 break;
50 }
51
52 a = len_v3v3(bezt_curr->vec[1], bezt_curr->vec[2]);
53 b = len_v3v3(bezt_curr->vec[2], bezt_next->vec[0]);
54 c = len_v3v3(bezt_next->vec[0], bezt_next->vec[1]);
55
56 len = a + b + c;
57 cur_resol = len / max_segment;
58
59 resol = std::max(resol, cur_resol);
60
61 if (resol >= MASK_RESOL_MAX) {
62 break;
63 }
64 }
65
66 return std::clamp(resol, 1, MASK_RESOL_MAX);
67}
68
69uint BKE_mask_spline_feather_resolution(MaskSpline *spline, int width, int height)
70{
71 const float max_segment = 0.005;
72 int resol = BKE_mask_spline_resolution(spline, width, height);
73 float max_jump = 0.0f;
74
75 /* Avoid checking the feather if we already hit the maximum value. */
76 if (resol >= MASK_RESOL_MAX) {
77 return MASK_RESOL_MAX;
78 }
79
80 for (int i = 0; i < spline->tot_point; i++) {
81 MaskSplinePoint *point = &spline->points[i];
82
83 float prev_u = 0.0f;
84 float prev_w = point->bezt.weight;
85
86 for (int j = 0; j < point->tot_uw; j++) {
87 const float w_diff = (point->uw[j].w - prev_w);
88 const float u_diff = (point->uw[j].u - prev_u);
89
90 /* avoid divide by zero and very high values,
91 * though these get clamped eventually */
92 if (u_diff > FLT_EPSILON) {
93 float jump = fabsf(w_diff / u_diff);
94
95 max_jump = max_ff(max_jump, jump);
96 }
97
98 prev_u = point->uw[j].u;
99 prev_w = point->uw[j].w;
100 }
101 }
102
103 resol += max_jump / max_segment;
104
105 return std::clamp(resol, 1, MASK_RESOL_MAX);
106}
107
109{
110 if (spline->flag & MASK_SPLINE_CYCLIC) {
111 return spline->tot_point * resol;
112 }
113
114 return ((spline->tot_point - 1) * resol) + 1;
115}
116
118 const uint resol,
119 uint *r_tot_diff_point))[2]
120{
121 MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
122
123 MaskSplinePoint *point_curr, *point_prev;
124 float (*diff_points)[2], (*fp)[2];
125 const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol);
126 int a;
127
128 if (spline->tot_point <= 1) {
129 /* nothing to differentiate */
130 *r_tot_diff_point = 0;
131 return nullptr;
132 }
133
134 /* len+1 because of 'forward_diff_bezier' function */
135 *r_tot_diff_point = tot;
136 diff_points = fp = MEM_calloc_arrayN<float[2]>(tot + 1, "mask spline vets");
137
138 a = spline->tot_point - 1;
139 if (spline->flag & MASK_SPLINE_CYCLIC) {
140 a++;
141 }
142
143 point_prev = points_array;
144 point_curr = point_prev + 1;
145
146 while (a--) {
147 BezTriple *bezt_prev;
148 BezTriple *bezt_curr;
149 int j;
150
151 if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) {
152 point_curr = points_array;
153 }
154
155 bezt_prev = &point_prev->bezt;
156 bezt_curr = &point_curr->bezt;
157
158 for (j = 0; j < 2; j++) {
159 BKE_curve_forward_diff_bezier(bezt_prev->vec[1][j],
160 bezt_prev->vec[2][j],
161 bezt_curr->vec[0][j],
162 bezt_curr->vec[1][j],
163 &(*fp)[j],
164 resol,
165 sizeof(float[2]));
166 }
167
168 fp += resol;
169
170 if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) {
171 copy_v2_v2(*fp, bezt_curr->vec[1]);
172 }
173
174 point_prev = point_curr;
175 point_curr++;
176 }
177
178 return diff_points;
179}
180
182 MaskSpline *spline, int width, int height, uint *r_tot_diff_point))[2]
183{
184 int resol = BKE_mask_spline_resolution(spline, width, height);
185
186 return BKE_mask_spline_differentiate_with_resolution(spline, resol, r_tot_diff_point);
187}
188
189/* ** feather points self-intersection collapse routine ** */
190
196
197static void feather_bucket_add_edge(FeatherEdgesBucket *bucket, int start, int end)
198{
199 const int alloc_delta = 256;
200
201 if (bucket->tot_segment >= bucket->alloc_segment) {
202 if (!bucket->segments) {
203 bucket->segments = MEM_calloc_arrayN<int[2]>(alloc_delta, "feather bucket segments");
204 }
205 else {
206 bucket->segments = static_cast<int (*)[2]>(MEM_reallocN(
207 bucket->segments, (alloc_delta + bucket->tot_segment) * sizeof(*bucket->segments)));
208 }
209
210 bucket->alloc_segment += alloc_delta;
211 }
212
213 bucket->segments[bucket->tot_segment][0] = start;
214 bucket->segments[bucket->tot_segment][1] = end;
215
216 bucket->tot_segment++;
217}
218
219static void feather_bucket_check_intersect(float (*feather_points)[2],
220 int tot_feather_point,
221 FeatherEdgesBucket *bucket,
222 int cur_a,
223 int cur_b)
224{
225 const float *v1 = (float *)feather_points[cur_a];
226 const float *v2 = (float *)feather_points[cur_b];
227
228 for (int i = 0; i < bucket->tot_segment; i++) {
229 int check_a = bucket->segments[i][0];
230 int check_b = bucket->segments[i][1];
231
232 const float *v3 = (float *)feather_points[check_a];
233 const float *v4 = (float *)feather_points[check_b];
234
235 if (check_a >= cur_a - 1 || cur_b == check_a) {
236 continue;
237 }
238
239 if (isect_seg_seg_v2_simple(v1, v2, v3, v4)) {
240 int k;
241 float p[2];
242 float min_a[2], max_a[2];
243 float min_b[2], max_b[2];
244
245 isect_seg_seg_v2_point(v1, v2, v3, v4, p);
246
247 INIT_MINMAX2(min_a, max_a);
248 INIT_MINMAX2(min_b, max_b);
249
250 /* collapse loop with smaller AABB */
251 for (k = 0; k < tot_feather_point; k++) {
252 if (k >= check_b && k <= cur_a) {
253 minmax_v2v2_v2(min_a, max_a, feather_points[k]);
254 }
255 else {
256 minmax_v2v2_v2(min_b, max_b, feather_points[k]);
257 }
258 }
259
260 if (max_a[0] - min_a[0] < max_b[0] - min_b[0] || max_a[1] - min_a[1] < max_b[1] - min_b[1]) {
261 for (k = check_b; k <= cur_a; k++) {
262 copy_v2_v2(feather_points[k], p);
263 }
264 }
265 else {
266 for (k = 0; k <= check_a; k++) {
267 copy_v2_v2(feather_points[k], p);
268 }
269
270 if (cur_b != 0) {
271 for (k = cur_b; k < tot_feather_point; k++) {
272 copy_v2_v2(feather_points[k], p);
273 }
274 }
275 }
276 }
277 }
278}
279
280static int feather_bucket_index_from_coord(const float co[2],
281 const float min[2],
282 const float bucket_scale[2],
283 const int buckets_per_side)
284{
285 int x = int((co[0] - min[0]) * bucket_scale[0]);
286 int y = int((co[1] - min[1]) * bucket_scale[1]);
287
288 if (x == buckets_per_side) {
289 x--;
290 }
291
292 if (y == buckets_per_side) {
293 y--;
294 }
295
296 return y * buckets_per_side + x;
297}
298
300 int start_bucket_index,
301 int end_bucket_index,
302 int buckets_per_side,
303 FeatherEdgesBucket **r_diagonal_bucket_a,
304 FeatherEdgesBucket **r_diagonal_bucket_b)
305{
306 int start_bucket_x = start_bucket_index % buckets_per_side;
307 int start_bucket_y = start_bucket_index / buckets_per_side;
308
309 int end_bucket_x = end_bucket_index % buckets_per_side;
310 int end_bucket_y = end_bucket_index / buckets_per_side;
311
312 int diagonal_bucket_a_index = start_bucket_y * buckets_per_side + end_bucket_x;
313 int diagonal_bucket_b_index = end_bucket_y * buckets_per_side + start_bucket_x;
314
315 *r_diagonal_bucket_a = &buckets[diagonal_bucket_a_index];
316 *r_diagonal_bucket_b = &buckets[diagonal_bucket_b_index];
317}
318
320 float (*feather_points)[2],
321 const uint tot_feather_point)
322{
323#define BUCKET_INDEX(co) feather_bucket_index_from_coord(co, min, bucket_scale, buckets_per_side)
324
325 int buckets_per_side, tot_bucket;
326 float bucket_size, bucket_scale[2];
327
328 FeatherEdgesBucket *buckets;
329
330 float min[2], max[2];
331 float max_delta_x = -1.0f, max_delta_y = -1.0f, max_delta;
332
333 if (tot_feather_point < 4) {
334 /* self-intersection works only for quads at least,
335 * in other cases polygon can't be self-intersecting anyway
336 */
337
338 return;
339 }
340
341 /* find min/max corners of mask to build buckets in that space */
343
344 for (uint i = 0; i < tot_feather_point; i++) {
345 uint next = i + 1;
346 float delta;
347
348 minmax_v2v2_v2(min, max, feather_points[i]);
349
350 if (next == tot_feather_point) {
351 if (spline->flag & MASK_SPLINE_CYCLIC) {
352 next = 0;
353 }
354 else {
355 break;
356 }
357 }
358
359 delta = fabsf(feather_points[i][0] - feather_points[next][0]);
360 max_delta_x = std::max(delta, max_delta_x);
361
362 delta = fabsf(feather_points[i][1] - feather_points[next][1]);
363 max_delta_y = std::max(delta, max_delta_y);
364 }
365
366 /* Prevent divisions by zero by ensuring bounding box is not collapsed. */
367 if (max[0] - min[0] < FLT_EPSILON) {
368 max[0] += 0.01f;
369 min[0] -= 0.01f;
370 }
371
372 if (max[1] - min[1] < FLT_EPSILON) {
373 max[1] += 0.01f;
374 min[1] -= 0.01f;
375 }
376
377 /* use dynamically calculated buckets per side, so we likely wouldn't
378 * run into a situation when segment doesn't fit two buckets which is
379 * pain collecting candidates for intersection
380 */
381
382 max_delta_x /= max[0] - min[0];
383 max_delta_y /= max[1] - min[1];
384
385 max_delta = std::max(max_delta_x, max_delta_y);
386
387 buckets_per_side = min_ii(512, 0.9f / max_delta);
388
389 if (buckets_per_side == 0) {
390 /* happens when some segment fills the whole bounding box across some of dimension */
391
392 buckets_per_side = 1;
393 }
394
395 tot_bucket = buckets_per_side * buckets_per_side;
396 bucket_size = 1.0f / buckets_per_side;
397
398 /* pre-compute multipliers, to save mathematical operations in loops */
399 bucket_scale[0] = 1.0f / ((max[0] - min[0]) * bucket_size);
400 bucket_scale[1] = 1.0f / ((max[1] - min[1]) * bucket_size);
401
402 /* fill in buckets' edges */
403 buckets = MEM_calloc_arrayN<FeatherEdgesBucket>(tot_bucket, "feather buckets");
404
405 for (int i = 0; i < tot_feather_point; i++) {
406 int start = i, end = i + 1;
407 int start_bucket_index, end_bucket_index;
408
409 if (end == tot_feather_point) {
410 if (spline->flag & MASK_SPLINE_CYCLIC) {
411 end = 0;
412 }
413 else {
414 break;
415 }
416 }
417
418 start_bucket_index = BUCKET_INDEX(feather_points[start]);
419 end_bucket_index = BUCKET_INDEX(feather_points[end]);
420
421 feather_bucket_add_edge(&buckets[start_bucket_index], start, end);
422
423 if (start_bucket_index != end_bucket_index) {
424 FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index];
425 FeatherEdgesBucket *diagonal_bucket_a, *diagonal_bucket_b;
426
428 start_bucket_index,
429 end_bucket_index,
430 buckets_per_side,
431 &diagonal_bucket_a,
432 &diagonal_bucket_b);
433
434 feather_bucket_add_edge(end_bucket, start, end);
435 feather_bucket_add_edge(diagonal_bucket_a, start, end);
436 feather_bucket_add_edge(diagonal_bucket_a, start, end);
437 }
438 }
439
440 /* check all edges for intersection with edges from their buckets */
441 for (int i = 0; i < tot_feather_point; i++) {
442 int cur_a = i, cur_b = i + 1;
443 int start_bucket_index, end_bucket_index;
444
445 FeatherEdgesBucket *start_bucket;
446
447 if (cur_b == tot_feather_point) {
448 cur_b = 0;
449 }
450
451 start_bucket_index = BUCKET_INDEX(feather_points[cur_a]);
452 end_bucket_index = BUCKET_INDEX(feather_points[cur_b]);
453
454 start_bucket = &buckets[start_bucket_index];
455
456 feather_bucket_check_intersect(feather_points, tot_feather_point, start_bucket, cur_a, cur_b);
457
458 if (start_bucket_index != end_bucket_index) {
459 FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index];
460 FeatherEdgesBucket *diagonal_bucket_a, *diagonal_bucket_b;
461
463 start_bucket_index,
464 end_bucket_index,
465 buckets_per_side,
466 &diagonal_bucket_a,
467 &diagonal_bucket_b);
468
469 feather_bucket_check_intersect(feather_points, tot_feather_point, end_bucket, cur_a, cur_b);
471 feather_points, tot_feather_point, diagonal_bucket_a, cur_a, cur_b);
473 feather_points, tot_feather_point, diagonal_bucket_b, cur_a, cur_b);
474 }
475 }
476
477 /* free buckets */
478 for (int i = 0; i < tot_bucket; i++) {
479 if (buckets[i].segments) {
480 MEM_freeN(buckets[i].segments);
481 }
482 }
483
484 MEM_freeN(buckets);
485
486#undef BUCKET_INDEX
487}
488
490static float (
492 const uint resol,
493 const bool do_feather_isect,
494 uint *r_tot_feather_point))[2]
495{
496 MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
497 MaskSplinePoint *point_curr, *point_prev;
498 float (*feather)[2], (*fp)[2];
499
500 const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol);
501 int a;
502
503 /* tot+1 because of 'forward_diff_bezier' function */
504 feather = fp = MEM_calloc_arrayN<float[2]>(tot + 1, "mask spline feather diff points");
505
506 a = spline->tot_point - 1;
507 if (spline->flag & MASK_SPLINE_CYCLIC) {
508 a++;
509 }
510
511 point_prev = points_array;
512 point_curr = point_prev + 1;
513
514 while (a--) {
515 // BezTriple *bezt_prev; /* UNUSED */
516 // BezTriple *bezt_curr; /* UNUSED */
517 int j;
518
519 if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) {
520 point_curr = points_array;
521 }
522
523 // bezt_prev = &point_prev->bezt;
524 // bezt_curr = &point_curr->bezt;
525
526 for (j = 0; j < resol; j++, fp++) {
527 float u = float(j) / resol, weight;
528 float co[2], n[2];
529
530 /* TODO: these calls all calculate similar things
531 * could be unified for some speed */
532 BKE_mask_point_segment_co(spline, point_prev, u, co);
533 BKE_mask_point_normal(spline, point_prev, u, n);
534 weight = BKE_mask_point_weight(spline, point_prev, u);
535
536 madd_v2_v2v2fl(*fp, co, n, weight);
537 }
538
539 if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) {
540 float u = 1.0f, weight;
541 float co[2], n[2];
542
543 BKE_mask_point_segment_co(spline, point_prev, u, co);
544 BKE_mask_point_normal(spline, point_prev, u, n);
545 weight = BKE_mask_point_weight(spline, point_prev, u);
546
547 madd_v2_v2v2fl(*fp, co, n, weight);
548 }
549
550 point_prev = point_curr;
551 point_curr++;
552 }
553
554 *r_tot_feather_point = tot;
555
556 if ((spline->flag & MASK_SPLINE_NOINTERSECT) && do_feather_isect) {
558 }
559
560 return feather;
561}
562
565 MaskSpline *spline,
566 const uint resol,
567 const bool do_feather_isect,
568 uint *r_tot_feather_point))[2]
569{
570 MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
571
572 MaskSplinePoint *point_curr, *point_prev;
573 float (*feather)[2], (*fp)[2];
574 const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol);
575 int a;
576
577 if (spline->tot_point <= 1) {
578 /* nothing to differentiate */
579 *r_tot_feather_point = 0;
580 return nullptr;
581 }
582
583 /* len+1 because of 'forward_diff_bezier' function */
584 *r_tot_feather_point = tot;
585 feather = fp = MEM_calloc_arrayN<float[2]>(tot + 1, "mask spline vets");
586
587 a = spline->tot_point - 1;
588 if (spline->flag & MASK_SPLINE_CYCLIC) {
589 a++;
590 }
591
592 point_prev = points_array;
593 point_curr = point_prev + 1;
594
595 while (a--) {
596 BezTriple local_prevbezt;
597 BezTriple local_bezt;
598 float point_prev_n[2], point_curr_n[2], tvec[2];
599 float weight_prev, weight_curr;
600 float len_base, len_feather, len_scalar;
601
602 BezTriple *bezt_prev;
603 BezTriple *bezt_curr;
604 int j;
605
606 if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) {
607 point_curr = points_array;
608 }
609
610 bezt_prev = &point_prev->bezt;
611 bezt_curr = &point_curr->bezt;
612
613 /* modified copy for feather */
614 local_prevbezt = *bezt_prev;
615 local_bezt = *bezt_curr;
616
617 bezt_prev = &local_prevbezt;
618 bezt_curr = &local_bezt;
619
620 /* calc the normals */
621 sub_v2_v2v2(tvec, bezt_prev->vec[1], bezt_prev->vec[0]);
622 normalize_v2(tvec);
623 point_prev_n[0] = -tvec[1];
624 point_prev_n[1] = tvec[0];
625
626 sub_v2_v2v2(tvec, bezt_curr->vec[1], bezt_curr->vec[0]);
627 normalize_v2(tvec);
628 point_curr_n[0] = -tvec[1];
629 point_curr_n[1] = tvec[0];
630
631 weight_prev = bezt_prev->weight;
632 weight_curr = bezt_curr->weight;
633
634 mul_v2_fl(point_prev_n, weight_prev);
635 mul_v2_fl(point_curr_n, weight_curr);
636
637 /* before we transform verts */
638 len_base = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]);
639
640 // add_v2_v2(bezt_prev->vec[0], point_prev_n); /* Not needed. */
641 add_v2_v2(bezt_prev->vec[1], point_prev_n);
642 add_v2_v2(bezt_prev->vec[2], point_prev_n);
643
644 add_v2_v2(bezt_curr->vec[0], point_curr_n);
645 add_v2_v2(bezt_curr->vec[1], point_curr_n);
646 // add_v2_v2(bezt_curr->vec[2], point_curr_n); /* Not needed. */
647
648 len_feather = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]);
649
650 /* scale by change in length */
651 len_scalar = len_feather / len_base;
652 dist_ensure_v2_v2fl(bezt_prev->vec[2],
653 bezt_prev->vec[1],
654 len_scalar * len_v2v2(bezt_prev->vec[2], bezt_prev->vec[1]));
655 dist_ensure_v2_v2fl(bezt_curr->vec[0],
656 bezt_curr->vec[1],
657 len_scalar * len_v2v2(bezt_curr->vec[0], bezt_curr->vec[1]));
658
659 for (j = 0; j < 2; j++) {
660 BKE_curve_forward_diff_bezier(bezt_prev->vec[1][j],
661 bezt_prev->vec[2][j],
662 bezt_curr->vec[0][j],
663 bezt_curr->vec[1][j],
664 &(*fp)[j],
665 resol,
666 sizeof(float[2]));
667 }
668
669 /* scale by the uw's */
670 if (point_prev->tot_uw) {
671 for (j = 0; j < resol; j++, fp++) {
672 float u = float(j) / resol;
673 float weight_uw, weight_scalar;
674 float co[2];
675
676 /* TODO: these calls all calculate similar things
677 * could be unified for some speed */
678 BKE_mask_point_segment_co(spline, point_prev, u, co);
679
680 weight_uw = BKE_mask_point_weight(spline, point_prev, u);
681 weight_scalar = BKE_mask_point_weight_scalar(spline, point_prev, u);
682
683 dist_ensure_v2_v2fl(*fp, co, len_v2v2(*fp, co) * (weight_uw / weight_scalar));
684 }
685 }
686 else {
687 fp += resol;
688 }
689
690 if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) {
691 copy_v2_v2(*fp, bezt_curr->vec[1]);
692 }
693
694 point_prev = point_curr;
695 point_curr++;
696 }
697
698 if ((spline->flag & MASK_SPLINE_NOINTERSECT) && do_feather_isect) {
700 }
701
702 return feather;
703}
704
707 const uint resol,
708 const bool do_feather_isect,
709 uint *r_tot_feather_point))[2]
710{
711 switch (spline->offset_mode) {
714 spline, resol, do_feather_isect, r_tot_feather_point);
716 default:
718 spline, resol, do_feather_isect, r_tot_feather_point);
719 }
720}
721
722float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *r_tot_feather_point))[2]
723{
724 MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
725
726 int i, tot = 0;
727 float (*feather)[2], (*fp)[2];
728
729 /* count */
730 for (i = 0; i < spline->tot_point; i++) {
731 MaskSplinePoint *point = &points_array[i];
732
733 tot += point->tot_uw + 1;
734 }
735
736 /* create data */
737 feather = fp = MEM_calloc_arrayN<float[2]>(tot, "mask spline feather points");
738
739 for (i = 0; i < spline->tot_point; i++) {
740 MaskSplinePoint *point = &points_array[i];
741 BezTriple *bezt = &point->bezt;
742 float weight, n[2];
743 int j;
744
745 BKE_mask_point_normal(spline, point, 0.0f, n);
746 weight = BKE_mask_point_weight(spline, point, 0.0f);
747
748 madd_v2_v2v2fl(*fp, bezt->vec[1], n, weight);
749 fp++;
750
751 for (j = 0; j < point->tot_uw; j++) {
752 float u = point->uw[j].u;
753 float co[2];
754
755 BKE_mask_point_segment_co(spline, point, u, co);
756 BKE_mask_point_normal(spline, point, u, n);
757 weight = BKE_mask_point_weight(spline, point, u);
758
759 madd_v2_v2v2fl(*fp, co, n, weight);
760 fp++;
761 }
762 }
763
764 *r_tot_feather_point = tot;
765
766 return feather;
767}
768
770 MaskSpline *spline, MaskSplinePoint *point, int width, int height, uint *r_tot_feather_point)
771{
772 float *feather, *fp;
773 uint resol = BKE_mask_spline_feather_resolution(spline, width, height);
774
775 feather = fp = MEM_calloc_arrayN<float>(2 * resol, "mask point spline feather diff points");
776
777 for (uint i = 0; i < resol; i++, fp += 2) {
778 float u = float(i % resol) / resol, weight;
779 float co[2], n[2];
780
781 BKE_mask_point_segment_co(spline, point, u, co);
782 BKE_mask_point_normal(spline, point, u, n);
783 weight = BKE_mask_point_weight(spline, point, u);
784
785 fp[0] = co[0] + n[0] * weight;
786 fp[1] = co[1] + n[1] * weight;
787 }
788
789 *r_tot_feather_point = resol;
790
791 return feather;
792}
793
795 MaskSpline *spline, MaskSplinePoint *point, int width, int height, uint *r_tot_diff_point)
796{
797 MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point);
798
799 BezTriple *bezt, *bezt_next;
800 float *diff_points, *fp;
801 int j, resol = BKE_mask_spline_resolution(spline, width, height);
802
803 bezt = &point->bezt;
804 bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point);
805
806 if (!bezt_next) {
807 return nullptr;
808 }
809
810 /* resol+1 because of 'forward_diff_bezier' function */
811 *r_tot_diff_point = resol + 1;
812 diff_points = fp = MEM_calloc_arrayN<float>(2 * (resol + 1), "mask segment vets");
813
814 for (j = 0; j < 2; j++) {
816 bezt->vec[2][j],
817 bezt_next->vec[0][j],
818 bezt_next->vec[1][j],
819 fp + j,
820 resol,
821 sizeof(float[2]));
822 }
823
824 copy_v2_v2(fp + 2 * resol, bezt_next->vec[1]);
825
826 return diff_points;
827}
828
829static void mask_evaluate_apply_point_parent(MaskSplinePoint *point, float ctime)
830{
831 float parent_matrix[3][3];
832 BKE_mask_point_parent_matrix_get(point, ctime, parent_matrix);
833 mul_m3_v2(parent_matrix, point->bezt.vec[0]);
834 mul_m3_v2(parent_matrix, point->bezt.vec[1]);
835 mul_m3_v2(parent_matrix, point->bezt.vec[2]);
836}
837
838void BKE_mask_layer_evaluate_animation(MaskLayer *masklay, const float ctime)
839{
840 /* animation if available */
841 MaskLayerShape *masklay_shape_a;
842 MaskLayerShape *masklay_shape_b;
844 masklay, ctime, &masklay_shape_a, &masklay_shape_b);
845 if (found) {
846 if (found == 1) {
847#if 0
848 printf("%s: exact %d %d (%d)\n",
849 __func__,
850 int(ctime),
852 masklay_shape_a->frame);
853#endif
854 BKE_mask_layer_shape_to_mask(masklay, masklay_shape_a);
855 }
856 else if (found == 2) {
857 float w = masklay_shape_b->frame - masklay_shape_a->frame;
858#if 0
859 printf("%s: tween %d %d (%d %d)\n",
860 __func__,
861 int(ctime),
863 masklay_shape_a->frame,
864 masklay_shape_b->frame);
865#endif
867 masklay, masklay_shape_a, masklay_shape_b, (ctime - masklay_shape_a->frame) / w);
868 }
869 else {
870 /* always fail, should never happen */
871 BLI_assert(found == 2);
872 }
873 }
874}
875
876void BKE_mask_layer_evaluate_deform(MaskLayer *masklay, const float ctime)
877{
879 LISTBASE_FOREACH (MaskSpline *, spline, &masklay->splines) {
880 bool need_handle_recalc = false;
882 for (int i = 0; i < spline->tot_point; i++) {
883 MaskSplinePoint *point = &spline->points[i];
884 MaskSplinePoint *point_deform = &spline->points_deform[i];
885 BKE_mask_point_free(point_deform);
886 *point_deform = *point;
887 point_deform->uw = point->uw ? static_cast<MaskSplinePointUW *>(MEM_dupallocN(point->uw)) :
888 nullptr;
889 mask_evaluate_apply_point_parent(point_deform, ctime);
890 if (ELEM(point->bezt.h1, HD_AUTO, HD_VECT)) {
891 need_handle_recalc = true;
892 }
893 }
894 /* if the spline has auto or vector handles, these need to be
895 * recalculated after deformation.
896 */
897 if (need_handle_recalc) {
898 for (int i = 0; i < spline->tot_point; i++) {
899 MaskSplinePoint *point_deform = &spline->points_deform[i];
900 if (ELEM(point_deform->bezt.h1, HD_AUTO, HD_VECT)) {
901 BKE_mask_calc_handle_point(spline, point_deform);
902 }
903 }
904 }
905 /* end extra calc handles loop */
906 }
907}
908
910{
911 float ctime = DEG_get_ctime(depsgraph);
912 DEG_debug_print_eval(depsgraph, __func__, mask->id.name, mask);
913 LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
914 BKE_mask_layer_evaluate_animation(mask_layer, ctime);
915 }
916 mask->runtime.last_update = DEG_get_update_count(depsgraph);
917}
918
920{
921 const bool is_depsgraph_active = DEG_is_active(depsgraph);
922 float ctime = DEG_get_ctime(depsgraph);
923 DEG_debug_print_eval(depsgraph, __func__, mask->id.name, mask);
924 LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
925 BKE_mask_layer_evaluate_deform(mask_layer, ctime);
926 }
927
928 if (is_depsgraph_active) {
929 Mask *mask_orig = DEG_get_original(mask);
930 for (MaskLayer *masklay_orig = static_cast<MaskLayer *>(mask_orig->masklayers.first),
931 *masklay_eval = static_cast<MaskLayer *>(mask->masklayers.first);
932 masklay_orig != nullptr;
933 masklay_orig = masklay_orig->next, masklay_eval = masklay_eval->next)
934 {
935 for (MaskSpline *spline_orig = static_cast<MaskSpline *>(masklay_orig->splines.first),
936 *spline_eval = static_cast<MaskSpline *>(masklay_eval->splines.first);
937 spline_orig != nullptr;
938 spline_orig = spline_orig->next, spline_eval = spline_eval->next)
939 {
940 for (int i = 0; i < spline_eval->tot_point; i++) {
941 MaskSplinePoint *point_eval = &spline_eval->points[i];
942 MaskSplinePoint *point_orig = &spline_orig->points[i];
943 point_orig->bezt = point_eval->bezt;
944 }
945 }
946 }
947 }
948 mask->runtime.last_update = DEG_get_update_count(depsgraph);
949}
void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride)
Definition curve.cc:1669
void BKE_mask_layer_shape_to_mask(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape)
struct MaskSplinePoint * BKE_mask_spline_point_array_from_point(struct MaskSpline *spline, const struct MaskSplinePoint *point_ref)
void BKE_mask_layer_shape_to_mask_interp(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape_a, struct MaskLayerShape *masklay_shape_b, float fac)
void BKE_mask_calc_handle_point(struct MaskSpline *spline, struct MaskSplinePoint *point)
void BKE_mask_point_free(struct MaskSplinePoint *point)
int BKE_mask_layer_shape_find_frame_range(struct MaskLayer *masklay, float frame, struct MaskLayerShape **r_masklay_shape_a, struct MaskLayerShape **r_masklay_shape_b)
struct BezTriple * BKE_mask_spline_point_next_bezt(struct MaskSpline *spline, struct MaskSplinePoint *points_array, struct MaskSplinePoint *point)
void BKE_mask_spline_ensure_deform(struct MaskSpline *spline)
float BKE_mask_point_weight(struct MaskSpline *spline, struct MaskSplinePoint *point, float u)
float BKE_mask_point_weight_scalar(struct MaskSpline *spline, struct MaskSplinePoint *point, float u)
void BKE_mask_layer_calc_handles(struct MaskLayer *masklay)
void BKE_mask_point_parent_matrix_get(struct MaskSplinePoint *point, float ctime, float parent_matrix[3][3])
void BKE_mask_point_normal(struct MaskSpline *spline, struct MaskSplinePoint *point, float u, float n[2])
void BKE_mask_point_segment_co(struct MaskSpline *spline, struct MaskSplinePoint *point, float u, float co[2])
#define MASK_RESOL_MAX
Definition BKE_mask.h:329
struct MaskSplinePoint * BKE_mask_spline_point_array(struct MaskSpline *spline)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
bool isect_seg_seg_v2_simple(const float v1[2], const float v2[2], const float v3[2], const float v4[2])
int isect_seg_seg_v2_point(const float v0[2], const float v1[2], const float v2[2], const float v3[2], float r_vi[2])
void mul_m3_v2(const float m[3][3], float r[2])
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v2_v2v2fl(float r[2], const float a[2], const float b[2], float f)
MINLINE float len_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void copy_v2_v2(float r[2], const float a[2])
void dist_ensure_v2_v2fl(float v1[2], const float v2[2], float dist)
void minmax_v2v2_v2(float min[2], float max[2], const float vec[2])
MINLINE void add_v2_v2(float r[2], const float a[2])
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE float normalize_v2(float n[2])
unsigned int uint
#define INIT_MINMAX2(min, max)
#define ELEM(...)
uint64_t DEG_get_update_count(const Depsgraph *depsgraph)
Definition depsgraph.cc:355
bool DEG_is_active(const Depsgraph *depsgraph)
Definition depsgraph.cc:323
void DEG_debug_print_eval(Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address)
float DEG_get_ctime(const Depsgraph *graph)
T * DEG_get_original(T *id)
@ HD_VECT
@ HD_AUTO
@ MASK_SPLINE_CYCLIC
@ MASK_SPLINE_NOINTERSECT
@ MASK_SPLINE_OFFSET_SMOOTH
@ MASK_SPLINE_OFFSET_EVEN
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
BPy_StructRNA * depsgraph
void jump(const btVector3 &v=btVector3(0, 0, 0))
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
nullptr float
#define printf(...)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static void feather_bucket_get_diagonal(FeatherEdgesBucket *buckets, int start_bucket_index, int end_bucket_index, int buckets_per_side, FeatherEdgesBucket **r_diagonal_bucket_a, FeatherEdgesBucket **r_diagonal_bucket_b)
float(* BKE_mask_spline_feather_points(MaskSpline *spline, int *r_tot_feather_point))[2]
int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height)
void BKE_mask_layer_evaluate_animation(MaskLayer *masklay, const float ctime)
static float(* mask_spline_feather_differentiated_points_with_resolution__even(MaskSpline *spline, const uint resol, const bool do_feather_isect, uint *r_tot_feather_point))[2]
static void mask_evaluate_apply_point_parent(MaskSplinePoint *point, float ctime)
int BKE_mask_spline_differentiate_calc_total(const MaskSpline *spline, const uint resol)
void BKE_mask_spline_feather_collapse_inner_loops(MaskSpline *spline, float(*feather_points)[2], const uint tot_feather_point)
void BKE_mask_eval_animation(Depsgraph *depsgraph, Mask *mask)
float(* BKE_mask_spline_feather_differentiated_points_with_resolution(MaskSpline *spline, const uint resol, const bool do_feather_isect, uint *r_tot_feather_point))[2]
float(* BKE_mask_spline_differentiate(MaskSpline *spline, int width, int height, uint *r_tot_diff_point))[2]
static void feather_bucket_check_intersect(float(*feather_points)[2], int tot_feather_point, FeatherEdgesBucket *bucket, int cur_a, int cur_b)
#define BUCKET_INDEX(co)
void BKE_mask_layer_evaluate_deform(MaskLayer *masklay, const float ctime)
float(* BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline, const uint resol, uint *r_tot_diff_point))[2]
static float(* mask_spline_feather_differentiated_points_with_resolution__double(MaskSpline *spline, const uint resol, const bool do_feather_isect, uint *r_tot_feather_point))[2]
uint BKE_mask_spline_feather_resolution(MaskSpline *spline, int width, int height)
void BKE_mask_eval_update(Depsgraph *depsgraph, Mask *mask)
static void feather_bucket_add_edge(FeatherEdgesBucket *bucket, int start, int end)
static int feather_bucket_index_from_coord(const float co[2], const float min[2], const float bucket_scale[2], const int buckets_per_side)
float * BKE_mask_point_segment_diff(MaskSpline *spline, MaskSplinePoint *point, int width, int height, uint *r_tot_diff_point)
float * BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint *point, int width, int height, uint *r_tot_feather_point)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
static ulong * next
#define fabsf
#define min(a, b)
Definition sort.cc:36
float vec[3][3]
void * first
struct MaskLayer * next
ListBase splines_shapes
ListBase splines
MaskSplinePointUW * uw
MaskSplinePoint * points_deform
struct MaskSpline * next
MaskSplinePoint * points
ListBase masklayers
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
uint len