(* $Id$ *) class planet area = object (self) val area : GlGtk.area = area val mutable year = 0.0 val mutable day = 0.0 val mutable eye = 0.0 val mutable time = 0.0 method tick new_time = if time = 0. then time <- new_time else let diff = new_time -. time in time <- new_time; day <- mod_float (day +. diff *. 200.) 360.0; year <- mod_float (year +. diff *. 20.) 360.0 method day_add () = day <- mod_float (day +. 10.0) 360.0 method day_subtract () = day <- mod_float (day -. 10.0) 360.0 method year_add () = year <- mod_float (year +. 5.0) 360.0 method year_subtract () = year <- mod_float (year -. 5.0) 360.0 method eye x = eye <- x; self#display () method display () = GlClear.clear [`color;`depth]; GlDraw.color (1.0, 1.0, 1.0); GlMat.push(); GlMat.rotate ~angle:eye ~x:1. (); (* draw sun *) GlLight.material ~face:`front (`specular (1.0,1.0,0.0,1.0)); GlLight.material ~face:`front (`shininess 5.0); GluQuadric.sphere ~radius:1.0 ~slices:32 ~stacks:32 (); (* draw smaller planet *) GlMat.rotate ~angle:year ~y:1.0 (); GlMat.translate ~x:3.0 (); GlMat.rotate ~angle:day ~y:1.0 (); GlDraw.color (0.0, 1.0, 1.0); GlDraw.shade_model `flat; GlLight.material ~face:`front(`shininess 128.0); GluQuadric.sphere ~radius:0.2 ~slices:10 ~stacks:10 (); GlDraw.shade_model `smooth; GlMat.pop (); Gl.flush (); area#swap_buffers () end let myinit () = let light_ambient = 0.5, 0.5, 0.5, 1.0 and light_diffuse = 1.0, 0.8, 0.2, 1.0 and light_specular = 1.0, 1.0, 1.0, 1.0 (* light_position is NOT default value *) and light_position = 1.0, 1.0, 1.0, 0.0 in List.iter ~f:(GlLight.light ~num:0) [ `ambient light_ambient; `diffuse light_diffuse; `specular light_specular; `position light_position ]; GlFunc.depth_func `less; List.iter ~f:Gl.enable [`lighting; `light0; `depth_test]; GlDraw.shade_model `smooth let my_reshape ~width:w ~height:h = GlDraw.viewport ~x:0 ~y:0 ~w ~h; GlMat.mode `projection; GlMat.load_identity(); GluMat.perspective ~fovy:60.0 ~aspect:(float w /. float h) ~z:(1.0,20.0); GlMat.mode `modelview; GlMat.load_identity(); GlMat.translate ~z:(-5.0) () (* Main Loop * Open window with initial window size, title bar, * RGBA display mode, and handle input events. *) open GMain open GdkKeysyms let main () = let w = GWindow.window ~title:"Planet" () in w#connect#destroy ~callback:(fun () -> Main.quit (); exit 0); w#set_resize_mode `IMMEDIATE; let hb = GPack.hbox ~packing:w#add () in let area = GlGtk.area [`DOUBLEBUFFER;`RGBA;`DEPTH_SIZE 1] ~width:700 ~height:500 ~packing:hb#add () in area#event#add [`KEY_PRESS]; let planet = new planet area in let adjustment = GData.adjustment ~value:0. ~lower:(-90.) ~upper:90. ~step_incr:1. ~page_incr:5. ~page_size:5. () in let scale = GRange.scale `VERTICAL ~adjustment ~draw_value:false ~packing:hb#pack () in adjustment#connect#value_changed ~callback:(fun () -> planet#eye adjustment#value); w#event#connect#key_press ~callback: begin fun ev -> let key = GdkEvent.Key.keyval ev in if key = _Left then planet#year_subtract () else if key = _Right then planet#year_add () else if key = _Up then planet#day_add () else if key = _Down then planet#day_subtract () else if key = _Escape then w#destroy (); planet#display (); true end; Timeout.add ~ms:20 ~callback: begin fun () -> planet#tick (Sys.time ()); planet#display (); true end; area#connect#display ~callback:planet#display; area#connect#reshape ~callback:my_reshape; area#connect#realize ~callback: begin fun () -> myinit (); my_reshape ~width:700 ~height:500 end; w#show (); Main.main () let _ = Printexc.print main ()