# How to make precisely defined trails along orbits in space

I'll be animating a large number of small objects following pre-calculated orbits. I'd like to add glowing trails that follow the orbit with an intensity that drops off with a specified decay function. Actually I'd like to emulate this effect as close as possible.

Below is a small demo example to give a rough idea. The script generates an animation ready to run, but the trails are implemented as zillions of mesh objects. This obviously wouldn't scale.

The real thing will be bigger (imagine asteroid belt or Oort cloud or space junk), so I need those narrow, but beautifully defined trails as seen in the first link or here also.

I am thinking of creating one-dimensional mesh objects (a line of connected vertices) and assigning some kind of non-linear material ramp (would that even work?), but maybe there is a better approach.

Run the animation generated by the script...

def RK4(x, v, n, h, F):

for i in range(n):  # written for readability, not speed

kv1 = F( x[:, i]                   )
kx1 =    v[:, i]

kv2 = F( x[:, i] + kx1 * (h/2.0) )
kx2 =    v[:, i] + kv1 * (h/2.0)

kv3 = F( x[:, i] + kx2 * (h/2.0) )
kx3 =    v[:, i] + kv2 * (h/2.0)

kv4 = F( x[:, i] + kx3 * h          )
kx4 =    v[:, i] + kv3 * h

v[:, i+1] = v[:, i] + (h/6.0) * (kv1 + 2.*(kv2 + kv3) + kv4)
x[:, i+1] = x[:, i] + (h/6.0) * (kx1 + 2.*(kx2 + kx3) + kx4)

def acc(x):
""" acceleration due to the sun's gravity (NumPy version) """
return -Gm * x / ( ((x**2).sum(axis=1)**1.5)[:,None] )

import bpy
import numpy as np

Gm     = 1.3271244002E+20  # m^3 s^-2   (Wikipedia Standard Gravitational Parameter)
t_year = 31558464.         # s  (roughly)
scale = 4.0E-11    # blender units per meter

n_frames = 250
Dt       = t_year / float(n_frames)   # time step

n = 8

X = np.zeros((n, 1000, 3))
V = np.zeros((n, 1000, 3))
T = np.zeros((n, 1000))

tilt = 30. * (np.pi/180.)  #radians
sin_tilt, cos_tilt = np.sin(tilt), np.cos(tilt)

X[:,0] = np.array([1.5E+11, 0.0, 0.0])[None, :] # start in the same place...

V[:,0] = 29300. * (np.linspace(0.5, 1.2, n)[:, None] *
np.array([0.0, cos_tilt, sin_tilt])[None, :] ) # ...but different initial velocities

# NOTE!! This is just for quickie demos only.
# Will give wrong result if step size too big.

RK4(X, V, n_frames, Dt, acc)  # pre-calculate orbits

p_size, s_size = 0.2, 0.5

# Create the Universe
ok = bpy.ops.mesh.primitive_ico_sphere_add(size=s_size, location=(0.0, 0.0, 0.0))
sun = bpy.context.active_object
sun.name = "Sun"

n_echos, frames_per_echo = 20, 1
e_sizes = np.linspace(p_size, 0, n_echos+1)[:-1]

things, trails = [], []

for i in range(n):

ok = bpy.ops.mesh.primitive_ico_sphere_add(size=p_size, location=(0.0, 0.0, 0.0))

p = bpy.context.active_object
p.name = "p" + str(i)
things.append(p)

echos = []

for i_echo in range(n_echos):

ok = bpy.ops.mesh.primitive_ico_sphere_add(size=e_sizes[i_echo], location=(0.0, 0.0, 0.0))

e = bpy.context.active_object
e.name = "p" + str(i) + "e" + str(i_echo)
echos.append(e)

trails.append(echos)

# Animate the Universe
bpy.context.scene.frame_end = n_frames

for i_frame in range(n_frames):

for i, p in enumerate(things):

p.location = scale * X[i, i_frame]
p.keyframe_insert(data_path="location", frame = i_frame + 1, index=-1)

for iecho, echo in enumerate(trails[i]):

i_frame_echo = max(0, i_frame - frames_per_echo*(iecho+1))
echo.location = scale * X[i, i_frame_echo]
echo.keyframe_insert(data_path="location", frame = i_frame + 1, index=-1)

• Do the trails have to be generated from python? Is there any way to create the orbits with curve paths? If you could, it would be easy to make a single teardrop mesh follow and deform with the curve. You could also make the path glow separately from the mesh object as well. Jul 15 '15 at 4:38
• That's an interesting idea @ToddMcIntosh, and I'll look into it. I don't actually want a teardrop shape this time - that was just a quick way to show how some orbits speed up when they whip around close to the sun in the animation. What I really want are hundreds of thin lines (like the paths in the included links) where I can map brightness and color gradients.
– uhoh
Jul 15 '15 at 6:57
• I wonder if this may be any use to you (Blender diplom - light streaks tutorial) : youtube.com/watch?v=bZudmvS8DJU. Making an object for each part of the gradient is not efficient. Jul 15 '15 at 7:02
• While this isn't a full answer (and that's why i've deleted my attempt below - for now) it might help to think in terms of Trajectories only, and not keyframing the gradiented primitives gist.github.com/zeffii/667616a3d23105708ca2 Jul 15 '15 at 8:58
• maybe related? blender.stackexchange.com/questions/34377/…
– user1853
Oct 3 '15 at 1:35

Trails can be created in Blender using particles. These trails can be generated from simulations or animation. Since the trails are created as geometry, modifiers, shaders, and compositing can be used to achieve a broad range of effects. This image below was generated using this approach.

Step by step instructions (Blender 2.76)

1. Setup a scene with an object which which will move. For this example, a physics simulation will generate the motion of a bouncing ball. The details of the physics setup are not discussed. Add a sphere out of view of the camera. Call this sphere 'particle-sphere'. It will be used to visualize the trail with the particle system.

1. Parent a single vertex to the object. This vertex will be the emitter for all particles on the trail. The vertex will emit the particles for the trail.

2. Create a particle system for the vertex. To simplify things, choose a large number, like 2000, and set the number of particles, the lifetime of the particles and the emission end at this number. This will lead to a single particle being emitted at each frame. Set the render object to a sphere added for visualization. Set the field weight for gravity to 0. This will prevent the particles from moving.

1. Simulate/animate the scene. Usually, the spacing between the particles will be too high, resulting in a dotted trail. (This will be corrected in a few steps.)

1. To fade the trail, a shader is used which make the particles increasingly transparent as they age.

1. To close up the spacing on the dots, the timing needs to be adjusted. First adjust the animation end time. For this example, the end time will be set to 2000 frames. The retiming can be done in several ways. One method is to retime the physics. The other is to bake the physics, (see How to bake rigid body physics frame in blender render? ) then retime the animation. This is opening the dope sheet, selecting the animation channels, a scaling using 's'. In this example, the original 250 frame animation was scaled by 8 to stretch to 2000 frames.

1. Finally, this retiming will change the real time playback of the animation. To fix this, the animation is rendered skipping frames. Since the animation was retimed by a factor of 8, the animation is rendered using every 8th frame.

1. This animation is finally generated!

The blend file for the space animation is located here:

The blend file for the example is located here:

• I'm really impressed that the particle system method can make such a... normal looking line - uniform and flat rather than lumpy and glowing - incredible! OK I will give this a try.
– uhoh
Jan 17 '16 at 3:45
• This approach can get to be a little expensive because of all of the polygons. Also, on extreme zooms, some lumpiness can reappear. There are some additional things which can be done to deal with both issues. Jan 17 '16 at 3:50
• OK I'll spend some time with this and then follow up. Thanks!
– uhoh
Jan 17 '16 at 3:55
• I am following the steps but collision occurs between the falling object and the trail particles. They crash against each other and get scattered. Neither the particles nor the object they are based on have physics in my setup. Are there physics in your particles setup? Nov 5 '19 at 1:14