Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
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