Python
"""
Self-Contained Magnetic Swarm Effector
No external dependencies - uses built-in random for turbulence
Same features as original but with simplified noise
"""
import c4d
import math
import random
# Global swarm storage
swarm_system = {
"positions": [],
"velocities": [],
"accelerations": [],
"initialized": False,
"random_seeds": []
}
def simple_noise(x, y, z, seed):
"""Built-in pseudo-noise function to replace Perlin noise"""
random.seed(int(x*100 + y*1000 + z*10000 + seed))
return random.random() * 2 - 1 # Returns -1 to 1
def main() -> bool:
global swarm_system
# Get MoGraph data
data = c4d.modules.mograph.GeGetMoData(op)
if data is None:
return True
# Get current frame and count
frame = doc.GetTime().GetFrame(doc.GetFps())
matrices = data.GetArray(c4d.MODATA_MATRIX)
count = data.GetCount()
# Access user data
flock_radius = op[c4d.ID_USERDATA, 1] or 150.0
cohesion = op[c4d.ID_USERDATA, 2] or 0.8
alignment = op[c4d.ID_USERDATA, 3] or 1.2
magnetism = op[c4d.ID_USERDATA, 4] or 3.0
goal_strength = op[c4d.ID_USERDATA, 5] or 1.5
turbulence = op[c4d.ID_USERDATA, 6] or 0.3
max_speed = op[c4d.ID_USERDATA, 7] or 150.0
goal_object = op[c4d.ID_USERDATA, 8]
show_forces = op[c4d.ID_USERDATA, 10] or False
# Handle reset button
reset_simulation = False
button_state = op.GetDataInstance().GetContainer(c4d.ID_USERDATA).GetData(c4d.ID_USERDATA + 9)
if button_state and button_state.GetInt32(c4d.BITBUTTON_CLICKED):
reset_simulation = True
button_state.SetInt32(c4d.BITBUTTON_CLICKED, 0)
op.SetDirty(c4d.DIRTYFLAGS_DATA)
# Initialize system
if not swarm_system["initialized"] or reset_simulation or len(swarm_system["positions"]) != count:
swarm_system["positions"] = [m.off for m in matrices]
swarm_system["velocities"] = [c4d.Vector(
random.random()-0.5,
random.random()-0.5,
random.random()-0.5
) * 10 for _ in range(count)]
swarm_system["accelerations"] = [c4d.Vector(0,0,0) for _ in range(count)]
swarm_system["random_seeds"] = [random.randint(0,1000) for _ in range(count)]
swarm_system["initialized"] = True
try:
# Get goal position
goal_pos = goal_object.GetMg().off if goal_object else c4d.Vector(0,0,0)
for i in range(count):
pos = swarm_system["positions"][i]
vel = swarm_system["velocities"][i]
accel = c4d.Vector(0,0,0)
seed = swarm_system["random_seeds"][i]
# FLOCKING BEHAVIOR
neighbors = []
center = c4d.Vector(0,0,0)
avg_vel = c4d.Vector(0,0,0)
neighbor_count = 0
for j in range(count):
if i == j:
continue
dist = (pos - swarm_system["positions"][j]).GetLength()
if dist < flock_radius:
neighbors.append(j)
center += swarm_system["positions"][j]
avg_vel += swarm_system["velocities"][j]
neighbor_count += 1
if neighbor_count > 0:
center /= neighbor_count
avg_vel /= neighbor_count
accel += (center - pos).GetNormalized() * cohesion
accel += avg_vel.GetNormalized() * alignment
# MAGNETIC BEHAVIOR
if abs(magnetism) > 0.1:
for j in neighbors:
delta = pos - swarm_system["positions"][j]
dist = delta.GetLength()
if dist > 0:
force = delta.GetNormalized() * magnetism / (dist * 0.1)
accel += force
# GOAL SEEKING
if goal_strength > 0:
to_goal = (goal_pos - pos).GetNormalized()
accel += to_goal * goal_strength
# SIMPLIFIED TURBULENCE
if turbulence > 0:
time = frame * 0.05
accel.x += simple_noise(pos.x*0.1, pos.y*0.1, time, seed) * turbulence
accel.y += simple_noise(pos.y*0.1, time, pos.z*0.1, seed+1) * turbulence
accel.z += simple_noise(time, pos.z*0.1, pos.x*0.1, seed+2) * turbulence
# Update physics
vel += accel
speed = vel.GetLength()
if speed > max_speed:
vel = vel.GetNormalized() * max_speed
swarm_system["velocities"][i] = vel
swarm_system["positions"][i] += vel * 0.1
matrices[i].off = swarm_system["positions"][i]
# Orientation
if speed > 0.1:
forward = vel.GetNormalized()
up = c4d.Vector(0,1,0) if abs(forward.y) < 0.99 else c4d.Vector(0,0,1)
right = up.Cross(forward).GetNormalized()
up = forward.Cross(right).GetNormalized()
matrices[i].v1 = right
matrices[i].v2 = up
matrices[i].v3 = forward
# Debug visualization
if show_forces:
c4d.utils.DrawLine(pos, pos+accel*20, c4d.Vector(1,0,0), c4d.DRAWLINE_FORCEFULL)
c4d.utils.DrawLine(pos, pos+vel, c4d.Vector(0,1,0), c4d.DRAWLINE_FORCEFULL)
if goal_object:
c4d.utils.DrawLine(pos, goal_pos, c4d.Vector(1,1,0), c4d.DRAWLINE_FORCEFULL)
except Exception as e:
print(f"Swarm Error: {str(e)}")
swarm_system["initialized"] = False
return True
data.SetArray(c4d.MODATA_MATRIX, matrices, op[c4d.FIELDS].HasContent())
return True
