From 267170167d52cab9e97f879d9127a1cf04f6bb58 Mon Sep 17 00:00:00 2001 From: Martin Peach Date: Tue, 15 Mar 2011 20:53:57 +0000 Subject: This is a version of Claude Heiland-Allen's lua for Pd. The objects are named pdlua and pdluax instead of lua and luax. So far it seems to work on linux. svn path=/trunk/externals/pdlua/; revision=15030 --- examples/swarm.pd_lua | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 examples/swarm.pd_lua (limited to 'examples/swarm.pd_lua') 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 -- cgit v1.2.1