Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > c00aac9511e40e4946e24ea6485133f4 > files > 328

ocaml-glmlite-devel-0.03.35-1mdv2010.0.i586.rpm

(*
 This code was created by Jeff Molofee '99
 If you've found this code useful, please let me know.

 The full tutorial associated with this file is available here:
 http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=08

 (OCaml version by Florent Monnier)
*)
open GL       (* Module For The OpenGL Library *)
open Glu      (* Module For The GLu Library *)
open Glut     (* Module For The GLUT Library *)


(* lighting on/off (1 = on, 0 = off) *)
let light = ref false

let xrot = ref 0.0   (* x rotation *)
let yrot = ref 0.0   (* y rotation *)
let xspeed = ref 0.0 (* x rotation speed *)
let yspeed = ref 0.0 (* y rotation speed *)

let z = ref (-5.0)   (* depth into the screen. *)


(* white ambient light at half intensity (rgba) *)
let lightAmbient = (0.5, 0.5, 0.5, 1.0)

(* super bright, full intensity diffuse light. *)
let lightDiffuse = (1.0, 1.0, 1.0, 1.0)

(* position of light (x, y, z, (position of light)) *)
let lightPosition = (0.0, 0.0, 2.0, 1.0)

let filter = ref 0        (* Which Filter To Use (nearest/linear/mipmapped) *)

let ( += ) a b =
  a := !a +. b;
;;

let ( -= ) a b =
  a := !a -. b;
;;


(* Load Bitmaps And Convert To Textures *)
let loadGLTextures() =
  (* Load Texture *)
  let image_data, sizeX, sizeY, tex_internal_fmt, pixel_data_fmt =
    Png_loader.load_img (Filename "Data/lesson7/crate.png")
  in

  (* Create Textures *)
  let texture = glGenTextures 3 in

  (* texture 1 (poor quality scaling) *)
  glBindTexture BindTex.GL_TEXTURE_2D texture.(0);   (* 2d texture (x and y size) *)

  glTexParameter TexParam.GL_TEXTURE_2D (TexParam.GL_TEXTURE_MAG_FILTER Mag.GL_NEAREST); (* cheap scaling when image bigger than texture *)
  glTexParameter TexParam.GL_TEXTURE_2D (TexParam.GL_TEXTURE_MIN_FILTER Min.GL_NEAREST); (* cheap scaling when image smalled than texture *)

  (* 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
     border 0 (normal), rgb color data, unsigned byte data, and finally the data itself. *)
  glTexImage2D TexTarget.GL_TEXTURE_2D 0 (Cnst 3) sizeX sizeY 0 GL_RGB GL_UNSIGNED_BYTE image_data;

  (* texture 2 (linear scaling) *)
  glBindTexture BindTex.GL_TEXTURE_2D texture.(1);   (* 2d texture (x and y size) *)
  glTexParameter TexParam.GL_TEXTURE_2D (TexParam.GL_TEXTURE_MAG_FILTER Mag.GL_LINEAR); (* scale linearly when image bigger than texture *)
  glTexParameter TexParam.GL_TEXTURE_2D (TexParam.GL_TEXTURE_MIN_FILTER Min.GL_LINEAR); (* scale linearly when image smalled than texture *)
  glTexImage2D TexTarget.GL_TEXTURE_2D 0 (Cnst 3) sizeX sizeY 0 GL_RGB GL_UNSIGNED_BYTE image_data;

  (* texture 3 (mipmapped scaling) *)
  glBindTexture BindTex.GL_TEXTURE_2D texture.(2);   (* 2d texture (x and y size) *)
  glTexParameter TexParam.GL_TEXTURE_2D (TexParam.GL_TEXTURE_MAG_FILTER Mag.GL_LINEAR); (* scale linearly when image bigger than texture *)
  glTexParameter TexParam.GL_TEXTURE_2D (TexParam.GL_TEXTURE_MIN_FILTER Min.GL_LINEAR_MIPMAP_NEAREST); (* scale linearly + mipmap when image smalled than texture *)
  glTexImage2D TexTarget.GL_TEXTURE_2D 0 (Cnst 3) sizeX sizeY 0 GL_RGB GL_UNSIGNED_BYTE image_data;

  (* 2d texture, 3 colors, width, height, RGB in that order, byte data, and the data. *)
  gluBuild2DMipmaps (Cnst 3) sizeX sizeY GL_RGB GL_UNSIGNED_BYTE image_data;

  (texture)
