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