Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2011-03-12 04:09:40 +0300
committerJoshua Leung <aligorith@gmail.com>2011-03-12 04:09:40 +0300
commit80de27914d4d0cedf8a46d960b496db7126d118e (patch)
treebc31cd5536c11ffc213a608848344152470cc877 /source/blender/editors/animation
parentc786a2c80506397f64d3bc3ad91d97774e867d8d (diff)
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.
Diffstat (limited to 'source/blender/editors/animation')
-rw-r--r--source/blender/editors/animation/keyframes_general.c46
1 files changed, 22 insertions, 24 deletions
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index 53d8b4d67f1..07069a69c40 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -279,28 +279,21 @@ void clean_fcurve(FCurve *fcu, float thresh)
/* 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 @@ void smooth_fcurve (FCurve *fcu)
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 @@ void smooth_fcurve (FCurve *fcu)
* - 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 @@ void smooth_fcurve (FCurve *fcu)
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 */