Blender  V2.93
mask_evaluate.c
Go to the documentation of this file.
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 
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 
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 
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 
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 
131  const unsigned int resol,
132  unsigned int *r_tot_diff_point))[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  *r_tot_diff_point = 0;
144  return NULL;
145  }
146 
147  /* len+1 because of 'forward_diff_bezier' function */
148  *r_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 
195  MaskSpline *spline, int width, int height, unsigned int *r_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, resol, r_tot_diff_point);
200 }
201 
202 /* ** feather points self-intersection collapse routine ** */
203 
204 typedef struct FeatherEdgesBucket {
206  int (*segments)[2];
209 
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 
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 
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 
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 
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 
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 
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);
489  feather_points, tot_feather_point, diagonal_bucket_a, cur_a, cur_b);
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 
509  MaskSpline *spline,
510  const unsigned int resol,
511  const bool do_feather_isect,
512  unsigned int *r_tot_feather_point))[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  *r_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 
583  MaskSpline *spline,
584  const unsigned int resol,
585  const bool do_feather_isect,
586  unsigned int *r_tot_feather_point))[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  *r_tot_feather_point = 0;
598  return NULL;
599  }
600 
601  /* len+1 because of 'forward_diff_bezier' function */
602  *r_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 change 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 
728  MaskSpline *spline,
729  const unsigned int resol,
730  const bool do_feather_isect,
731  unsigned int *r_tot_feather_point))[2]
732 {
733  switch (spline->offset_mode) {
736  spline, resol, do_feather_isect, r_tot_feather_point);
738  default:
740  spline, resol, do_feather_isect, r_tot_feather_point);
741  }
742 }
743 
744 float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *r_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  *r_tot_feather_point = tot;
787 
788  return feather;
789 }
790 
791 /* *** mask point functions which involve evaluation *** */
793  MaskSplinePoint *point,
794  int width,
795  int height,
796  unsigned int *r_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  *r_tot_feather_point = resol;
816 
817  return feather;
818 }
819 
821  MaskSplinePoint *point,
822  int width,
823  int height,
824  unsigned int *r_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  *r_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++) {
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 
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 
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;
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,
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,
892  masklay_shape_a->frame,
893  masklay_shape_b->frame);
894 #endif
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 
905 void BKE_mask_layer_evaluate_deform(MaskLayer *masklay, const float ctime)
906 {
908  for (MaskSpline *spline = masklay->splines.first; spline != NULL; spline = spline->next) {
909  bool need_handle_recalc = false;
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 
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 
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 }
typedef float(TangentPoint)[2]
void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride)
Definition: curve.c:1804
void BKE_mask_layer_shape_to_mask(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape)
Definition: mask.c:1669
int BKE_mask_layer_shape_find_frame_range(struct MaskLayer *masklay, const float frame, struct MaskLayerShape **r_masklay_shape_a, struct MaskLayerShape **r_masklay_shape_b)
Definition: mask.c:1764
void BKE_mask_calc_handle_point(struct MaskSpline *spline, struct MaskSplinePoint *point)
Definition: mask.c:1462
void BKE_mask_layer_shape_to_mask_interp(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape_a, struct MaskLayerShape *masklay_shape_b, const float fac)
Definition: mask.c:1701
void BKE_mask_point_free(struct MaskSplinePoint *point)
Definition: mask.c:1061
void BKE_mask_spline_ensure_deform(struct MaskSpline *spline)
Definition: mask.c:1560
void BKE_mask_layer_calc_handles(struct MaskLayer *masklay)
Definition: mask.c:1550
struct MaskSplinePoint * BKE_mask_spline_point_array_from_point(struct MaskSpline *spline, const struct MaskSplinePoint *point_ref)
void BKE_mask_point_parent_matrix_get(struct MaskSplinePoint *point, float ctime, float parent_matrix[3][3])
Definition: mask.c:1297
void BKE_mask_point_normal(struct MaskSpline *spline, struct MaskSplinePoint *point, float u, float n[2])
Definition: mask.c:795
void BKE_mask_point_segment_co(struct MaskSpline *spline, struct MaskSplinePoint *point, float u, float co[2])
Definition: mask.c:767
struct MaskSplinePoint * BKE_mask_spline_point_array(struct MaskSpline *spline)
Definition: mask.c:328
#define MASK_RESOL_MAX
Definition: BKE_mask.h:263
float BKE_mask_point_weight_scalar(struct MaskSpline *spline, struct MaskSplinePoint *point, const float u)
Definition: mask.c:853
struct BezTriple * BKE_mask_spline_point_next_bezt(struct MaskSpline *spline, struct MaskSplinePoint *points_array, struct MaskSplinePoint *point)
Definition: mask.c:313
float BKE_mask_point_weight(struct MaskSpline *spline, struct MaskSplinePoint *point, const float u)
Definition: mask.c:873
#define BLI_assert(a)
Definition: BLI_assert.h:58
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])
Definition: math_geom.c:1360
int isect_seg_seg_v2_point(const float v0[2], const float v1[2], const float v2[2], const float v3[2], float vi[2])
Definition: math_geom.c:1353
void mul_m3_v2(const float m[3][3], float r[2])
Definition: math_matrix.c:727
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 void mul_v2_fl(float r[2], float f)
MINLINE void copy_v2_v2(float r[2], const float a[2])
void minmax_v2v2_v2(float min[2], float max[2], const float vec[2])
Definition: math_vector.c:1043
MINLINE void add_v2_v2(float r[2], const float a[2])
void dist_ensure_v2_v2fl(float v1[2], const float v2[2], const float dist)
Definition: math_vector.c:1079
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE float len_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v2(float r[2])
unsigned int uint
Definition: BLI_sys_types.h:83
#define INIT_MINMAX2(min, max)
#define CLAMPIS(a, b, c)
#define MAX2(a, b)
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
bool DEG_is_active(const struct Depsgraph *depsgraph)
Definition: depsgraph.cc:331
void DEG_debug_print_eval(struct Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address)
float DEG_get_ctime(const Depsgraph *graph)
struct ID * DEG_get_original_id(struct 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.
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
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
const Depsgraph * depsgraph
#define fabsf(x)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:42
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
float(* BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline, const unsigned int resol, unsigned int *r_tot_diff_point))[2]
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)
static float(* mask_spline_feather_differentiated_points_with_resolution__double(MaskSpline *spline, const unsigned int resol, const bool do_feather_isect, unsigned int *r_tot_feather_point))[2]
float(* BKE_mask_spline_feather_points(MaskSpline *spline, int *r_tot_feather_point))[2]
void BKE_mask_layer_evaluate_animation(MaskLayer *masklay, const float ctime)
int BKE_mask_spline_differentiate_calc_total(const MaskSpline *spline, const unsigned int resol)
void BKE_mask_eval_update(struct Depsgraph *depsgraph, Mask *mask)
static void mask_evaluate_apply_point_parent(MaskSplinePoint *point, float ctime)
float * BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint *point, int width, int height, unsigned int *r_tot_feather_point)
unsigned int BKE_mask_spline_feather_resolution(MaskSpline *spline, int width, int height)
Definition: mask_evaluate.c:82
void BKE_mask_spline_feather_collapse_inner_loops(MaskSpline *spline, float(*feather_points)[2], const unsigned int tot_feather_point)
void BKE_mask_eval_animation(struct Depsgraph *depsgraph, Mask *mask)
float(* BKE_mask_spline_differentiate(MaskSpline *spline, int width, int height, unsigned int *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)
float * BKE_mask_point_segment_diff(MaskSpline *spline, MaskSplinePoint *point, int width, int height, unsigned int *r_tot_diff_point)
void BKE_mask_layer_evaluate_deform(MaskLayer *masklay, const float ctime)
struct FeatherEdgesBucket FeatherEdgesBucket
static float(* mask_spline_feather_differentiated_points_with_resolution__even(MaskSpline *spline, const unsigned int resol, const bool do_feather_isect, unsigned int *r_tot_feather_point))[2]
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)
unsigned int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height)
Definition: mask_evaluate.c:43
float(* BKE_mask_spline_feather_differentiated_points_with_resolution(MaskSpline *spline, const unsigned int resol, const bool do_feather_isect, unsigned int *r_tot_feather_point))[2]
static ulong * next
static unsigned c
Definition: RandGen.cpp:97
static unsigned a[3]
Definition: RandGen.cpp:92
#define min(a, b)
Definition: sort.c:51
float vec[3][3]
void * first
Definition: DNA_listBase.h:47
ListBase splines_shapes
ListBase splines
MaskSplinePointUW * uw
MaskSplinePoint * points_deform
struct MaskSpline * next
MaskSplinePoint * points
ListBase masklayers
float max
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
uint len