The code below (2017 update: updated for the introduction of integers in Lua 5.3) builds on my recent experiments with pastel colours and the golden angle to generate procedural flowers. The petals are drawn with a mesh using quadratic Bézier curves. The flowers, once initialised, draw themselves as a sprite. (Update) An example of its output is below:
--
-- Bloom
--
supportedOrientations(LANDSCAPE_ANY)
function setup()
w2, h2 = WIDTH / 2, HEIGHT / 2
bImg = image(WIDTH, HEIGHT)
setContext(bImg)
background(100, 175, 60)
rectMode(CENTER)
for i = 1, 1000 do
resetMatrix()
rotate(math.random(-10, 10))
fill(math.random(90, 110),
math.random(150, 200),
math.random(50, 70))
rect(math.random(WIDTH), math.random(HEIGHT),
math.random(5, 10), 100)
end
setContext()
f = {}
print("Touch, hold and release viewer to grow a bloom.")
end
function draw()
sprite(bImg, w2, h2)
for i = 1, #f do
f[i]:draw()
end
end
function touched(touch)
local tx, ty, state = touch.x, touch.y, touch.state
if state == BEGAN and not id then
touchTime = ElapsedTime
id = touch.id
elseif state == ENDED and touch.id == id then
local size = math.min(50 + (ElapsedTime - touchTime) * 50, 100)
table.insert(f, Flower(size, 21, tx, ty, math.random()))
id = nil
end
end
-- A function to generate a spectrum of pastel colours
-- h is [0, 1); strength is [0, 1]
function pastelH2RGB(h, strength)
local s = strength / 2 + 0.25
local r, g, b = 1, 1, 1
local i = h * 3
local x = (i % 1) * (1 - s)
if i < 1 then r, g = 1 - x, s + x
elseif i < 2 then r, b = s + x, 1 - x
else g, b = 1 - x, s + x end
return color(255 * r, 255 * g, 255 * b)
end
B2 = class()
function B2:init(p)
self.p = p
end
function B2:point(t)
local p = self.p
local t1 = 1 - t
return t1 * t1 * p[1] + 2 * t * t1 * p[2] + t * t * p[3]
end
Petal = class()
function Petal:init(size, a, b)
local as, bs = a * size, b * size
local n = 20
self.mesh = mesh()
local b1 = B2({vec2(0, 0), vec2(-as , bs), vec2(0, size)})
local b2 = B2({vec2(0, 0), vec2(as, bs), vec2(0, size)})
local v = {
b1:point(0), b2:point(1/n), b1:point(1/n),
b1:point(1), b1:point(1 - 1/n), b2:point(1 - 1/n)}
for i = 2, n - 1 do
local t1 = (i - 1) / n
local t2 = i / n
table.append(v,
triangulate({b1:point(t1), b1:point(t2),
b2:point(t2), b2:point(t1)}))
end
self.mesh.vertices = v
end
function Petal:setColor(col)
self.color = col
end
function Petal:draw()
pushMatrix()
translate(self.x - 2, self.y - 2)
rotate(self.angle)
self.mesh:setColors(0, 0, 0, 16)
self.mesh:draw()
popMatrix()
pushMatrix()
translate(self.x, self.y)
rotate(self.angle)
self.mesh:setColors(self.color)
self.mesh:draw()
popMatrix()
end
-- Helper function
function table.append(t1, t2)
local n = #t1
for i = 1, #t2 do
t1[n + i] = t2[i]
end
end
Flower = class()
function Flower:init(size, n, x, y, hue)
self.x, self.y = x, y
self.img = image(size * 2.1, size * 2.1)
local petals = {}
local a = math.random(360)
local pa = 0.3 + 0.3 * math.random()
local pb = 0.2 + 0.6 * math.random()
local phi = (1 + math.sqrt(5)) / 2 -- Golden ratio
local ga = 360 / phi ^ 2 -- Golden angle (radians)
for i = 1, n do
local p = Petal(math.random((size * 0.95) // 1, (size * 1.05) // 1), pa, pb)
p.x, p.y = 0, 0
p.angle = a
local col = (hue + math.random() / 10 - 0.05) % 1
p:setColor(pastelH2RGB(col, 0.5))
table.insert(petals, p)
a = a + ga
end
setContext(self.img)
translate(size * 1.05, size * 1.05)
for i = 1, #petals do
petals[i]:draw()
end
a = 0
ga = math.rad(ga)
for i = 1, 20 do
local r = math.sqrt(i) * size / 20
local x, y = r * math.cos(a), r * math.sin(a)
fill(245, 200, 0)
ellipse(x - 1, y - 1, 7)
fill(250, 250, 0)
ellipse(x, y, 7)
a = a + ga
end
setContext()
end
function Flower:draw()
sprite(self.img, self.x, self.y)
end