Skip to content

Instantly share code, notes, and snippets.

@quephird
Last active August 29, 2015 13:57
Show Gist options
  • Save quephird/9651977 to your computer and use it in GitHub Desktop.
Save quephird/9651977 to your computer and use it in GitHub Desktop.
This was a procedural version of drawing I made using ArtRage for the iPad and inspired by lichens: http://quephird.deviantart.com/art/lichens-434718646. This code makes me retch, but it's functional and I need to mull things over a bit before I return to it.
(ns procedural-lichens
(:use quil.core))
(def screen-w 2880)
(def screen-h 1800)
(def lichens (atom []))
(defn intersects? [[x1 y1 r1] [x2 y2 r2]]
"Determines if the two circles passed in intersect"
(let [dx (- x2 x1)
dy (- y2 y1)
distance-squared (+ (* dx dx) (* dy dy))
sum-of-radii-squared (* (+ r1 r2) (+ r1 r2))]
(<= distance-squared sum-of-radii-squared)))
(defn intersects-any? [test-circle existing-circles]
"Determines if the test circle intersects with any of the existing circles"
(some true? (map #(intersects? test-circle %) existing-circles)))
(defn random-circle [[min-x max-x min-y max-y min-r max-r] existing-circles]
"Returns a random representation of a circle that does not intersect
with the set of circles passed in. The parameters of the resultant circle
are further restricted to the min and max values for x, y, and r."
(let [x (+ min-x (random (- max-x min-x)))
y (+ min-y (random (- max-y min-y)))
r (+ min-r (random (- max-r min-r)))]
(if (intersects-any? [x y r] existing-circles)
(recur [min-x max-x min-y max-y min-r max-r] existing-circles)
[x y r])))
(defn random-color [seed-c variance]
"Returns a color that is a slight, random deviation from the seeded color"
(let [dc (repeatedly 3 (fn [] (- (* variance 0.5) (random variance))))]
(map + seed-c dc)))
(defn apothecia [max-r cup-c]
"Renders the set of spore cups for the center of a particular lichen"
(apply fill cup-c)
(no-stroke)
; TODO:
;
; Need better distribution of cups
(doseq [_ (range 20)]
(let [x (random (- max-r) max-r)
y (random (- max-r) max-r)
w (random (* max-r 0.2) (* max-r 0.4))
l (* w (random 1 1.2))
φ (random 180)]
(push-matrix)
(rotate (radians φ))
(ellipse x y w l)
(pop-matrix))))
(defn- lichen [outer-r outer-lobes outer-c]
"Renders a lichen, randomizing each of the lobes of each layer"
(let [sw (/ (* PI outer-r) outer-lobes)
multipliers [1 0.85 0.7]
rs (map #(* % outer-r) multipliers)
lobess (map #(* % outer-lobes) multipliers)
cs (map (fn [m] (map (fn [c] (* m c)) outer-c)) multipliers)
layers (map vector rs lobess cs)
apothecia-r (* outer-r 0.6)
apothecia-c (map #(* % 0.4) outer-c)]
(stroke-weight sw)
; Render each of the three layers
(doseq [[r lobes c] layers]
(apply stroke c)
(let [dθ (/ 360 lobes)]
(doseq [_ (range lobes)]
(let [left-dx (rand-int 20)
right-dx (rand-int 20)
dy (rand-int 20)]
(bezier 0 0 0 0 0 (+ r dy) (- left-dx) (+ r dy))
(bezier 0 0 0 0 0 (+ r dy) right-dx (+ r dy))
(rotate (radians dθ))))))
(apothecia apothecia-r apothecia-c)))
(defn all-lichens []
(doseq [each_lichen (range 32)]
(let [[x y r] (random-circle [0 screen-w 0 screen-h 100 200] @lichens)
lobes (+ 20 (random 5))
c (random-color [255 127 0] 50)]
(push-matrix)
(translate x y)
(lichen r lobes c)
(pop-matrix)
(swap! lichens conj [x y r]))))
(defn rock-surface []
; Base color
(background (+ 20 (random 50)))
(push-matrix)
; Base skew angle
(rotate (radians (random 45)))
(doseq [x (repeatedly 25 (fn [] (random screen-w)))]
; Vary the thickness of each stroke
(stroke-weight (+ 100 (random 200)))
; Vary the shade of grey
(stroke (+ 50 (random 50)))
; Rotate each stroke a little bit from the baseline angle
(push-matrix)
(rotate (radians (random 10)))
(line x (- screen-h) x screen-h)
(pop-matrix))
(pop-matrix))
(defn setup []
(smooth)
(background 0)
(no-loop))
(defn draw []
; TODO:
;
; Need to introduce clumping; randomly choose starting number 2 to 4 and clump around them
(rock-surface)
(all-lichens))
(sketch
:title "procedural lichens"
:setup setup
:draw draw
:renderer :java2d
:size [screen-w screen-h])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment