plasma

plasma

animation from a one line formula, such as:

function(x,y) return abs(floor(16*(sin(x/a + t*c) + cos(y/b + t*d))))%16 end,

please PR additional funcs! (or post them here)

  • encoders control time, func, and vars a,b,c,d
  • grid optional (pattern shown on screen as well)
  • currently no sonification. may add cc out and/or drone synth when i find a minute (contribs welcome also)

install

;install https://github.com/tehn/plasma

edit: also in the community catalog

danger!

some configurations could cause intense flashing.

about

here is a good intro to plasmas. very similar to the bytebeat by the legendary viznut

47 Likes

This is really cool and I’m very excited to run this. Will give it a shot in seamstress too. Been wanting something resembling a boot animation to my script. Add a function with a nice little timer.

Thanks for sharing!

1 Like

additional func added! ty @mei!

5 Likes

here’s a seamstress version. would love to add this to the seamstress repo as an example script if that’s all right with you @tehn!

--- plasma!
-- written by @tehn for norns
-- adapted by @ryleelyman for seamstress
-- 
-- +/-                time
-- number keys        func
-- up/down            a
-- left/right         b
-- shift + up/down    c
-- shift + left/right d
--
-- submit new funcs!

abs = math.abs
floor = math.floor
sin = math.sin
cos = math.cos
sqrt = math.sqrt

func = {
	function(x,y) return abs(floor(16*(sin(x/a + t*c) + cos(y/b + t*d))))%16 end,
	function(x,y) return abs(floor(16*(sin(x/y)*a + t*b)))%16 end,
	function(x,y) return abs(floor(16*(sin(sin(t*a)*c + (t*b) + sqrt(y*y*(y*c) + x*(x/d))))))%16 end,
}
f = 1
p = {}
t = 0
time = 0.02
a = 3.0
b = 5.0
c = 1.0
d = 1.1
alt = false

g = grid.connect()

function tick()
	while true do
		t = t+(time*0.1)
		process()
		redraw()
		grid_redraw()
		clock.sleep(1/60)
	end
end

function init()
	print("hello")
	process()
	redraw()
	clock.run(tick)
end

function process()
  for x=1,16 do
		for y=1,16 do
			p[y*16+x] = func[f](x,y)
		end
	end
end

function grid_redraw()
	for y=1,16 do
		for x=1,16 do
			g:led(x,y,p[x+y*16])
		end
	end
	g:refresh()
end

function screen.key(char, modifiers, _, state)
  if state == 1 then
    if char == "1" then
      f = 1
    elseif char == "2" then
      f = 2
    elseif char == "3" then
      f = 3
    elseif char == "-" then
      time = time - 0.001
    elseif char == "=" then
      time = time + 0.001
    elseif char.name == "up" then
      if tab.contains(modifiers, "shift") then
        c = c + 0.01
      else
        a = a + 0.01
      end
    elseif char.name == "down" then
      if tab.contains(modifiers, "shift") then
        c = c - 0.01
      else
        a = a - 0.01
      end
    elseif char.name == "left" then
      if tab.contains(modifiers, "shift") then
        d = d - 0.01
      else
        b = b - 0.01
      end
    elseif char.name == "right" then
      if tab.contains(modifiers, "shift") then
        d = d + 0.01
      else
        b = b + 0.01
      end
    end
  end
end

function color(x, y)
  local r = util.linlin(0, 15, 0, 255, p[y*16+x])
  local g = util.linlin(0, 15, 0, 255, p[y*16+y])
  local b = util.linlin(0, 15, 0, 255, p[x*16+y])
  return r, g, b
end

function redraw()
	screen.clear()
  for x=1,16 do
		for y=1,16 do
			screen.color(color(x,y))
			screen.pixel((x-1)*4, (y-1)*4)
		end
	end
	screen.color(255, 255, 255)
	screen.move(120,10)
	screen.text("t")
	screen.move(115,10)
	screen.text_right(time)
	screen.move(120,20)
	screen.text("f")
	screen.move(115,20)
	screen.text_right(f)
	screen.move(120,30)
	screen.text("a")
	screen.move(115,30)
	screen.text_right(a)
	screen.move(120,40)
	screen.text("b")
	screen.move(115,40)
	screen.text_right(b)
	screen.move(120,50)
	screen.text("c")
	screen.move(115,50)
	screen.text_right(c)
	screen.move(120,60)
	screen.text("d")
	screen.move(115,60)
	screen.text_right(d)
	screen.refresh()
end
4 Likes

hoooray and yes absolutely (and also i bet you have some great function ideas to add!)

4 Likes

Here are two more functions i adapted from the pico-8 page that @tehn linked.

	function(x,y) return abs(floor(16*(sin(x/a + t*c) + cos(y/b + t*d) + (sin(x/a)/c))))%16 end,
	function(x,y) return abs(floor(16*(sin(x/a + t*c) + cos(y/b + (sin(x/a)*c) + (cos(y/b - t)*c*2 + cos(x/b+y/(a/2)+t*c*2))))))%16 end,
