Sophie

Sophie

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

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

(*
 * Simon Werner, 23.07.2000
 *
 * OpenGL lesson 18. This lesson is the Linux version based on lesson 18
 * written by NeHe (Jeff Molofee):
 * http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=18
 * It is also based on other ports done by Richard Campbell.
 * This code includes snippets from lessons 5, 6, 7 and 8.
 *)

open GL                 (* Module For The OpenGL Library *)
open Glu                (* Module For The GLu Library *)
open Glut               (* Module for the GLUT library *)


let light = ref false   (* Lighting ON/OFF *)
let blend = ref false   (* Toggle blending *)

let part1 = ref 0       (* Start Of Disc  *)
let part2 = ref 0       (* End Of Disc *)
let p1 = ref 0          (* Increase 1 *)
let p2 = ref 1          (* Increase 2 *)

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

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 ( += ) a b =
  a := !a +. b;
;;

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


(* Draws the cube *)
let drawCube() =

  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. *)
;;


(* The main drawing function. *)
let drawGLScene quadratic 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 5 units into 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. *)

  begin match !object_ with           (* Check object To Find Out What To Draw *)
  | 0 ->                              (* Drawing object *)
      drawCube();                     (* Draw the cube *)

  | 1 ->                              (* Drawing object 2 *)
      glTranslate 0.0 0.0 (-1.5);     (* Center the cylinder *)
      gluCylinder quadratic 1.0 1.0 3.0 32 32;    (* Draw Our Cylinder *)

  | 2 ->                                          (* Drawing Object 3 *)
      gluDisk quadratic 0.5 1.5 32 32;            (* Draw A Disc (CD Shape) *)

  | 3 ->                                          (* Drawing Object 4 *)
      gluSphere quadratic 1.3 32 32;              (* Draw A Sphere *)

  | 4 ->                                          (* Drawing Object 5 *)
      glTranslate 0.0 0.0 (-1.5);                 (* Center The Cone *)
      gluCylinder quadratic 1.0 0.2 3.0 32 32;    (* A Cone With A Bottom Radius Of .5 And A Height Of 2 *)

  | 5 ->                                          (* Drawing Object 6 *)
      part1 := !part1 + !p1;                      (* Increase Start Angle *)
      part2 := !part2 + !p2;                      (* Increase Sweep Angle *)

      if !part1 > 359 then begin                  (* 360 Degrees *)
        p1 := 0;                                  (* Stop Increasing Start Angle *)
        part1 := 0;                               (* Set Start Angle To Zero *)
        p2 := 1;                                  (* Start Increasing Sweep Angle *)
        part2 := 0;                               (* Start Sweep Angle At Zero *)
      end;

      if !part2 > 359 then begin                  (* 360 Degrees *)
        p1 := 1;                                  (* Start Increasing Start Angle *)
        p2 := 0;                                  (* Stop Increasing Sweep Angle *)
      end;

      gluPartialDisk quadratic 0.5 1.5 32 32 (float !part1) (float(!part2 - !part1));  (* A Disk Like The One Before *)

  | _ -> ()
  end;

  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();
;;


(* Load texture *)
let loadGLTextures() =
  let image_data, sizeX, sizeY, tex_internal_fmt, pixel_data_fmt =
    Png_loader.load_img (Filename "./Data/lesson18/crate.png")
  in

  (* create Texture *)
  let texture = glGenTextures 3 in            (* Storage for 3 textures. *)

  (* 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 *)

  (* 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. *)

  (* setup blending *)
  glBlendFunc Sfactor.GL_SRC_ALPHA Dfactor.GL_ONE;         (* Set The Blending Function For Translucency *)
  glColor4 1.0 1.0 1.0 0.5;

  let quadratic = gluNewQuadric() in        (* Create A Pointer To The Quadric Object ( NEW ) *)

  (* Can also use GLU_NONE, GLU_FLAT *)
  gluQuadricNormals quadratic GLU_SMOOTH;   (* Create Smooth Normals *)
  gluQuadricTexture quadratic true;         (* Create Texture Coords ( NEW ) *)

  (quadratic, 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 function called whenever a key is pressed. *)
let keyPressed ~window ~key ~x ~y =
  match key with
  | 'Q'
  | 'q'
  | '\027' ->  (* 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 false and true. *)
      Printf.printf "Light is now: %b\n%!" !light;
      if !light
      then glEnable GL_LIGHTING
      else glDisable GL_LIGHTING;

  | 'F'
  | 'f' ->  (* switch the filter. *)
      Printf.printf "F/f pressed; filter is: %d\n%!" !filter;
      incr filter;
      if !filter > 2
      then filter := 0;       
      Printf.printf "Filter is now: %d\n%!" !filter;
    
  | 'b'
  | 'B' ->                            (* switch the blending. *)
      Printf.printf "B/b pressed; blending is: %b\n%!" !blend;
      blend := not !blend;            (* switch the current value of blend, between 0 and 1. *)
      Printf.printf "Blend is now: %b\n%!" !blend;
      if !blend then begin
        glEnable GL_BLEND;            (* Turn Blending On *)
        glDisable GL_DEPTH_TEST;      (* Turn Depth Testing Off *)
      end else begin
        glDisable GL_BLEND;           (* Turn Blending Off *)
        glEnable GL_DEPTH_TEST;       (* Turn Depth Testing On *)
      end

  | ' ' ->                            (* Is Spacebar Being Pressed? *)
      incr object_;                   (* Cycle Through The Objects *)
      if !object_ > 5 then            (* Is object Greater Than 5? *)
        object_ := 0;                 (* If So, Set To Zero *)

  | _ ->
      Printf.printf "Key %d pressed. No action there yet.\n%!" (Obj.magic key : int);
;;


(* The function called whenever a normal 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://reality.sgi.com/mjk/spec3/spec3.html *)  
  let _ = glutInit Sys.argv in

  (* Select type of Display mode:   
     Double buffer 
     RGBA color
     Alpha components supported (use GLUT_ALPHA)
     Depth buffer *)  
  glutInitDisplayMode [GLUT_RGB; GLUT_DOUBLE; GLUT_DEPTH];

  (* 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 "My GL Tutorial" in

  (* Initialize our window. *)
  let quadratic, texture = initGL 640 480 in

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

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

  (* Even if there are no events, redraw our gl scene. *)
  glutIdleFunc (drawGLScene quadratic 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();  
;;