aboutsummaryrefslogtreecommitdiff
path: root/examples/swarm.pd_lua
diff options
context:
space:
mode:
Diffstat (limited to 'examples/swarm.pd_lua')
-rw-r--r--examples/swarm.pd_lua100
1 files changed, 100 insertions, 0 deletions
diff --git a/examples/swarm.pd_lua b/examples/swarm.pd_lua
new file mode 100644
index 0000000..d6e7f0a
--- /dev/null
+++ b/examples/swarm.pd_lua
@@ -0,0 +1,100 @@
+-- see also: http://www.vergenet.net/~conrad/boids/pseudocode.html
+local swarm = pd.Class:new():register("swarm")
+
+function swarm:initialize(sel, atoms) -- constructor
+ if type(atoms[1]) ~= "number" or atoms[1] < 2 then return false end
+ if type(atoms[2]) ~= "number" or atoms[2] < 3 then return false end
+ self.dim = math.floor(atoms[1])
+ self.count = math.floor(atoms[2])
+ self.cluster = 0.05 -- magic values look ok in the help patch..
+ self.distance2 = 0.2
+ self.similar2 = 0.1
+ self.friction = 0.96
+ self.flock = { }
+ self:in_1_randomize()
+ self.inlets = 2
+ self.outlets = 2
+ return true
+end
+
+function swarm:in_1_randomize() -- randomize positions, no movement
+ for i = 1, self.count do
+ self.flock[i] = { x = { }, dx = { } }
+ for j = 1, self.dim do
+ self.flock[i].x[j] = math.random() - 0.5
+ self.flock[i].dx[j] = 0
+ end
+ self.flock[i].w = math.random() + 0.5
+ end
+end
+
+function swarm:in_1_bang() -- update and output
+ local c = self:center()
+ for i = 1, self.count do
+ f = self.flock[i] -- update
+ local v1 = self:rule1(c, f)
+ local v2 = self:rule2(i, f)
+ local v3 = self:rule3(i, f)
+ for k = 1, self.dim do f.dx[k] = f.dx[k] + v1[k] + v2[k] + v3[k] end
+ for k = 1, self.dim do f.dx[k] = f.dx[k] * self.friction end
+ for k = 1, self.dim do f.x[k] = f.x[k] + f.dx[k] end
+ self:outlet(2, "float", { i }) -- output
+ self:outlet(1, "list", f.x)
+ end
+end
+
+function swarm:center() -- center of mass
+ local c = { }
+ local w = 0
+ for k = 1, self.dim do c[k] = 0 end
+ for i = 1, self.count do
+ w = w + self.flock[i].w
+ for k = 1, self.dim do c[k] = c[k] + self.flock[i].w * self.flock[i].x[k] end
+ end
+ for k = 1, self.dim do c[k] = c[k] / w end
+ return c
+end
+
+function swarm:rule1(c, f) -- clustering
+ local v = { }
+ for k = 1, self.dim do v[k] = self.cluster * (c[k] - (1 + f.w) * f.x[k]) end
+ return v
+end
+
+function swarm:rule2(i, f) -- avoidance
+ local v = { }
+ for k = 1, self.dim do v[k] = 0 end
+ for j = 1, self.count do
+ if i ~= j then
+ g = self.flock[j]
+ local d = { }
+ local m = 0
+ for k = 1, self.dim do d[k] = g.x[k] - f.x[k] ; m = m + d[k] * d[k] end
+ if m < self.distance2 then
+ for k = 1, self.dim do v[k] = v[k] - d[k] end
+ end
+ end
+ end
+ for k = 1, self.dim do v[k] = 0.01 * v[k] end
+ return v
+end
+
+function swarm:rule3(i, f) -- similarity
+ local v = { }
+ for k = 1, self.dim do v[k] = 0 end
+ for j = 1, self.count do
+ if i ~= j then
+ g = self.flock[j]
+ local d = { }
+ local m = 0
+ for k = 1, self.dim do d[k] = g.dx[k] - f.dx[k] ; m = m + d[k] * d[k] end
+ if m < self.similar2 then
+ for k = 1, self.dim do v[k] = v[k] + d[k] end
+ end
+ end
+ end
+ for k = 1, self.dim do v[k] = 0.004 * v[k] end
+ return v
+end
+
+-- exercise: make the right inlet control individual elements