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

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

## Comments

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

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!

This is a really beautiful demo. Great colour choices.

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.

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

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`

: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.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`

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

Great explanation! Nice post, too.

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.

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.

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

Original code

Change code

What does

`//`

do?It rounds the result of division.

`math.floor(20/11) == 20//11`

https://www.lua.org/manual/5.3/manual.html#3.4.1

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