(module ex3d mzscheme
(require (planet "util.ss" ("kazzmir" "allegro.plt" 1 0))
(planet "keyboard.ss" ("kazzmir" "allegro.plt" 1 0))
(prefix image- (planet "image.ss" ("kazzmir" "allegro.plt" 1 0))))
(define (real->int i)
(inexact->exact (round i)))
(define (make-num-list min max)
(let loop ((nums '())
(n min))
(if (> n max)
(reverse! nums)
(loop (cons n nums) (add1 n)))))
(define (setup-colors!)
(image-create-rgb-table (image-make-palette))
(let ((p (image-make-palette)))
(image-set-palette! p 0 0 0 0)
(for-each (lambda (num)
(let-values (((r g b)
(image-get-rgb
(image-get-desktop-color num))))
(image-set-palette! p num r g b)))
(make-num-list 1 63))
(for-each (lambda (num)
(let ((r (* 2 (- num 64))))
(image-set-palette! p num r 0 0)))
(make-num-list 64 95))
(for-each (lambda (num)
(let ((g (* 2 (- num 96))))
(image-set-palette! p num 0 g 0)))
(make-num-list 96 127))
(for-each (lambda (num)
(let ((grey (real->int (/ (- num 128) 2))))
(image-set-palette! p num grey grey grey)))
(make-num-list 128 255))
(image-set-palette! p 255 63 63 63)
(image-set-palette! p)
(for-each (lambda (num)
(printf "~a p = ~a color = ~a\n"
num (image-get-palette p num)
(image-get-palette-color num)))
(make-num-list 0 255))
(image-rgb-map (image-create-rgb-table p))
(image-create-light-table p 0 0 0)
(set-trans-blender! 0 0 0 192)
))
(define-struct quad (v1 v2 v3 v4))
(define-struct vertex (x y z))
(define-struct shape (x y z rx ry rz dz drx dry drz ))
(define points '((-32 -32 -32)
(-32 32 -32)
(32 32 -32)
(32 -32 -32)
(-32 -32 32)
(-32 32 32)
(32 32 32)
(32 -32 32)))
(define (flatten lst)
(if (null? lst)
null
(let ((x (car lst)))
(cond
((pair? x) (append (flatten x) (flatten (cdr lst))))
(else (cons x (flatten (cdr lst))))))))
(define (get-points num)
(list-ref points num))
(define (get-points-x num)
(car (get-points num)))
(define (get-points-y num)
(cadr (get-points num)))
(define (get-points-z num)
(caddr (get-points num)))
(define faces '((0 3 2 1)
(4 5 6 7)
(0 1 5 4)
(2 3 7 6)
(0 4 7 3)
(1 2 6 5)))
(define (get-face-1 num)
(car (list-ref faces num)))
(define (get-face-2 num)
(cadr (list-ref faces num)))
(define (get-face-3 num)
(caddr (list-ref faces num)))
(define (get-face-4 num)
(cadddr (list-ref faces num)))
(define (init-shape)
(let ((x (- (bitwise-and (random 256) 255) 128))
(y (- (bitwise-and (random 256) 255) 128))
(z 768)
(rx 0)
(ry 0)
(rz 0)
(dz (+ 0.2 (/ (- (random 100) 9) 4)))
(drx (/ (- (random 31) 16) 3))
(dry (/ (- (random 31) 16) 3))
(drz (/ (- (random 31) 16) 3)))
(make-shape x y z rx ry rz dz drx dry drz)))
(define (move-shape shape)
(let ((z (+ (shape-z shape) (shape-dz shape)))
(rx (+ (shape-rx shape) (shape-drx shape)))
(ry (+ (shape-ry shape) (shape-dry shape)))
(rz (+ (shape-rz shape) (shape-drz shape))))
(when (or (> z 1024) (< z 192))
(set-shape-dz! shape (- (shape-dz shape))))
(set-shape-z! shape z)
(set-shape-rx! shape rx)
(set-shape-ry! shape ry)
(set-shape-rz! shape rz)))
(define (mid x1 x2 x3)
(max x1 (min x2 x3)))
(define (vertex-color vt1 vt2)
(let ((z (/ (+ (vertex-z vt1) (vertex-z vt2)) 2)))
(real->int (mid 150
(- 255
(/ (* 128 (- z 192))
(- 1024 192)))
255))))
(define (wire buffer vt1 vt2)
(let ((color (image-get-palette-color (vertex-color vt1 vt2))))
(image-line buffer
(real->int (vertex-x vt1))
(real->int (vertex-y vt1))
(real->int (vertex-x vt2))
(real->int (vertex-y vt2))
color)))
(define (sort lst bigger?)
(cond
((<= (length lst) 1) lst)
(else
(let ((pivot (car lst)))
(let loop ((rest (cdr lst))
(big '())
(small '()))
(cond
((null? rest) (append
(sort small bigger?)
(list pivot)
(sort big bigger?)))
((bigger? (car rest) pivot) (loop (cdr rest)
(cons (car rest) big)
small))
(else (loop (cdr rest) big (cons (car rest) small)))))))))
(define modes (let ((modes '(wire-frame
POLYTYPE-FLAT
POLYTYPE-GCOL
POLYTYPE-GRGB
POLYTYPE-ATEX
POLYTYPE-PTEX
POLYTYPE-ATEX-TRANS
POLYTYPE-PTEX-TRANS
POLYTYPE-ATEX-MASK
POLYTYPE-PTEX-MASK
POLYTYPE-ATEX-MASK-TRANS
POLYTYPE-PTEX-MASK-TRANS
POLYTYPE-ATEX-LIT
POLYTYPE-PTEX-LIT
POLYTYPE-ATEX-MASK-LIT
POLYTYPE-PTEX-MASK-LIT)))
(set-cdr! (let loop ((n modes))
(if (null? (cdr n)) n (loop (cdr n))))
modes)
modes))
(provide run)
(define (run)
(define max-shapes 8)
(define points #f)
(define max-vertices 8)
(define mode modes)
(define space-pressed 0)
(easy-init 640 480 16)
(setup-colors!)
(let ((texture (let ((image (image-create 32 32))
(color (image-get-palette-color 1)))
(image-clear image (image-mask-color image))
(image-line image 0 0 31 31 color)
(image-line image 0 31 31 0 color)
(image-rectangle image 0 0 31 31 color)
(image-print image 0 0 (image-get-palette-color 2) -1 "dead")
(image-print image 0 8 (image-get-palette-color 2) -1 "pigs")
(image-print image 0 16 (image-get-palette-color 2) -1 "cant")
(image-print image 0 24 (image-get-palette-color 2) -1 "fly.")
image))
(shapes (map (lambda (num)
(init-shape))
(make-num-list 1 max-shapes))))
(set-projection-viewport 0 0 screen-x screen-y)
(game-loop
(lambda ()
(when (and (keypressed? 'SPACE) (= space-pressed 0))
(set! space-pressed 4)
(set! mode (cdr mode)))
(when (> space-pressed 0)
(set! space-pressed (sub1 space-pressed)))
(set! points
(map (lambda (shape)
(move-shape shape)
(let ((matrix
(get-transformation-matrix
1.0
(shape-rx shape)
(shape-ry shape)
(shape-rz shape)
(shape-x shape)
(shape-y shape)
(shape-z shape))))
(map
(lambda (num)
(let-values
(((x y z)
(apply-matrix matrix
(get-points-x num)
(get-points-y num)
(get-points-z num))))
(let-values (((px py) (persp-project x y z)))
(list px py z))))
(make-num-list 0 (sub1 max-vertices)))))
shapes))
(keypressed? 'ESC))
(lambda (buffer)
(image-print buffer 5 10 (image-get-palette-color 255) -1 (format "Mode: ~a" (car mode)))
(for-each (lambda (quad)
(let ((current-mode (car mode)))
(case current-mode
((wire-frame) (begin
(wire buffer (quad-v1 quad) (quad-v2 quad))
(wire buffer (quad-v2 quad) (quad-v3 quad))
(wire buffer (quad-v3 quad) (quad-v4 quad))
(wire buffer (quad-v4 quad) (quad-v1 quad))))
((POLYTYPE-ATEX-LIT
POLYTYPE-PTEX-LIT
POLYTYPE-ATEX-MASK-LIT
POLYTYPE-PTEX-MASK-LIT)
(begin
(let ((get-color (lambda (z)
(real->int (- 255 (mid 0 (/ z 4) 255))))))
(let-values (((color1 color2 color3 color4)
(values
(get-color (vertex-z (quad-v1 quad)))
(get-color (vertex-z (quad-v2 quad)))
(get-color (vertex-z (quad-v3 quad)))
(get-color (vertex-z (quad-v4 quad))))))
(let ((vtx1 (let ((q (quad-v1 quad)))
(image-make-v3d (vertex-x q)
(vertex-y q)
(vertex-z q)
0 0
color1)))
(vtx2 (let ((q (quad-v2 quad)))
(image-make-v3d (vertex-x q)
(vertex-y q)
(vertex-z q)
32 0
color2)))
(vtx3 (let ((q (quad-v3 quad)))
(image-make-v3d (vertex-x q)
(vertex-y q)
(vertex-z q)
32 32
color3)))
(vtx4 (let ((q (quad-v4 quad)))
(image-make-v3d (vertex-x q)
(vertex-y q)
(vertex-z q)
0 32
color4))))
(image-quad3d buffer
current-mode
texture
vtx1
vtx2
vtx3
vtx4))))))
((POLYTYPE-ATEX
POLYTYPE-PTEX
POLYTYPE-ATEX-TRANS
POLYTYPE-PTEX-TRANS
POLYTYPE-ATEX-MASK
POLYTYPE-PTEX-MASK
POLYTYPE-ATEX-MASK-TRANS
POLYTYPE-PTEX-MASK-TRANS)
(begin
(let ((vtx1 (let ((q (quad-v1 quad)))
(image-make-v3d (vertex-x q)
(vertex-y q)
(vertex-z q)
0 0 0)))
(vtx2 (let ((q (quad-v2 quad)))
(image-make-v3d (vertex-x q)
(vertex-y q)
(vertex-z q)
32 0 0)))
(vtx3 (let ((q (quad-v3 quad)))
(image-make-v3d (vertex-x q)
(vertex-y q)
(vertex-z q)
32 32 0)))
(vtx4 (let ((q (quad-v4 quad)))
(image-make-v3d (vertex-x q)
(vertex-y q)
(vertex-z q)
0 32 0))))
(when (>= (polygon-z-normal vtx1 vtx2 vtx2) 0)
(image-quad3d buffer
current-mode
texture
vtx1
vtx2
vtx3
vtx4)))))
((POLYTYPE-GCOL
POLYTYPE-FLAT
POLYTYPE-GRGB)
(begin
(let-values (((color1 color2 color3 color4)
(case current-mode
((POLYTYPE-FLAT) (let ((c (image-get-palette-color
(vertex-color (quad-v1 quad)
(quad-v2 quad)))))
(values c c c c)))
((POLYTYPE-GCOL) (values (image-get-palette-color #xD0)
(image-get-palette-color #x80)
(image-get-palette-color #xB0)
(image-get-palette-color #xFF)))
((POLYTYPE-GRGB) (values #x000000
#x7F0000
#xFF0000
#x7F0000)))))
(let ((vtx1 (let ((q (quad-v1 quad)))
(image-make-v3d (vertex-x q)
(vertex-y q)
(vertex-z q)
0 0 color1)))
(vtx2 (let ((q (quad-v2 quad)))
(image-make-v3d (vertex-x q)
(vertex-y q)
(vertex-z q)
32 0 color2)))
(vtx3 (let ((q (quad-v3 quad)))
(image-make-v3d (vertex-x q)
(vertex-y q)
(vertex-z q)
32 32 color3)))
(vtx4 (let ((q (quad-v4 quad)))
(image-make-v3d (vertex-x q)
(vertex-y q)
(vertex-z q)
0 32 color4))))
(when (>= (polygon-z-normal vtx1 vtx2 vtx2) 0)
(image-quad3d buffer
current-mode
texture
vtx1
vtx2
vtx3
vtx4)))))))))
(sort
(flatten
(map (lambda (num)
(let ((vertices (list-ref points num)))
(map (lambda (face-num)
(define (make lst)
(let ((x (car lst))
(y (cadr lst))
(z (caddr lst)))
(make-vertex x y z)))
(let ((v1 (make (list-ref vertices
(get-face-1 face-num))))
(v2 (make (list-ref vertices
(get-face-2 face-num))))
(v3 (make (list-ref vertices
(get-face-3 face-num))))
(v4 (make (list-ref vertices
(get-face-4 face-num)))))
(make-quad v1 v2 v3 v4)))
(make-num-list 0 5))))
(make-num-list 0 (sub1 max-shapes))))
(lambda (quad1 quad2)
(let ((z1 (+ (vertex-z (quad-v1 quad1))
(vertex-z (quad-v2 quad1))
(vertex-z (quad-v3 quad1))
(vertex-z (quad-v4 quad1))))
(z2 (+ (vertex-z (quad-v1 quad2))
(vertex-z (quad-v2 quad2))
(vertex-z (quad-v3 quad2))
(vertex-z (quad-v4 quad2)))))
(> z2 z1))))))
(fps 20)))
(easy-exit))
)