[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [35483] trunk/blender/source/blender/ editors/animation/keyframes_general.c: Bugfix [#26222] Alt-O (smooth) in Graph editor destroys fcurve handle

Joshua Leung aligorith at gmail.com
Sat Mar 12 02:09:40 CET 2011


Revision: 35483
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=35483
Author:   aligorith
Date:     2011-03-12 01:09:40 +0000 (Sat, 12 Mar 2011)
Log Message:
-----------
Bugfix [#26222] Alt-O (smooth) in Graph editor destroys fcurve handle
type and data

Recoded Keyframe Smoothing operator to work better for continuous
curves (i.e. ones with monotonically increasing slopes in sections) as
opposed to hypothetically jagged ones.

The old method assumed that handles should be flat as otherwise, you'd
often get unsmooth curves just because you went and tilted some of the
handles for local extrema, causing some unkeyframed overshoots, which
also leads to changes in timing, which in turn often means unsmooth
motion. Hence, the code took advantage of this to do things with less
extra data.

However, now we have a proper "flatten handles" tool (under snap ->
horizontal) so this functionality is not needed in the general case
where it will lead to stair-stepping artifacts.

Modified Paths:
--------------
    trunk/blender/source/blender/editors/animation/keyframes_general.c

Modified: trunk/blender/source/blender/editors/animation/keyframes_general.c
===================================================================
--- trunk/blender/source/blender/editors/animation/keyframes_general.c	2011-03-12 01:03:15 UTC (rev 35482)
+++ trunk/blender/source/blender/editors/animation/keyframes_general.c	2011-03-12 01:09:40 UTC (rev 35483)
@@ -279,28 +279,21 @@
 /* temp struct used for smooth_fcurve */
 typedef struct tSmooth_Bezt {
 	float *h1, *h2, *h3;	/* bezt->vec[0,1,2][1] */
+	float y1, y2, y3;		/* averaged before/new/after y-values */
 } tSmooth_Bezt;
 
 /* Use a weighted moving-means method to reduce intensity of fluctuations */
+// TODO: introduce scaling factor for weighting falloff
 void smooth_fcurve (FCurve *fcu)
 {
 	BezTriple *bezt;
 	int i, x, totSel = 0;
 	
-	/* first loop through - count how many verts are selected, and fix up handles 
-	 *	this is done for both modes
-	 */
+	/* first loop through - count how many verts are selected */
 	bezt= fcu->bezt;
 	for (i=0; i < fcu->totvert; i++, bezt++) {						
-		if (BEZSELECTED(bezt)) {							
-			/* line point's handles up with point's vertical position */
-			bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1];
-			if ((bezt->h1==HD_AUTO) || (bezt->h1==HD_VECT)) bezt->h1= HD_ALIGN;
-			if ((bezt->h2==HD_AUTO) || (bezt->h2==HD_VECT)) bezt->h2= HD_ALIGN;
-			
-			/* add value to total */
+		if (BEZSELECTED(bezt))
 			totSel++;
-		}
 	}
 	
 	/* if any points were selected, allocate tSmooth_Bezt points to work on */
@@ -320,7 +313,7 @@
 				tsb->h3 = &bezt->vec[2][1];
 				
 				/* advance to the next tsb to populate */
-				if (x < totSel- 1) 
+				if (x < totSel-1) 
 					tsb++;
 				else
 					break;
@@ -334,10 +327,10 @@
 		 *	- 	next: w/a ratio = 1:1:2:5:3
 		 */
 		
-		/* round 1: calculate previous and next */ 
+		/* round 1: calculate smoothing deltas and new values */ 
 		tsb= tarray;
 		for (i=0; i < totSel; i++, tsb++) {
-			/* don't touch end points (otherwise, curves slowly explode) */
+			/* don't touch end points (otherwise, curves slowly explode, as we don't have enough data there) */
 			if (ELEM(i, 0, (totSel-1)) == 0) {
 				const tSmooth_Bezt *tP1 = tsb - 1;
 				const tSmooth_Bezt *tP2 = (i-2 > 0) ? (tsb - 2) : (NULL);
@@ -350,21 +343,26 @@
 				const float n1 = *tN1->h2;
 				const float n2 = (tN2) ? (*tN2->h2) : (*tN1->h2);
 				
-				/* calculate previous and next */
-				*tsb->h1= (3*p2 + 5*p1 + 2*c1 + n1 + n2) / 12;
-				*tsb->h3= (p2 + p1 + 2*c1 + 5*n1 + 3*n2) / 12;
+				/* calculate previous and next, then new position by averaging these */
+				tsb->y1= (3*p2 + 5*p1 + 2*c1 + n1 + n2) / 12;
+				tsb->y3= (p2 + p1 + 2*c1 + 5*n1 + 3*n2) / 12;
+				
+				tsb->y2 = (tsb->y1 + tsb->y3) / 2;
 			}
 		}
 		
-		/* round 2: calculate new values and reset handles */
+		/* round 2: apply new values */
 		tsb= tarray;
 		for (i=0; i < totSel; i++, tsb++) {
-			/* calculate new position by averaging handles */
-			*tsb->h2 = (*tsb->h1 + *tsb->h3) / 2;
-			
-			/* reset handles now */
-			*tsb->h1 = *tsb->h2;
-			*tsb->h3 = *tsb->h2;
+			/* don't touch end points, as their values were't touched above */
+			if (ELEM(i, 0, (totSel-1)) == 0) {
+				/* y2 takes the average of the 2 points */
+				*tsb->h2 = tsb->y2;
+				
+				/* handles are weighted between their original values and the averaged values */
+				*tsb->h1 = ((*tsb->h1) * 0.7f) + (tsb->y1 * 0.3f); 
+				*tsb->h3 = ((*tsb->h3) * 0.7f) + (tsb->y3 * 0.3f);
+			}
 		}
 		
 		/* free memory required for tarray */




More information about the Bf-blender-cvs mailing list