open Config open Point open Vector open Object open Graphics let no_color = { x = 0.; y = 0.; z = 0. } let rec render_ray amb depth initial obj lights p v multx multy multz = if depth < 0 then no_color else match Intersect.intersect_ray p v obj initial with None -> !horizon_color | Some(t, bobj) -> if t = 0.0 then !inside_object_color (* trapped inside! *) else begin let inter_w = Vector.point_along p v t in let inter_o = Matrix.apply_to_point bobj.world2obj inter_w in (* Surface characteristics *) let (surf,face) = match bobj.surf with SurfFun f -> let (face, surf_u, surf_v) = Surface.coords bobj inter_o in f face surf_u surf_v , face | SurfArray t -> let face = Surface.faces bobj inter_o in t.(face), face | SurfConst s -> let face = Surface.faces bobj inter_o in s, face in (* Construct the vectors on figure 4 *) let n1 = Object.normal_vector bobj inter_w face in let dotprod = Vector.dotproduct v n1 in let s = Vector.sub v (Vector.scale n1 (2.0 *. dotprod)) in let n = if dotprod <= 0.0 then n1 else Vector.opposite n1 in (* Light sources *) let il = Light.color_from_lights obj inter_w v n surf.kd surf.ks surf.phong lights in (* Recursive call for ray along s *) let is = let multx = multx *. surf.ks *. surf.color.x in let multy = multy *. surf.ks *. surf.color.y in let multz = multz *. surf.ks *. surf.color.z in if not !no_dl && multx < 0.1 && multy < 0.1 && multz < 0.1 then no_color else render_ray amb (depth-1) false obj lights inter_w s multx multy multz in (* Compute final color *) { x = (surf.kd *. amb.x +. il.x +. surf.ks *. is.x) *. surf.color.x; y = (surf.kd *. amb.y +. il.y +. surf.ks *. is.y) *. surf.color.y; z = (surf.kd *. amb.z +. il.z +. surf.ks *. is.z) *. surf.color.z } end let convert_color x = let n = truncate (x *. 255.0) in if n < 0 then 0 else if n > 255 then 255 else n let render amb lights obj depth fov wid ht file = if !graphic then open_graph (Printf.sprintf " %dx%d" wid ht); let obj = Simplify.simplify obj in let wid2 = float wid /. 2.0 and ht2 = float ht /. 2.0 in let scale = tan (fov /. 2.0) /. wid2 in let oc = open_out file in Printf.fprintf oc "P6\n# Camls 'R Us\n%d %d\n255\n" wid ht; let npoints = float_of_int (ht * wid) in let ncomp = ref (-1.0) in for j = ht - 1 downto 0 do if !progress then begin Printf.printf " %s : %d %%\r" file (int_of_float (!ncomp /. npoints *. 100.)); flush stdout; end; let y = (float j -. ht2 +. 0.5) *. scale in for i = 0 to wid - 1 do ncomp := !ncomp +. 1.; let x = (float i -. wid2 +. 0.5) *. scale in let color = if (not !antialias) then render_ray amb depth true obj lights {x = 0.0; y = 0.0; z = -1.0} {dx = x; dy = y; dz = 1.0} 255.0 255.0 255.0 else begin let micron = scale /. 4. in let color1 = render_ray amb depth true obj lights {x = 0.0; y = 0.0; z = -1.0} {dx = x +. micron; dy = y +. micron; dz = 1.0} 255.0 255.0 255.0 in let color2 = render_ray amb depth true obj lights {x = 0.0; y = 0.0; z = -1.0} {dx = x +. micron; dy = y -. micron; dz = 1.0} 255.0 255.0 255.0 in let color3 = render_ray amb depth true obj lights {x = 0.0; y = 0.0; z = -1.0} {dx = x -. micron; dy = y +. micron; dz = 1.0} 255.0 255.0 255.0 in let color4 = render_ray amb depth true obj lights {x = 0.0; y = 0.0; z = -1.0} {dx = x -. micron; dy = y +. micron; dz = 1.0} 255.0 255.0 255.0 in {x = (color1.x +. color2.x +. color3.x +. color4.x) /. 4.; y = (color1.y +. color2.y +. color3.y +. color4.y) /. 4.; z = (color1.z +. color2.z +. color3.z +. color4.z) /. 4.} end in let r = convert_color color.x and g = convert_color color.y and b = convert_color color.z in if !graphic then begin set_color (rgb r g b); plot i j end; output_byte oc r; output_byte oc g; output_byte oc b; done done; close_out oc; if !start_xv then ignore (Sys.command (Printf.sprintf "xv %s &" file)); if !graphic then begin ignore(read_key()); close_graph() end