170 likes | 289 Views
Functional programming. 08 Numbers2 – Mathematics. Representation. fixnum and bignum > (values most-positive- fixnum most-negative- fixnum ) 16777215 -16777216 > ( typep 1 ‘ fixnum ) T > ( typep (1+ most-positive- fixnum ) ‘ bignum ) T. Representation. Floating-point numbers
E N D
Functional programming 08 Numbers2 – Mathematics
Representation • fixnum and bignum • > (values most-positive-fixnum most-negative-fixnum)16777215-16777216 • > (typep 1 ‘fixnum)T • > (typep (1+ most-positive-fixnum) ‘bignum)T
Representation • Floating-point numbers • Short-float • Single-float • Double-float • Long-float • > (* most-positive-long-float 10)Error: floating-point-overflow
Example: Ray-Tracing • Input: 一堆球的座標,半徑,顏色
Example: Ray-Tracing • Output: 這些球在平面上的投射
Example: Ray-Tracing • Step 1: 主程式 ray-test • 擺好所有的球(defsphere) • 針對這些球作投射(tracer )寫到圖片檔案(xxx.pgm) (defunray-test (&optional (res 1));可自由指定解析度res (setf *world* nil) (defsphere 0 -300 -1200 200 .8) (defsphere -80 -150 -1200 200 .7) (defsphere 70 -100 -1200 200 .9) (do ((x -2 (1+ x))) ((> x 2)) (do ((z 2 (1+ z))) ((> z 7)) (defsphere (* x 200) 300 (* z -400) 40 .75))) (tracer (make-pathname :name "spheres.pgm") res))
Example: Ray-Tracing • Step 2: 擺球 defsphere • 定義sphere這個structure (defstructsurface color); 先定一個球表面的structure (defstruct (sphere (:include surface)) ;再定球本身 radius center) • 寫一個defsphere函數來擺球 (defparameter*world* nil) (defstruct (point (:conc-name nil )) ;定好一個點的structure x y z) (defundefsphere (x y z r c) (let ((s (make-sphere :radius r;半徑 :center (make-point :x x :y y :z z);球心 :color c))) ;顏色 (原屬於surface) (push s *world*);放到全域變數*world* s))
Example: Ray-Tracing • Step 3: 開始寫tracer • Example: Ray-Tracing先定好眼睛(假設光源在這兒) (defconstanteye (make-point :x 0 :y 0 :z 200)) ;眼睛定在原點沿著z軸往正方向走200 units • Tracer 主程式 (defuntracer (pathname &optional (res 1)) (with-open-file (p pathname :direction :output) (format p “P2 ~A ~A 255” (* res 100) (* res 100)) ;寫成pgm之p2格式 (let ((inc (/ res)));平面為100*100 (do ((y -50 (+ y inc))) ;y從-50 ((< (- 50 y) inc)) ;到50 (do ((x -50 (+ x inc))) ;x從-50 ((< (- 50 x) inc)) ;到50 (print (color-at x y) p)))))) ;印出 (x,y)座標的顏色
Example: Ray-Tracing • Step 4: 開始計算某個座標(x,y)的顏色 • 主程式 color-at (defuncolor-at (x y) (multiple-value-bind (xr yr zr) (unit-vector (- x (x eye)) ;單位向量 (- y (y eye)) (- 0 (z eye))) (round (* (sendray eye xr yr zr) 255))));從眼睛發射出去 (看過去)
Example: Ray-Tracing • 單位向量 • 平方 (defunsq (x) (* x x)) • 向量長度 (defunmag (x y z) (sqrt (+ (sq x) (sq y) (sq z ) ) )) • 單位向量 (defununit-vector (x y z) (let ((d (mag x y z))) (values (/ x d) (/ y d) (/ z d))))
Example: Ray-Tracing • Sendray 從眼睛看穿平面到球堆 (defunsendray (pt xr yr zr) (multiple-value-bind (s int) (first-hit pt xr yr zr) (if s (* (lamberts intxr yr zr) (surface-color s)) 0))) • First-hit: 從pt沿著(xr,yr,zr)方向到球堆最先碰到誰(s球的int點) • Lambert: 按照Lambert’s law,亦即平面上一點的反射光會跟這點的法向量N與從此點到光源的單位向量之內積成正比(與N同向的分量才要計入)i=N‧L
Example: Ray-Tracing • Lambert’s law (defunlambert (s intxr yr zr) (multiple-value-bind (xnynzn) (normal s int) (max 0 (+ (* xrxn) (* yr yn) (* zrzn))))) int N S L
Example: Ray-Tracing • Normal (defunnormal (s pt) (let ((c (sphere-center s))) (unit-vector (- (x c) (x pt)) (- (y c) (y pt)) (- (z c) (z pt)))))
Example: Ray-Tracing • First-hit (defunfirst-hit (pt xr yr zr) (let (surface hit dist) ;先宣告有三個變數 (dolist (s *world*);對於*world中的每一顆球s (let ((h (intersect s pt xr yr zr))) ;從pt沿著(xr,yr,zr)射出光線到s 之交點 (when h (let ((d (distance h pt))) (when (or (null dist) (< d dist));找與pt最近的交點 (setf surface s hit h dist d)))))) (values surface hit))) • (defundistance (p1 p2) (mag- (x p1) (x p2)) (- (y p1) (y p2)) (- (z p1) (z p2))))
Example: Ray-Tracing • 找直線與球面的交點 (defunintersect (s pt xr yr zr) (let* ((c (sphere-center s)) (n (minroot(+ (sq xr) (sq yr) (sq zr));找從pt發射擁有之最小長度之解 (* 2 (+ (* (- (x pt) (x c)) xr) (* (- (y pt) (y c)) yr) (* (- (z pt) (z c)) zr))) (+ (sq (- (x pt) (x c))) (sq (- (y pt) (y c))) (sq (- (z pt) (z c))) (- (sq (sphere-radius s))))))) (if n (make-point :x (+ (x pt) (* n xr)) :y (+ (y pt) (* n yr)) :z (+ (z pt) (* n zr))))))
Example: Ray-Tracing • 從眼睛(x0,y0,z0)射出之最小長度解 • Pt+nV=(x0,y0,z0)+n(xr,yr,zr) • 交點與球心的距離必為r • 改寫成
Example: Ray-Tracing • 找最小距離解 (defunminroot(a b c) (if (zerop a) (/ (- c) b) (let ((disc (- (sq b) (* 4 a c ) ) )) (unless (minusp disc) (let ((discrt (sqrt disc))) (min (/ (+ (- b) discrt) (* 2 a)) (/ (- (- b) discrt) (* 2 a ))))))))