(*========================================================================
 This is a small test application for GLFW.
 The program shows texture loading with mipmap generation and trilinear
 filtering.
 ======================================================================== *)

let running = ref true
let frames = ref 0
let main () =
	try
	    (* Initialise GLFW *)
		if (Glfw.init () = 0) then failwith "glfwInit failed";
		(* Open OpenGL window *)
		if (Glfw.open_window 640 480 0 0 0 0 0 0 Glfw.window = 0) then begin
			Glfw.terminate ();
			failwith "glfwOpenWindow failed";	
		end;
		(* Enable sticky keys *)
		Glfw.enable Glfw.sticky_keys;
		
		(* Disable vertical sync (on cards that support it) *)
		Glfw.swap_interval 0;
		
		(* Get and select a texture object ID *)
		let texid = GlTex.gen_texture () in
		GlTex.bind_texture `texture_2d texid;
		
		(* Load texture from file, and build all mipmap levels. The
    	   texture is automatically uploaded to texture memory. *)
		if (Glfw.load_texture_2d "images/mipmaps.tga" Glfw.build_mipmaps_bit = 0) then begin
			Glfw.terminate ();
			failwith "glfwLoadTexture2D failed";	
		end;
		
		(* Use trilinear interpolation (GL_LINEAR_MIPMAP_LINEAR)*)
		List.iter (GlTex.parameter ~target:`texture_2d)  [`min_filter `linear_mipmap_linear; `mag_filter `linear];
		
		(* Enable texturing *)
		Gl.enable `texture_2d;
		
		(* Main loop *)
		let t0 = Glfw.get_time () in
		let rec r () =
			if not !running then ()
			else begin
				(* Get time and mouse position *)
				let t = Glfw.get_time () 
				and (x, y) = Glfw.get_mouse_pos () in
					if t -. t0 > 1.0 || !frames = 0 then begin
						(*  Calculate and display FPS (frames per second) *)
					    let fps = float !frames /. (t -. t0) in
					    	let s = Printf.sprintf "Spinning triangle (%.1f FPS)" fps in
					    		 Glfw.set_window_title s;
					end;	
					frames := !frames + 1;	
					(* Get window size (may be different than the requested size) *)
					let (width, height) = Glfw.get_window_size () in 
					let height = if height > 0 then height else 1 in
						(* Set viewport *)
						GlDraw.viewport 0 0 width height;
					    
						(* Clear color buffer *)
						GlClear.color (((float x) /. 256.0), ((float y) /. 256.0), ((float x *. float y) /. 65530.0));
					    GlClear.clear [`color];
					    
					    (* Select and setup the projection matrix *)
					    GlMat.mode `projection;
					    GlMat.load_identity ();
					    GluMat.perspective ~fovy:(65.0) ~aspect:(float width /. float height) ~z:(1.0 ,100.0);
					    
					    (* Select and setup the modelview matrix *)
					    GlMat.mode `modelview;
						GlMat.load_identity();
					    GluMat.look_at ~eye:(0.0, 3.0, (-20.0))  ~center:(0.0, (-4.0), (-11.0)) ~up:(0.0, 1.0, 0.0);

					    (* Draw a textured quad *)
					    GlMat.rotate  ~y:1.0  ~angle:(0.3 *. float x +. (t -. t0) *. 100.0) () ; 
					    GlDraw.begins `quads;
							GlTex.coord2 ((-20.0) , 20.0);
							GlDraw.vertex3 ((-50.0), 0.0, (-50.0));
							GlTex.coord2 (20.0 , 20.0);
							GlDraw.vertex3 (50.0, 0.0, (-50.0));
							GlTex.coord2 (20.0 , (-20.0));
							GlDraw.vertex3 (50.0, 0.0, 50.0);
							GlTex.coord2 ((-20.0) , (-20.0));
							GlDraw.vertex3 ((-50.0), 0.0, 50.0);
					    GlDraw.ends ();
					    
					    (* Swap buffers *)					
					    Glfw.swap_buffers ();	
					    
					    (* Check if the ESC key was pressed or the window was closed *)
					    if ((Glfw.get_key Glfw.key_esc) = 1)  or  ((Glfw.get_window_param Glfw.opened) = 0) then running := false;		 
				r ();
			end;	
		in
		r ();	
		(* Close OpenGL window and terminate GLFW *)
		Glfw.terminate ();
	with
		Failure s -> Printf.printf "Failure: %s\n" s
;;

main ()
