Little refactor (WIP), more mouse interaction
This commit is contained in:
parent
01642f221f
commit
6cd73c7323
10
README.md
10
README.md
@ -31,13 +31,9 @@ to run the ClojureScript version in the browser.
|
|||||||
|
|
||||||
- Better docs.
|
- Better docs.
|
||||||
- Make things more interactive, e.g. let the user place obstacles.
|
- Make things more interactive, e.g. let the user place obstacles.
|
||||||
- Factor out the potential function rather than burying it in
|
|
||||||
`update-state`.
|
|
||||||
- Visualize amplitude function & potential function. I have
|
- Visualize amplitude function & potential function. I have
|
||||||
`draw-field` which `show-fn` enables, but it is rudimentary.
|
`draw-field` which `show-fn` enables, but it is rudimentary.
|
||||||
- Figure out reasonable boundary behavior. I'd like to do toroidal,
|
|
||||||
but I would need to gradually blend the potential function at the
|
|
||||||
edges for this to work right (otherwise particles are just stuck at
|
|
||||||
the boundaries due to the discontinuity).
|
|
||||||
- Use 'real' simplex or OpenSimplex noise implementation that has a
|
- Use 'real' simplex or OpenSimplex noise implementation that has a
|
||||||
gradient instead of doing it numerically?
|
gradient instead of doing it numerically.
|
||||||
|
- Add multi-octave noise and look into what the paper says about
|
||||||
|
turbulence. (Look up 'advection' technique it mentions too.)
|
||||||
|
|||||||
@ -6,9 +6,9 @@
|
|||||||
(def res-x 500)
|
(def res-x 500)
|
||||||
(def res-y res-x)
|
(def res-y res-x)
|
||||||
;; Number of particles to use:
|
;; Number of particles to use:
|
||||||
(def particles 2000)
|
(def particles 1000)
|
||||||
;; Lower alpha produces *longer* particle trails
|
;; Lower alpha produces *longer* particle trails
|
||||||
(def alpha 40)
|
(def alpha 30)
|
||||||
|
|
||||||
(def renderer #?(:clj :java2d
|
(def renderer #?(:clj :java2d
|
||||||
:cljs :p2d))
|
:cljs :p2d))
|
||||||
@ -56,32 +56,70 @@
|
|||||||
l (+ (dist (max 0.0 dx) (max 0.0 dy)) (min (max dx dy) 0.0))]
|
l (+ (dist (max 0.0 dx) (max 0.0 dy)) (min (max dx dy) 0.0))]
|
||||||
l))
|
l))
|
||||||
|
|
||||||
|
|
||||||
|
;; Domain scale for noise function:
|
||||||
|
(def scale 500.0)
|
||||||
|
;; Amplitude multiplier for noise:
|
||||||
|
(def noise-scale (* scale 5.0))
|
||||||
|
|
||||||
|
(def f-inv (/ scale))
|
||||||
|
;; Potential function (2D + time):
|
||||||
|
(defn potential [x y t]
|
||||||
|
"2D (+ time) potential function. Returns a scalar.
|
||||||
|
|
||||||
|
The absolute value of the scalar doesn't matter, but its gradient of
|
||||||
|
determines particle velocity. "
|
||||||
|
(* noise-scale
|
||||||
|
(+ (q/noise (* f-inv x) (* f-inv y) (* f-inv t))
|
||||||
|
(q/noise (* f-inv x 2.0) (* f-inv y 2.0) (* f-inv t 1.61))
|
||||||
|
)))
|
||||||
|
;; 1.61 is sort of arbitrarily chosen so that periods of the octaves
|
||||||
|
;; don't line up exactly
|
||||||
|
|
||||||
|
;; Delta used for 'gradient'. Multiplying screen width/height by 1e-3
|
||||||
|
;; to 1e-4 usually gives an acceptable value.
|
||||||
|
(def eps 0.5)
|
||||||
|
(def eps-inv (/ eps))
|
||||||
|
|
||||||
|
(defn gradient [p-fn x y t]
|
||||||
|
"Numerical gradient of potential function 'p-fn' via finite differences.
|
||||||
|
|
||||||
|
'p-fn' should be a function that takes 3 arguments - (x,y,t) - and
|
||||||
|
returns a scalar for the potential at that position and time.
|
||||||
|
|
||||||
|
Returns [d/dx, d/dy] of 'p-fn' at (x, y, t)."
|
||||||
|
(let [p (p-fn x y t)
|
||||||
|
p-dx (p-fn (+ x eps) y t)
|
||||||
|
p-dy (p-fn x (+ y eps) t)
|
||||||
|
grad-x (* (- p-dx p) eps-inv)
|
||||||
|
grad-y (* (- p-dy p) eps-inv)]
|
||||||
|
[grad-x grad-y]))
|
||||||
|
|
||||||
|
(defn move-point [x y]
|
||||||
|
"Move a particle by the potential at a point.
|
||||||
|
|
||||||
|
Returns [x y] of the 'updated' point."
|
||||||
|
)
|
||||||
|
|
||||||
(defn update-state [state]
|
(defn update-state [state]
|
||||||
(let [w (q/width)
|
(let [w (q/width)
|
||||||
h (q/height)
|
h (q/height)
|
||||||
;; Overall multiplier for velocity of particle:
|
;; Overall multiplier for velocity of particle:
|
||||||
vf 0.1
|
vf 0.1
|
||||||
;; Domain scale for noise function:
|
|
||||||
scale 500.0
|
|
||||||
;; Amplitude multiplier for noise:
|
|
||||||
noise-scale (* scale 10.0)
|
|
||||||
;; Radius for mouse-thingy:
|
;; Radius for mouse-thingy:
|
||||||
rad 20.0
|
rad 20.0
|
||||||
;; Radius for rounded corners:
|
;; Radius for rounded corners:
|
||||||
rect-rad 100.0
|
rect-rad 100.0
|
||||||
margin 0
|
margin 0
|
||||||
eps (* w 1e-3)
|
|
||||||
mx (q/mouse-x)
|
mx (q/mouse-x)
|
||||||
my (q/mouse-y)
|
my (q/mouse-y)
|
||||||
f-inv (/ scale)
|
|
||||||
;; "width of the modified region":
|
;; "width of the modified region":
|
||||||
d0 150.0
|
d0 200.0
|
||||||
;; distance of point to a circle of radius 'rad'
|
;; distance of point to a circle of radius 'rad'
|
||||||
;; centered at mouse cursor:
|
;; centered at mouse cursor:
|
||||||
d-mouse #(if (q/mouse-pressed?)
|
d-mouse #(if (q/mouse-pressed?)
|
||||||
(- (dist (- mx %1) (- my %2)) rad)
|
(- (dist (- mx %1) (- my %2)) rad)
|
||||||
1e6 ;; arbitrarily large value
|
1e6)
|
||||||
)
|
|
||||||
;; function for distance to the border:
|
;; function for distance to the border:
|
||||||
d-border #(- rect-rad
|
d-border #(- rect-rad
|
||||||
(sdf-box (- %1 rect-rad) ; x
|
(sdf-box (- %1 rect-rad) ; x
|
||||||
@ -90,20 +128,17 @@
|
|||||||
(- h (* rect-rad 2)) ; height
|
(- h (* rect-rad 2)) ; height
|
||||||
))
|
))
|
||||||
;; potential modulation function - takes (x,y):
|
;; potential modulation function - takes (x,y):
|
||||||
amp-fn (fn [_ _] 1.0)
|
amp-fn (fn [x y] (ramp (/ (d-mouse x y) d0)))
|
||||||
;; #(ramp (min (/ (d-mouse %1 %2) d0)
|
;; #(ramp (min (/ (d-mouse %1 %2) d0)
|
||||||
;; (/ (d-border %1 %2) d0)
|
;; (/ (d-border %1 %2) d0)
|
||||||
;; ))
|
;; ))
|
||||||
mouse-drift #(if (q/mouse-pressed?)
|
mouse-drift #(if (or (< mx 0) (< my 0) (> mx w) (> my h))
|
||||||
|
0.0
|
||||||
(+
|
(+
|
||||||
(* (- (/ mx w) 0.5) %2 0.01)
|
(* (- (/ mx w) 0.5) %2 20)
|
||||||
(* (- (/ my h) 0.5) %1 -0.01))
|
(* (- (/ my h) 0.5) %1 -20)))
|
||||||
0.0)
|
|
||||||
;; Noise function - must take 3 arguments, (x,y,z):
|
;; Noise function - must take 3 arguments, (x,y,z):
|
||||||
n-fn #(* noise-scale
|
n-fn #(+ (mouse-drift %1 %2) (potential %1 %2 %3))
|
||||||
(+
|
|
||||||
(mouse-drift %1 %2)
|
|
||||||
(q/noise (* f-inv %1) (* f-inv %2) (* f-inv %3))))
|
|
||||||
;; Overall amplitude function:
|
;; Overall amplitude function:
|
||||||
p-fn #(* vf (amp-fn %1 %2) (n-fn %1 %2 %3))
|
p-fn #(* vf (amp-fn %1 %2) (n-fn %1 %2 %3))
|
||||||
points
|
points
|
||||||
@ -113,25 +148,28 @@
|
|||||||
border (if (and (and (> x margin) (< x (- w margin)))
|
border (if (and (and (> x margin) (< x (- w margin)))
|
||||||
(and (> y margin) (< x (- h margin))))
|
(and (> y margin) (< x (- h margin))))
|
||||||
1.0 0.0)
|
1.0 0.0)
|
||||||
;; Potential at (x, y, z):
|
|
||||||
n (p-fn x y z)
|
f #(* vf
|
||||||
n-dx (p-fn (+ x eps) y z)
|
(+ (mouse-drift %1 %2)
|
||||||
n-dy (p-fn x (+ y eps) z)
|
(* (potential %1 %2 %3)
|
||||||
;; Velocity by finite differences:
|
(amp-fn %1 %2))))
|
||||||
vx (/ (- n-dy n) eps)
|
[gx gy] (gradient f x y z)
|
||||||
vy (/ (- n n-dx) eps)
|
|
||||||
;; Updated point position:
|
;; Update points (move perpendicular to gradient):
|
||||||
x2 (+ x vx)
|
x2 (+ x gy)
|
||||||
y2 (+ y vy)
|
y2 (- y gx)
|
||||||
[x3 y3] (if (or (< x2 0) (> x2 w) (< y2 0) (> y2 h))
|
[x3 y3] (if (or (< x2 0) (> x2 w) (< y2 0) (> y2 h))
|
||||||
[(q/random w) (q/random h)]
|
[(q/random w) (q/random h)]
|
||||||
[x2 y2])
|
[x2 y2])
|
||||||
;; This boundary behavior is a little more
|
;; This boundary behavior is a little more
|
||||||
;; interesting: when a particle leaves the edges,
|
;; interesting: when a particle leaves the edges,
|
||||||
;; it just reappears in a random place.
|
;; it just reappears in a random place.
|
||||||
|
[x4 y4] (if (and (q/mouse-pressed?) (< (dist (- mx x) (- my y)) rad))
|
||||||
|
[(q/random w) (q/random h)]
|
||||||
|
[x3 y3])
|
||||||
]
|
]
|
||||||
|
|
||||||
[x3 y3]
|
[x4 y4]
|
||||||
)) (:grid state))]
|
)) (:grid state))]
|
||||||
(-> state
|
(-> state
|
||||||
(update :frame inc)
|
(update :frame inc)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user