The humble cone contains the answers to fundamental questions about the universe. But not _this_ one, its just pixels on the screen. What is mildly interesting about this cone is the way it is generated - a 2D polyline forms the bottom side and hypotenuse of a right-handed triangle in the X-Y plane. This flat shape is then "extruded" into three …
(ns enchilada.wireframe-extrusion | |
(: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.primitives :refer [extrude make-line make-point 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) | |
(def intervals->radians | |
(let [atan8 (* (Math/atan 1.0) 8.0)] | |
(fn [num-intervals] (/ atan8 (double num-intervals))))) | |
(defn polyline-2d [& points] | |
(apply make-line (map (fn [[x y]] (make-point x y 0)) points))) | |
(defn make-cone [n] | |
(extrude | |
(polyline-2d | |
[0.0 0.0] | |
[1.0 0.0] | |
[2.0 0.0] | |
[3.0 0.0] | |
[4.0 0.0] | |
[5.0 0.0] | |
[4.5 1.0] | |
[4.0 2.0] | |
[3.5 3.0] | |
[3.0 4.0] | |
[2.5 5.0] | |
[2.0 6.0] | |
[1.5 7.0] | |
[1.0 8.0] | |
[0.5 9.0] | |
[0.0 10]) | |
(rotate :y (intervals->radians n)) | |
n)) | |
(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-cone divisions) | |
(center-at-origin) | |
(inflate (js/parseFloat (value-of :scale 0.25))))) | |
(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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment