(in-package :cube-modeller) (defstruct fakecube origin size) (defstruct size x y z) (defstruct origin x y z) (defun copy-and-update-in-direction (source-list direction &key new-value) (let ((list (copy-list source-list))) (setf (nth direction list) new-value) list)) ;; (defvar *number-of-displayed-leds* 125) ;; (defvar *led-count* 0) (defun draw-leds (cube viewray &key draw-led recursion) "Draw leds from back to front with the BSP algorithm (binary space partitioning / painters algorithm). This is a very simplified version of the BSP algorithm that only works because of the simplicity and regularity of our scene." (declare (ignore recursion)) ;; (unless recursion ;; (setf *led-count* 0)) (if (equal (fakecube-size cube) '(1 1 1)) ;; end of recursion (funcall draw-led (fakecube-origin cube)) ;; (progn ;; (incf *led-count*) ;; (when (<= *led-count* *number-of-displayed-leds*) ;; (funcall draw-led (fakecube-origin cube)))) ;; recurse (let* ((origin (fakecube-origin cube)) (size (fakecube-size cube)) (direction-dimension (apply #'max size)) (direction (position direction-dimension size)) (back-direction-dimension (floor (/ direction-dimension 2))) (back-cube (make-fakecube :origin origin :size (copy-and-update-in-direction size direction :new-value back-direction-dimension))) (front-cube (make-fakecube :origin (copy-and-update-in-direction origin direction :new-value (+ (nth direction origin) back-direction-dimension)) :size (copy-and-update-in-direction size direction :new-value (- (nth direction size) back-direction-dimension))))) ;; (list front-cube back-cube)))) (if (< (nth direction viewray) 0.0) (progn (draw-leds back-cube viewray :draw-led draw-led :recursion t) (draw-leds front-cube viewray :draw-led draw-led :recursion t)) (progn (draw-leds front-cube viewray :draw-led draw-led :recursion t) (draw-leds back-cube viewray :draw-led draw-led :recursion t))))) nil) (defun draw-led (position) (gl:push-matrix) (destructuring-bind (x y z) position ;; (gl:translate-f (- (* y *led-distance*)) (* z *led-distance*) (- (* x *led-distance*))) (apply #'gl:translate-f (apply #'cube->opengl (mapcar (lambda (x) (* x *led-distance*)) position))) (let ((LED-intensity (ensure-intensity-to-be-of-number (aref (current-cube) x y z)))) ;; (draw-untranslated-led LED-intensity)) (gl:call-list (get-led-display-list LED-intensity)))) (gl:pop-matrix)) (defun draw-untranslated-led (LED-intensity) (let ((grey-value (- .9f0 (* (- 5 LED-intensity) (/ 0.8 5)))) (alpha-value (- .9f0 (* (- 5 LED-intensity) (/ 0.5 5)))) (old-grey-value (* (- 5 LED-intensity) (/ 0.9 5)))) (if (eq LED-intensity 0) (sgum:with-single-float-values (emission 0f0 0f0 0f0 0f0) (gl:material-fv gl:+front+ gl:+emission+ emission)) (sgum:with-single-float-values (emission .1f0 0f0 0f0 0f0) (gl:material-fv gl:+front+ gl:+emission+ emission))) (if *dark-mode* (sgum:with-single-float-values (diffuse grey-value 0f0 0f0 alpha-value) (gl:material-fv gl:+front+ gl:+diffuse+ diffuse)) (sgum:with-single-float-values (diffuse 0.9f0 old-grey-value old-grey-value 1f0) (gl:material-fv gl:+front+ gl:+diffuse+ diffuse)))) ;; (gl:enable gl:+depth-test+) (draw-sphere *LED-DIAMETER*) ;; (gl:disable gl:+depth-test+) ) ;; call lists for the LEDs (defvar *led-display-lists* nil "Contains the 12 display lists (while the viewer is running): - elements 0 to 5 are the 6 display lists for the night mode - elements 6 to 11 are the 6 display lists for the day mode") (defun get-led-display-list (intensity) (unless *dark-mode* (setf intensity (mod intensity 6)) ;; limit to 5, in case INTENSITY indexes already the day mode (incf intensity 6)) (nth intensity *led-display-lists*)) (defun create-led-display-lists () (setf *led-display-lists* (loop for i from 0 to 11 collect (gl:gen-lists 1))) (let ((*dark-mode* t)) ;; save global value (dotimes (intensity 12) (gl:new-list (get-led-display-list intensity) gl:+compile+) (setf *dark-mode* (if (< intensity 6) ;; set *dark-mode* for DRAW-UNTRANSLATED-LED t nil)) (draw-untranslated-led (mod intensity 6)) (gl:end-list)))) (defun destroy-led-display-lists () (let ((*dark-mode* t)) (dotimes (intensity 12) (gl:delete-lists (get-led-display-list intensity) 1))) (setf *led-display-lists* nil))