Skip to content

Commit b70a08e

Browse files
committed
Chapter 0 Exercise 10
1 parent b1d26ff commit b70a08e

File tree

4 files changed

+133
-22
lines changed

4 files changed

+133
-22
lines changed

notebooks/chapter_0.md

+14
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,17 @@ Well this one is pretty cool. The sliders control (in order from left to right):
252252
* Amount `yoff` is incremented by
253253

254254
Finally there is a checkbox to enable animation using the 3rd dimension of the perlin noise.
255+
256+
257+
## [Exercise 0.9: Perlin Noise Landscape](https://natureofcode.com/random/#exercise-09)
258+
259+
```clojure
260+
^{::clerk/no-cache true ::clerk/viewer clerk/code}
261+
(slurp "src/noc/chapter_0_10e.cljs")
262+
(show-sketch :c0.10e)
263+
```
264+
265+
The performance for this one is pretty bad here in the notebook. I'm not 100%
266+
sure why. I switched from a naive nested 2-d vector to using transients, but
267+
that didn't have much of an effect. Some day I'll come back and investigate
268+
more.

src/noc/chapter_0_10e.cljs

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
(ns noc.chapter-0-10e
2+
(:require
3+
[quil.sketch :as ap :include-macros true]
4+
[quil.core :as q]))
5+
6+
(def size [640 240])
7+
8+
(defn init-terrain [cell-size width height]
9+
(let [cols (quot width cell-size)
10+
rows (quot height cell-size)]
11+
{:cell-size cell-size
12+
:w width
13+
:h height
14+
:cols cols
15+
:rows rows
16+
:zoff 0.0
17+
:cells []}))
18+
19+
;; My initial naive impl
20+
#_(defn tick-terrain [{:keys [cols rows zoff] :as terrain}]
21+
(let [updated-cells (vec (map-indexed
22+
(fn [i _]
23+
(vec (map-indexed
24+
(fn [j _]
25+
(q/map-range (q/noise (+ (* i 0.1) zoff) (+ (* j 0.1) zoff) zoff) 0 1 -120 120))
26+
(range rows))))
27+
(range cols)))
28+
new-zoff (+ zoff 0.01)]
29+
(assoc terrain :cells updated-cells :zoff new-zoff)))
30+
31+
;; Using transients to try and speed it up
32+
(defn tick-terrain [{:keys [cols rows zoff] :as terrain}]
33+
(let [updated-cells (persistent!
34+
(reduce
35+
(fn [acc i]
36+
(assoc! acc i
37+
(persistent!
38+
(reduce
39+
(fn [inner-acc j]
40+
(assoc! inner-acc j
41+
(q/map-range (q/noise (+ (* i 0.1) zoff) (+ (* j 0.1) zoff) zoff) 0 1 -120 120)))
42+
(transient []) (range rows)))))
43+
(transient []) (range cols)))
44+
new-zoff (+ zoff 0.01)]
45+
(assoc terrain :cells updated-cells :zoff new-zoff)))
46+
47+
(defn init-state [{:keys [width height]}]
48+
{:terrain
49+
(tick-terrain (init-terrain 20 800 400))
50+
:theta 0.0})
51+
52+
(defn setup! [{:keys [width height terrain]}]
53+
(q/background 255))
54+
55+
(defn tick [state]
56+
(-> state
57+
(update :terrain tick-terrain)
58+
(update :theta #(+ % 0.0025))))
59+
60+
(defn draw-terrain! [{:keys [cells cell-size cols rows w h]}]
61+
(doseq [x (range (dec cols))]
62+
;; Quil bug https://github.com/quil/quil/issues/415
63+
(.beginShape (ap/current-applet) (aget js/p5.prototype "QUAD_STRIP"))
64+
(doseq [y (range rows)]
65+
(q/stroke 0)
66+
(let [current-elevation (get-in cells [x y])
67+
current-shade (q/map-range current-elevation -120 120 0 255)
68+
x-coordinate (- (* x cell-size) (/ w 2))
69+
y-coordinate (- (* y cell-size) (/ h 2))]
70+
(q/fill current-shade 255)
71+
(q/vertex x-coordinate y-coordinate current-elevation)
72+
(q/vertex (+ x-coordinate cell-size) y-coordinate (get-in cells [(inc x) y]))))
73+
(q/end-shape)))
74+
75+
(defn draw! [{:keys [terrain theta] :as state}]
76+
(q/background 255)
77+
(q/push-style)
78+
(q/push-matrix)
79+
(q/translate 0 20 -200)
80+
(q/rotate-x (/ q/PI 3))
81+
(q/rotate-z theta)
82+
(draw-terrain! terrain)
83+
(q/pop-matrix)
84+
(q/pop-style))

src/noc/sketch.clj

+8
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,11 @@
66
:tick ~(symbol (str chapter "/tick"))
77
:draw ~(symbol (str chapter "/draw!"))
88
:size ~(symbol (str chapter "/size"))})
9+
10+
(defmacro sketch-3d-> [chapter]
11+
`{:init ~(symbol (str chapter "/init-state"))
12+
:setup ~(symbol (str chapter "/setup!"))
13+
:tick ~(symbol (str chapter "/tick"))
14+
:draw ~(symbol (str chapter "/draw!"))
15+
:size ~(symbol (str chapter "/size"))
16+
:renderer :p3d})

src/noc/sketch.cljs

+27-22
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
(ns noc.sketch
2-
(:require-macros [noc.sketch :refer [sketch->]])
2+
(:require-macros [noc.sketch :refer [sketch-> sketch-3d->]])
33
(:require [quil.core :as q]
44
[quil.middleware :as m]
55
[quil.sketch :as ap :include-macros true]
@@ -17,22 +17,25 @@
1717
[noc.chapter-0-7e :as c0.7e]
1818
[noc.chapter-0-7 :as c0.7]
1919
[noc.chapter-0-8e :as c0.8e]
20-
[noc.chapter-0-9e :as c0.9e]))
20+
[noc.chapter-0-9e :as c0.9e]
21+
[noc.chapter-0-10e :as c0.10e]))
2122

22-
(def sketches {:walker (sketch-> c0.1)
23-
:rand-dist (sketch-> c0.2)
24-
:walker-right (sketch-> c0.3)
25-
:walker-dynamic (sketch-> c0.3e)
26-
:random-gaussian (sketch-> c0.4)
27-
:c0.4e (sketch-> c0.4e)
28-
:c0.5e (sketch-> c0.5e)
29-
:c0.5 (sketch-> c0.5)
30-
:c0.6e (sketch-> c0.6e)
31-
:c0.6 (sketch-> c0.6)
32-
:c0.7e (sketch-> c0.7e)
33-
:c0.7 (sketch-> c0.7)
34-
:c0.8e (sketch-> c0.8e)
35-
:c0.9e (sketch-> c0.9e)})
23+
(def sketches
24+
{:walker (sketch-> c0.1)
25+
:rand-dist (sketch-> c0.2)
26+
:walker-right (sketch-> c0.3)
27+
:walker-dynamic (sketch-> c0.3e)
28+
:random-gaussian (sketch-> c0.4)
29+
:c0.4e (sketch-> c0.4e)
30+
:c0.5e (sketch-> c0.5e)
31+
:c0.5 (sketch-> c0.5)
32+
:c0.6e (sketch-> c0.6e)
33+
:c0.6 (sketch-> c0.6)
34+
:c0.7e (sketch-> c0.7e)
35+
:c0.7 (sketch-> c0.7)
36+
:c0.8e (sketch-> c0.8e)
37+
:c0.9e (sketch-> c0.9e)
38+
:c0.10e (sketch-3d-> c0.10e)})
3639

3740
(defn load-sketch [s]
3841
(when-let [sk (get sketches s)]
@@ -141,12 +144,14 @@
141144

142145
(defn show-sketch [adjust-frame {:keys [init setup tick draw size] :as opts} el]
143146
{:applet (apply q/sketch (apply concat
144-
(-> opts
145-
(assoc :middleware [m/fun-mode])
146-
(assoc :host el)
147-
(assoc :update (partial tick-wrapper tick))
148-
(assoc :setup (partial setup-wrapper (partial adjust-frame el) init setup))
149-
(assoc :draw (partial draw-wrapper draw)))))
147+
(doto
148+
(-> opts
149+
(assoc :middleware [m/fun-mode])
150+
(assoc :host el)
151+
(assoc :update (partial tick-wrapper tick))
152+
(assoc :setup (partial setup-wrapper (partial adjust-frame el) init setup))
153+
(assoc :draw (partial draw-wrapper draw)))
154+
prn)))
150155
:sketch-name (:sketch-name opts)
151156
:opts opts
152157
:el el})

0 commit comments

Comments
 (0)