(local pxl8 (require :pxl8)) (local debug-ui (require :mod.debug_ui)) (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 cam-x 0) (var cam-y 2) (var cam-z 12) (var cam-yaw 0) (var cam-pitch -0.2) (var show-debug-ui false) (var fps 0) (var fps-accumulator 0) (var fps-frame-count 0) (fn init [] (set angle-x 0) (set angle-y 0) (set angle-z 0) (set auto-rotate true) (set orthographic true) (set wireframe true) (set time 0) (set zoom 5.0) (set use-texture false) (set affine false) (set cam-x 0) (set cam-y 2) (set cam-z 12) (set cam-yaw 0) (set cam-pitch -0.2) (set show-debug-ui false) (set fps 0) (set fps-accumulator 0) (set fps-frame-count 0) (set texture-id (pxl8.load_sprite "res/sprites/pxl8_logo.ase")) (pxl8.upload_atlas)) (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 update [dt] (set time (+ time dt)) (set fps-accumulator (+ fps-accumulator dt)) (set fps-frame-count (+ fps-frame-count 1)) (when (>= fps-accumulator 0.25) (set fps (/ fps-frame-count fps-accumulator)) (set fps-accumulator 0) (set fps-frame-count 0)) (let [wheel-y (pxl8.mouse_wheel_y)] (when (and (not= wheel-y 0) (not (pxl8.ui_has_mouse_focus))) (if orthographic (set zoom (math.max 0.5 (math.min (- zoom (* wheel-y 0.2)) 10.0))) (let [zoom-speed 0.5 forward-x (* (math.sin cam-yaw) wheel-y zoom-speed) forward-z (* (math.cos cam-yaw) wheel-y zoom-speed)] (set cam-x (+ cam-x forward-x)) (set cam-z (- cam-z forward-z)))))) (let [move-speed 5.0 rot-speed 2.0 zoom-speed 2.0 forward-x (* (math.sin cam-yaw) move-speed dt) forward-z (* (math.cos cam-yaw) move-speed dt) right-x (* (math.cos cam-yaw) move-speed dt) right-z (* (- (math.sin cam-yaw)) move-speed dt)] (if orthographic (do (when (pxl8.key_down "w") (set zoom (math.max 0.5 (- zoom (* zoom-speed dt))))) (when (pxl8.key_down "s") (set zoom (math.min 10.0 (+ zoom (* zoom-speed dt))))) (when (pxl8.key_down "a") (set cam-x (- cam-x right-x)) (set cam-z (- cam-z right-z))) (when (pxl8.key_down "d") (set cam-x (+ cam-x right-x)) (set cam-z (+ cam-z right-z))) (when (pxl8.key_down "q") (set cam-y (- cam-y (* move-speed dt)))) (when (pxl8.key_down "e") (set cam-y (+ cam-y (* move-speed dt))))) (do (when (pxl8.key_down "w") (set cam-x (+ cam-x forward-x)) (set cam-z (- cam-z forward-z))) (when (pxl8.key_down "s") (set cam-x (- cam-x forward-x)) (set cam-z (+ cam-z forward-z))) (when (pxl8.key_down "a") (set cam-x (- cam-x right-x)) (set cam-z (- cam-z right-z))) (when (pxl8.key_down "d") (set cam-x (+ cam-x right-x)) (set cam-z (+ cam-z right-z))) (when (pxl8.key_down "q") (set cam-y (- cam-y (* move-speed dt)))) (when (pxl8.key_down "e") (set cam-y (+ cam-y (* move-speed dt)))))) (when (pxl8.key_down "left") (set cam-yaw (- cam-yaw (* rot-speed dt)))) (when (pxl8.key_down "right") (set cam-yaw (+ cam-yaw (* rot-speed dt)))) (when (pxl8.key_down "up") (set cam-pitch (+ cam-pitch (* rot-speed dt)))) (when (pxl8.key_down "down") (set cam-pitch (- cam-pitch (* rot-speed dt)))) (set cam-pitch (math.max -1.5 (math.min cam-pitch 1.5)))) (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 (pxl8.key_pressed "F8") (set show-debug-ui (not show-debug-ui)) (pxl8.ui_window_set_open "Debug Menu (F8)" show-debug-ui)) (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 draw-cube [pos scale rotation-offset] (let [[x y z] pos model (-> (pxl8.mat4_identity) (pxl8.mat4_multiply (pxl8.mat4_scale scale scale scale)) (pxl8.mat4_multiply (pxl8.mat4_rotate_x (+ angle-x rotation-offset))) (pxl8.mat4_multiply (pxl8.mat4_rotate_y (+ angle-y (* rotation-offset 1.3)))) (pxl8.mat4_multiply (pxl8.mat4_rotate_z (+ angle-z (* rotation-offset 0.7)))) (pxl8.mat4_multiply (pxl8.mat4_translate x y 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))))))) (fn 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 zoom aspect (/ (pxl8.get_width) (pxl8.get_height)) w (* size aspect) h size] (pxl8.set_projection (pxl8.mat4_ortho (- w) w (- h) h 1.0 100.0))) (let [aspect (/ (pxl8.get_width) (pxl8.get_height)) fov (* (/ 60.0 180.0) 3.14159)] (pxl8.set_projection (pxl8.mat4_perspective fov aspect 0.1 100.0)))) (let [target-x (* (math.sin cam-yaw) (math.cos cam-pitch)) target-y (math.sin cam-pitch) target-z (* (- (math.cos cam-yaw)) (math.cos cam-pitch)) look-x (+ cam-x target-x) look-y (+ cam-y target-y) look-z (+ cam-z target-z)] (pxl8.set_view (pxl8.mat4_lookat [cam-x cam-y cam-z] [look-x look-y look-z] [0 1 0]))) (draw-cube [0 0 0] 1.0 0) (draw-cube [-3 0 -4] 0.8 0.5) (draw-cube [3 1 -7] 0.9 1.2) (draw-cube [0 -2 -10] 1.1 -0.7) (let [new-state (debug-ui.render {:show-debug-ui show-debug-ui :fps fps :wireframe wireframe :auto-rotate auto-rotate :orthographic orthographic :use-texture use-texture :affine affine})] (when (not= new-state.show-debug-ui nil) (set show-debug-ui new-state.show-debug-ui)) (when (not= new-state.wireframe nil) (set wireframe new-state.wireframe)) (when (not= new-state.auto-rotate nil) (set auto-rotate new-state.auto-rotate)) (when (not= new-state.orthographic nil) (set orthographic new-state.orthographic)) (when (not= new-state.use-texture nil) (set use-texture new-state.use-texture)) (when (not= new-state.affine nil) (set affine new-state.affine)))) {:init init :update update :frame frame}