#### Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

# Bloom: a first experiment with procedural flowers

edited October 2017 Posts: 489

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 + 2 * t * t1 * p + t * t * p
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
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
```
Tagged:

• Posts: 666

Man, that is some beautiful work! Very pretty pastels and 'shadowing' effect! Fast, too!

• Posts: 666

Any thoughts on how to make this into trees? I would love to touch-drag and create different trees by dragging up for heat and seeing growth as it gets taller.

Seems possible, but I don't yet understand what in the world this code is doing to make the mesh! • Posts: 5,054

This is a really beautiful demo. Great colour choices.

• Posts: 489

Thank you. @aciolino, the petal boundary is formed by two quadratic Bézier curves that are mirror images of each other, each curve being defined by its three control points and parameterized by a parameter that runs from 0 to 1. Where the two curves meet forms a triangle, at the top and bottom of the petal. The rest of the petal can be approximated by a series of quads with vertices on the boundary curves. I divide the petal into 20 pieces in this way.

• Posts: 666

So, what are these classes? How / what does the bezier calculation? I'm really interested in how this code works. • Posts: 489

Hello @aciolino. I hope the following helps.

Flowers (Codea class: `Flower`) are made up of petals (class: `Petal`) which are defined by two 2nd-order (that is, quadratic) Bezier curves (class: `B2`).

Taking a couple of steps back: What, in general, are Bezier curves? What do they look like?

An answer to the first question is provided by this Wikipedia article.

An answer to the second is provided by @Codeslinger's Interactive Bezier Curve Animation. The default for the animation is four control points (a cubic Bezier curve); you need to delete a control point to see a 2nd-order curve.

Class `B2` is simple. An array referred to by field `p` holds the three control points (as `vec2` userdata values) and a function `point(t)` returns the point parameterised by variable `t`:

```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 + 2 * t * t1 * p + t * t * p
end
```

Class `Petal` is also simple. A `mesh` userdata value referred to by field `mesh` holds the mesh for the petal. Local variables `b1` and `b2` refer to the two Bezier curves.

The two curves both start at `0, 0` and end at `0, size`. The middle control points are placed symmetrically at `-as, bs` and `+as, bs`. If `b` is 0.5, then the petal will be symmetical. If `a` is large, then the petal will be fat.

Local variable `v` refers to an array that holds the vertices for the triangles of the mesh. It is initialised with the top and bottom triangles and then helper function `table.append(t1, t2)` is used to add more triangles.

The Codea API function `triangulate` is used to triangulate each quad before its triangles are added to `v`. The top vertices of each quad lie at point `t2` on the curves and the bottom vertices of each quad lie at point `t1` on the curves.

```Petal = class()

function Petal:init(size, a, b)
-- Scale up a and b for size
local as, bs = a * size, b * size
-- Set number of segments for petal
local n = 20
-- Establish the mesh
self.mesh = mesh()
-- Establish the two Bezier curves
local b1 = B2({vec2(0, 0), vec2(-as , bs), vec2(0, size)})
local b2 = B2({vec2(0, 0), vec2(as, bs), vec2(0, size)})
-- Establish the top and bottom triangles
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)}
-- Work through the remaining quads
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
-- Set the vertices of the mesh
self.mesh.vertices = v
end
```

This mesh has a particular location (the origin) and orientation (vertical). The petal also records its location (fields `x` and `y`) and orientation (field `angle`) and the mesh is translated and rotated before it is drawn, accordingly. The petal also records its colour (field `color`).

• Posts: 115

Thank you for taking the time to share. It really helps out newbs such as myself.

• Posts: 666

Great explanation! Nice post, too.

• Posts: 489

The shadow effect mentioned by @aciolino above (see also the screen shot in the updated original post) dramatically improved the quality of the output. It built on an idea for improved contrast here by @KalimMalik.

Each petal is drawn twice, first in transparent black offset a couple of pixels below and to the left (the shadow) and then in the colour of the petal.

```function Petal:draw()
pushMatrix()
translate(self.x - 2, self.y - 2) -- offset a couple of pixels
rotate(self.angle)
self.mesh:setColors(0, 0, 0, 16)  -- transparent black
self.mesh:draw()
popMatrix()
pushMatrix()
translate(self.x, self.y)       -- set location of petal origin on the viewer
rotate(self.angle)              -- rotate the petal about its origin
self.mesh:setColors(self.color) -- the colour of the petal
self.mesh:draw()
popMatrix()
end
```
• Posts: 557

If anyone else is interested in running this, they will find that it stops due to errors when you touch the screen. This is apparently because it was written before Lua had integers, at least that's my best guess, so math.random doesn't know what to do with some decimals that get passed to it.

I tried to account for that by mildly adjusting the code in that section, and I think now it runs like it was meant to. I know this is a very old post but it is still kind of cool.

``````--
-- 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 + 2 * t * t1 * p + t * t * p
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 rParam1 = math.floor(size * 0.95 * 100000)
local rParam2 = math.floor(size * 1.05 * 100000)
local random = math.random(rParam1, rParam2) * 0.00001
local p = Petal(random, 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
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
``````
• Posts: 7,922

@UberGoober The line in the original code just needed to be change to what I show.

Original code

`````` local p = Petal(math.random(size * 0.95, size * 1.05), pa, pb)
``````

Change code

`````` local p = Petal(math.random((size * 0.95)//1, (size * 1.05)//1), pa, pb)
``````
• edited October 2017 Posts: 557

What does `//` do?

• edited October 2017 Posts: 194

It rounds the result of division. `math.floor(20/11) == 20//11`

• Posts: 194
• edited October 2017 Posts: 489

I’ve restored the example image (Dropbox no longer works) and applied @dave1707's fix to update the original code for Lua 5.3.