for
when
By varying
Try translucent, opaque or shaded styles (these are all a bit slower due to the extra hidden face removal calculations required)
Built using the wireframes library.
(ns enchilada.boys-surface | |
(:require | |
[enchilada :refer [canvas ctx value-of canvas-size]] | |
[wireframes.renderer.canvas :refer [draw-solid ->canvas]] | |
[wireframes.renderer.color :refer [wireframe solid]] | |
[wireframes.transform :refer [point combine rotate scale translate degrees->radians]] | |
[wireframes.shapes.platonic-solids :refer [cube tetrahedron icosahedron dodecahedron]] | |
[wireframes.shapes.primitives :refer [mesh transform-shape center-at-origin]] | |
[jayq.core :refer [show]] | |
[inkspot.color :refer [coerce]] | |
[monet.canvas :refer [get-context fill-rect fill-style]] | |
[big-bang.core :refer [big-bang]])) | |
(def root2 (Math/sqrt 2)) | |
(def Π Math/PI) | |
(def sin Math/sin) | |
(def cos Math/cos) | |
(defn make-boys-surface [divisions alpha] | |
(let [i (/ Π divisions) | |
d (fn [u v] (- 2 (* alpha root2 (sin (* 3 u)) (sin (* 2 v))))) | |
x (fn [u v] (+ (* root2 (cos v) (cos v) (cos (* 2 u))) (* (cos u) (sin (* 2 v))))) | |
y (fn [u v] (- (* root2 (cos v) (cos v) (sin (* 2 u))) (* (sin u) (sin (* 2 v))))) | |
z (fn [u v] (* 3 (cos v) (cos v))) | |
u (range (/ Π -2) (+ (/ Π 2) i) i) | |
v (range 0 (+ Π i) i)] | |
{:polygons (vec | |
(mesh | |
(dec (count u)) | |
(dec (count v)))) | |
:points (vec | |
(for [v' v | |
u' u | |
:let [d (d u' v')]] | |
(point | |
(/ (x u' v') d) | |
(/ (y u' v') d) | |
(/ (z u' v') d))))})) | |
(def rect | |
(let [[width height] (canvas-size)] | |
{:x 0 :y 0 :w width :h height})) | |
(def dimensions | |
(mapv rect [:w :h])) | |
(defn inflate [shape multiplier] | |
((transform-shape (scale multiplier)) shape)) | |
(def divisions | |
(js/parseInt (value-of :divisions 40))) | |
(def alpha | |
(js/parseFloat (value-of :alpha 1))) | |
(def shape | |
(-> | |
(make-boys-surface divisions alpha) | |
(center-at-origin) | |
(inflate (js/parseFloat (value-of :scale 1))))) | |
(def style | |
(keyword (value-of :style :transparent))) | |
(def color | |
(coerce (value-of :color :white))) | |
(def color-fn | |
(condp = style | |
:transparent (wireframe color style) | |
:translucent (wireframe color style) | |
:opaque (wireframe color style) | |
:shaded (solid color))) | |
(defn render-shape | |
"Draws the shape at the given state of the world (the x,y,z rotation angles)" | |
[[x y z]] | |
(-> ctx | |
(fill-style "rgba(255,255,255,0.75") | |
(fill-rect rect)) | |
((->canvas ctx) | |
(partial draw-solid | |
{:style style | |
:focal-length 3 | |
:color-fn color-fn | |
:shape shape | |
:transform (combine | |
(rotate :x (degrees->radians x)) | |
(rotate :y (degrees->radians y)) | |
(rotate :z (degrees->radians z)) | |
(translate 0 0 10))}) | |
dimensions)) | |
(defn update-state | |
"Increment/decrement the rotation angles around the x,y and z axes" | |
[event [x y z]] | |
[(+ x 0.3) (- y 0.7) (+ z 0.5)]) | |
(-> | |
ctx | |
(fill-style :white) | |
(fill-rect rect)) | |
(show canvas) | |
(big-bang | |
:initial-state [0 0 0] | |
:on-tick update-state | |
:to-draw render-shape) |
for
when
By varying
Try translucent, opaque or shaded styles (these are all a bit slower due to the extra hidden face removal calculations required)
Built using the wireframes library.