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.
|
||||
- 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
|
||||
`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
|
||||
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-y res-x)
|
||||
;; Number of particles to use:
|
||||
(def particles 2000)
|
||||
(def particles 1000)
|
||||
;; Lower alpha produces *longer* particle trails
|
||||
(def alpha 40)
|
||||
(def alpha 30)
|
||||
|
||||
(def renderer #?(:clj :java2d
|
||||
:cljs :p2d))
|
||||
@ -56,32 +56,70 @@
|
||||
l (+ (dist (max 0.0 dx) (max 0.0 dy)) (min (max dx dy) 0.0))]
|
||||
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]
|
||||
(let [w (q/width)
|
||||
h (q/height)
|
||||
;; Overall multiplier for velocity of particle:
|
||||
vf 0.1
|
||||
;; Domain scale for noise function:
|
||||
scale 500.0
|
||||
;; Amplitude multiplier for noise:
|
||||
noise-scale (* scale 10.0)
|
||||
;; Radius for mouse-thingy:
|
||||
rad 20.0
|
||||
;; Radius for rounded corners:
|
||||
rect-rad 100.0
|
||||
margin 0
|
||||
eps (* w 1e-3)
|
||||
mx (q/mouse-x)
|
||||
my (q/mouse-y)
|
||||
f-inv (/ scale)
|
||||
;; "width of the modified region":
|
||||
d0 150.0
|
||||
d0 200.0
|
||||
;; distance of point to a circle of radius 'rad'
|
||||
;; centered at mouse cursor:
|
||||
d-mouse #(if (q/mouse-pressed?)
|
||||
(- (dist (- mx %1) (- my %2)) rad)
|
||||
1e6 ;; arbitrarily large value
|
||||
)
|
||||
1e6)
|
||||
;; function for distance to the border:
|
||||
d-border #(- rect-rad
|
||||
(sdf-box (- %1 rect-rad) ; x
|
||||
@ -90,20 +128,17 @@
|
||||
(- h (* rect-rad 2)) ; height
|
||||
))
|
||||
;; 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)
|
||||
;; (/ (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)
|
||||
(* (- (/ my h) 0.5) %1 -0.01))
|
||||
0.0)
|
||||
(* (- (/ mx w) 0.5) %2 20)
|
||||
(* (- (/ my h) 0.5) %1 -20)))
|
||||
;; Noise function - must take 3 arguments, (x,y,z):
|
||||
n-fn #(* noise-scale
|
||||
(+
|
||||
(mouse-drift %1 %2)
|
||||
(q/noise (* f-inv %1) (* f-inv %2) (* f-inv %3))))
|
||||
n-fn #(+ (mouse-drift %1 %2) (potential %1 %2 %3))
|
||||
;; Overall amplitude function:
|
||||
p-fn #(* vf (amp-fn %1 %2) (n-fn %1 %2 %3))
|
||||
points
|
||||
@ -113,25 +148,28 @@
|
||||
border (if (and (and (> x margin) (< x (- w margin)))
|
||||
(and (> y margin) (< x (- h margin))))
|
||||
1.0 0.0)
|
||||
;; Potential at (x, y, z):
|
||||
n (p-fn x y z)
|
||||
n-dx (p-fn (+ x eps) y z)
|
||||
n-dy (p-fn x (+ y eps) z)
|
||||
;; Velocity by finite differences:
|
||||
vx (/ (- n-dy n) eps)
|
||||
vy (/ (- n n-dx) eps)
|
||||
;; Updated point position:
|
||||
x2 (+ x vx)
|
||||
y2 (+ y vy)
|
||||
|
||||
f #(* vf
|
||||
(+ (mouse-drift %1 %2)
|
||||
(* (potential %1 %2 %3)
|
||||
(amp-fn %1 %2))))
|
||||
[gx gy] (gradient f x y z)
|
||||
|
||||
;; Update points (move perpendicular to gradient):
|
||||
x2 (+ x gy)
|
||||
y2 (- y gx)
|
||||
[x3 y3] (if (or (< x2 0) (> x2 w) (< y2 0) (> y2 h))
|
||||
[(q/random w) (q/random h)]
|
||||
[x2 y2])
|
||||
;; This boundary behavior is a little more
|
||||
;; interesting: when a particle leaves the edges,
|
||||
;; 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))]
|
||||
(-> state
|
||||
(update :frame inc)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user