| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2012 Blender Foundation. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 08:08:12 +11:00
										 |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup bke | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Functions for evaluating the mask beziers into points for the outline and feather. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stddef.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_math.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-19 09:33:03 +01:00
										 |  |  | #include "BLI_utildefines.h"
 | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "DNA_mask_types.h"
 | 
					
						
							| 
									
										
										
										
											2018-04-06 12:07:27 +02:00
										 |  |  | #include "DNA_object_types.h"
 | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "BKE_curve.h"
 | 
					
						
							|  |  |  | #include "BKE_mask.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-14 16:16:14 +05:00
										 |  |  | #include "DEG_depsgraph.h"
 | 
					
						
							| 
									
										
										
										
											2018-04-06 12:07:27 +02:00
										 |  |  | #include "DEG_depsgraph_query.h"
 | 
					
						
							| 
									
										
										
										
											2017-09-14 16:16:14 +05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | unsigned int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float max_segment = 0.01f; | 
					
						
							|  |  |  |   unsigned int i, resol = 1; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (width != 0 && height != 0) { | 
					
						
							|  |  |  |     max_segment = 1.0f / (float)max_ii(width, height); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   for (i = 0; i < spline->tot_point; i++) { | 
					
						
							|  |  |  |     MaskSplinePoint *point = &spline->points[i]; | 
					
						
							|  |  |  |     BezTriple *bezt_curr, *bezt_next; | 
					
						
							|  |  |  |     float a, b, c, len; | 
					
						
							|  |  |  |     unsigned int cur_resol; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     bezt_curr = &point->bezt; | 
					
						
							|  |  |  |     bezt_next = BKE_mask_spline_point_next_bezt(spline, spline->points, point); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     if (bezt_next == NULL) { | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     a = len_v3v3(bezt_curr->vec[1], bezt_curr->vec[2]); | 
					
						
							|  |  |  |     b = len_v3v3(bezt_curr->vec[2], bezt_next->vec[0]); | 
					
						
							|  |  |  |     c = len_v3v3(bezt_next->vec[0], bezt_next->vec[1]); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     len = a + b + c; | 
					
						
							|  |  |  |     cur_resol = len / max_segment; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     resol = MAX2(resol, cur_resol); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     if (resol >= MASK_RESOL_MAX) { | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return CLAMPIS(resol, 1, MASK_RESOL_MAX); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | unsigned int BKE_mask_spline_feather_resolution(MaskSpline *spline, int width, int height) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const float max_segment = 0.005; | 
					
						
							|  |  |  |   unsigned int resol = BKE_mask_spline_resolution(spline, width, height); | 
					
						
							|  |  |  |   float max_jump = 0.0f; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* avoid checking the featrher if we already hit the maximum value */ | 
					
						
							|  |  |  |   if (resol >= MASK_RESOL_MAX) { | 
					
						
							|  |  |  |     return MASK_RESOL_MAX; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-09 16:35:20 +02:00
										 |  |  |   for (int i = 0; i < spline->tot_point; i++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     MaskSplinePoint *point = &spline->points[i]; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-09 16:35:20 +02:00
										 |  |  |     float prev_u = 0.0f; | 
					
						
							|  |  |  |     float prev_w = point->bezt.weight; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-09 16:35:20 +02:00
										 |  |  |     for (int j = 0; j < point->tot_uw; j++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       const float w_diff = (point->uw[j].w - prev_w); | 
					
						
							|  |  |  |       const float u_diff = (point->uw[j].u - prev_u); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       /* avoid divide by zero and very high values,
 | 
					
						
							|  |  |  |        * though these get clamped eventually */ | 
					
						
							|  |  |  |       if (u_diff > FLT_EPSILON) { | 
					
						
							|  |  |  |         float jump = fabsf(w_diff / u_diff); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         max_jump = max_ff(max_jump, jump); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       prev_u = point->uw[j].u; | 
					
						
							|  |  |  |       prev_w = point->uw[j].w; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   resol += max_jump / max_segment; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return CLAMPIS(resol, 1, MASK_RESOL_MAX); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int BKE_mask_spline_differentiate_calc_total(const MaskSpline *spline, const unsigned int resol) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (spline->flag & MASK_SPLINE_CYCLIC) { | 
					
						
							|  |  |  |     return spline->tot_point * resol; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-07 12:30:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return ((spline->tot_point - 1) * resol) + 1; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-20 16:00:05 +06:00
										 |  |  | float (*BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline, | 
					
						
							|  |  |  |                                                       unsigned int *tot_diff_point, | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |                                                       const unsigned int resol))[2] | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   MaskSplinePoint *point_curr, *point_prev; | 
					
						
							|  |  |  |   float(*diff_points)[2], (*fp)[2]; | 
					
						
							|  |  |  |   const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol); | 
					
						
							|  |  |  |   int a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (spline->tot_point <= 1) { | 
					
						
							|  |  |  |     /* nothing to differentiate */ | 
					
						
							|  |  |  |     *tot_diff_point = 0; | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* len+1 because of 'forward_diff_bezier' function */ | 
					
						
							|  |  |  |   *tot_diff_point = tot; | 
					
						
							|  |  |  |   diff_points = fp = MEM_mallocN((tot + 1) * sizeof(*diff_points), "mask spline vets"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   a = spline->tot_point - 1; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (spline->flag & MASK_SPLINE_CYCLIC) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     a++; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   point_prev = points_array; | 
					
						
							|  |  |  |   point_curr = point_prev + 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (a--) { | 
					
						
							|  |  |  |     BezTriple *bezt_prev; | 
					
						
							|  |  |  |     BezTriple *bezt_curr; | 
					
						
							|  |  |  |     int j; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       point_curr = points_array; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     bezt_prev = &point_prev->bezt; | 
					
						
							|  |  |  |     bezt_curr = &point_curr->bezt; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (j = 0; j < 2; j++) { | 
					
						
							|  |  |  |       BKE_curve_forward_diff_bezier(bezt_prev->vec[1][j], | 
					
						
							|  |  |  |                                     bezt_prev->vec[2][j], | 
					
						
							|  |  |  |                                     bezt_curr->vec[0][j], | 
					
						
							|  |  |  |                                     bezt_curr->vec[1][j], | 
					
						
							|  |  |  |                                     &(*fp)[j], | 
					
						
							|  |  |  |                                     resol, | 
					
						
							| 
									
										
										
										
											2020-08-08 13:29:21 +10:00
										 |  |  |                                     sizeof(float[2])); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fp += resol; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) { | 
					
						
							|  |  |  |       copy_v2_v2(*fp, bezt_curr->vec[1]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     point_prev = point_curr; | 
					
						
							|  |  |  |     point_curr++; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return diff_points; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | float (*BKE_mask_spline_differentiate( | 
					
						
							|  |  |  |     MaskSpline *spline, int width, int height, unsigned int *tot_diff_point))[2] | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-02-08 01:02:18 +11:00
										 |  |  |   uint resol = BKE_mask_spline_resolution(spline, width, height); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return BKE_mask_spline_differentiate_with_resolution(spline, tot_diff_point, resol); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ** feather points self-intersection collapse routine ** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct FeatherEdgesBucket { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int tot_segment; | 
					
						
							|  |  |  |   int (*segments)[2]; | 
					
						
							|  |  |  |   int alloc_segment; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | } FeatherEdgesBucket; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void feather_bucket_add_edge(FeatherEdgesBucket *bucket, int start, int end) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const int alloc_delta = 256; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (bucket->tot_segment >= bucket->alloc_segment) { | 
					
						
							|  |  |  |     if (!bucket->segments) { | 
					
						
							|  |  |  |       bucket->segments = MEM_callocN(alloc_delta * sizeof(*bucket->segments), | 
					
						
							|  |  |  |                                      "feather bucket segments"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       bucket->segments = MEM_reallocN( | 
					
						
							|  |  |  |           bucket->segments, (alloc_delta + bucket->tot_segment) * sizeof(*bucket->segments)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     bucket->alloc_segment += alloc_delta; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   bucket->segments[bucket->tot_segment][0] = start; | 
					
						
							|  |  |  |   bucket->segments[bucket->tot_segment][1] = end; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   bucket->tot_segment++; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | static void feather_bucket_check_intersect(float (*feather_points)[2], | 
					
						
							|  |  |  |                                            int tot_feather_point, | 
					
						
							|  |  |  |                                            FeatherEdgesBucket *bucket, | 
					
						
							|  |  |  |                                            int cur_a, | 
					
						
							|  |  |  |                                            int cur_b) | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const float *v1 = (float *)feather_points[cur_a]; | 
					
						
							|  |  |  |   const float *v2 = (float *)feather_points[cur_b]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-09 16:35:20 +02:00
										 |  |  |   for (int i = 0; i < bucket->tot_segment; i++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     int check_a = bucket->segments[i][0]; | 
					
						
							|  |  |  |     int check_b = bucket->segments[i][1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const float *v3 = (float *)feather_points[check_a]; | 
					
						
							|  |  |  |     const float *v4 = (float *)feather_points[check_b]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     if (check_a >= cur_a - 1 || cur_b == check_a) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       continue; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (isect_seg_seg_v2_simple(v1, v2, v3, v4)) { | 
					
						
							|  |  |  |       int k; | 
					
						
							|  |  |  |       float p[2]; | 
					
						
							|  |  |  |       float min_a[2], max_a[2]; | 
					
						
							|  |  |  |       float min_b[2], max_b[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       isect_seg_seg_v2_point(v1, v2, v3, v4, p); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       INIT_MINMAX2(min_a, max_a); | 
					
						
							|  |  |  |       INIT_MINMAX2(min_b, max_b); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* collapse loop with smaller AABB */ | 
					
						
							|  |  |  |       for (k = 0; k < tot_feather_point; k++) { | 
					
						
							|  |  |  |         if (k >= check_b && k <= cur_a) { | 
					
						
							|  |  |  |           minmax_v2v2_v2(min_a, max_a, feather_points[k]); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |           minmax_v2v2_v2(min_b, max_b, feather_points[k]); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       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]) { | 
					
						
							|  |  |  |         for (k = check_b; k <= cur_a; k++) { | 
					
						
							|  |  |  |           copy_v2_v2(feather_points[k], p); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							|  |  |  |         for (k = 0; k <= check_a; k++) { | 
					
						
							|  |  |  |           copy_v2_v2(feather_points[k], p); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (cur_b != 0) { | 
					
						
							|  |  |  |           for (k = cur_b; k < tot_feather_point; k++) { | 
					
						
							|  |  |  |             copy_v2_v2(feather_points[k], p); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 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) | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int x = (int)((co[0] - min[0]) * bucket_scale[0]); | 
					
						
							|  |  |  |   int y = (int)((co[1] - min[1]) * bucket_scale[1]); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (x == buckets_per_side) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     x--; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (y == buckets_per_side) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     y--; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return y * buckets_per_side + x; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 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) | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int start_bucket_x = start_bucket_index % buckets_per_side; | 
					
						
							|  |  |  |   int start_bucket_y = start_bucket_index / buckets_per_side; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int end_bucket_x = end_bucket_index % buckets_per_side; | 
					
						
							|  |  |  |   int end_bucket_y = end_bucket_index / buckets_per_side; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int diagonal_bucket_a_index = start_bucket_y * buckets_per_side + end_bucket_x; | 
					
						
							|  |  |  |   int diagonal_bucket_b_index = end_bucket_y * buckets_per_side + start_bucket_x; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   *r_diagonal_bucket_a = &buckets[diagonal_bucket_a_index]; | 
					
						
							|  |  |  |   *r_diagonal_bucket_b = &buckets[diagonal_bucket_b_index]; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | void BKE_mask_spline_feather_collapse_inner_loops(MaskSpline *spline, | 
					
						
							|  |  |  |                                                   float (*feather_points)[2], | 
					
						
							|  |  |  |                                                   const unsigned int tot_feather_point) | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | #define BUCKET_INDEX(co) feather_bucket_index_from_coord(co, min, bucket_scale, buckets_per_side)
 | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int buckets_per_side, tot_bucket; | 
					
						
							|  |  |  |   float bucket_size, bucket_scale[2]; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   FeatherEdgesBucket *buckets; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float min[2], max[2]; | 
					
						
							|  |  |  |   float max_delta_x = -1.0f, max_delta_y = -1.0f, max_delta; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (tot_feather_point < 4) { | 
					
						
							|  |  |  |     /* self-intersection works only for quads at least,
 | 
					
						
							|  |  |  |      * in other cases polygon can't be self-intersecting anyway | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* find min/max corners of mask to build buckets in that space */ | 
					
						
							|  |  |  |   INIT_MINMAX2(min, max); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-09 16:35:20 +02:00
										 |  |  |   for (uint i = 0; i < tot_feather_point; i++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     unsigned int next = i + 1; | 
					
						
							|  |  |  |     float delta; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     minmax_v2v2_v2(min, max, feather_points[i]); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     if (next == tot_feather_point) { | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       if (spline->flag & MASK_SPLINE_CYCLIC) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         next = 0; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     delta = fabsf(feather_points[i][0] - feather_points[next][0]); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     if (delta > max_delta_x) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       max_delta_x = delta; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     delta = fabsf(feather_points[i][1] - feather_points[next][1]); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     if (delta > max_delta_y) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       max_delta_y = delta; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* prevent divisionsby zero by ensuring bounding box is not collapsed */ | 
					
						
							|  |  |  |   if (max[0] - min[0] < FLT_EPSILON) { | 
					
						
							|  |  |  |     max[0] += 0.01f; | 
					
						
							|  |  |  |     min[0] -= 0.01f; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (max[1] - min[1] < FLT_EPSILON) { | 
					
						
							|  |  |  |     max[1] += 0.01f; | 
					
						
							|  |  |  |     min[1] -= 0.01f; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* use dynamically calculated buckets per side, so we likely wouldn't
 | 
					
						
							|  |  |  |    * run into a situation when segment doesn't fit two buckets which is | 
					
						
							|  |  |  |    * pain collecting candidates for intersection | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   max_delta_x /= max[0] - min[0]; | 
					
						
							|  |  |  |   max_delta_y /= max[1] - min[1]; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   max_delta = MAX2(max_delta_x, max_delta_y); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   buckets_per_side = min_ii(512, 0.9f / max_delta); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (buckets_per_side == 0) { | 
					
						
							|  |  |  |     /* happens when some segment fills the whole bounding box across some of dimension */ | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     buckets_per_side = 1; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   tot_bucket = buckets_per_side * buckets_per_side; | 
					
						
							|  |  |  |   bucket_size = 1.0f / buckets_per_side; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* pre-compute multipliers, to save mathematical operations in loops */ | 
					
						
							|  |  |  |   bucket_scale[0] = 1.0f / ((max[0] - min[0]) * bucket_size); | 
					
						
							|  |  |  |   bucket_scale[1] = 1.0f / ((max[1] - min[1]) * bucket_size); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* fill in buckets' edges */ | 
					
						
							|  |  |  |   buckets = MEM_callocN(sizeof(FeatherEdgesBucket) * tot_bucket, "feather buckets"); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-09 16:35:20 +02:00
										 |  |  |   for (int i = 0; i < tot_feather_point; i++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     int start = i, end = i + 1; | 
					
						
							|  |  |  |     int start_bucket_index, end_bucket_index; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     if (end == tot_feather_point) { | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       if (spline->flag & MASK_SPLINE_CYCLIC) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         end = 0; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     start_bucket_index = BUCKET_INDEX(feather_points[start]); | 
					
						
							|  |  |  |     end_bucket_index = BUCKET_INDEX(feather_points[end]); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     feather_bucket_add_edge(&buckets[start_bucket_index], start, end); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     if (start_bucket_index != end_bucket_index) { | 
					
						
							|  |  |  |       FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index]; | 
					
						
							|  |  |  |       FeatherEdgesBucket *diagonal_bucket_a, *diagonal_bucket_b; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       feather_bucket_get_diagonal(buckets, | 
					
						
							|  |  |  |                                   start_bucket_index, | 
					
						
							|  |  |  |                                   end_bucket_index, | 
					
						
							|  |  |  |                                   buckets_per_side, | 
					
						
							|  |  |  |                                   &diagonal_bucket_a, | 
					
						
							|  |  |  |                                   &diagonal_bucket_b); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       feather_bucket_add_edge(end_bucket, start, end); | 
					
						
							|  |  |  |       feather_bucket_add_edge(diagonal_bucket_a, start, end); | 
					
						
							|  |  |  |       feather_bucket_add_edge(diagonal_bucket_a, start, end); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* check all edges for intersection with edges from their buckets */ | 
					
						
							| 
									
										
										
										
											2020-09-09 16:35:20 +02:00
										 |  |  |   for (int i = 0; i < tot_feather_point; i++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     int cur_a = i, cur_b = i + 1; | 
					
						
							|  |  |  |     int start_bucket_index, end_bucket_index; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     FeatherEdgesBucket *start_bucket; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     if (cur_b == tot_feather_point) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       cur_b = 0; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     start_bucket_index = BUCKET_INDEX(feather_points[cur_a]); | 
					
						
							|  |  |  |     end_bucket_index = BUCKET_INDEX(feather_points[cur_b]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     start_bucket = &buckets[start_bucket_index]; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     feather_bucket_check_intersect(feather_points, tot_feather_point, start_bucket, cur_a, cur_b); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     if (start_bucket_index != end_bucket_index) { | 
					
						
							|  |  |  |       FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index]; | 
					
						
							|  |  |  |       FeatherEdgesBucket *diagonal_bucket_a, *diagonal_bucket_b; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       feather_bucket_get_diagonal(buckets, | 
					
						
							|  |  |  |                                   start_bucket_index, | 
					
						
							|  |  |  |                                   end_bucket_index, | 
					
						
							|  |  |  |                                   buckets_per_side, | 
					
						
							|  |  |  |                                   &diagonal_bucket_a, | 
					
						
							|  |  |  |                                   &diagonal_bucket_b); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       feather_bucket_check_intersect(feather_points, tot_feather_point, end_bucket, cur_a, cur_b); | 
					
						
							|  |  |  |       feather_bucket_check_intersect( | 
					
						
							|  |  |  |           feather_points, tot_feather_point, diagonal_bucket_a, cur_a, cur_b); | 
					
						
							|  |  |  |       feather_bucket_check_intersect( | 
					
						
							|  |  |  |           feather_points, tot_feather_point, diagonal_bucket_b, cur_a, cur_b); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* free buckets */ | 
					
						
							| 
									
										
										
										
											2020-09-09 16:35:20 +02:00
										 |  |  |   for (int i = 0; i < tot_bucket; i++) { | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     if (buckets[i].segments) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       MEM_freeN(buckets[i].segments); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   MEM_freeN(buckets); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #undef BUCKET_INDEX
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-20 16:00:05 +06:00
										 |  |  | /** only called from #BKE_mask_spline_feather_differentiated_points_with_resolution() ! */ | 
					
						
							| 
									
										
										
										
											2014-03-16 03:24:05 +11:00
										 |  |  | static float (*mask_spline_feather_differentiated_points_with_resolution__even( | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     MaskSpline *spline, | 
					
						
							|  |  |  |     unsigned int *tot_feather_point, | 
					
						
							|  |  |  |     const unsigned int resol, | 
					
						
							|  |  |  |     const bool do_feather_isect))[2] | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); | 
					
						
							|  |  |  |   MaskSplinePoint *point_curr, *point_prev; | 
					
						
							|  |  |  |   float(*feather)[2], (*fp)[2]; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol); | 
					
						
							|  |  |  |   int a; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* tot+1 because of 'forward_diff_bezier' function */ | 
					
						
							|  |  |  |   feather = fp = MEM_mallocN((tot + 1) * sizeof(*feather), "mask spline feather diff points"); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   a = spline->tot_point - 1; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (spline->flag & MASK_SPLINE_CYCLIC) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     a++; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   point_prev = points_array; | 
					
						
							|  |  |  |   point_curr = point_prev + 1; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   while (a--) { | 
					
						
							|  |  |  |     /* BezTriple *bezt_prev; */ /* UNUSED */ | 
					
						
							|  |  |  |     /* BezTriple *bezt_curr; */ /* UNUSED */ | 
					
						
							|  |  |  |     int j; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       point_curr = points_array; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     /* bezt_prev = &point_prev->bezt; */ | 
					
						
							|  |  |  |     /* bezt_curr = &point_curr->bezt; */ | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     for (j = 0; j < resol; j++, fp++) { | 
					
						
							|  |  |  |       float u = (float)j / resol, weight; | 
					
						
							|  |  |  |       float co[2], n[2]; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       /* TODO - these calls all calculate similar things
 | 
					
						
							|  |  |  |        * could be unified for some speed */ | 
					
						
							|  |  |  |       BKE_mask_point_segment_co(spline, point_prev, u, co); | 
					
						
							|  |  |  |       BKE_mask_point_normal(spline, point_prev, u, n); | 
					
						
							|  |  |  |       weight = BKE_mask_point_weight(spline, point_prev, u); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       madd_v2_v2v2fl(*fp, co, n, weight); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) { | 
					
						
							|  |  |  |       float u = 1.0f, weight; | 
					
						
							|  |  |  |       float co[2], n[2]; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       BKE_mask_point_segment_co(spline, point_prev, u, co); | 
					
						
							|  |  |  |       BKE_mask_point_normal(spline, point_prev, u, n); | 
					
						
							|  |  |  |       weight = BKE_mask_point_weight(spline, point_prev, u); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       madd_v2_v2v2fl(*fp, co, n, weight); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     point_prev = point_curr; | 
					
						
							|  |  |  |     point_curr++; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   *tot_feather_point = tot; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if ((spline->flag & MASK_SPLINE_NOINTERSECT) && do_feather_isect) { | 
					
						
							|  |  |  |     BKE_mask_spline_feather_collapse_inner_loops(spline, feather, tot); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return feather; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-20 16:00:05 +06:00
										 |  |  | /** only called from #BKE_mask_spline_feather_differentiated_points_with_resolution() ! */ | 
					
						
							| 
									
										
										
										
											2014-03-16 03:24:05 +11:00
										 |  |  | static float (*mask_spline_feather_differentiated_points_with_resolution__double( | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     MaskSpline *spline, | 
					
						
							|  |  |  |     unsigned int *tot_feather_point, | 
					
						
							|  |  |  |     const unsigned int resol, | 
					
						
							|  |  |  |     const bool do_feather_isect))[2] | 
					
						
							| 
									
										
										
										
											2012-08-27 09:44:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   MaskSplinePoint *point_curr, *point_prev; | 
					
						
							|  |  |  |   float(*feather)[2], (*fp)[2]; | 
					
						
							|  |  |  |   const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol); | 
					
						
							|  |  |  |   int a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (spline->tot_point <= 1) { | 
					
						
							|  |  |  |     /* nothing to differentiate */ | 
					
						
							|  |  |  |     *tot_feather_point = 0; | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* len+1 because of 'forward_diff_bezier' function */ | 
					
						
							|  |  |  |   *tot_feather_point = tot; | 
					
						
							|  |  |  |   feather = fp = MEM_mallocN((tot + 1) * sizeof(*feather), "mask spline vets"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   a = spline->tot_point - 1; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (spline->flag & MASK_SPLINE_CYCLIC) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     a++; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   point_prev = points_array; | 
					
						
							|  |  |  |   point_curr = point_prev + 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (a--) { | 
					
						
							|  |  |  |     BezTriple local_prevbezt; | 
					
						
							|  |  |  |     BezTriple local_bezt; | 
					
						
							|  |  |  |     float point_prev_n[2], point_curr_n[2], tvec[2]; | 
					
						
							|  |  |  |     float weight_prev, weight_curr; | 
					
						
							|  |  |  |     float len_base, len_feather, len_scalar; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     BezTriple *bezt_prev; | 
					
						
							|  |  |  |     BezTriple *bezt_curr; | 
					
						
							|  |  |  |     int j; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       point_curr = points_array; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     bezt_prev = &point_prev->bezt; | 
					
						
							|  |  |  |     bezt_curr = &point_curr->bezt; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* modified copy for feather */ | 
					
						
							|  |  |  |     local_prevbezt = *bezt_prev; | 
					
						
							|  |  |  |     local_bezt = *bezt_curr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bezt_prev = &local_prevbezt; | 
					
						
							|  |  |  |     bezt_curr = &local_bezt; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* calc the normals */ | 
					
						
							|  |  |  |     sub_v2_v2v2(tvec, bezt_prev->vec[1], bezt_prev->vec[0]); | 
					
						
							|  |  |  |     normalize_v2(tvec); | 
					
						
							|  |  |  |     point_prev_n[0] = -tvec[1]; | 
					
						
							|  |  |  |     point_prev_n[1] = tvec[0]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sub_v2_v2v2(tvec, bezt_curr->vec[1], bezt_curr->vec[0]); | 
					
						
							|  |  |  |     normalize_v2(tvec); | 
					
						
							|  |  |  |     point_curr_n[0] = -tvec[1]; | 
					
						
							|  |  |  |     point_curr_n[1] = tvec[0]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     weight_prev = bezt_prev->weight; | 
					
						
							|  |  |  |     weight_curr = bezt_curr->weight; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     mul_v2_fl(point_prev_n, weight_prev); | 
					
						
							|  |  |  |     mul_v2_fl(point_curr_n, weight_curr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* before we transform verts */ | 
					
						
							|  |  |  |     len_base = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // add_v2_v2(bezt_prev->vec[0], point_prev_n);  // not needed
 | 
					
						
							|  |  |  |     add_v2_v2(bezt_prev->vec[1], point_prev_n); | 
					
						
							|  |  |  |     add_v2_v2(bezt_prev->vec[2], point_prev_n); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     add_v2_v2(bezt_curr->vec[0], point_curr_n); | 
					
						
							|  |  |  |     add_v2_v2(bezt_curr->vec[1], point_curr_n); | 
					
						
							|  |  |  |     // add_v2_v2(bezt_curr->vec[2], point_curr_n); // not needed
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     len_feather = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* scale by chane in length */ | 
					
						
							|  |  |  |     len_scalar = len_feather / len_base; | 
					
						
							|  |  |  |     dist_ensure_v2_v2fl(bezt_prev->vec[2], | 
					
						
							|  |  |  |                         bezt_prev->vec[1], | 
					
						
							|  |  |  |                         len_scalar * len_v2v2(bezt_prev->vec[2], bezt_prev->vec[1])); | 
					
						
							|  |  |  |     dist_ensure_v2_v2fl(bezt_curr->vec[0], | 
					
						
							|  |  |  |                         bezt_curr->vec[1], | 
					
						
							|  |  |  |                         len_scalar * len_v2v2(bezt_curr->vec[0], bezt_curr->vec[1])); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (j = 0; j < 2; j++) { | 
					
						
							|  |  |  |       BKE_curve_forward_diff_bezier(bezt_prev->vec[1][j], | 
					
						
							|  |  |  |                                     bezt_prev->vec[2][j], | 
					
						
							|  |  |  |                                     bezt_curr->vec[0][j], | 
					
						
							|  |  |  |                                     bezt_curr->vec[1][j], | 
					
						
							|  |  |  |                                     &(*fp)[j], | 
					
						
							|  |  |  |                                     resol, | 
					
						
							| 
									
										
										
										
											2020-08-08 13:29:21 +10:00
										 |  |  |                                     sizeof(float[2])); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* scale by the uw's */ | 
					
						
							|  |  |  |     if (point_prev->tot_uw) { | 
					
						
							|  |  |  |       for (j = 0; j < resol; j++, fp++) { | 
					
						
							|  |  |  |         float u = (float)j / resol; | 
					
						
							|  |  |  |         float weight_uw, weight_scalar; | 
					
						
							|  |  |  |         float co[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* TODO - these calls all calculate similar things
 | 
					
						
							|  |  |  |          * could be unified for some speed */ | 
					
						
							|  |  |  |         BKE_mask_point_segment_co(spline, point_prev, u, co); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         weight_uw = BKE_mask_point_weight(spline, point_prev, u); | 
					
						
							|  |  |  |         weight_scalar = BKE_mask_point_weight_scalar(spline, point_prev, u); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         dist_ensure_v2_v2fl(*fp, co, len_v2v2(*fp, co) * (weight_uw / weight_scalar)); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       fp += resol; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) { | 
					
						
							|  |  |  |       copy_v2_v2(*fp, bezt_curr->vec[1]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     point_prev = point_curr; | 
					
						
							|  |  |  |     point_curr++; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ((spline->flag & MASK_SPLINE_NOINTERSECT) && do_feather_isect) { | 
					
						
							|  |  |  |     BKE_mask_spline_feather_collapse_inner_loops(spline, feather, tot); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return feather; | 
					
						
							| 
									
										
										
										
											2012-08-27 09:44:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2013-12-20 16:00:05 +06:00
										 |  |  |  * values align with #BKE_mask_spline_differentiate_with_resolution | 
					
						
							| 
									
										
										
										
											2012-08-27 09:44:56 +00:00
										 |  |  |  * when \a resol arguments match. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 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))[2] | 
					
						
							| 
									
										
										
										
											2012-08-27 09:44:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   switch (spline->offset_mode) { | 
					
						
							|  |  |  |     case MASK_SPLINE_OFFSET_EVEN: | 
					
						
							|  |  |  |       return mask_spline_feather_differentiated_points_with_resolution__even( | 
					
						
							|  |  |  |           spline, tot_feather_point, resol, do_feather_isect); | 
					
						
							|  |  |  |     case MASK_SPLINE_OFFSET_SMOOTH: | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return mask_spline_feather_differentiated_points_with_resolution__double( | 
					
						
							|  |  |  |           spline, tot_feather_point, resol, do_feather_isect); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-27 09:44:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point))[2] | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int i, tot = 0; | 
					
						
							|  |  |  |   float(*feather)[2], (*fp)[2]; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* count */ | 
					
						
							|  |  |  |   for (i = 0; i < spline->tot_point; i++) { | 
					
						
							|  |  |  |     MaskSplinePoint *point = &points_array[i]; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     tot += point->tot_uw + 1; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* create data */ | 
					
						
							|  |  |  |   feather = fp = MEM_mallocN(tot * sizeof(*feather), "mask spline feather points"); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   for (i = 0; i < spline->tot_point; i++) { | 
					
						
							|  |  |  |     MaskSplinePoint *point = &points_array[i]; | 
					
						
							|  |  |  |     BezTriple *bezt = &point->bezt; | 
					
						
							|  |  |  |     float weight, n[2]; | 
					
						
							|  |  |  |     int j; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     BKE_mask_point_normal(spline, point, 0.0f, n); | 
					
						
							|  |  |  |     weight = BKE_mask_point_weight(spline, point, 0.0f); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     madd_v2_v2v2fl(*fp, bezt->vec[1], n, weight); | 
					
						
							|  |  |  |     fp++; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     for (j = 0; j < point->tot_uw; j++) { | 
					
						
							|  |  |  |       float u = point->uw[j].u; | 
					
						
							|  |  |  |       float co[2]; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       BKE_mask_point_segment_co(spline, point, u, co); | 
					
						
							|  |  |  |       BKE_mask_point_normal(spline, point, u, n); | 
					
						
							|  |  |  |       weight = BKE_mask_point_weight(spline, point, u); | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       madd_v2_v2v2fl(*fp, co, n, weight); | 
					
						
							|  |  |  |       fp++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   *tot_feather_point = tot; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return feather; | 
					
						
							| 
									
										
										
										
											2012-08-26 13:41:40 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2012-08-26 18:09:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* *** mask point functions which involve evaluation *** */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, | 
					
						
							|  |  |  |                                            MaskSplinePoint *point, | 
					
						
							|  |  |  |                                            int width, | 
					
						
							|  |  |  |                                            int height, | 
					
						
							| 
									
										
										
										
											2013-12-20 16:00:05 +06:00
										 |  |  |                                            unsigned int *tot_feather_point) | 
					
						
							| 
									
										
										
										
											2012-08-26 18:09:01 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float *feather, *fp; | 
					
						
							|  |  |  |   unsigned int resol = BKE_mask_spline_feather_resolution(spline, width, height); | 
					
						
							| 
									
										
										
										
											2012-08-26 18:09:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   feather = fp = MEM_callocN(2 * resol * sizeof(float), "mask point spline feather diff points"); | 
					
						
							| 
									
										
										
										
											2012-08-26 18:09:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-09 16:35:20 +02:00
										 |  |  |   for (uint i = 0; i < resol; i++, fp += 2) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     float u = (float)(i % resol) / resol, weight; | 
					
						
							|  |  |  |     float co[2], n[2]; | 
					
						
							| 
									
										
										
										
											2012-08-26 18:09:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     BKE_mask_point_segment_co(spline, point, u, co); | 
					
						
							|  |  |  |     BKE_mask_point_normal(spline, point, u, n); | 
					
						
							|  |  |  |     weight = BKE_mask_point_weight(spline, point, u); | 
					
						
							| 
									
										
										
										
											2012-08-26 18:09:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     fp[0] = co[0] + n[0] * weight; | 
					
						
							|  |  |  |     fp[1] = co[1] + n[1] * weight; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 18:09:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   *tot_feather_point = resol; | 
					
						
							| 
									
										
										
										
											2012-08-26 18:09:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return feather; | 
					
						
							| 
									
										
										
										
											2012-08-26 18:09:01 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | float *BKE_mask_point_segment_diff(MaskSpline *spline, | 
					
						
							|  |  |  |                                    MaskSplinePoint *point, | 
					
						
							|  |  |  |                                    int width, | 
					
						
							|  |  |  |                                    int height, | 
					
						
							|  |  |  |                                    unsigned int *tot_diff_point) | 
					
						
							| 
									
										
										
										
											2012-08-26 18:09:01 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); | 
					
						
							| 
									
										
										
										
											2012-08-26 18:09:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BezTriple *bezt, *bezt_next; | 
					
						
							|  |  |  |   float *diff_points, *fp; | 
					
						
							|  |  |  |   int j, resol = BKE_mask_spline_resolution(spline, width, height); | 
					
						
							| 
									
										
										
										
											2012-08-26 18:09:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   bezt = &point->bezt; | 
					
						
							|  |  |  |   bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point); | 
					
						
							| 
									
										
										
										
											2012-08-26 18:09:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (!bezt_next) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 18:09:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* resol+1 because of 'forward_diff_bezier' function */ | 
					
						
							|  |  |  |   *tot_diff_point = resol + 1; | 
					
						
							| 
									
										
										
										
											2020-08-08 13:29:21 +10:00
										 |  |  |   diff_points = fp = MEM_callocN(sizeof(float[2]) * (resol + 1), "mask segment vets"); | 
					
						
							| 
									
										
										
										
											2012-08-26 18:09:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   for (j = 0; j < 2; j++) { | 
					
						
							|  |  |  |     BKE_curve_forward_diff_bezier(bezt->vec[1][j], | 
					
						
							|  |  |  |                                   bezt->vec[2][j], | 
					
						
							|  |  |  |                                   bezt_next->vec[0][j], | 
					
						
							|  |  |  |                                   bezt_next->vec[1][j], | 
					
						
							|  |  |  |                                   fp + j, | 
					
						
							|  |  |  |                                   resol, | 
					
						
							| 
									
										
										
										
											2020-08-08 13:29:21 +10:00
										 |  |  |                                   sizeof(float[2])); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-08-26 18:09:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   copy_v2_v2(fp + 2 * resol, bezt_next->vec[1]); | 
					
						
							| 
									
										
										
										
											2012-08-26 18:09:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return diff_points; | 
					
						
							| 
									
										
										
										
											2012-08-26 18:09:01 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-09-14 16:09:06 +05:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void mask_evaluate_apply_point_parent(MaskSplinePoint *point, float ctime) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float parent_matrix[3][3]; | 
					
						
							|  |  |  |   BKE_mask_point_parent_matrix_get(point, ctime, parent_matrix); | 
					
						
							|  |  |  |   mul_m3_v2(parent_matrix, point->bezt.vec[0]); | 
					
						
							|  |  |  |   mul_m3_v2(parent_matrix, point->bezt.vec[1]); | 
					
						
							|  |  |  |   mul_m3_v2(parent_matrix, point->bezt.vec[2]); | 
					
						
							| 
									
										
										
										
											2017-09-14 16:09:06 +05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BKE_mask_layer_evaluate_animation(MaskLayer *masklay, const float ctime) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* animation if available */ | 
					
						
							|  |  |  |   MaskLayerShape *masklay_shape_a; | 
					
						
							|  |  |  |   MaskLayerShape *masklay_shape_b; | 
					
						
							|  |  |  |   int found; | 
					
						
							|  |  |  |   if ((found = BKE_mask_layer_shape_find_frame_range( | 
					
						
							|  |  |  |            masklay, ctime, &masklay_shape_a, &masklay_shape_b))) { | 
					
						
							|  |  |  |     if (found == 1) { | 
					
						
							| 
									
										
										
										
											2017-09-14 16:09:06 +05:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       printf("%s: exact %d %d (%d)\n", | 
					
						
							|  |  |  |              __func__, | 
					
						
							|  |  |  |              (int)ctime, | 
					
						
							|  |  |  |              BLI_listbase_count(&masklay->splines_shapes), | 
					
						
							|  |  |  |              masklay_shape_a->frame); | 
					
						
							| 
									
										
										
										
											2017-09-14 16:09:06 +05:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       BKE_mask_layer_shape_to_mask(masklay, masklay_shape_a); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (found == 2) { | 
					
						
							|  |  |  |       float w = masklay_shape_b->frame - masklay_shape_a->frame; | 
					
						
							| 
									
										
										
										
											2017-09-14 16:09:06 +05:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       printf("%s: tween %d %d (%d %d)\n", | 
					
						
							|  |  |  |              __func__, | 
					
						
							|  |  |  |              (int)ctime, | 
					
						
							|  |  |  |              BLI_listbase_count(&masklay->splines_shapes), | 
					
						
							| 
									
										
										
										
											2019-04-17 08:24:14 +02:00
										 |  |  |              masklay_shape_a->frame, | 
					
						
							|  |  |  |              masklay_shape_b->frame); | 
					
						
							| 
									
										
										
										
											2017-09-14 16:09:06 +05:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       BKE_mask_layer_shape_to_mask_interp( | 
					
						
							|  |  |  |           masklay, masklay_shape_a, masklay_shape_b, (ctime - masklay_shape_a->frame) / w); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       /* always fail, should never happen */ | 
					
						
							|  |  |  |       BLI_assert(found == 2); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-09-14 16:09:06 +05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BKE_mask_layer_evaluate_deform(MaskLayer *masklay, const float ctime) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BKE_mask_layer_calc_handles(masklay); | 
					
						
							|  |  |  |   for (MaskSpline *spline = masklay->splines.first; spline != NULL; spline = spline->next) { | 
					
						
							|  |  |  |     bool need_handle_recalc = false; | 
					
						
							|  |  |  |     BKE_mask_spline_ensure_deform(spline); | 
					
						
							|  |  |  |     for (int i = 0; i < spline->tot_point; i++) { | 
					
						
							|  |  |  |       MaskSplinePoint *point = &spline->points[i]; | 
					
						
							|  |  |  |       MaskSplinePoint *point_deform = &spline->points_deform[i]; | 
					
						
							|  |  |  |       BKE_mask_point_free(point_deform); | 
					
						
							|  |  |  |       *point_deform = *point; | 
					
						
							|  |  |  |       point_deform->uw = point->uw ? MEM_dupallocN(point->uw) : NULL; | 
					
						
							|  |  |  |       mask_evaluate_apply_point_parent(point_deform, ctime); | 
					
						
							|  |  |  |       if (ELEM(point->bezt.h1, HD_AUTO, HD_VECT)) { | 
					
						
							|  |  |  |         need_handle_recalc = true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* if the spline has auto or vector handles, these need to be
 | 
					
						
							|  |  |  |      * recalculated after deformation. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (need_handle_recalc) { | 
					
						
							|  |  |  |       for (int i = 0; i < spline->tot_point; i++) { | 
					
						
							|  |  |  |         MaskSplinePoint *point_deform = &spline->points_deform[i]; | 
					
						
							|  |  |  |         if (ELEM(point_deform->bezt.h1, HD_AUTO, HD_VECT)) { | 
					
						
							|  |  |  |           BKE_mask_calc_handle_point(spline, point_deform); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* end extra calc handles loop */ | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-09-14 16:09:06 +05:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-09-14 16:12:01 +05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-06 12:07:27 +02:00
										 |  |  | void BKE_mask_eval_animation(struct Depsgraph *depsgraph, Mask *mask) | 
					
						
							| 
									
										
										
										
											2017-09-14 16:12:01 +05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float ctime = DEG_get_ctime(depsgraph); | 
					
						
							|  |  |  |   DEG_debug_print_eval(depsgraph, __func__, mask->id.name, mask); | 
					
						
							|  |  |  |   for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer != NULL; | 
					
						
							|  |  |  |        mask_layer = mask_layer->next) { | 
					
						
							|  |  |  |     BKE_mask_layer_evaluate_animation(mask_layer, ctime); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-09-14 16:12:01 +05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-06 12:07:27 +02:00
										 |  |  | void BKE_mask_eval_update(struct Depsgraph *depsgraph, Mask *mask) | 
					
						
							| 
									
										
										
										
											2017-09-14 16:12:01 +05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-05-21 17:29:58 +02:00
										 |  |  |   const bool is_depsgraph_active = DEG_is_active(depsgraph); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float ctime = DEG_get_ctime(depsgraph); | 
					
						
							|  |  |  |   DEG_debug_print_eval(depsgraph, __func__, mask->id.name, mask); | 
					
						
							|  |  |  |   for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer != NULL; | 
					
						
							|  |  |  |        mask_layer = mask_layer->next) { | 
					
						
							|  |  |  |     BKE_mask_layer_evaluate_deform(mask_layer, ctime); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-05-21 17:29:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (is_depsgraph_active) { | 
					
						
							|  |  |  |     Mask *mask_orig = (Mask *)DEG_get_original_id(&mask->id); | 
					
						
							|  |  |  |     for (MaskLayer *masklay_orig = mask_orig->masklayers.first, | 
					
						
							|  |  |  |                    *masklay_eval = mask->masklayers.first; | 
					
						
							|  |  |  |          masklay_orig != NULL; | 
					
						
							|  |  |  |          masklay_orig = masklay_orig->next, masklay_eval = masklay_eval->next) { | 
					
						
							|  |  |  |       for (MaskSpline *spline_orig = masklay_orig->splines.first, | 
					
						
							|  |  |  |                       *spline_eval = masklay_eval->splines.first; | 
					
						
							|  |  |  |            spline_orig != NULL; | 
					
						
							|  |  |  |            spline_orig = spline_orig->next, spline_eval = spline_eval->next) { | 
					
						
							|  |  |  |         for (int i = 0; i < spline_eval->tot_point; i++) { | 
					
						
							|  |  |  |           MaskSplinePoint *point_eval = &spline_eval->points[i]; | 
					
						
							|  |  |  |           MaskSplinePoint *point_orig = &spline_orig->points[i]; | 
					
						
							|  |  |  |           point_orig->bezt = point_eval->bezt; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-09-14 16:12:01 +05:00
										 |  |  | } |