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