2026-01-31 09:31:17 -06:00
|
|
|
(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)
|
2026-02-27 06:50:49 -06:00
|
|
|
(create-fireball-mesh)))
|
2026-01-31 09:31:17 -06:00
|
|
|
|
2026-02-27 06:50:49 -06:00
|
|
|
(fn render-fireball [x y z]
|
2026-01-31 09:31:17 -06:00
|
|
|
(when fireball-mesh
|
|
|
|
|
(pxl8.draw_mesh fireball-mesh {:x x :y y :z z
|
2026-02-27 06:50:49 -06:00
|
|
|
:emissive true})))
|
2026-01-31 09:31:17 -06:00
|
|
|
|
|
|
|
|
{:FIREBALL_COLOR FIREBALL_COLOR
|
|
|
|
|
:init init
|
2026-02-27 06:50:49 -06:00
|
|
|
:render-fireball render-fireball}
|