(local pxl8 (require :pxl8)) (local FIREBALL_COLOR 218) (var fireball-mesh nil) (fn create-fireball-mesh [] (let [verts [] indices [] radius 5 rings 4 segments 6 core-color (+ FIREBALL_COLOR 6) spike-color (- FIREBALL_COLOR 1)] (table.insert verts {:x 0 :y radius :z 0 :nx 0 :ny 1 :nz 0 :color core-color :light 255}) (for [ring 1 (- rings 1)] (let [phi (* (/ ring rings) math.pi) sin-phi (math.sin phi) cos-phi (math.cos phi) y (* radius cos-phi) ring-radius (* radius sin-phi)] (for [seg 0 (- segments 1)] (let [theta (* (/ seg segments) math.pi 2) x (* ring-radius (math.cos theta)) z (* ring-radius (math.sin theta)) nx (* sin-phi (math.cos theta)) nz (* sin-phi (math.sin theta))] (table.insert verts {:x x :y y :z z :nx nx :ny cos-phi :nz nz :color core-color :light 255}))))) (let [bottom-idx (length verts)] (table.insert verts {:x 0 :y (- radius) :z 0 :nx 0 :ny -1 :nz 0 :color core-color :light 255}) (for [seg 0 (- segments 1)] (let [next-seg (% (+ seg 1) segments)] (table.insert indices 0) (table.insert indices (+ 1 next-seg)) (table.insert indices (+ 1 seg)))) (for [ring 0 (- rings 3)] (for [seg 0 (- segments 1)] (let [next-seg (% (+ seg 1) segments) curr-row (+ 1 (* ring segments)) next-row (+ 1 (* (+ ring 1) segments))] (table.insert indices (+ curr-row seg)) (table.insert indices (+ curr-row next-seg)) (table.insert indices (+ next-row seg)) (table.insert indices (+ curr-row next-seg)) (table.insert indices (+ next-row next-seg)) (table.insert indices (+ next-row seg))))) (let [last-ring-start (+ 1 (* (- rings 2) segments))] (for [seg 0 (- segments 1)] (let [next-seg (% (+ seg 1) segments)] (table.insert indices bottom-idx) (table.insert indices (+ last-ring-start seg)) (table.insert indices (+ last-ring-start next-seg)))))) (let [num-spikes 12 spike-len 8 base-size 1.2 golden-ratio (/ (+ 1 (math.sqrt 5)) 2)] (for [i 0 (- num-spikes 1)] (let [y (- 1 (* (/ i (- num-spikes 1)) 2)) r-at-y (math.sqrt (- 1 (* y y))) theta (* math.pi 2 i golden-ratio) nx (* r-at-y (math.cos theta)) ny y nz (* r-at-y (math.sin theta)) tx (if (> (math.abs ny) 0.9) 1 0) ty (if (> (math.abs ny) 0.9) 0 1) tz 0 px (- (* ty nz) (* tz ny)) py (- (* tz nx) (* tx nz)) pz (- (* tx ny) (* ty nx)) pl (math.sqrt (+ (* px px) (* py py) (* pz pz))) px (/ px pl) py (/ py pl) pz (/ pz pl) qx (- (* ny pz) (* nz py)) qy (- (* nz px) (* nx pz)) qz (- (* nx py) (* ny px)) bx (* radius 0.8 nx) by (* radius 0.8 ny) bz (* radius 0.8 nz) sx (* (+ radius spike-len) nx) sy (* (+ radius spike-len) ny) sz (* (+ radius spike-len) nz) base-idx (length verts)] (table.insert verts {:x (+ bx (* base-size px) (* base-size qx)) :y (+ by (* base-size py) (* base-size qy)) :z (+ bz (* base-size pz) (* base-size qz)) :nx nx :ny ny :nz nz :color core-color :light 255}) (table.insert verts {:x (+ bx (* base-size px) (* (- base-size) qx)) :y (+ by (* base-size py) (* (- base-size) qy)) :z (+ bz (* base-size pz) (* (- base-size) qz)) :nx nx :ny ny :nz nz :color core-color :light 255}) (table.insert verts {:x (+ bx (* (- base-size) px) (* (- base-size) qx)) :y (+ by (* (- base-size) py) (* (- base-size) qy)) :z (+ bz (* (- base-size) pz) (* (- base-size) qz)) :nx nx :ny ny :nz nz :color core-color :light 255}) (table.insert verts {:x (+ bx (* (- base-size) px) (* base-size qx)) :y (+ by (* (- base-size) py) (* base-size qy)) :z (+ bz (* (- base-size) pz) (* base-size qz)) :nx nx :ny ny :nz nz :color core-color :light 255}) (table.insert verts {:x sx :y sy :z sz :nx nx :ny ny :nz nz :color spike-color :light 255}) (table.insert indices base-idx) (table.insert indices (+ base-idx 1)) (table.insert indices (+ base-idx 4)) (table.insert indices (+ base-idx 1)) (table.insert indices (+ base-idx 2)) (table.insert indices (+ base-idx 4)) (table.insert indices (+ base-idx 2)) (table.insert indices (+ base-idx 3)) (table.insert indices (+ base-idx 4)) (table.insert indices (+ base-idx 3)) (table.insert indices base-idx) (table.insert indices (+ base-idx 4))))) (set fireball-mesh (pxl8.create_mesh verts indices)))) (fn init [textures] (when (not fireball-mesh) (create-fireball-mesh))) (fn render-fireball [x y z] (when fireball-mesh (pxl8.draw_mesh fireball-mesh {:x x :y y :z z :emissive true}))) {:FIREBALL_COLOR FIREBALL_COLOR :init init :render-fireball render-fireball}