: Real 3D wireframe cube — actual 3D math, perspective projection.
: 8 vertices rotated on X+Y+Z, projected through a focal length.
: ESC quits. Press SPACE to toggle face filling.

const W = 800
const H = 800
gui_native "AyaanScript+ — Native 3D Cube" W H
gui_fps 60

: helper: project a 3D point (x,y,z) into screen coords
: stores result in proj_sx / proj_sy / proj_depth
: depends on globals: ax, ay, az (rotation), cx, cy (screen center),
:                    scale (size), distance (camera distance)
func project x y z
    : rotate around X: y' = y*cosX - z*sinX, z' = y*sinX + z*cosX
    set sx_v = {sin(ax)}
    set cx_v = {cos(ax)}
    set sy_v = {sin(ay)}
    set cy_v = {cos(ay)}
    set sz_v = {sin(az)}
    set cz_v = {cos(az)}

    : X rotation
    set y1 = {y * cx_v - z * sx_v}
    set z1 = {y * sx_v + z * cx_v}
    set x1 = x

    : Y rotation
    set x2 = {x1 * cy_v + z1 * sy_v}
    set z2 = {0 - x1 * sy_v + z1 * cy_v}
    set y2 = y1

    : Z rotation
    set x3 = {x2 * cz_v - y2 * sz_v}
    set y3 = {x2 * sz_v + y2 * cz_v}
    set z3 = z2

    : perspective project
    set pz = {z3 + distance}
    set proj_sx = {cx + (x3 * focal) / pz}
    set proj_sy = {cy + (y3 * focal) / pz}
    set proj_depth = pz
endfunc

set cx = 400
set cy = 400
set focal = 600
set distance = 4
set ax = 0
set ay = 0
set az = 0
set running = 1

while running == 1
    gui_open running
    if running == 0
        break
    endif

    gui_clear "#0a0a14"

    : HUD
    gui_text 20 20 "AYAANSCRIPT+ 3D CUBE" "white"
    gui_text 20 35 "ESC to quit. ARROWS rotate." "gray"
    gui_text 20 50 "60 FPS via gui_fps" "lightgray"

    : project all 8 vertices
    call project -1 -1 -1
    set v0x = {proj_sx}
    set v0y = {proj_sy}
    call project  1 -1 -1
    set v1x = {proj_sx}
    set v1y = {proj_sy}
    call project  1  1 -1
    set v2x = {proj_sx}
    set v2y = {proj_sy}
    call project -1  1 -1
    set v3x = {proj_sx}
    set v3y = {proj_sy}
    call project -1 -1  1
    set v4x = {proj_sx}
    set v4y = {proj_sy}
    call project  1 -1  1
    set v5x = {proj_sx}
    set v5y = {proj_sy}
    call project  1  1  1
    set v6x = {proj_sx}
    set v6y = {proj_sy}
    call project -1  1  1
    set v7x = {proj_sx}
    set v7y = {proj_sy}

    : back face (0-1-2-3)
    gui_line v0x v0y v1x v1y "cyan"
    gui_line v1x v1y v2x v2y "cyan"
    gui_line v2x v2y v3x v3y "cyan"
    gui_line v3x v3y v0x v0y "cyan"

    : front face (4-5-6-7)
    gui_line v4x v4y v5x v5y "yellow"
    gui_line v5x v5y v6x v6y "yellow"
    gui_line v6x v6y v7x v7y "yellow"
    gui_line v7x v7y v4x v4y "yellow"

    : connecting edges (back to front)
    gui_line v0x v0y v4x v4y "magenta"
    gui_line v1x v1y v5x v5y "magenta"
    gui_line v2x v2y v6x v6y "magenta"
    gui_line v3x v3y v7x v7y "magenta"

    : vertex dots
    gui_fill_circle v0x v0y 4 "white"
    gui_fill_circle v1x v1y 4 "white"
    gui_fill_circle v2x v2y 4 "white"
    gui_fill_circle v3x v3y 4 "white"
    gui_fill_circle v4x v4y 4 "white"
    gui_fill_circle v5x v5y 4 "white"
    gui_fill_circle v6x v6y 4 "white"
    gui_fill_circle v7x v7y 4 "white"

    : input
    gui_key_down "esc" -> esc
    if esc == 1
        set running = 0
    endif

    gui_key_down "left" -> kl
    gui_key_down "right" -> kr
    gui_key_down "up" -> ku
    gui_key_down "down" -> kd

    : auto-rotate (always advance angles)
    set ay = {ay + 0.012}
    set ax = {ax + 0.008}
    set az = {az + 0.004}

    : manual override - if arrow held, rotate faster on that axis
    if kl == 1
        set ay = {ay - 0.04}
    endif
    if kr == 1
        set ay = {ay + 0.04}
    endif
    if ku == 1
        set ax = {ax - 0.04}
    endif
    if kd == 1
        set ax = {ax + 0.04}
    endif

    gui_update
endwhile

gui_close
psyska -/ "Window closed. Goodbye!"