;;



(* A general OpenGL initialization function.  Sets all of the initial parameters. *)
let initGL ~width ~height =                   (* We call this right after our OpenGL window is created. *)
  let texture = loadGLTextures() in           (* load the textures. *)
  glEnable GL_TEXTURE_2D;                     (* Enable texture mapping. *)

  glClearColor 0.0 0.0 0.0 0.0;               (* This Will Clear The Background Color To Black *)
  glClearDepth 1.0;                           (* Enables Clearing Of The Depth Buffer *)
  glDepthFunc GL_LESS;                        (* The Type Of Depth Test To Do *)
  glEnable GL_DEPTH_TEST;                     (* Enables Depth Testing *)
  glShadeModel GL_SMOOTH;                     (* Enables Smooth Color Shading *)

  glMatrixMode GL_PROJECTION;
  glLoadIdentity();                           (* Reset The Projection Matrix *)

  gluPerspective 45.0 ((float width)/.(float height)) 0.1 100.0;  (* Calculate The Aspect Ratio Of The Window *)

  glMatrixMode GL_MODELVIEW;

  (* set up light number 1. *)
  glLight (GL_LIGHT 1) (Light.GL_AMBIENT  lightAmbient);  (* add lighting (ambient). *)
  glLight (GL_LIGHT 1) (Light.GL_DIFFUSE  lightDiffuse);  (* add lighting (diffuse). *)
  glLight (GL_LIGHT 1) (Light.GL_POSITION lightPosition); (* set light position. *)
  glEnable GL_LIGHT1;                                     (* turn light 1 on. *)

  (texture)
;;


(* The function called when our window is resized (which shouldn't happen, because we're fullscreen) *)
let reSizeGLScene ~width ~height =
  let height =
    if height = 0                             (* Prevent A Divide By Zero If The Window Is Too Small *)
    then 1
    else height
  in

  glViewport 0 0 width height;                (* Reset The Current Viewport And Perspective Transformation *)

  glMatrixMode GL_PROJECTION;
  glLoadIdentity();

  gluPerspective 45.0 ((float width) /. (float height)) 0.1 100.0;
  glMatrixMode GL_MODELVIEW;
;;


