let fos = float_of_string let ios = int_of_string let split = Str.split (Str.regexp_string " ") let rec read vs is ch = match try Some(split (input_line ch)) with _ -> None with | None -> vs, is | Some[x;y;z;_;_] -> read ((fos x, fos y, fos z) :: vs) is ch | Some["3";i;j;k] -> read vs ((ios i, ios j, ios k) :: is) ch | Some s -> read vs is ch let vertices, indices = let ch = open_in "data/bun_zipper.ply" in let vs, is = read [] [] ch in close_in ch; Printf.printf "%d vertices, %d triangles\n%!" (List.length vs) (List.length is); Array.of_list (List.rev vs), is let ( +| ) (x0, y0, z0) (x1, y1, z1) = x0 +. x1, y0 +. y1, z0 +. z1 let ( -| ) (x0, y0, z0) (x1, y1, z1) = x0 -. x1, y0 -. y1, z0 -. z1 let ( *| ) s (x, y, z) = s *. x, s *. y, s *. z let dot (x0, y0, z0) (x1, y1, z1) = x0 *. x1 +. y0 *. y1 +. z0 *. z1 let norm r = 1. /. sqrt(dot r r) *| r let cross (x0, y0, z0) (x1, y1, z1) = z0 *. y1 -. z1 *. y0, x0 *. z1 -. x1 *. z0, y0 *. x1 -. y1 *. x0 let normals = let vs = vertices in let ns = Array.make (Array.length vs) (0., 0., 0.) in let aux (i, j, k) = let n = norm(cross (vs.(j) -| vs.(i)) (vs.(k) -| vs.(i))) in List.iter (fun i -> ns.(i) <- ns.(i) +| n) [i;j;k] in List.iter aux indices; Array.map norm ns let time = let start = Unix.gettimeofday () in fun () -> Unix.gettimeofday () -. start let draw_triangle (i, j, k) = List.iter (fun i -> GlDraw.normal3 normals.(i); GlDraw.vertex3 vertices.(i)) [i;j;k] let draw_bunny() = GlDraw.begins `triangles; List.iter draw_triangle indices; GlDraw.ends() let memoize f = let display_list = ref None in fun () -> match !display_list with | Some list -> GlList.call list | None -> display_list := Some (GlList.create `compile); f(); GlList.ends () let draw_bunny = memoize draw_bunny let width = ref 1 and height = ref 1 let reshape ~w ~h = width := max 1 w; height := max 1 h; GlDraw.viewport 0 0 w h let ot = ref (int_of_float (time())) let frames = ref 0 let render() = incr frames; let t = int_of_float (time()) in if t <> !ot then begin Printf.printf "%d fps\n%!" !frames; frames := 0; ot := t end; GlClear.clear [`color; `depth]; Gl.enable `depth_test; GlMat.mode `projection; GlMat.load_identity (); let aspect = float !width /. float !height in GluMat.perspective ~fovy:45.0 ~aspect ~z:(0.1, 1.); GluMat.look_at ~eye:(0., 0.12, -0.25) ~center:(0., 0.1, 0.) ~up:(0., 1., 0.); GlMat.mode `modelview; GlMat.load_identity (); Gl.enable `lighting; Gl.enable `light0; GlLight.light ~num:0 (`position (1., -1., 1., 1.)); GlMat.rotate3 (15. *. time()) (0., 1., 0.); GlLight.material `both (`shininess 100.); Gl.enable `color_material; GlLight.color_material `both `specular; GlLight.color_material `both `ambient_and_diffuse; GlDraw.color (0.5, 0.4, 0.4); draw_bunny(); Gl.flush (); Glut.swapBuffers () let _ = let _ = Glut.init Sys.argv in Glut.initDisplayMode ~depth:true ~double_buffer:true (); let _ = Glut.createWindow ~title:"Stanford bunny" in Glut.reshapeFunc ~cb:reshape; Glut.displayFunc ~cb:render; Glut.idleFunc ~cb:(Some Glut.postRedisplay); Glut.keyboardFunc ~cb:(fun ~key ~x ~y -> if key=27 then exit 0); Glut.mainLoop ()