(************************************************************ * proto.ml Created : Wed Mar 13 01:44:21 2002 * Last modified: Wed Mar 20 02:34:41 2002 * Compile: make # ************************************************************) (* プロトタイプ * 原点にある球 * * 球と直線の交点 => 二次方程式の解 * (p - s)*(p - s) = r*r * p = e + vt を解きtの小さい方をとる (負ならば裏) * *) (*type point3d = Point of float * float * float*) type vector3d = Vector of float * float * float let normalize (Vector(x,y,z)) = let len = sqrt (x*.x +. y*.y +. z*.z) in Vector(x/.len,y/.len,z/.len) let (-^) (Vector(a1,a2,a3)) (Vector(b1,b2,b3)) = Vector(a1-.b1,a2-.b2,a3-.b3) let (+^) (Vector(a1,a2,a3)) (Vector(b1,b2,b3)) = Vector(a1+.b1,a2+.b2,a3+.b3) let scale t (Vector(x,y,z)) = Vector(t*.x,t*.y,t*.z) let inner_product (Vector(a1,a2,a3)) (Vector(b1,b2,b3)) = a1*.b1 +. a2*.b2 +. a3*.b3 let origin = Vector (0.0,0.0,0.0) (*let object_color = Graphics.color 0x99 0x00 0x99*) let object_red = 0x99 let object_green = 0x0 let object_blue = 0x99 let object_center_position = origin let radius = 60.0 let ray_vector = Vector(1.0,1.0,-0.3) (* 平行光線 *) let screen_center_position = Vector(0.0,0.0,-100.0) let screen_width = 200 let screen_height = 200 let snx = Vector(1.0,0.0,0.0) let sny = Vector(0.0,1.0,0.0) let object_red_float = float_of_int object_red let object_green_float = float_of_int object_green let object_blue_float = float_of_int object_blue let screen_width_half = (float_of_int screen_width)/. 2.0 let screen_height_half = (float_of_int screen_height) /. 2.0 let eye_position = Vector(0.0,0.0,-200.0) let eye_to_screen_vector = screen_center_position -^ eye_position let eye_to_object_vector = eye_position -^ object_center_position let c = (inner_product eye_to_object_vector eye_to_object_vector) -. radius*.radius (*let d4 nvvec =*) (* let t = (eye_position -^ object_center_position) in*) (* (inner_product (eye_position -^ object_center_position) v)*) (* -. (inner_product t t) +. radius*.radius*) (* 外積 *) let cross_product (Vector(a1,a2,a3)) (Vector(b1,b2,b3)) = let r1 = a2*.b3 -. a3*.b2 and r2 = a3*.b1 -. a1*.b3 and r3 = a1*.b2 -. a2*.b1 in Vector(r1,r2,r3) (* 内積 *) let inner_product (Vector(a1,a2,a3)) (Vector(b1,b2,b3)) = a1*.b1 +. a2*.b2 +. a3*.b3 let plot sx sy color = let rsx = int_of_float(sx+.screen_width_half) and rsy = int_of_float(sy+.screen_height_half) in begin Graphics.set_color color; Graphics.plots [| (rsx,rsy) |]; end (* あるやもしれんしないかもしれんよ * (sx,sy)はスクリーン上の座標?? * *) let delta = 1.0 let rec draw_line sx sy = if sx <= screen_width_half then let vvec = (scale sx snx) +^ (scale sy sny) +^ eye_to_screen_vector in(* 絶対 *) let nvvec = normalize vvec in (* 視線単位 *) let b = inner_product eye_to_object_vector nvvec in let d = b*.b -. c in begin if d > 0.0 then let t = -.b -. (sqrt d) in if t > 0.0 then let p = eye_position +^ (scale t nvvec) in (* 交点絶対 *) let npvec = normalize (p -^ object_center_position) in (* 表面の法線 *) let nrefvec = (scale (-2.0*.(inner_product nvvec npvec)) npvec) -^ nvvec in let ray_ratio = inner_product nrefvec ray_vector in if ray_ratio > 0.0 then let red = ray_ratio *. object_red_float and green = ray_ratio *. object_green_float and blue = ray_ratio *. object_blue_float in let c = Graphics.rgb (int_of_float red) (int_of_float green) (int_of_float blue) in plot sx sy c else plot sx sy Graphics.black else plot sx sy Graphics.black else plot sx sy Graphics.black; draw_line (sx+.delta) sy; end else () (* 反射ベクトル *) let rec draw_lines sy = if sy < screen_height_half then begin draw_line (-.screen_width_half) sy; draw_lines (sy +. delta) end else () let draw_all () = draw_lines (-.screen_height_half) let _ = begin Graphics.open_graph " 200x200+0-0"; draw_all (); while true do () done; end