             [thi.ng.geom.core.matrix :refer [M44]]
             [thi.ng.geom.aabb        :refer [aabb]]
             [thi.ng.geom.basicmesh   :as bm]
+            [thi.ng.geom.circle      :refer [circle]]
+            [thi.ng.geom.sphere      :refer [sphere]]
             [thi.ng.math.core        :as m]))
 
 (defn expand-l-system

  "Returns a mesh generated by an L-System that produces 3D version of a Koch curve."
  []
  (build-lsystem (constantly (m/radians 90))
                 (partial grow-cuboid 3)
                 (expand-l-system {\F "FF-F-F&F-F-F+F"} "F" 3)))

(defn toroid
  "Generates a toroid using the L-System support functions."

  [[M44] (bm/basic-mesh)])

(defn grow-cuboid
  "Add a cuboid branch of `length` to `mesh` using position and rotation in the 4x4 matrix `mat`."
  [length mat mesh]
  (let [curr-mat (last mat)]
    [(conj (pop mat) (g/translate curr-mat 0 0 length))
     (g/into mesh (-> (aabb (vec3 -0.25 -0.25 0) (vec3 0.5 0.5 length))
                      (g/transform curr-mat)
                      (g/as-mesh)))]))

(defn grow-cylinder
  "Add a cylinder branch of `length` to `mesh` using position and rotation in the 4x4 matrix `mat`."
  [thickness length mat mesh]
  (let [curr-mat (last mat)]
    [(conj (pop mat) (g/translate curr-mat 0 0 length))
     (let [tube (-> (circle thickness)
                    (g/center)
                    (g/extrude {:depth length}))
           ball (-> (sphere thickness) ;; for nicer joins
                    (g/center)
                    (g/as-mesh))]
       (g/into mesh (g/transform (g/into tube ball) curr-mat)))]))

(defn- execute-op
  "Execute a single L-System operation and return the new state of the system. The `angle-fn` is used to determine angle changes and the `grow-fn` to extend a branch."
