;;; Scheme Recursive Art Contest Entry
;;;
;;; Please do not include your name or personal info in this file.
;;;
;;; Title: Parentheses Out For Harambe
;;;
;;; Description:
;;;
;;; Cincinnati Zoo.
;;; He was just a gorilla.
;;; But now, he's a god.
; If you are interested in rendering this, I would recommend lowering NUM_CUTS
; and then doing something else, like passing spring semester courses, before
; coming back to check if this has finished.
; Rendering instructions:
; 1. Be very, very, very, (define (f n) (if (> n 0) (begin (print "very, ") (f (- n 1)))))(f 1000000000) very patient.
; 2. Repeat the previous step a few billion times.
; 3. Write out the next few billion steps following the template "Repeat the previous step a few billion times.".
; 7. Write out the next few billion steps following the template "Repeat the previous step a few billion times.".
; 7. Write out the next few billion steps following the template "Repeat the previous step a few billion times.".
; 8. We're now at depth 3. Repeat until depth is roughly a few billion.
; 9. Assuming the universe has not ended yet, invent a time machine, and start at 1 again, loop through the steps a few billion times for good measure.
; 10. Hopefully it's finished now (it will almost certainly take upwards of a few hours). If not, please wait a bit longer.
; 11. The screenshot provided uses (define NUM_CUTS 50). This takes an absurd amount of time to render (read: days-weeks).
; This number represents how many line segments each bezier curve is broken up into; for a much faster render (with less smooth curves),
; you can reduce this from 50 to 4-5. Do still expect to wait a long time; rendering with NUM_CUTS=4 on derby took hours.
; It's also possible to parallelize the drawing process a bit if desired: edit tscheme_pixel in scheme_primitives.py to print out (pixel X Y COLOR)
; instead of drawing it, then change START/END to be, say, 0/131071 for the first instance, and 131072/262143 for the second instance.
; Pipe the output to a single file, and then combine and run with the standard pixel instruction to draw.
; How many cuts to break each bezier curve into.
; I would suggest not lowering this beyond 4-5, as that's
; the point where the figure is no longer recognizable.
; Above 20 or so, and you're looking at days-weeks of render time.
(define NUM_CUTS 50)
; START index (0 <= START < END)
(define START 0)
; END index (START < END < 262144 = 2^9*2^9 - 1)
(define END 262143)
(define (draw)
(hideturtle)
(speed 0)
(define (clamp t) (cond ((< t 0) 0) ((> t 1) 1) (else t)))
(define (here-be-memes curves i)
(define (distance point p1) (hypot (- (car point) (car p1)) (- (cdr point) (cdr p1))))
(define (memes x t last point sum sumweight)
(define (bezier s n)
(+
(* (car s) (expt (- 1 t) 3))
(* (car (cdr s)) 3 (expt (- 1 t) 2) t)
(* (car (cdr (cdr s))) 3 (- 1 t) t t)
(* (car (cdr (cdr (cdr s)))) t t t)))
(if (null? x)
(let ((L (/ sum sumweight)))
(define (cmp p) (clamp (+ L (* p (- 1 (abs (+ L L -1)))))))
(pixel (+ 50 (car point)) (+ 50 (cdr point)) (rgb (cmp -.49) (cmp 0) (cmp .49)))
(forward 0))
(let ((next (cons (bezier (car (car x)) 3) (bezier (cdr (car x)) 3)))
(lx (car last))
(ly (cdr last)))
(define (dot c) (+ (* (- (car c) lx) (- (car next) lx)) (* (- (cdr c) ly) (- (cdr next) ly))))
(define (closest-segment-point)
(let ((t (/ (dot point) (dot next))))
(cons (+ lx (* (- (car next) lx) (clamp t))) (+ ly (* (- (cdr next) ly) (clamp t))))))
(if
(> t 1)
(memes (cdr x) 0 next point sum sumweight)
(if (zero? t)
(memes x (+ t (/ 1 NUM_CUTS)) next point sum sumweight)
(let ((source (closest-segment-point)))
(define dps (distance point source))
(define fsdps (* 4 (sqrt dps)))
(define wave-dps (* (exp (* dps -0.02)) (cos fsdps)))
(let
((phi1 (atan2 (- (* -0.02 wave-dps fsdps) (* 8 (exp (* -0.02 dps)) (sin fsdps))) fsdps)))
(define (light-source x y z)
; does anyone recognize the spherical law of cosines?
(let ((phi (atan2 (distance point (cons x y)) (- z wave-dps))))
(abs (+
(* (sin phi1) (sin phi) (cos (-
(atan2 (- (cdr point) (cdr source)) (- (car point) (car source))) (atan2 (- y (cdr point)) (- x (car point))))))
(* (cos phi1) (cos phi))))))
(define L1 (light-source -250 600 100))
(define L2 (light-source -150 600 100))
(define L3 (light-source -50 600 100))
(define L4 (light-source 50 600 100))
(define L5 (light-source 150 600 100))
(define L6 (light-source 256 600 100))
(define L7 (light-source 356 600 100))
(define L8 (light-source 456 600 100))
(define L9 (light-source 556 600 100))
(define LA (light-source 656 600 100))
(define LB (light-source 756 600 100))
(define L (/ (+ L1 L2 L3 L4 L5 L6 L7 L8 L9 LA LB) 11))
(memes x (+ t (/ 1 NUM_CUTS)) next point
(+ sum (/ (* 1000000 L) (* dps dps dps dps)))
(+ sumweight (/ 1000000 (* dps dps dps dps)))))))))))
(memes curves 0 (cons (modulo i 512) (quotient i 512)) (cons (modulo i 512) (quotient i 512)) 0 0)
(if (= i START) () (here-be-memes curves (- i 1))))
; here be the bezier curves. changing things will change the curve drawn.
; here is also where all those tokens went.
(here-be-memes '(((147.1 -138.2 650.2 364.9) . (399.1 -74.30000000000001 -74.30000000000001 399.1))
((147.1 223.6 288.4 364.9) . (399.1 435.1 435.1 399.1))
((147.1 144.39999999999998 367.6 364.9) . (399.1 486.4 486.4 399.1))
((210.1 219.1 292.9 301.9) . (349.6 360.4 360.4 349.6))
((120.1 82.29999999999998 429.70000000000005 391.9) . (347.8 310.9 310.9 347.8))
((163.3 191.2 256 256) . (326.2 189.39999999999998 276.7 324.4))
((348.7 320.8 256 256) . (326.2 189.39999999999998 276.7 324.4))
((213.7 268.6 115.6 256) . (253.3 213.7 138.1 152.5))
((298.3 243.4 396.4 256) . (253.3 213.7 138.1 152.5))
((256 256 238.9 236.2) . (193.9 228.1 217.3 216.4))
((256 256 273.1 275.8) . (193.9 228.1 217.3 216.4))
((236.2 235.3 242.5 256) . (216.4 210.1 189.39999999999998 194.8))
((275.8 276.7 269.5 256) . (216.4 210.1 189.39999999999998 194.8)))
END)
(exitonclick))
(draw)