(local pxl8 (require :pxl8)) (var angle-x 0) (var angle-y 0) (var angle-z 0) (var auto-rotate true) (var orthographic true) (var wireframe true) (var time 0) (var zoom 5.0) (var texture-id nil) (var use-texture false) (var affine false) (var texture-initialized false) (fn init-texture [] (when (not texture-initialized) (pxl8.load_palette "sprites/pxl8_logo.ase") (set texture-id (pxl8.load_sprite "sprites/pxl8_logo.ase")) (pxl8.upload_atlas) (set texture-initialized true))) (fn make-cube-vertices [] [[-1 -1 -1] [1 -1 -1] [1 1 -1] [-1 1 -1] [-1 -1 1] [1 -1 1] [1 1 1] [-1 1 1]]) (fn make-cube-faces [] [[0 1 2] [0 2 3] [1 5 6] [1 6 2] [5 4 7] [5 7 6] [4 0 3] [4 3 7] [3 2 6] [3 6 7] [4 5 1] [4 1 0]]) (fn make-cube-faces-with-uvs [] [{:tri [0 1 2] :uvs [[0 0] [1 0] [1 1]]} {:tri [0 2 3] :uvs [[0 0] [1 1] [0 1]]} {:tri [1 5 6] :uvs [[0 0] [1 0] [1 1]]} {:tri [1 6 2] :uvs [[0 0] [1 1] [0 1]]} {:tri [5 4 7] :uvs [[0 0] [1 0] [1 1]]} {:tri [5 7 6] :uvs [[0 0] [1 1] [0 1]]} {:tri [4 0 3] :uvs [[0 0] [1 0] [1 1]]} {:tri [4 3 7] :uvs [[0 0] [1 1] [0 1]]} {:tri [3 2 6] :uvs [[0 0] [1 0] [1 1]]} {:tri [3 6 7] :uvs [[0 0] [1 1] [0 1]]} {:tri [4 5 1] :uvs [[0 0] [1 0] [1 1]]} {:tri [4 1 0] :uvs [[0 0] [1 1] [0 1]]}]) (fn get-face-color [face-idx] (let [colors [12 22 30 16 28 20]] (. colors (+ 1 (% face-idx 6))))) (fn cube-update [dt] (set time (+ time dt)) (when (pxl8.key_down "w") (set angle-x (- angle-x (* dt 2.0)))) (when (pxl8.key_down "s") (set angle-x (+ angle-x (* dt 2.0)))) (when (pxl8.key_down "a") (set angle-y (- angle-y (* dt 2.0)))) (when (pxl8.key_down "d") (set angle-y (+ angle-y (* dt 2.0)))) (when (pxl8.key_down "q") (set angle-z (- angle-z (* dt 2.0)))) (when (pxl8.key_down "e") (set angle-z (+ angle-z (* dt 2.0)))) (when (pxl8.key_pressed " ") (set wireframe (not wireframe))) (when (pxl8.key_pressed "f") (set affine (not affine))) (when (pxl8.key_pressed "p") (set orthographic (not orthographic))) (when (pxl8.key_pressed "r") (set auto-rotate (not auto-rotate))) (when (pxl8.key_pressed "t") (set use-texture (not use-texture)) (when use-texture (init-texture))) (when (pxl8.key_down "=") (set zoom (- zoom (* dt 2.0)))) (when (pxl8.key_down "-") (set zoom (+ zoom (* dt 2.0)))) (set zoom (math.max 1.0 (math.min zoom 20.0))) (when auto-rotate (set angle-x (+ angle-x (* dt 0.7))) (set angle-y (+ angle-y (* dt 0.5))) (set angle-z (+ angle-z (* dt 0.3))))) (fn cube-frame [] (pxl8.clr 0) (pxl8.clear_zbuffer) (pxl8.set_affine_textures affine) (pxl8.set_backface_culling true) (pxl8.set_wireframe wireframe) (if orthographic (let [size (* 2.5 (/ zoom 5.0)) aspect (/ (pxl8.get_width) (pxl8.get_height)) w (* size aspect) h size] (pxl8.set_projection (pxl8.mat4_ortho (- w) w (- h) h 1.0 50.0))) (let [aspect (/ (pxl8.get_width) (pxl8.get_height)) fov (/ 3.14159 (+ 2.0 (/ zoom 5.0)))] (pxl8.set_projection (pxl8.mat4_perspective fov aspect 1.0 50.0)))) (pxl8.set_view (pxl8.mat4_lookat [0 0 zoom] [0 0 0] [0 1 0])) (let [model (-> (pxl8.mat4_identity) (pxl8.mat4_multiply (pxl8.mat4_rotate_x angle-x)) (pxl8.mat4_multiply (pxl8.mat4_rotate_y angle-y)) (pxl8.mat4_multiply (pxl8.mat4_rotate_z angle-z)))] (pxl8.set_model model)) (let [vertices (make-cube-vertices)] (if (and use-texture texture-id) (let [faces (make-cube-faces-with-uvs)] (each [i face-data (ipairs faces)] (let [tri-indices face-data.tri tri-uvs face-data.uvs v0 (. vertices (+ 1 (. tri-indices 1))) v1 (. vertices (+ 1 (. tri-indices 2))) v2 (. vertices (+ 1 (. tri-indices 3))) uv0 (. tri-uvs 1) uv1 (. tri-uvs 2) uv2 (. tri-uvs 3)] (pxl8.draw_triangle_3d_textured v0 v1 v2 uv0 uv1 uv2 texture-id)))) (let [faces (make-cube-faces)] (each [i face (ipairs faces)] (let [[i0 i1 i2] face v0 (. vertices (+ 1 i0)) v1 (. vertices (+ 1 i1)) v2 (. vertices (+ 1 i2)) color (get-face-color (math.floor (/ (- i 1) 2)))] (pxl8.draw_triangle_3d v0 v1 v2 color)))))) (pxl8.text "WASD/QE: Rotate | +/-: Zoom | Space: Wire | R: Auto | P: Proj" 5 5 15) (pxl8.text (.. "T: Texture | F: Affine | Mode: " (if wireframe "Wire" "Fill") " | Texture: " (if use-texture "On" "Off") " | Mapping: " (if affine "Affine" "Persp")) 5 15 15)) {:update cube-update :frame cube-frame}