I've been trying to create a spirograph effect by using a few parented empties, rotating at different rates, with an emmisive object at the end of the partent chain.

I tried using motion blur to get a long line drawn of the object's path, but what I get is just two lines. I guess the motion blur time resolution was not enough. So I have cranked that up for my emissive object, but nothing has changed. I guess it's because of the empties.

I tried slowing down the animation so the motion will span more frames to hopefully make the motion blur arcs more precise - but nothing has changed.

I wonder if there are any other approaches that could help me generate Lissajous curves with Blender.


2 Answers 2


Lissajous curves are described using the parameteric equations:

$$ \begin{aligned} x &= A\sin{(at+\delta)}\\ y &= B\sin{(bt)} \end{aligned} $$

So there is no need to take an implicit approach. We can easily implement this system of paremeteric equations in Animation Nodes as follows:

Node Tree

  • 1
    $\begingroup$ Fabulous! I wonder if I could use an audio file (waveform) as input to get a vectorscope effect with this. $\endgroup$
    – unfa
    Mar 27, 2018 at 11:52
  • 1
    $\begingroup$ @unfa I suppose yes, I am not entirely sure what how an audio vectorscope. But what ever it is, it is possible. $\endgroup$
    – Omar Emara
    Mar 27, 2018 at 16:21

How about tracing the position of your object with an edgeline?

import bpy

start_frame = 1 # when do you want to start the tracking?
end_frame = 1000 # and when should it stop again?
stylus = 'Empty' # name of the object to track
new_name = "Whirl" # name of the created object

verts = [] # list of all vertices
edges = [] # list of all edges

sce = bpy.context.scene # the current scene
old_frame = sce.frame_current # remember the current frame

vertex_count = start_frame
while vertex_count <= end_frame: # iterate through the specified time
    sce.frame_set(vertex_count) # set the frame so the object is in the right place for any given frame
    loc = bpy.data.objects[stylus].matrix_world.translation # the global coordinates of the stylus
    verts.append((loc.x, loc.y, loc.z)) # add the position to the vertex list  
    vertex_count += 1

edge_count = 1 # starting with the second vert because the edge list is one item shorter
end = len(verts)

while edge_count < end: # building the edges
    edges.append((edge_count - 1, edge_count)) # assigns the indices of the verts to the edges
    edge_count += 1

#edges = [(x-1 , x) for x in range(len(verts)) if x > 0] # this does the same as the above edge code. list comprehensions are scary 

mesh_data = bpy.data.meshes.new(new_name + '-mesh') # makes a new mesh
mesh_data.from_pydata(verts, edges, []) # fills verts and edges into the mesh

obj = bpy.data.objects.new(new_name, mesh_data) # makes a new object with the mesh linked

sce.frame_set(old_frame) # repair the frame position


round round get around

You can even animate it using a Build Modifier. And if you want a particle effect, just convert the mesh into a curve with ALTC, maybe change the spline type into bezier with auto handles and you can let a particle emitter follow the path.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .