
Cinema 4D Enhanced Orbital Motion Generator: Powerful Procedural Animation with Python
Unlock the next level of procedural animation and motion design in Cinema 4D with this feature-rich Python generator! This script creates dynamic orbital systems, perfect for sci-fi interfaces, kinetic sculptures, abstract art, and educational visualizations. With a comprehensive set of user data options, you can customize every aspect — from orbital tilts and object types to animated pulsations, spiral effects, and sophisticated color modes.
What Does This Script Do?
This Cinema 4D Python generator creates a series of orbits populated with objects (spheres, cubes, or cones), each following a circular path. It’s not just static: you can animate rotation, apply a breathing (pulsating) effect, visualize orbits as splines, and add a 3D spiral offset. Plus, every object can be colored randomly, or you can create beautiful gradient color transitions along the orbits.
Key Features:
- Multiple Orbits: Stack any number of orbits, with customizable radius and spacing.
- Object Types: Instantly switch between spheres, cubes, or cones for all orbital objects.
- Tilt and Spiral: Add tilt to orbits and spiral vertical offsets for 3D complexity.
- Rotation Animation: Orbits can rotate at different speeds, animated in real time.
- Breathing Effect: Enable pulsating scale for organic, lively motion.
- Color Modes: Assign static random colors or interpolate along a color gradient.
- Spline Visualization: Optionally visualize each orbit path with splines.
- Robust User Data: All parameters can be controlled via User Data for creative flexibility.
User Data: Full Control at Your Fingertips
All animation and design parameters are easily adjustable via User Data in the Python Generator object:
Option | Type | Default | Description |
---|---|---|---|
Number of Orbits | Integer | 3 | Total number of orbital paths |
Objects per Orbit | Integer | 12 | Objects distributed along each orbit |
Initial Orbit Radius | Float | 200.0 | Radius of innermost orbit |
Orbit Gap | Float | 100.0 | Spacing between orbits |
Object Base Size | Float | 20.0 | Size/dimension for all objects |
Orbit Tilt Angle | Float | 0.0 | Tilt in degrees for all orbits |
Animate Rotation | Bool | True | Enable/disable animation |
Base Rotation Speed | Float | 30.0 | Degrees per second (base speed, per orbit multiplier) |
Random Colors | Bool | False | Assign a static random color to each object |
Enable Object Pulsation | Bool | False | Animate object size with a sine-wave (breathing) |
Pulsation Speed | Float | 2.0 | Cycles per second for pulsation |
Pulsation Amplitude | Float | 0.5 | Scale variation factor for pulsation |
Create Orbit Spline Visualization | Bool | False | Add visible splines for each orbit |
Spiral Vertical Offset per Orbit | Float | 0.0 | Step up each orbit vertically for spiral structure |
Object Type | Integer | 0 | 0 = Sphere, 1 = Cube, 2 = Cone |
Use Gradient Color Mode | Bool | False | Interpolate colors between two endpoints |
Gradient Start Color | Vector | (1.0, 0.0, 0.0) | RGB (0–1), default Red |
Gradient End Color | Vector | (0.0, 0.0, 1.0) | RGB (0–1), default Blue |
import c4d, math, random
def lerp_color(color1, color2, t):
# Linear interpolation between two colors.
return c4d.Vector(
color1.x + (color2.x - color1.x) * t,
color1.y + (color2.y - color1.y) * t,
color1.z + (color2.z - color1.z) * t
)
def main() -> c4d.BaseObject:
"""
Enhanced Orbital Motion Generator for Cinema 4D 2025 with Extended Features
This Python generator creates a series of orbits populated with objects that can be dynamically changed
between spheres, cubes, or cones. The orbits are circular paths with objects equally distributed along
their circumference.
Additional features include:
- Optional tilt for each orbit.
- Animation for continuous rotation.
- Optional random coloring for each object with static colors across frames.
- Variable rotation speeds per orbit by introducing a rotation speed multiplier.
- Pulsating scale effect for objects driven by a sine wave (breathing effect).
- Orbit spline visualization for visualizing orbital paths.
- Spiral offset to create a vertical displacement per orbit for a 3D spiral effect.
- Object Type selection (Sphere, Cube, Cone).
- Gradient color mode to interpolate between two colors along the orbits.
User Data Options:
---------------------------------------------------------------
1. Number of Orbits
- Type: Integer
- Default: 3
2. Objects per Orbit
- Type: Integer
- Default: 12
3. Initial Orbit Radius
- Type: Float
- Default: 200.0
4. Orbit Gap
- Type: Float
- Default: 100.0
5. Object Base Size (Dimension for Sphere, Cube edge length, and Cone overall scale)
- Type: Float
- Default: 20.0
6. Orbit Tilt Angle (Degrees)
- Type: Float
- Default: 0.0
7. Animate Rotation
- Type: Boolean
- Default: True
8. Base Rotation Speed (Degrees per Second)
- Type: Float
- Default: 30.0
9. Random Colors
- Type: Boolean
- Default: False
10. Enable Object Pulsation
- Type: Boolean
- Default: False
11. Pulsation Speed (Cycles per Second)
- Type: Float
- Default: 2.0
12. Pulsation Amplitude (Scale Variation Factor)
- Type: Float
- Default: 0.5
13. Create Orbit Spline Visualization
- Type: Boolean
- Default: False
14. Spiral Vertical Offset per Orbit
- Type: Float
- Default: 0.0
15. Object Type
- Type: Integer
- Options: 0 = Sphere, 1 = Cube, 2 = Cone
- Default: 0
16. Use Gradient Color Mode
- Type: Boolean
- Default: False
17. Gradient Start Color (R, G, B values from 0 to 1)
- Type: Vector
- Default: (1.0, 0.0, 0.0) [Red]
18. Gradient End Color (R, G, B values from 0 to 1)
- Type: Vector
- Default: (0.0, 0.0, 1.0) [Blue]
Notes:
- For rotation animation, ensure the Python Generator's "Always Active" and "Update on Scene Change" options are enabled.
- When Random Colors is enabled, a deterministic method ensures colors remain static across frames.
- Enabling Object Pulsation modulates the object size over time using a sine wave.
- Enabling Orbit Spline Visualization creates a circular spline matching each orbit’s path.
- Spiral Vertical Offset lifts each successive orbit to create a spiral effect.
- In Gradient Color Mode, the object's color will be interpolated between the start and end colors based on its orbit and index.
- The object's dimension (base size) controls the overall geometry:
Sphere: radius;
Cube: uniform edge length;
Cone: overall scale via object's transformation.
"""
# Retrieve user data values with defaults.
orbits = int(op[c4d.ID_USERDATA, 1]) if op[c4d.ID_USERDATA, 1] is not None else 3
objects_per_orbit = int(op[c4d.ID_USERDATA, 2]) if op[c4d.ID_USERDATA, 2] is not None else 12
init_radius = float(op[c4d.ID_USERDATA, 3]) if op[c4d.ID_USERDATA, 3] is not None else 200.0
orbit_gap = float(op[c4d.ID_USERDATA, 4]) if op[c4d.ID_USERDATA, 4] is not None else 100.0
base_size = float(op[c4d.ID_USERDATA, 5]) if op[c4d.ID_USERDATA, 5] is not None else 20.0
tilt_angle = float(op[c4d.ID_USERDATA, 6]) if op[c4d.ID_USERDATA, 6] is not None else 0.0
animate = bool(op[c4d.ID_USERDATA, 7]) if op[c4d.ID_USERDATA, 7] is not None else True
base_rotation_speed = float(op[c4d.ID_USERDATA, 8]) if op[c4d.ID_USERDATA, 8] is not None else 30.0
random_colors = bool(op[c4d.ID_USERDATA, 9]) if op[c4d.ID_USERDATA, 9] is not None else False
pulsate = bool(op[c4d.ID_USERDATA, 10]) if op[c4d.ID_USERDATA, 10] is not None else False
pulsation_speed = float(op[c4d.ID_USERDATA, 11]) if op[c4d.ID_USERDATA, 11] is not None else 2.0
pulsation_amp = float(op[c4d.ID_USERDATA, 12]) if op[c4d.ID_USERDATA, 12] is not None else 0.5
create_spline = bool(op[c4d.ID_USERDATA, 13]) if op[c4d.ID_USERDATA, 13] is not None else False
spiral_offset = float(op[c4d.ID_USERDATA, 14]) if op[c4d.ID_USERDATA, 14] is not None else 0.0
object_type = int(op[c4d.ID_USERDATA, 15]) if op[c4d.ID_USERDATA, 15] is not None else 0
use_gradient = bool(op[c4d.ID_USERDATA, 16]) if op[c4d.ID_USERDATA, 16] is not None else False
gradient_start = op[c4d.ID_USERDATA, 17] if op[c4d.ID_USERDATA, 17] is not None else c4d.Vector(1.0, 0.0, 0.0)
gradient_end = op[c4d.ID_USERDATA, 18] if op[c4d.ID_USERDATA, 18] is not None else c4d.Vector(0.0, 0.0, 1.0)
# Convert angles and rotation speed to radians.
tilt_rad = math.radians(tilt_angle)
base_rotation_speed_rad = math.radians(base_rotation_speed)
# Get current time in seconds for animation.
time_sec = 0.0
if animate:
time_sec = doc.GetTime().Get()
# Create a null object to hold all orbits.
orbital_null = c4d.BaseObject(c4d.Onull)
orbital_null.SetName("OrbitalMotionEnhanced")
# Optional: Parent for orbit splines.
spline_parent = None
if create_spline:
spline_parent = c4d.BaseObject(c4d.Onull)
spline_parent.SetName("OrbitSplines")
spline_parent.InsertUnder(orbital_null)
# Loop over each orbit.
for orbit_index in range(orbits):
orbit_rotation_multiplier = 1.0 + (orbit_index / max(1, orbits))
current_rotation_speed_rad = base_rotation_speed_rad * orbit_rotation_multiplier
current_radius = init_radius + orbit_index * orbit_gap
vertical_offset = spiral_offset * orbit_index
# Create a null for the current orbit.
orbit_null = c4d.BaseObject(c4d.Onull)
orbit_null.SetName(f"Orbit_{orbit_index + 1}")
orbit_null.SetRelRot(c4d.Vector(tilt_rad, 0, 0))
orbit_null.InsertUnder(orbital_null)
# Optional: Create orbit spline visualization.
if create_spline:
segments = 36
spline = c4d.SplineObject(segments, c4d.SPLINETYPE_LINEAR)
spline.SetName(f"OrbitSpline_{orbit_index + 1}")
points = []
for i in range(segments):
theta = (2 * math.pi / segments) * i
x = current_radius * math.cos(theta)
y = vertical_offset
z = current_radius * math.sin(theta)
points.append(c4d.Vector(x, y, z))
for i, point in enumerate(points):
spline.SetPoint(i, point)
spline.Message(c4d.MSG_UPDATE)
spline.InsertUnder(spline_parent)
# Loop over objects on the orbit.
for obj_index in range(objects_per_orbit):
base_angle = (2 * math.pi / objects_per_orbit) * obj_index
extra_angle = time_sec * current_rotation_speed_rad if animate else 0.0
angle = base_angle + extra_angle
x = current_radius * math.cos(angle)
z = current_radius * math.sin(angle)
pos = c4d.Vector(x, vertical_offset, z)
# Create the object based on the chosen type.
obj = None
if object_type == 0:
# Sphere
obj = c4d.BaseObject(c4d.Osphere)
obj[c4d.PRIM_SPHERE_RAD] = base_size
elif object_type == 1:
# Cube - setting its length uniformly.
obj = c4d.BaseObject(c4d.Ocube)
obj[c4d.PRIM_CUBE_LEN] = c4d.Vector(base_size, base_size, base_size)
elif object_type == 2:
# Cone - since direct parameter control is not available in this version,
# control its overall dimension using the object's scale.
obj = c4d.BaseObject(c4d.Ocone)
obj.SetRelScale(c4d.Vector(base_size, base_size, base_size))
else:
obj = c4d.BaseObject(c4d.Osphere)
obj[c4d.PRIM_SPHERE_RAD] = base_size
obj.SetRelPos(pos)
obj.SetName(f"Object_{orbit_index + 1}_{obj_index + 1}")
# Optionally assign color.
if random_colors:
seed = orbit_index * 1000 + obj_index
rng = random.Random(seed)
color = c4d.Vector(rng.random(), rng.random(), rng.random())
obj[c4d.ID_BASEOBJECT_USECOLOR] = 2
obj[c4d.ID_BASEOBJECT_COLOR] = color
elif use_gradient:
t = ((orbit_index * objects_per_orbit) + obj_index) / float(orbits * objects_per_orbit - 1)
grad_color = lerp_color(gradient_start, gradient_end, t)
obj[c4d.ID_BASEOBJECT_USECOLOR] = 2
obj[c4d.ID_BASEOBJECT_COLOR] = grad_color
# Apply pulsation if enabled.
final_size = base_size
if pulsate and animate:
scale_factor = 1.0 + pulsation_amp * math.sin(2 * math.pi * pulsation_speed * time_sec + base_angle)
final_size = base_size * scale_factor
if object_type == 0:
obj[c4d.PRIM_SPHERE_RAD] = final_size
elif object_type == 1:
obj[c4d.PRIM_CUBE_LEN] = c4d.Vector(final_size, final_size, final_size)
elif object_type == 2:
obj.SetRelScale(c4d.Vector(final_size, final_size, final_size))
obj.InsertUnder(orbit_null)
return orbital_null
How to Use
- Open Cinema 4D 2025 and create a new Python Generator object.
- Add User Data according to the table above for complete customization (right-click the generator, choose “User Data > Add User Data…”).
- Paste the script into the Python field of the generator.
- Tweak parameters live in the Attribute Manager to explore countless design and animation possibilities!