Add thi.ng.geom.physics based sketch
This commit is contained in:
parent
2c7a630adb
commit
2716edb747
1 changed files with 107 additions and 0 deletions
107
src/aphorisms/thirty_eight.clj
Normal file
107
src/aphorisms/thirty_eight.clj
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
(ns aphorisms.thirty-eight
|
||||
(:require [thi.ng.geom.core :as g]
|
||||
[thi.ng.geom.physics.core :as phys]
|
||||
[thi.ng.geom.vector :as v]
|
||||
[quil.core :as q]
|
||||
[quil.middleware :as qm]
|
||||
[thi.ng.geom.rect :as r]
|
||||
[thi.ng.geom.circle :as c]))
|
||||
|
||||
;; toying around with thi.ng.geom.physics; loosely based on
|
||||
;; https://piped.video/watch?v=3v7SsOdxxww, which explains toxiclibs verlet
|
||||
;; physics and trying to get close to the differential line growth algorithm
|
||||
;; described in https://inconvergent.net/generative/differential-line
|
||||
|
||||
(def bounds (r/rect 500 500))
|
||||
(def radius 10)
|
||||
(def shape (-> (c/circle 100)
|
||||
(g/translate (g/centroid bounds))
|
||||
(g/as-polygon)))
|
||||
|
||||
(defn world []
|
||||
;; play around with this, re-evaluate it and hit `r` in a running sketch!
|
||||
(let [particles (mapv (fn [p]
|
||||
(phys/particle p 10)) (g/vertices shape))
|
||||
edges (->> (cycle particles)
|
||||
(partition-all 2 1)
|
||||
(take (count particles)))]
|
||||
(phys/physics
|
||||
{:particles particles
|
||||
:springs (mapv (fn [[a b]]
|
||||
(phys/spring a b (/ (g/circumference shape) (count particles) 2) 0.1)) edges)
|
||||
:drag 1
|
||||
:constraints {:bounds (phys/shape-constraint-inside bounds)}
|
||||
#_#_:listeners {:iter (fn [world _n]
|
||||
;; record a history of all particle positions
|
||||
(swap! state update :history conj (mapv phys/position (:particles world))))}})))
|
||||
|
||||
(def tmp (world))
|
||||
|
||||
(defn setup []
|
||||
(q/frame-rate 30)
|
||||
(q/color-mode :hsb 360 100 100)
|
||||
(q/rect-mode :center)
|
||||
(q/ellipse-mode :center)
|
||||
(q/background 350)
|
||||
{:world (world)})
|
||||
|
||||
(defn mouse-pressed [state ev]
|
||||
(let [rsq (* radius radius)
|
||||
mouse (v/vec2 ev)
|
||||
hits (into #{}
|
||||
(filter #(<= (g/dist-squared (phys/position %) mouse) rsq))
|
||||
(-> state :world :particles))]
|
||||
(when hits
|
||||
(doseq [hit hits] ; dirty dirty side effects
|
||||
(phys/lock hit)))
|
||||
(assoc state :hits hits)))
|
||||
|
||||
(defn mouse-dragged [state ev]
|
||||
(let [mouse (v/vec2 ev)]
|
||||
(doseq [p (:hits state)] ; again, embracing the side-effects in thi.ng.geom.physics
|
||||
(phys/set-position p mouse)))
|
||||
state)
|
||||
|
||||
(defn mouse-released [state _ev]
|
||||
(doseq [hit (:hits state)] ; side effects everywhere
|
||||
(phys/unlock hit))
|
||||
(dissoc state :hits))
|
||||
|
||||
(defn key-pressed [state ev]
|
||||
(case (:key ev)
|
||||
:r (assoc state :world (world))
|
||||
state))
|
||||
|
||||
(defn update-state [state]
|
||||
(update state :world phys/timestep 1))
|
||||
|
||||
(defn draw-state [state]
|
||||
(q/background 180 0 98)
|
||||
(q/no-stroke)
|
||||
(doseq [particle (-> state :world :particles)]
|
||||
(let [[x y] (phys/position particle)
|
||||
color (if ((:hits state #{}) particle)
|
||||
[100 80 80]
|
||||
[100 20 80])]
|
||||
(apply q/fill color)
|
||||
(q/ellipse x y radius radius)))
|
||||
(doseq [{pa :a pb :b} (-> state :world :springs)]
|
||||
(let [color [100 20 80]]
|
||||
(apply q/stroke color)
|
||||
(q/line (phys/position pa) (phys/position pb)))))
|
||||
|
||||
#_:clj-kondo/ignore
|
||||
(q/defsketch thirty-eight
|
||||
:title "Thirty eight"
|
||||
:size [(g/width bounds) (g/height bounds)]
|
||||
:settings #(q/pixel-density (q/display-density))
|
||||
:setup setup
|
||||
:key-pressed key-pressed
|
||||
:mouse-pressed mouse-pressed
|
||||
:mouse-dragged mouse-dragged
|
||||
:mouse-released mouse-released
|
||||
:update update-state
|
||||
:draw draw-state
|
||||
#_#_:renderer :p2d
|
||||
:features [:keep-on-top :no-bind-output]
|
||||
:middleware [qm/pause-on-error qm/fun-mode])
|
||||
Loading…
Add table
Add a link
Reference in a new issue