From 47769b5f402503d602e532b9c4dfb89173e5fc06 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 30 Apr 2017 00:01:16 +1000 Subject: Curve Fitting: minor change to re-fitting method Avoid calculating a new split-index when re-fitting. While checking if a knot can be removed, the index with the highest error can be used as a candidate to replace the knot (in the case it can't be removed). --- extern/curve_fit_nd/curve_fit_nd.h | 10 +-- extern/curve_fit_nd/intern/curve_fit_cubic.c | 17 +++--- extern/curve_fit_nd/intern/curve_fit_cubic_refit.c | 71 +++++++++++++++++++--- source/blender/editors/curve/editcurve.c | 3 +- 4 files changed, 80 insertions(+), 21 deletions(-) diff --git a/extern/curve_fit_nd/curve_fit_nd.h b/extern/curve_fit_nd/curve_fit_nd.h index 7232f802e28..18244799b0f 100644 --- a/extern/curve_fit_nd/curve_fit_nd.h +++ b/extern/curve_fit_nd/curve_fit_nd.h @@ -36,7 +36,7 @@ /* curve_fit_cubic.c */ /** - * Takes a flat array of points and evalues that to calculate a bezier spline. + * Takes a flat array of points and evaluates that to calculate a bezier spline. * * \param points, points_len: The array of points to calculate a cubics from. * \param dims: The number of dimensions for for each element in \a points. @@ -82,7 +82,7 @@ int curve_fit_cubic_to_points_fl( unsigned int **r_corners_index_array, unsigned int *r_corners_index_len); /** - * Takes a flat array of points and evalues that to calculate handle lengths. + * Takes a flat array of points and evaluates that to calculate handle lengths. * * \param points, points_len: The array of points to calculate a cubics from. * \param dims: The number of dimensions for for each element in \a points. @@ -107,7 +107,8 @@ int curve_fit_cubic_to_points_single_db( double r_handle_l[], double r_handle_r[], - double *r_error_sq); + double *r_error_sq, + unsigned int *r_error_index); int curve_fit_cubic_to_points_single_fl( const float *points, @@ -120,7 +121,8 @@ int curve_fit_cubic_to_points_single_fl( float r_handle_l[], float r_handle_r[], - float *r_error_sq); + float *r_error_sq, + unsigned int *r_error_index); enum { CURVE_FIT_CALC_HIGH_QUALIY = (1 << 0), diff --git a/extern/curve_fit_nd/intern/curve_fit_cubic.c b/extern/curve_fit_nd/intern/curve_fit_cubic.c index 0a32f1e796a..ed855d34b08 100644 --- a/extern/curve_fit_nd/intern/curve_fit_cubic.c +++ b/extern/curve_fit_nd/intern/curve_fit_cubic.c @@ -554,8 +554,8 @@ static void cubic_from_points_fallback( r_cubic->orig_span = (points_offset_len - 1); #endif - /* p1 = p0 - (tan_l * alpha_l); - * p2 = p3 + (tan_r * alpha_r); + /* p1 = p0 - (tan_l * alpha); + * p2 = p3 + (tan_r * alpha); */ msub_vn_vnvn_fl(p1, p0, tan_l, alpha, dims); madd_vn_vnvn_fl(p2, p3, tan_r, alpha, dims); @@ -1436,12 +1436,11 @@ int curve_fit_cubic_to_points_single_db( double r_handle_l[], double r_handle_r[], - double *r_error_max_sq) + double *r_error_max_sq, + uint *r_error_index) { Cubic *cubic = alloca(cubic_alloc_size(dims)); - uint split_index; - /* in this instance theres no advantage in using length cache, * since we're not recursively calculating values. */ #ifdef USE_LENGTH_CACHE @@ -1462,7 +1461,7 @@ int curve_fit_cubic_to_points_single_db( #endif tan_l, tan_r, error_threshold, dims, - cubic, r_error_max_sq, &split_index); + cubic, r_error_max_sq, r_error_index); #ifdef USE_LENGTH_CACHE if (points_length_cache_alloc) { @@ -1487,7 +1486,8 @@ int curve_fit_cubic_to_points_single_fl( float r_handle_l[], float r_handle_r[], - float *r_error_sq) + float *r_error_sq, + uint *r_error_index) { const uint points_flat_len = points_len * dims; double *points_db = malloc(sizeof(double) * points_flat_len); @@ -1521,7 +1521,8 @@ int curve_fit_cubic_to_points_single_fl( (double)error_threshold, tan_l_db, tan_r_db, r_handle_l_db, r_handle_r_db, - &r_error_sq_db); + &r_error_sq_db, + r_error_index); free(points_db); diff --git a/extern/curve_fit_nd/intern/curve_fit_cubic_refit.c b/extern/curve_fit_nd/intern/curve_fit_cubic_refit.c index bf1ab99995f..96ec9a33270 100644 --- a/extern/curve_fit_nd/intern/curve_fit_cubic_refit.c +++ b/extern/curve_fit_nd/intern/curve_fit_cubic_refit.c @@ -207,7 +207,7 @@ struct KnotCornerState { /* Utility functions */ -#ifdef USE_KNOT_REFIT +#if defined(USE_KNOT_REFIT) && !defined(USE_KNOT_REFIT_REMOVE) /** * Find the most distant point between the 2 knots. */ @@ -269,7 +269,7 @@ static uint knot_find_split_point( return split_point; } -#endif /* USE_KNOT_REFIT */ +#endif /* USE_KNOT_REFIT && !USE_KNOT_REFIT_REMOVE */ #ifdef USE_CORNER_DETECT @@ -322,7 +322,7 @@ static double knot_remove_error_value( const double *points_offset_length_cache, const uint dims, /* Avoid having to re-calculate again */ - double r_handle_factors[2]) + double r_handle_factors[2], uint *r_error_index) { double error_sq = FLT_MAX; @@ -338,7 +338,7 @@ static double knot_remove_error_value( points_offset, points_offset_len, points_offset_length_cache, dims, 0.0, tan_l, tan_r, handle_factor_l, handle_factor_r, - &error_sq); + &error_sq, r_error_index); assert(error_sq != FLT_MAX); @@ -363,6 +363,7 @@ static double knot_calc_curve_error_value( ((knot_r->index + pd->points_len) - knot_l->index)) + 1; if (points_offset_len != 2) { + uint error_index_dummy; return knot_remove_error_value( tan_l, tan_r, &pd->points[knot_l->index * dims], points_offset_len, @@ -372,7 +373,55 @@ static double knot_calc_curve_error_value( NULL, #endif dims, - r_handle_factors); + r_handle_factors, &error_index_dummy); + } + else { + /* No points between, use 1/3 handle length with no error as a fallback. */ + assert(points_offset_len == 2); +#ifdef USE_LENGTH_CACHE + r_handle_factors[0] = r_handle_factors[1] = pd->points_length_cache[knot_l->index] / 3.0; +#else + r_handle_factors[0] = r_handle_factors[1] = len_vnvn( + &pd->points[(knot_l->index + 0) * dims], + &pd->points[(knot_l->index + 1) * dims], dims) / 3.0; +#endif + return 0.0; + } +} + +#ifdef USE_KNOT_REFIT_REMOVE + +static double knot_calc_curve_error_value_and_index( + const struct PointData *pd, + const struct Knot *knot_l, const struct Knot *knot_r, + const double *tan_l, const double *tan_r, + const uint dims, + double r_handle_factors[2], + uint *r_error_index) +{ + const uint points_offset_len = ((knot_l->index < knot_r->index) ? + (knot_r->index - knot_l->index) : + ((knot_r->index + pd->points_len) - knot_l->index)) + 1; + + if (points_offset_len != 2) { + const double error_sq = knot_remove_error_value( + tan_l, tan_r, + &pd->points[knot_l->index * dims], points_offset_len, +#ifdef USE_LENGTH_CACHE + &pd->points_length_cache[knot_l->index], +#else + NULL, +#endif + dims, + r_handle_factors, r_error_index); + + /* Adjust the offset index to the global index & wrap if needed. */ + *r_error_index += knot_l->index; + if (*r_error_index >= pd->points_len) { + *r_error_index -= pd->points_len; + } + + return error_sq; } else { /* No points between, use 1/3 handle length with no error as a fallback. */ @@ -384,9 +433,11 @@ static double knot_calc_curve_error_value( &pd->points[(knot_l->index + 0) * dims], &pd->points[(knot_l->index + 1) * dims], dims) / 3.0; #endif + *r_error_index = 0; return 0.0; } } +#endif /* USE_KNOT_REFIT_REMOVE */ struct KnotRemove_Params { Heap *heap; @@ -556,15 +607,18 @@ static void knot_refit_error_recalculate( assert(k->can_remove); #ifdef USE_KNOT_REFIT_REMOVE + (void)knots_len; + + uint refit_index = SPLIT_POINT_INVALID; { double handles[2]; /* First check if we can remove, this allows to refit and remove as we go. */ - const double cost_sq = knot_calc_curve_error_value( + const double cost_sq = knot_calc_curve_error_value_and_index( p->pd, k->prev, k->next, k->prev->tan[1], k->next->tan[0], dims, - handles); + handles, &refit_index); if (cost_sq < error_sq_max) { struct KnotRefitState *r; @@ -598,13 +652,14 @@ static void knot_refit_error_recalculate( } #else (void)error_sq_max; -#endif /* USE_KNOT_REFIT_REMOVE */ const uint refit_index = knot_find_split_point( p->pd, k->prev, k->next, knots_len, dims); +#endif /* USE_KNOT_REFIT_REMOVE */ + if ((refit_index == SPLIT_POINT_INVALID) || (refit_index == k->index)) { diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 648fe930030..a69264cd012 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -5850,6 +5850,7 @@ static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op)) BLI_assert(points_stride + dims == points + (points_len * dims)); float tan_l[3], tan_r[3], error_sq_dummy; + unsigned int error_index_dummy; sub_v3_v3v3(tan_l, bezt_prev->vec[1], bezt_prev->vec[2]); normalize_v3(tan_l); @@ -5860,7 +5861,7 @@ static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op)) points, points_len, NULL, dims, FLT_EPSILON, tan_l, tan_r, bezt_prev->vec[2], bezt_next->vec[0], - &error_sq_dummy); + &error_sq_dummy, &error_index_dummy); if (!ELEM(bezt_prev->h2, HD_FREE, HD_ALIGN)) { bezt_prev->h2 = (bezt_prev->h2 == HD_VECT) ? HD_FREE : HD_ALIGN; -- cgit v1.2.3 From a1164eb3ddbdc9ad1c8393bcf125c289cbb0966c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 30 Apr 2017 02:38:38 +1000 Subject: View3D: support both orbit select & depth When using both preferences, use cursor depth when nothings selected. --- source/blender/editors/space_view3d/view3d_edit.c | 36 +++++++++++------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index f712c790663..4e3f279e12e 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -700,22 +700,21 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3]) } enum eViewOpsOrbit { - VIEWOPS_ORBIT_DEFAULT = 0, - VIEWOPS_ORBIT_SELECT = 1, - VIEWOPS_ORBIT_DEPTH = 2, + VIEWOPS_ORBIT_SELECT = (1 << 0), + VIEWOPS_ORBIT_DEPTH = (1 << 1), }; static enum eViewOpsOrbit viewops_orbit_mode_ex(bool use_select, bool use_depth) { + enum eViewOpsOrbit flag = 0; if (use_select) { - return VIEWOPS_ORBIT_SELECT; + flag |= VIEWOPS_ORBIT_SELECT; } - else if (use_depth) { - return VIEWOPS_ORBIT_DEPTH; - } - else { - return VIEWOPS_ORBIT_DEFAULT; + if (use_depth) { + flag |= VIEWOPS_ORBIT_DEPTH; } + + return flag; } static enum eViewOpsOrbit viewops_orbit_mode(void) @@ -736,7 +735,7 @@ static void viewops_data_create_ex( RegionView3D *rv3d = vod->rv3d; /* we need the depth info before changing any viewport options */ - if (orbit_mode == VIEWOPS_ORBIT_DEPTH) { + if (orbit_mode & VIEWOPS_ORBIT_DEPTH) { float fallback_depth_pt[3]; view3d_operator_needs_opengl(C); /* needed for zbuf drawing */ @@ -775,15 +774,16 @@ static void viewops_data_create_ex( vod->origkey = event->type; /* the key that triggered the operator. */ copy_v3_v3(vod->ofs, rv3d->ofs); - if (orbit_mode == VIEWOPS_ORBIT_SELECT) { - - vod->use_dyn_ofs = true; - - view3d_orbit_calc_center(C, vod->dyn_ofs); - - negate_v3(vod->dyn_ofs); + if (orbit_mode & VIEWOPS_ORBIT_SELECT) { + float ofs[3]; + if (view3d_orbit_calc_center(C, ofs) || (vod->use_dyn_ofs == false)) { + vod->use_dyn_ofs = true; + negate_v3_v3(vod->dyn_ofs, ofs); + orbit_mode &= ~VIEWOPS_ORBIT_DEPTH; + } } - else if (orbit_mode == VIEWOPS_ORBIT_DEPTH) { + + if (orbit_mode & VIEWOPS_ORBIT_DEPTH) { if (vod->use_dyn_ofs) { if (rv3d->is_persp) { float my_origin[3]; /* original G.vd->ofs */ -- cgit v1.2.3 From 0fbce637b3dba02bf1f496d0e902b317793915fc Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 30 Apr 2017 02:58:36 +1000 Subject: Cleanup: comment blocks --- source/blender/editors/gpencil/drawgpencil.c | 18 +++++++++--------- source/blender/editors/gpencil/gpencil_brush.c | 6 +++--- source/blender/editors/gpencil/gpencil_paint.c | 6 +++--- source/blender/editors/gpencil/gpencil_utils.c | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index f091609da49..ecab37c729f 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -528,15 +528,15 @@ static void gp_draw_stroke_fill( } else { /* As an initial implementation, we use the OpenGL filled polygon drawing - * here since it's the easiest option to implement for this case. It does - * come with limitations (notably for concave shapes), though it shouldn't - * be much of an issue in most cases. - * - * We keep this legacy implementation around despite now having the high quality - * fills, as this is necessary for keeping everything working nicely for files - * created using old versions of Blender which may have depended on the artifacts - * the old fills created. - */ + * here since it's the easiest option to implement for this case. It does + * come with limitations (notably for concave shapes), though it shouldn't + * be much of an issue in most cases. + * + * We keep this legacy implementation around despite now having the high quality + * fills, as this is necessary for keeping everything working nicely for files + * created using old versions of Blender which may have depended on the artifacts + * the old fills created. + */ bGPDspoint *pt; glBegin(GL_POLYGON); diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c index ec5a42c23a5..8ddf3a22517 100644 --- a/source/blender/editors/gpencil/gpencil_brush.c +++ b/source/blender/editors/gpencil/gpencil_brush.c @@ -297,9 +297,9 @@ static bool gp_brush_strength_apply( float inf; /* Compute strength of effect - * - We divide the strength by 10, so that users can set "sane" values. - * Otherwise, good default values are in the range of 0.093 - */ + * - We divide the strength by 10, so that users can set "sane" values. + * Otherwise, good default values are in the range of 0.093 + */ inf = gp_brush_influence_calc(gso, radius, co) / 10.0f; /* apply */ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index d6e40377e63..162b9466225 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1005,9 +1005,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) BLI_strncpy(gps->colorname, palcolor->info, sizeof(gps->colorname)); /* add stroke to frame, usually on tail of the listbase, but if on back is enabled the stroke is added on listbase head - * because the drawing order is inverse and the head stroke is the first to draw. This is very useful for artist - * when drawing the background - */ + * because the drawing order is inverse and the head stroke is the first to draw. This is very useful for artist + * when drawing the background + */ if ((ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK) && (p->paintmode != GP_PAINTMODE_DRAW_POLY)) { BLI_addhead(&p->gpf->strokes, gps); } diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 76e85f20c36..2b662d04f03 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -830,8 +830,8 @@ bool gp_smooth_stroke_strength(bGPDstroke *gps, int i, float inf) ptc = &gps->points[after]; /* the optimal value is the corresponding to the interpolation of the strength - * at the distance of point b - */ + * at the distance of point b + */ const float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x); const float optimal = (1.0f - fac) * pta->strength + fac * ptc->strength; -- cgit v1.2.3