(***********************************************************************) (* *) (* JoCamls'R Us - a not so simple ray tracer in JoCaml *) (* *) (* Luc Maranget, projet Moscova, INRIA Rocquencourt *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. This file is distributed under the terms of the *) (* GNU Public License version 2, http://www.gnu.org/licenses/gpl.txt *) (* *) (* Important: based upon the ray tracer of the Camls'R'Us team *) (* written at the occasion of the ICFP programming contest 2000 *) (* Copyright 2000 Institut National de Recherche en Informatique et *) (* en Automatique. *) (* *) (* *) (***********************************************************************) let demo,tag,host,port,wid,ht = try match Sys.argv with | [|_ ; demo ; tag ; host ; port ; wid ; ht; |] -> (demo = "demo"), tag, host, int_of_string port, int_of_string wid, int_of_string ht | _ -> raise Exit with _ -> Printf.eprintf "Usage: %s (demo|nodemo) rtag host port wid ht\n" Sys.argv.(0) ; exit 2 let extra = if demo then 200 else 0 let () = Draw.open_graph tag (wid+extra) ht open Unix let get_addr h = (gethostbyname h).h_addr_list.(0) let site = Join.Site.there (ADDR_INET (get_addr host, port)) let () = Join.Site.at_fail site (def k() = exit 0 ; 0 in k) let ns = Join.Ns.of_site site type msg = | Start of (int * ConfigJoin.id) | Lines of Draw.t let do_draw j a = Draw.draw j a let convert_intensity x = let n = Pervasives.truncate (x *. 255.0) in if n < 0 then 0 else if n > 255 then 255 else n let convert_color r g b = let r = convert_intensity r and g = convert_intensity g and b = convert_intensity b in Char.chr r, Char.chr g, Char.chr b let hsv_to_rgb h s v = let r,g,b = if s = 0.0 then v,v,v else let h = h /. 60.0 in let i = Pervasives.truncate h in let f = h -. float i in let p = v *. (1.0 -. s) in let q = v *. (1.0 -. (s *. f)) in let t = v *. (1.0 -. (s *. (1.0 -. f))) in match i with | 0 -> v,t,p | 1 -> q,v,p | 2 -> p,v,t | 3 -> p,q,v | 4 -> t,p,v | 5 -> v,p,q | _ -> failwith ("Bad HSV color specification") in convert_color r g b def state(t, ((h,s,k) as next)) & get_color(key) = let c,next = try Hashtbl.find t key,next with Not_found -> let c = hsv_to_rgb (float h) s 1.0 in Hashtbl.add t key c ; let h = h+37 and k = k+1 in let s = if k >= 10 then s *. 0.8 else s in let h = if h >= 360 then h - 360 else h and k = if k >= 10 then 0 else k in c,(h,s,k) in state(t,next) & reply c to get_color let () = spawn state(Hashtbl.create 17, (0,1.0,0)) let make_line cols = let t = Array.of_list cols in let t_len = Array.length t in let len = extra in let x = len/t_len in let get_color k = let kk = (k / x) mod t_len in t.(kk) in let line = String.create (len*3) in for k=0 to len-1 do let r,g,b = get_color k in let k3 = k*3 in line.[k3] <- r ; line.[k3+1] <- g ; line.[k3+2] <- b done ; line def lock(seen) & draw(j,a) = match a with | Start (k,id) -> let col = get_color id in let cols = try Hashtbl.find seen j with Not_found -> [] in let cols = col :: cols in Hashtbl.replace seen j cols ; let line = make_line cols in let img = Array.create k line in do_draw wid j img ; lock(seen) & reply to draw | Lines t -> do_draw 0 j t ; lock(seen) & reply to draw let () = spawn lock(Hashtbl.create 17) type t = (int * msg -> unit) * unit Join.chan def dead() & die() = reply to dead let () = Join.Ns.register ns ("spy."^tag) (draw,die : t) let () = spawn (ignore (Graphics.read_key()) ; die()) ; dead()