Created
December 4, 2013 23:11
-
-
Save yogthos/7797316 to your computer and use it in GitHub Desktop.
Metaballs examples
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns metaballs | |
(:import | |
[javax.swing JFrame] | |
[java.awt Canvas Graphics Color] | |
java.awt.image.BufferStrategy)) | |
(set! *warn-on-reflection* true) | |
(def SIZE 250) | |
;START:direction-and-position | |
;;reverse direction if we hit the edge of the screen | |
(defn direction [p v] | |
(if (or (> p SIZE) (neg? p)) (- v) v)) | |
;;compute the position and velocity of the ball | |
(defn move [{:keys [x y vx vy] :as ball}] | |
(let [vx (direction x vx) | |
vy (direction y vy)] | |
(assoc ball :x (+ x vx) :y (+ y vy) :vx vx :vy vy))) | |
;END:direction-and-position | |
;START:color | |
(defn color-in-range [c] | |
(int (if (< c 0) 0 (if (> c 255) 255 c)))) | |
(defn color [r g b] | |
(Color. (color-in-range r) (color-in-range g) (color-in-range b))) | |
;END:color | |
;START:influence-and-color | |
;;compute influence of each metaball | |
(defn influence [{:keys [x y radius]} px py] | |
(let [dx (- x px) | |
dy (- y py)] | |
(/ radius (Math/sqrt (+ (* dx dx) (* dy dy)))))) | |
;;compute the resulting RGB values based on influence | |
(defn compute-color [x y rgb ball] | |
(let [influence (influence ball x y) | |
[r g b] (:color ball)] | |
(map #(+ %1 (* influence %2)) rgb (:color ball)))) | |
;END:influence-and-color | |
(defn paint-square [g [red green blue] x y size] | |
(doto g | |
(.setColor (color red green blue)) | |
(.fillRect x y size size))) | |
(defn draw [canvas balls] | |
(let [buffer (.getBufferStrategy canvas) | |
g (.getDrawGraphics buffer) | |
step 2] | |
(try | |
(loop [x 0] | |
(loop [y 0] | |
(paint-square g | |
;START:compute-colors | |
;;for each x,y coordinate compute the color | |
(reduce (partial compute-color x y) [0 0 0] balls) | |
;END:compute-colors | |
x y step) | |
(if (< y (- SIZE step)) (recur (+ y step)))) | |
(if (< x (- SIZE step)) (recur (+ x step)))) | |
(finally (.dispose g))) | |
(if-not (.contentsLost buffer) | |
(.show buffer)) )) | |
(defn metaball [] | |
{:x (rand-int SIZE) | |
:y (rand-int SIZE) | |
:vx (inc (rand-int 6)) | |
:vy (inc (rand-int 6)) | |
:radius (+ 40 (rand-int 15)) | |
:color (repeatedly 3 #(rand-int 256))}) | |
(defn start [& [num-balls]] | |
(let [frame (JFrame. "Metaballs") | |
canvas (Canvas.)] | |
(doto frame | |
(.setSize SIZE SIZE) | |
(.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE) | |
(.setResizable false) | |
(.add canvas) | |
(.setVisible true)) | |
(doto canvas | |
(.createBufferStrategy 2) | |
(.setVisible true) | |
(.requestFocus)) | |
;START:main-loop | |
;;run this in a loop where we move the | |
;;balls around and render them | |
(loop [balls (repeatedly (or num-balls 2) metaball)] | |
(draw canvas balls) | |
(recur (map move balls))) | |
;END:main-loop | |
)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns metaballs-optimized | |
(:import | |
[javax.swing JFrame] | |
[java.awt Canvas Graphics Color] | |
java.awt.image.BufferStrategy)) | |
(set! *warn-on-reflection* true) | |
(def SIZE 250) | |
;START:direction-and-position | |
;;reverse direction if we hit the edge of the screen | |
(defn direction [p v] | |
(if (or (> p SIZE) (neg? p)) (- v) v)) | |
;;compute the position and velocity of the ball | |
(defn move [{:keys [x y vx vy] :as ball}] | |
(let [vx (direction x vx) | |
vy (direction y vy)] | |
(assoc ball :x (+ x vx) :y (+ y vy) :vx vx :vy vy))) | |
;END:direction-and-position | |
;START:color | |
(defn color-in-range [c] | |
(if (< c 0) 0 (if (> c 255) 255 c))) | |
(defn color [[r g b]] | |
(Color. ^int (color-in-range r) | |
^int (color-in-range r) | |
^int (color-in-range r))) | |
;END:color | |
;START:influence-and-color | |
;;compute influence of each metaball | |
(defn influence [{:keys [x y radius]} px py] | |
(let [dx (double (- x px)) | |
dy (double (- y py))] | |
(double (/ radius (Math/sqrt (+ (* dx dx) (* dy dy))))))) | |
;;compute the resulting RGB values based on influence | |
(defn compute-color [x y rgb ball] | |
(let [influence (influence ball x y) | |
[r g b] (:color ball)] | |
(map #(+ %1 (* influence %2)) rgb (:color ball)))) | |
;END:influence-and-color | |
(defn paint-square [^Graphics g rgb x y size] | |
(doto g | |
(.setColor ^Color (color rgb)) | |
(.fillRect x y size size))) | |
(defn draw [canvas balls] | |
(let [buffer (.getBufferStrategy canvas) | |
g (.getDrawGraphics buffer) | |
step 2] | |
(try | |
(loop [x 0] | |
(loop [y 0] | |
(paint-square g | |
;START:compute-colors | |
;;for each x,y coordinate compute the color | |
(reduce (partial compute-color x y) [0 0 0] balls) | |
;END:compute-colors | |
x y step) | |
(if (< y (- SIZE step)) (recur (+ y step)))) | |
(if (< x (- SIZE step)) (recur (+ x step)))) | |
(finally (.dispose g))) | |
(if-not (.contentsLost buffer) | |
(.show buffer)) )) | |
(defn metaball [] | |
{:x (rand-int SIZE) | |
:y (rand-int SIZE) | |
:vx (inc (rand-int 6)) | |
:vy (inc (rand-int 6)) | |
:radius (+ 40 (rand-int 15)) | |
:color (repeatedly 3 #(rand-int 256))}) | |
(defn start [& [num-balls]] | |
(let [frame (JFrame. "Metaballs") | |
canvas (Canvas.)] | |
(doto frame | |
(.setSize SIZE SIZE) | |
(.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE) | |
(.setResizable false) | |
(.add canvas) | |
(.setVisible true)) | |
(doto canvas | |
(.createBufferStrategy 2) | |
(.setVisible true) | |
(.requestFocus)) | |
;START:main-loop | |
;;run this in a loop where we move the | |
;;balls around and render them | |
(loop [balls (repeatedly (or num-balls 2) metaball)] | |
(draw canvas balls) | |
(recur (map move balls))) | |
;END:main-loop | |
)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment