[Bf-blender-cvs] [df8deb030b4] smooth-curves: Repeat the curve smoothing pass when clamping handles.

Alexander Gavrilov noreply at git.blender.org
Sat Apr 29 20:59:36 CEST 2017


Commit: df8deb030b4b25dc6fea35664033d151368097a7
Author: Alexander Gavrilov
Date:   Fri Jan 20 18:59:14 2017 +0300
Branches: smooth-curves
https://developer.blender.org/rBdf8deb030b4b25dc6fea35664033d151368097a7

Repeat the curve smoothing pass when clamping handles.

When non-extreme Auto Clamped handles are clamped to prevent
overshoot, it creates a discontinuity with the preceeding part
of the curve that was computed under assumption of no clamping.
Thus to avoid jumps in certain situations it is necessary to
lock these handles and run the smoothing pass again.

Handles are locked in this way only if they are clamped in the
right direction; points that are trying to move against the curve
are clamped to horizontal but left free to be modified by the
subsequent pass.

===================================================================

M	source/blender/blenkernel/BKE_curve.h
M	source/blender/blenkernel/intern/curve.c
M	source/blender/blenkernel/intern/fcurve.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 8f5b91991f4..e11e9830160 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -201,7 +201,7 @@ void BKE_nurb_bpoint_calc_normal(struct Nurb *nu, struct BPoint *bp, float r_nor
 
 void BKE_nurb_handle_calc(struct BezTriple *bezt, struct BezTriple *prev,  struct BezTriple *next,
                           const bool is_fcurve);
-void BKE_nurb_handle_calc_smooth(struct BezTriple *first, int count);
+bool BKE_nurb_handle_calc_smooth(struct BezTriple *first, int count);
 void BKE_nurb_handle_calc_simple(struct Nurb *nu, struct BezTriple *bezt);
 void BKE_nurb_handle_calc_simple_auto(struct Nurb *nu, struct BezTriple *bezt);
 
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 0d18b86fcba..5ef2350c1e5 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -3451,7 +3451,7 @@ static void calchandlesNurb_intern(Nurb *nu, bool skip_align)
  * 
  *
  */
-void BKE_nurb_handle_calc_smooth(BezTriple *first, int count)
+bool BKE_nurb_handle_calc_smooth(BezTriple *first, int count)
 {
 	static int mod3[3] = { 1, 2, 0 };
 	float *pl;
@@ -3465,9 +3465,10 @@ void BKE_nurb_handle_calc_smooth(BezTriple *first, int count)
 	float sign, dy, f;
 	BezTriple *bezt, *prev, *next;
 	int i, j, n, n1, n2, maxpoints;
+	bool final = true;
 
 	if (count < 3)
-		return;
+		return final;
 
 	pl = (float *)MEM_mallocN(sizeof(float)*count, "ha_prod_lamba");
 	l = (float *)MEM_mallocN(sizeof(float)*count, "ha_lamba");
@@ -3537,21 +3538,31 @@ void BKE_nurb_handle_calc_smooth(BezTriple *first, int count)
 		dy = h[n1];
 		if (bezt->h1 == HD_AUTO_ANIM || bezt->h2 == HD_AUTO_ANIM) {
 			/* avoid overshoot */
+			bool hard_clamped = false;
 			if (dy > 0.f) {
 				if (dy > (f = (next->vec[1][1]-y[i]))) {
 					dy = (f < 0.f) ? 0.f : f;
+					hard_clamped = hard_clamped || f >= 0.f;
 				}
 				if (dy > (f=l[i+1]*(y[i]-prev->vec[1][1]))) {
 					dy = (f < 0.f) ? 0.f : f;
+					hard_clamped = hard_clamped || f >= 0.f;
 				}
 			} else {
 				if (dy < (f = (next->vec[1][1]-y[i]))) {
 					dy = (f > 0.f) ? 0.f : f;
+					hard_clamped = hard_clamped || f <= 0.f;
 				}
 				if (dy < (f = l[i+1]*(y[i]-prev->vec[1][1]))) {
 					dy = (f > 0.f) ? 0.f : f;
+					hard_clamped = hard_clamped || f <= 0.f;
 				}
 			}
+			/* if clamping will result in a discontinuity, redo is required */
+			if (hard_clamped) {
+				bezt->f5 = HD_AUTOTYPE_SPECIAL;
+				final = false;
+			}
 		}
 		bezt->vec[2][1] = y[i]+dy;
 		bezt->vec[0][1] = y[i]-dy/l[i+1];
@@ -3564,6 +3575,7 @@ void BKE_nurb_handle_calc_smooth(BezTriple *first, int count)
 	MEM_freeN(a);
 	MEM_freeN(b);
 	MEM_freeN(y);
+	return final;
 }
 
 
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index f84153c6934..4453b98495e 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -887,7 +887,7 @@ void fcurve_store_samples(FCurve *fcu, void *data, int start, int end, FcuSample
  */
 void calchandles_fcurve(FCurve *fcu)
 {
-	BezTriple *bezt, *prev, *next, *first;
+	BezTriple *bezt, *prev, *next, *first, *last;
 	int a = fcu->totvert;
 	int count;
 
@@ -934,12 +934,12 @@ void calchandles_fcurve(FCurve *fcu)
 	}
 
 	/* do a second pass for auto handle: compute the handle to have 0 accelaration step */
-	a = fcu->totvert;
 	bezt = fcu->bezt;
+	last = bezt + fcu->totvert;
 	first = bezt;
 	count = 0;
 
-	while (a--) {
+	while (bezt < last) {
 		if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) && ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM) && bezt->f5 == HD_AUTOTYPE_NORMAL) {
 			/* count the number of auto keyframe in a row */
 			count++;
@@ -948,7 +948,10 @@ void calchandles_fcurve(FCurve *fcu)
 			if (count >= 2) {
 				/* there at least 1 auto handle to adjust (the first one excluded) */
 				count++;
-				BKE_nurb_handle_calc_smooth(first, count);
+				if (!BKE_nurb_handle_calc_smooth(first, count)) {
+					/* if some handles were clamped and set to HD_AUTOTYPE_SPECIAL, redo this section */
+					bezt = first;
+				}
 			}
 			/* restart counting for a new range */
 			first = bezt;




More information about the Bf-blender-cvs mailing list