19 Likes

that’s incredible! totally love it! sorry for the basic question, but how do i run your version?

Load the script up in maiden and then find lines 19-21. You can add functions to the list here.

2 Likes

Thank you!!! I’ll fire it up!

2 Likes

just added the two lines by @jasonw22 so you can simply update the script

(also added comments noting contributors)

5 Likes

Trying to replicate some of these functions in max/msp. Very trippy! Tixi.land also has some good examples of single line function animations. It might be good inspiration for those looking to expand upon this.

9 Likes

so i’m completely obsessed with plasma… and i could be on crack but i think the update broke some functionality… it seems that with the new update pressing the 2 lower buttons on norns and turning the 2 lower encoders doesn’t change the values of “c” and “d” anymore… unless that’s intentional?

isn’t it hold key1 and turn enc 2/3 for c/d?

2 Likes

Ah sorry, it’s been a long day. I was not thinking right when I tried out the new update!!

1 Like

quick and dirty port of plasma to arc (for seamstress)

--- plasma-arc!
-- based on plasma by @tehn for norns
--
-- +/-           time
-- number keys   func
-- ring 1        a
-- ring 2        b
-- ring 3        c
-- ring 4        d

abs = math.abs
floor = math.floor
sin = math.sin
cos = math.cos
sqrt = math.sqrt

func = {
  function(x, y)
    return abs(floor(16 * (sin(x / a + t * c) + cos(y / b + t * d)))) % 16
  end,
  function(x, y)
    return abs(floor(16 * (sin(x / y) * a + t * b))) % 16
  end,
  function(x, y)
    return abs(floor(16 * (sin(sin(t * a) * c + (t * b) + sqrt(y * y * (y * c) + x * (x / d)))))) % 16
  end,
}
f = 1
p = {}
t = 0
time = 0.02
a = 3.0
b = 5.0
c = 1.0
d = 1.1
alt = false

Arc = arc.connect()

function tick()
  while true do
    t = t + (time * 0.1)
    process()
    redraw()
    arc_redraw()
    clock.sleep(1 / 60)
  end
end

function process()
  for x = 1, 16 do
    for y = 1, 16 do
      p[(y - 1) * 16 + x] = func[f](x, y)
    end
  end
end

Arc.delta = function(n, delta)
  if n == 1 then
    a = a + 0.01 * delta
  elseif n == 2 then
    b = b + 0.01 * delta
  elseif n == 3 then
    c = c + 0.01 * delta
  elseif n == 4 then
    d = d + 0.01 * delta
  end
end


function init()
  print("hello")
  process()
  redraw()
  clock.run(tick)
end

function arc_redraw()
  for i = 1, 4 do
    for j = 1, 64 do
      Arc:led(i, j, p[j + (i - 1) * 64])
    end
  end
  Arc:refresh()
end

function screen.key(char, _, _, state)
  if state == 1 then
    if char == "1" then
      f = 1
    elseif char == "2" then
      f = 2
    elseif char == "3" then
      f = 3
    elseif char == "-" then
      time = time - 0.001
    elseif char == "=" then
      time = time + 0.001
    end
  end
end

function color(x, y)
  local r = util.linlin(0, 15, 0, 255, p[(y - 1) * 16 + x])
  local g = util.linlin(0, 15, 0, 255, p[(y - 1) * 16 + y])
  local b = util.linlin(0, 15, 0, 255, p[(x - 1) * 16 + y])
  return r, g, b
end

function redraw()
  screen.clear()
  for x = 1, 16 do
    for y = 1, 16 do
      screen.color(color(x, y))
      screen.pixel((x - 1) * 4, (y - 1) * 4)
    end
  end
  screen.color(255, 255, 255)
  screen.move(120, 10)
  screen.text("t")
  screen.move(115, 10)
  screen.text_right(time)
  screen.move(120, 20)
  screen.text("f")
  screen.move(115, 20)
  screen.text_right(f)
  screen.move(120, 30)
  screen.text("a")
  screen.move(115, 30)
  screen.text_right(a)
  screen.move(120, 40)
  screen.text("b")
  screen.move(115, 40)
  screen.text_right(b)
  screen.move(120, 50)
  screen.text("c")
  screen.move(115, 50)
  screen.text_right(c)
  screen.move(120, 60)
  screen.text("d")
  screen.move(115, 60)
  screen.text_right(d)
  screen.refresh()
end
11 Likes

so cool!
i actually was also working on an arc port :sweat_smile: but instead of looping through the coordinates like you did, i was doing a hilbert curve so some locality was preserved. maybe ill make another PR when i have a free moment

4 Likes

Plasma is cool! I missed the ability to rotate the grid, so I added this… and once I started on that, I decided to add all of the parameters as params so that you can modulate them:

4 Likes