(* The main drawing function. *)
let drawGLScene ~texture () =
  glClear [GL_COLOR_BUFFER_BIT; GL_DEPTH_BUFFER_BIT];  (* Clear The Screen And The Depth Buffer *)
  glLoadIdentity();                           (* Reset The View *)

  glTranslate 0.0 0.0 !z;                     (* move z units out from the screen. *)
  
  glRotate !xrot 1.0 0.0 0.0;                 (* Rotate On The X Axis *)
  glRotate !yrot 0.0 1.0 0.0;                 (* Rotate On The Y Axis *)

  glBindTexture BindTex.GL_TEXTURE_2D texture.(!filter);   (* choose the texture to use. *)

  glBegin GL_QUADS;                           (* begin drawing a cube *)

  (* Front Face (note that the texture's corners have to match the quad's corners) *)
  glNormal3 (0.0) (0.0) (1.0);                          (* front face points out of the screen on z. *)
  glTexCoord2 0.0 0.0; glVertex3 (-1.0) (-1.0) ( 1.0);  (* Bottom Left Of The Texture and Quad *)
  glTexCoord2 1.0 0.0; glVertex3 ( 1.0) (-1.0) ( 1.0);  (* Bottom Right Of The Texture and Quad *)
  glTexCoord2 1.0 1.0; glVertex3 ( 1.0) ( 1.0) ( 1.0);  (* Top Right Of The Texture and Quad *)
  glTexCoord2 0.0 1.0; glVertex3 (-1.0) ( 1.0) ( 1.0);  (* Top Left Of The Texture and Quad *)

  (* Back Face *)
  glNormal3 (0.0) (0.0) (-1.0);                         (* back face points into the screen on z. *)
  glTexCoord2 1.0 0.0; glVertex3 (-1.0) (-1.0) (-1.0);  (* Bottom Right Of The Texture and Quad *)
  glTexCoord2 1.0 1.0; glVertex3 (-1.0) ( 1.0) (-1.0);  (* Top Right Of The Texture and Quad *)
  glTexCoord2 0.0 1.0; glVertex3 ( 1.0) ( 1.0) (-1.0);  (* Top Left Of The Texture and Quad *)
  glTexCoord2 0.0 0.0; glVertex3 ( 1.0) (-1.0) (-1.0);  (* Bottom Left Of The Texture and Quad *)

  (* Top Face *)
  glNormal3 (0.0) (1.0) (0.0);                          (* top face points up on y. *)
  glTexCoord2 0.0 1.0; glVertex3 (-1.0) ( 1.0) (-1.0);  (* Top Left Of The Texture and Quad *)
  glTexCoord2 0.0 0.0; glVertex3 (-1.0) ( 1.0) ( 1.0);  (* Bottom Left Of The Texture and Quad *)
  glTexCoord2 1.0 0.0; glVertex3 ( 1.0) ( 1.0) ( 1.0);  (* Bottom Right Of The Texture and Quad *)
  glTexCoord2 1.0 1.0; glVertex3 ( 1.0) ( 1.0) (-1.0);  (* Top Right Of The Texture and Quad *)

  (* Bottom Face *)
  glNormal3 (0.0) (-1.0) (0.0);                         (* bottom face points down on y.  *)
  glTexCoord2 1.0 1.0; glVertex3 (-1.0) (-1.0) (-1.0);  (* Top Right Of The Texture and Quad *)
  glTexCoord2 0.0 1.0; glVertex3 ( 1.0) (-1.0) (-1.0);  (* Top Left Of The Texture and Quad *)
  glTexCoord2 0.0 0.0; glVertex3 ( 1.0) (-1.0) ( 1.0);  (* Bottom Left Of The Texture and Quad *)
  glTexCoord2 1.0 0.0; glVertex3 (-1.0) (-1.0) ( 1.0);  (* Bottom Right Of The Texture and Quad *)

  (* Right face *)
  glNormal3 ( 1.0) (0.0) (0.0);                         (* right face points right on x. *)
  glTexCoord2 1.0 0.0; glVertex3 ( 1.0) (-1.0) (-1.0);  (* Bottom Right Of The Texture and Quad *)
  glTexCoord2 1.0 1.0; glVertex3 ( 1.0) ( 1.0) (-1.0);  (* Top Right Of The Texture and Quad *)
  glTexCoord2 0.0 1.0; glVertex3 ( 1.0) ( 1.0) ( 1.0);  (* Top Left Of The Texture and Quad *)
  glTexCoord2 0.0 0.0; glVertex3 ( 1.0) (-1.0) ( 1.0);  (* Bottom Left Of The Texture and Quad *)

  (* Left Face *)
  glNormal3 (-1.0) (0.0) (0.0);                         (* left face points left on x. *)
  glTexCoord2 0.0 0.0; glVertex3 (-1.0) (-1.0) (-1.0);  (* Bottom Left Of The Texture and Quad *)
  glTexCoord2 1.0 0.0; glVertex3 (-1.0) (-1.0) ( 1.0);  (* Bottom Right Of The Texture and Quad *)
  glTexCoord2 1.0 1.0; glVertex3 (-1.0) ( 1.0) ( 1.0);  (* Top Right Of The Texture and Quad *)
  glTexCoord2 0.0 1.0; glVertex3 (-1.0) ( 1.0) (-1.0);  (* Top Left Of The Texture and Quad *)

  glEnd();                                    (* done with the polygon. *)

  xrot += !xspeed;                            (* X Axis Rotation *)
  yrot += !yspeed;                            (* Y Axis Rotation *)

  (* since this is double buffered, swap the buffers to display what just got drawn. *)
  glutSwapBuffers();
