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