Create custom graph and access values from Python

I need to allow the user to create their own transfer function y = f(x)

(I will then use this transfer function to warp the scene)

Currently I'm using a mathematical formula:

y = exp( 1/(x^2 + 1) )


But it doesn't allow a (non-mathematical) artist to shape the curve, and it is awkward even for a mathematician to turn an arbitrary shape into a mathematical formula.

Ideally I would like the user to be able to draw the curve freehand, or maybe in the same manner as constructing curves in Blender.

In fact, can I get away with using Blender's existing curve tool? Say I create a new scene, I suppose I can then create a curve that is constrained to the xy axis. But then how could I get y = f(x) from a Python script?

And also, is there some 2D curve tool, that might allow the curve to be designed from within some panel?

Is there any solution path I'm missing?

After a bit of investigation it seems you can't use Graph Editor for "standalone" FCurves. However, you can link them to any object and name them as you like. I used the default Cube in example below, but it might be as well an empty mesh.

Below script uses Cube as object that "holds" your curves within its animation_data.action. It creates them if they do not exist, and if they exists current one is picked.

import bpy

placeholder = bpy.context.scene.objects["Cube"]
if not placeholder.animation_data:
placeholder.animation_data_create()
if not placeholder.animation_data.action:
placeholder.animation_data.action = bpy.data.actions.get("curves") or bpy.data.actions.new("curves")
action = placeholder.animation_data.action

print(placeholder)
name = 'my_curve'

fcurves = action.fcurves
for f in fcurves:
if f.data_path == name:
break
else:
f = action.fcurves.new( name )
f.select = True
f.keyframe_points.insert( 0, 0 )
f.keyframe_points.insert( 100, 10 )


Then you have get to edit curve you can add points by duplicating existing ones using shift-d.

After shaping it you can use FCurve.evaluate() (API docs - bpy.types.FCurve). For example like this:

for i in range(100):
print(i, f.evaluate(i))

• I just had a look at FCurve wiki.blender.org/index.php/Doc:2.6/Manual/Animation/Editors/… -- they seem to be tied to time on the x-axis (frames). Is there any way I can choose my own x-axis e.g. theta from -pi/2 to +pi/2 ? – P i Apr 8 '14 at 15:35
• Again, will have to confirm when I will get my hands on Blender, but I don't think you are restricted in any way as far as x-axis is concerned. By default, yes, it is treated that input value is current frame. However as you're going to call evaluate() yourself you shouldn't be concerned about that (as long as you're not planning to plug it as some property). P.S. I am no expert in Blender Python scripting, just guessing from what I know (and it is not that much). – elmo Apr 8 '14 at 15:38