;;


(* The function called whenever a normal key is pressed. *)
let keyPressed ~window ~key ~x ~y =
  match key with
  | '\027' ->  (* escape, kill everything. *)
      (* shut down our window *)
      glutDestroyWindow window;

      (* exit the program...normal termination. *)
      exit 1;

  | 'L' | 'l' -> (* switch the lighting. *)
      Printf.printf "L/l pressed; light is: %b\n" !light;
      light := not(!light);               (* switch the current value of light, between 0 and 1. *)
      Printf.printf "Light is now: %b\n%!" !light;
      if not(!light)
      then glDisable GL_LIGHTING
      else glEnable GL_LIGHTING;

  | 'F' | 'f' -> (* switch the filter. *)
      Printf.printf "F/f pressed; filter is: %d\n" !filter;
      filter := !filter + 1;
      if !filter > 2 then
        filter := 0;
      Printf.printf "Filter is now: %d\n%!" !filter;

  | _ ->
      Printf.printf "Key %c pressed. No action there yet.\n%!" key;
;;


(* The function called whenever a special key is pressed. *)
let specialKeyPressed ~key ~x ~y =
  match key with
  | GLUT_KEY_PAGE_UP -> (* move the cube into the distance. *)
      z -= 0.02;

  | GLUT_KEY_PAGE_DOWN -> (* move the cube closer. *)
      z += 0.02;

  | GLUT_KEY_UP -> (* decrease x rotation speed; *)
      xspeed -= 0.01;

  | GLUT_KEY_DOWN -> (* increase x rotation speed; *)
      xspeed += 0.01;

  | GLUT_KEY_LEFT -> (* decrease y rotation speed; *)
      yspeed -= 0.01;

  | GLUT_KEY_RIGHT -> (* increase y rotation speed; *)
      yspeed += 0.01;

  | _ -> ()
;;


(* main *)
let () =
  (* Initialize GLUT state - glut will take any command line arguments that pertain to it or X Windows 
     look at its documentation at http://www.opengl.org/resources/libraries/glut/spec3/node10.html *)
  ignore(glutInit Sys.argv);

  (* Select type of Display mode:
   Double buffer
   RGBA color
   Depth buffer
   Alpha blending *)
  glutInitDisplayMode [GLUT_RGBA; GLUT_DOUBLE; GLUT_DEPTH; GLUT_ALPHA];

  (* get a 640 x 480 window *)
  glutInitWindowSize 640 480;

  (* the window starts at the upper left corner of the screen *)
  glutInitWindowPosition 0 0;

  (* Open a window *)
  let window = glutCreateWindow "Jeff Molofee's GL Code Tutorial ... NeHe '99" in

  (* Initialize OpenGL. *)
  let texture = initGL 640 480 in

  (* Register the function to do all our OpenGL drawing. *)
  glutDisplayFunc (drawGLScene ~texture);

  (* Go fullscreen.  This is as soon as possible. *)
  glutFullScreen();

  (* Even if there are no events, redraw our gl scene. *)
  glutIdleFunc (drawGLScene ~texture);

  (* Register the function called when our window is resized. *)
  glutReshapeFunc reSizeGLScene;

  (* Register the function called when the keyboard is pressed. *)
  glutKeyboardFunc (keyPressed ~window);

  (* Register the function called when special keys (arrows, page down, etc) are pressed. *)
  glutSpecialFunc specialKeyPressed;

  (* Start Event Processing Engine *)
  glutMainLoop();
;;