SchemeによるRaytracer

July 15, 2004

ANSI Common Lispの簡易レイトレーサをScheme (DrScheme)へ移植してみました。

dolistとpushのマクロを定義しています。

(define sq
  (lambda (x)
    (* x x)))

(define mag
  (lambda (x y z)
    (sqrt (+ (sq x) (sq y) (sq z)))))

(define unit-vector
  (lambda (x y z)
    (let ((d (mag x y z)))
      (values (/ x d) (/ y d) (/ z d)))))

(define-struct point (x y z))

(define distance
  (lambda (p1 p2)
    (mag (- (point-x p1) (point-x p2))
         (- (point-y p1) (point-y p2))
         (- (point-z p1) (point-z p2)))))

(define minroot
  (lambda (a b c)
    (if (zero? a)
        (/ (- c) b)
        (let ((disc (- (sq b) (* 4 a c))))
          (if (negative? disc)
              #f
              (let ((discrt (sqrt disc)))
                (min (/ (+ (- b) discrt) (* 2 a))
                     (/ (- (- b) discrt) (* 2 a)))))))))

(define-struct surface (color))

(define *world* null)

(define eye (make-point 0 0 200))

(define tracer
  (lambda (pathname res)
    (let ((p (open-output-file pathname 'replace)))
      (fprintf p "P2 ~A ~A 255 ~n" (* res 100) (* res 100))
      (let ((inc (/ res)))
        (do ((y -50 (+ y inc)))
          ((< (- 50 y) inc))
          (do ((x -50 (+ x inc)))
            ((< (- 50 x) inc))
            (fprintf p "~A ~n" (color-at x y)))))
      (close-output-port p))))

(define color-at
  (lambda (x y)
    (call-with-values
     (lambda ()
       (unit-vector (- x (point-x eye))
                    (- y (point-y eye))
                    (- 0 (point-z eye))))
     (lambda (xr yr zr)
       (inexact->exact
        (round (* (sendray eye xr yr zr) 255)))))))

(define sendray
  (lambda (pt xr yr zr)
    (call-with-values 
     (lambda () (first-hit pt xr yr zr))
     (lambda (s int)
       (if (null? s)
           0
           (* (lambert s int xr yr zr) (surface-color s)))))))

(define-syntax dolist 
  (syntax-rules ()
    ((dolist (el list) body1 body2 ...)
     (do ((to-do list (cdr to-do)))
       ((null? to-do))
       (let ((el (car to-do)))
         body1
         body2
         ...)))
    ((dolist (el list res) body1 body2 ...)
     (do ((to-do list (cdr to-do)))
       ((null? to-do) res)
       (let ((el (car to-do)))
         body1
         body2
         ...)))))

(define first-hit
  (lambda (pt xr yr zr)
    (let ((surface null) (hit null) (dist null))
      (dolist (s *world*)
              (let ((h (intersect s pt xr yr zr)))
                (when h
                  (let ((d (distance h pt)))
                    (when (or (null? dist) (< d dist))
                      (set! surface s)
                      (set! hit h)
                      (set! dist d))))))
      (values surface hit))))

(define lambert
  (lambda (s int xr yr zr)
    (call-with-values
     (lambda () (normal s int))
     (lambda (xn yn zn)
       (max 0 (+ (* xr xn) (* yr yn) (* zr zn)))))))

(define-struct (sphere surface) (radius center))

(define-syntax push
  (syntax-rules ()
    ((push item list)
     (set! list (cons item list)))))

(define defsphere
  (lambda (x y z r c)
    (let ((s (make-sphere c r (make-point x y z))))
      (push s *world*)
      s)))

(define intersect
  (lambda (s pt xr yr zr)
    (cond
      ((sphere? s) (sphere-intersect s pt xr yr zr)))))

(define sphere-intersect
  (lambda (s pt xr yr zr)
    (let* ((c (sphere-center s))
           (n (minroot 
               (+ (sq xr) (sq yr) (sq zr))
               (* 2 (+ (* (- (point-x pt) (point-x c)) xr)
                       (* (- (point-y pt) (point-y c)) yr)
                       (* (- (point-z pt) (point-z c)) zr)))
               (+ (sq (- (point-x pt) (point-x c)))
                  (sq (- (point-y pt) (point-y c)))
                  (sq (- (point-z pt) (point-z c)))
                  (- (sq (sphere-radius s)))))))
      (if n
          (make-point 
           (+ (point-x pt) (* n xr))
           (+ (point-y pt) (* n yr))
           (+ (point-z pt) (* n zr)))
          #f))))

(define normal
  (lambda (s pt)
    (cond
      ((sphere? s) (sphere-normal s pt)))))

(define sphere-normal
  (lambda (s pt)
    (let ((c (sphere-center s)))
      (unit-vector (- (point-x c) (point-x pt))
                   (- (point-y c) (point-y pt))
                   (- (point-z c) (point-z pt))))))

(define ray-test
  (lambda (res)
    (set! *world* null)
    (defsphere 0 -300 -1200 200 .8)
    (defsphere -80 -150 -1200 200 .7)
    (defsphere 70 -100 -1200 200 .9)
    (do ((x -2 (add1 x)))
      ((> x 2))
      (do ((z 2 (add1 z)))
	((> z 7))
        (defsphere (* x 200) 300 (* z -400) 40 .75)))
    (tracer "spheres.pgm" res)))

実行は、(ray-test 1)。生成されるファイルはpgm形式なので、Win/Mac系ではビューワが必要。

Common LispとSchemeのベンチマークはおもしろそうなので次回。実装に依存しまくりだろうけど。

TrackBack
TrackBack URL for this entry:
http://www.robios.org/x/mt/mt-tb.cgi/19
Comments

morgage morgage

Posted by: morgage at February 6, 2007 07:18 PM

web cam girls

Posted by: webcam girls at January 21, 2007 02:10 AM

webcam girls webcam girls

Posted by: webcam girls at January 20, 2007 06:39 AM

Good job!

Posted by: Markus at December 12, 2006 02:53 AM

The face is the index of the mind... Isaac

Posted by: Isaac at November 30, 2006 05:13 PM

Much will have more... Cesar

Posted by: Cesar at November 30, 2006 05:48 AM

Much will have more... Cesar

Posted by: Cesar at November 30, 2006 05:47 AM

animal sex pictures butt fuck straight male porn stars brunette models celebrity upskirts pantyhose pics hard cock horse sex women hardcore teen sex hentai babes free sex video clips free blonde galleries latin pussy male masturbation techniques interracial stories teen cum adult add leupold tactical models make it a hit cheerleader sex bikini and thong girls shemale clips exploited black teens girl cartoon spring break girls flashing incest fucking wet shaved pussy upskirt galleries hot tits gay guys black teen reality porn sites redheads naked piss webcam girls celebrity nudes scat fetish women forced to give oral sex chubby mature amanda bynes naked movies showtimes anal movies elisha cuthbert nude gay ass lesbian movie clips asian lesbians latin to english translator fat tits closeup mariah carey free gang bang lesbian bondage tenchi hentai video clips of tsunamis nude little girls brutal rape amateur pictures free anal sex pictures

Posted by: sex video at November 25, 2006 10:10 AM

All are not merry that dance lightly... Gabriel

Posted by: Gabriel at November 25, 2006 05:37 AM

He who likes borrowing dislikes paying... Gillam

Posted by: Gillam at November 25, 2006 05:02 AM

Get a name to rise early, and you may lie all day... Stephen

Posted by: Stephen at November 22, 2006 06:50 PM

The heart that once truly loves never forgets... Fulk

Posted by: Fulk at November 22, 2006 06:18 PM

http://stories.anzwers.net/gaymen/923982/directory.html complimentwhosewondered

Posted by: grip at February 28, 2006 11:32 AM

http://www.simonhome.net/wwwboard/messages/2592.html billydriverseducing

Posted by: existence at February 13, 2006 05:34 AM

http://www.femmesdenudees.com/lesbienne/hosenda/nudecelebs/live.html complimentwhosewondered

Posted by: except at January 18, 2006 06:52 PM

すごっ!!(^3^)

Posted by: ToA at July 20, 2004 11:04 AM
Post a comment









Remember personal info?






Creative Commons License This weblog is licensed under a Creative Commons License.