@@ 70,11 70,10 @@
height
(body (make-array (list width height) :initial-element (vector 0 0 0))))
-;; (defun create-canvas (width height)
-;; (make-array (list width height) :initial-element (vector 0 0 0)))
-
(defun write-pixel (canvas x y color)
- (setf (aref (canvas-body canvas) x y) color))
+ (destructuring-bind (n m) (array-dimensions (canvas-body canvas))
+ (if (and (< x n) (< y m))
+ (setf (aref (canvas-body canvas) x y) color))))
(defun wrap (text width)
(setq text (concatenate 'string text " "))
@@ 91,12 90,15 @@
(push (subseq text offset previous) lines)
(setq offset (1+ previous)))))
+(flatten (ls)
+ (labels ((mklist (x) (if (listp x) x (list x))))
+ (mapcan #'(lambda (x) (if (atom x) (mklist x) (flatten x))) ls)))
+
(defun canvas-pixel-strings (c)
(labels ((pixel->string (v) (format nil "~s ~s ~s" (Red v) (Green v) (Blue v))))
- (loop for pixel across
- (make-array (apply #'* (array-dimensions (canvas-body c)))
- :displaced-to (canvas-body c))
- collect (pixel->string pixel))))
+ (flatten (loop for i below (canvas-height c) collect
+ (loop for j below (canvas-width c)
+ collect (pixel->string (aref (canvas-body c) j i)))))))
(defun canvas->string (c)
(let* ((triplet-strings (canvas-pixel-strings c))
@@ 108,6 110,10 @@
(format nil "P3~%~s ~s~%255~%~a~%"
(canvas-width c) (canvas-height c) (canvas->string c)))
+(defun ppm->file (ppm-string path)
+ (with-open-file (stream path :direction :output :if-exists :supersede)
+ (format stream ppm-string)))
+
;;; tests:
(deftest adding-vec3
(let ((a (vector 3 -2 5))
@@ 189,7 195,7 @@
(check (equalp (cross-product v1 v2) (vector -1 2 -1))
(equalp (cross-product v2 v1) (vector 1 -2 1)))))
-(deftest chapter-1
+(deftest vector-basics
(adding-vec3)
(subtracting-vec3)
(point-minus-a-vector)
@@ 224,14 230,15 @@
(h (canvas-height c)))
(check (equalp w 10)
(equalp h 20)
- (loop for i across (make-array (* w h) :displaced-to (canvas-body c))
+ (loop for i across (make-array (array-total-size (canvas-body c))
+ :displaced-to (canvas-body c))
always (equalp i (vector 0 0 0))))))
(deftest canvas-write-pixel
(let ((canvas (make-canvas :width 10 :height 20))
(color (vector 1 0 0)))
(write-pixel canvas 2 3 color)
- (check (equalp (aref (canvas-body canvas) 2 3) (vector 1 0 0)))))
+ (check (equalp (aref (canvas-body canvas) 3 2) (vector 1 0 0)))))
(deftest check-canvas-pixel-string
(let ((c (make-canvas :width 1 :height 2)))
@@ 254,7 261,7 @@ 0 0 0 0 0 0 0 0 0 0
(let ((c (canvas->ppm (make-canvas :width 3 :height 5))))
(check (equalp 0 (position #\Newline (reverse c) :test #'char=)))))
-(deftest chapter-2
+(deftest canvas-and-visuals
(color-vector-getters)
(blending-colors)
(canvas-properties)
@@ 264,11 271,41 @@ 0 0 0 0 0 0 0 0 0 0
(output-canvas-to-ppm)
(ppm-includes-trailing-newline))
-(defun ppm->file (ppm-string path)
- (with-open-file (stream path :direction :output :if-exists :supersede)
- (format stream ppm-string)))
+(deftest suite
+ (vector-basics)
+ (canvas-and-visuals))
+
+;;; projectile tracking
+(defstruct projectile position velocity)
+(defstruct environment gravity wind)
+
+(defun tick (env proj)
+ (let ((p (VEC3+ (projectile-position proj) (projectile-velocity proj)))
+ (v (VEC3+ (projectile-velocity proj) (VEC3+ (environment-gravity env)
+ (environment-wind env)))))
+ (make-projectile :position p :velocity v)))
-(deftest suite
- (chapter-1)
- (chapter-2))
+(do* ((env (make-environment :gravity (vector 0 -0.1 0)
+ :wind (vector -0.01 0 0)))
+ (p (make-projectile :position (vector 0 1 0)
+ :velocity (normalize (vector 1 1 0)))
+ (tick env p)))
+ ((if (<= (Y (projectile-position p)) 0) (return p)))
+ (format t "~a~%" (projectile-position p)))
+;;; projectile visualization
+(do* ((env (make-environment :gravity (vector 0 -0.09 0)
+ :wind (vector -0.01 0 0)))
+ (p (make-projectile :position (vector 0 1 0)
+ :velocity (scale-vec3 (normalize (vector 1 1.5 0)) 10))
+ (tick env p))
+ (c (make-canvas :width 900 :height 550)))
+ ((<= (Y (projectile-position p)) 0)
+ (ppm->file (canvas->ppm c) "/home/nolan/test-output.ppm"))
+ (format t "~s ~s~%"
+ (max 0 (floor (X (projectile-position p))))
+ (max 0 (floor (- (canvas-height c) 100))))
+ (write-pixel c
+ (max 0 (floor (X (projectile-position p))))
+ (max 0 (floor (- (canvas-height c) (Y (projectile-position p)))))
+ (vector 255 255 255)))