src/looms/001-triangles.lisp @ 19aeb5ea3df9
Switch to 3d-vectors (partially)
| author | Steve Losh <steve@stevelosh.com> |
|---|---|
| date | Wed, 04 Apr 2018 23:37:07 -0400 |
| parents | b098ec32e059 |
| children | ebe16cb914fb |
(in-package :flax.looms.001-triangles) ;;;; Triangle Subdivision ;;; ;;; Based on http://www.tylerlhobbs.com/writings/triangle-subdivision ;;;; Utils -------------------------------------------------------------------- (defun round-to (number divisor) (* divisor (round number divisor))) ;;;; Elements ----------------------------------------------------------------- (defstruct (triangle (:conc-name "")) (a (vec 0 0) :type vec2) (b (vec 0 0) :type vec2) (c (vec 0 0) :type vec2)) (define-with-macro (triangle :conc-name "") a b c) (defun triangle (a b c) (make-triangle :a a :b b :c c)) ;;;; Element Conversion ------------------------------------------------------- (defun convert-triangle (triangle) (with-triangle (triangle) (flax.drawing:triangle (coord (vx a) (vy a)) (coord (vx b) (vy b)) (coord (vx c) (vy c))))) (defun convert (universe) (mapcar #'convert-triangle universe)) ;;;; Generation --------------------------------------------------------------- (defun initial-triangles () (list (triangle (vec 0 1) (vec 1 1) (vec 0 0)) (triangle (vec 1 0) (vec 1 1) (vec 0 0)))) (defun split-triangle-evenly (triangle) (with-triangle (triangle) (let* ((n 1/2) (p (vec2 (lerp (vx b) (vx c) n) (lerp (vy b) (vy c) n)))) (list (triangle p b a) (triangle p a c))))) (defun generate-universe-even (depth &aux (triangles (initial-triangles))) (do-repeat depth (zapf triangles (mappend #'split-triangle-evenly %))) triangles) (defun find-longest-side (triangle) (with-triangle (triangle) (let* ((ab (vdistance a b)) (bc (vdistance b c)) (ca (vdistance c a)) (longest (max ab bc ca))) (cond ((= longest ab) (list c a b)) ((= longest bc) (list a c b)) ((= longest ca) (list b c a)) (t (error "what?")))))) (defun split-triangle-self-balancing (triangle) (destructuring-bind (a b c) (find-longest-side triangle) (let ((p (-<> (random-gaussian 0.5 0.1 #'rand) (clamp 0.3 0.7 <>) (round-to <> 1/100) (vlerp b c <>)))) (list (triangle p b a) (triangle p a c))))) (defun generate-universe-balancing (depth) (gathering (labels ((should-stop-p (iteration) (or (= depth iteration) (and (> iteration 6) (randomp (map-range 0 depth 0.0 0.05 iteration) #'rand)))) (recur (triangle &optional (iteration 0)) (if (should-stop-p iteration) (gather triangle) (map nil (rcurry #'recur (1+ iteration)) (split-triangle-self-balancing triangle))))) (map nil #'recur (initial-triangles))))) ;;;; Main --------------------------------------------------------------------- (defun loom (seed filename filetype width height &key depth) (nest (with-seed seed) (randomly-initialize ((depth (random-range-inclusive 14 19 #'rand)))) (flax.drawing:with-rendering (canvas filetype filename width height)) (progn (-<> (generate-universe-balancing depth) convert (flax.drawing:render canvas <>)) (values depth)))) ;; (time (loom nil "out" :svg 800 800))