I have 2 keyframe points on an fcurve with free bezier handles, and using Python I want to insert a point in between these keyframes whilst keeping the custom shape of the curve with the handles. I can insert a keyframe point no problem using

fCurve.keyframe_points.insert(frame, value)

but I'm not sure how to do so without affecting the shape of the fcurve. Is this possible?

  • $\begingroup$ You would need to read the value at that frame and then insert a keyframe with that value, if you want to insert one but not change the f-curve. $\endgroup$ – Anthony Forwood Jul 7 '16 at 19:38
  • $\begingroup$ I can get the value at a keyframe between the points no problem, but the issue is if either of the existing points has free handles which have been moved to change the shape of the fcurve, then inserting a point won't keep that shape. I'm wondering if there is a way to insert a value (which I know lies on the curve) whilst keeping the custom shape defined by the handles? $\endgroup$ – Rajveer Jul 7 '16 at 19:42
  • $\begingroup$ This is actually relatively straightforward. The Python API has access to the coordinates of the keyframe_points of the fcurve .co and the handles .handle_left and .handle_right. You can create a new point between the other two and set up the handles using De Casteljau’s Algorithm : clear.rice.edu/comp360/lectures/BezSubd.pdf $\endgroup$ – Mutant Bob Jul 7 '16 at 20:04
  • $\begingroup$ possible duplicate of blender.stackexchange.com/questions/45311/… $\endgroup$ – Mutant Bob Jul 8 '16 at 14:51
  • $\begingroup$ Thank you, I've almost got it working with the snippets. The only problem is that I want to add a point at a particular keyframe between 2 existing keyframes, rather than at a time t along the Bezier path (e.g. midway between 2 keyframes isn't necessarily midway along the curve, so I can't use t = 0.5). I can't find if the Python API exposes the time t for a point on an f-curve or if I'm just missing something obvious :) $\endgroup$ – Rajveer Jul 11 '16 at 16:21

Subdividing Bezier curves is normally done using De Casteljau's algorithm. However, fcurves aren't pure Bezier curves. It is not hard to make a bezier curve "run backwards" along the time axis. Since this would create ambiguities in the animation system, blender prevents that by using modified handle coordinates whenever the handles could make the curve backtrack in the time axis. Once we understand that math, we have what is needed to properly subdivide the fcurve.

The solution is already covered at https://blender.stackexchange.com/a/57453/660 . It includes an excerpt from http://web.purplefrog.com/~thoth/blender/python-cookbook/subdivide-fcurve.html . I got bored and added the logic needed to map from frame->t so it should now be a fairly complete solution. I'm not copying the code over here, because keeping it up-to-date in both articles on stackexchange is tedious.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.