Sophie

Sophie

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

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

(*      This code has been created by Banu Cosmin aka Choko - 20 may 2000
 *      and uses NeHe tutorials as a starting point (window initialization,
 *      texture loading, GL initialization and code for keypresses) - very good
 *      tutorials, Jeff. If anyone is interested about the presented algorithm
 *      please e-mail me at boct@romwest.ro
 *
 *      Code Commmenting And Clean Up By Jeff Molofee ( NeHe )
 *      NeHe Productions    ...     http://nehe.gamedev.net
 *)
(* Ported from C to OCaml by Florent Monnier *)

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

(* Light Parameters *)
let lightAmb = (0.7, 0.7, 0.7, 1.0)                   (* Ambient Light *)
let lightDif = (1.0, 1.0, 1.0, 1.0)                   (* Diffuse Light *)
let lightPos = (4.0, 4.0, 6.0, 1.0)                   (* Light Position *)


let xrot      = ref  0.0                              (* X Rotation *)
let yrot      = ref  0.0                              (* Y Rotation *)
let xrotspeed = ref  0.0                              (* X Rotation Speed *)
let yrotspeed = ref  0.0                              (* Y Rotation Speed *)
let zoom      = ref(-7.0)                             (* Depth Into The Screen *)
let height    = ref  2.0                              (* Height Of Ball From Floor *)

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


let reshape ~width ~height =                          (* Resize And Initialize The GL Window *)
  let height =
    if height = 0                                     (* Prevent A Divide By Zero By *)
    then 1                                            (* Making Height Equal One *)
    else height
  in
  glViewport 0 0 width height;                        (* Reset The Current Viewport *)

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

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

  glMatrixMode GL_MODELVIEW;                          (* Select The Modelview Matrix *)
  glLoadIdentity();                                   (* Reset The Modelview Matrix *)
;;


let loadGLTextures() =                                (* Load Bitmaps And Convert To Textures *)
  (* Load Texture *)
  let load_image filename =
    let image_data, sizeX, sizeY, _, _ = Png_loader.load_img (Filename filename) in
    (sizeX, sizeY, image_data)
  in
  let files = [|
    "Data/lesson26/Envwall.png";                      (* The Floor Texture *)
    "Data/lesson26/Ball.png";                         (* the Light Texture *)
    "Data/lesson26/Envroll.png";                      (* the Wall Texture *)
  |] in
  let img_textures = Array.map load_image files in

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

  Array.iteri (fun i (sizeX, sizeY, image_data) ->
      glBindTexture BindTex.GL_TEXTURE_2D textures.(i);
      glTexImage2D TexTarget.GL_TEXTURE_2D 0 (Cnst 3) sizeX sizeY 0 GL_RGB GL_UNSIGNED_BYTE image_data;
      glTexParameter TexParam.GL_TEXTURE_2D (TexParam.GL_TEXTURE_MAG_FILTER Mag.GL_LINEAR);
      glTexParameter TexParam.GL_TEXTURE_2D (TexParam.GL_TEXTURE_MIN_FILTER Min.GL_LINEAR);
  ) img_textures;

  (textures)
;;


let initGL() =                                        (* All Setup For OpenGL Goes Here *)
  let texture = loadGLTextures() in                   (* If Loading The Textures Failed *)
  glShadeModel GL_SMOOTH;                             (* Enable Smooth Shading *)
  glClearColor 0.2 0.5 1.0 1.0;                       (* Background *)
  glClearDepth 1.0;                                   (* Depth Buffer Setup *)
  glClearStencil 0;                                   (* Clear The Stencil Buffer To 0 *)
  glEnable GL_DEPTH_TEST;                             (* Enables Depth Testing *)
  glDepthFunc GL_LEQUAL;                              (* The Type Of Depth Testing To Do *)
  glHint GL_PERSPECTIVE_CORRECTION_HINT  GL_NICEST;   (* Really Nice Perspective Calculations *)
  glEnable GL_TEXTURE_2D;                             (* Enable 2D Texture Mapping *)

  glLight (GL_LIGHT 0) (Light.GL_AMBIENT  lightAmb);  (* Set The Ambient Lighting For Light0 *)
  glLight (GL_LIGHT 0) (Light.GL_DIFFUSE  lightDif);  (* Set The Diffuse Lighting For Light0 *)
  glLight (GL_LIGHT 0) (Light.GL_POSITION lightPos);  (* Set The Position For Light0 *)

  glEnable GL_LIGHT0;                                 (* Enable Light 0 *)
  glEnable GL_LIGHTING;                               (* Enable Lighting *)

  let q = gluNewQuadric() in                          (* Create A New Quadratic For Drawing A Sphere *)
  gluQuadricNormals q GLU_SMOOTH;                     (* Generate Smooth Normals For The Quad *)
  gluQuadricTexture q true;                           (* Enable Texture Coords For The Quad *)

  glTexGen GL_S GL_TEXTURE_GEN_MODE GL_SPHERE_MAP;    (* Set Up Sphere Mapping *)
  glTexGen GL_T GL_TEXTURE_GEN_MODE GL_SPHERE_MAP;    (* Set Up Sphere Mapping *)

  (texture, q)
;;


let drawObject ~q ~texture =                          (* Draw Our Ball *)
  glColor3 1.0 1.0 1.0;                               (* Set Color To White *)
  glBindTexture BindTex.GL_TEXTURE_2D texture.(1);    (* Select Texture 2 (1) *)
  gluSphere q 0.35 32 16;                             (* Draw First Sphere *)

  glBindTexture BindTex.GL_TEXTURE_2D texture.(2);    (* Select Texture 3 (2) *)
  glColor4 1.0 1.0 1.0 0.4;                           (* Set Color To White With 40% Alpha *)
  glEnable GL_BLEND;                                  (* Enable Blending *)
  glBlendFunc Sfactor.GL_SRC_ALPHA Dfactor.GL_ONE;    (* Set Blending Mode To Mix Based On SRC Alpha *)
  glEnable GL_TEXTURE_GEN_S;                          (* Enable Sphere Mapping *)
  glEnable GL_TEXTURE_GEN_T;                          (* Enable Sphere Mapping *)

  gluSphere q 0.35 32 16;                             (* Draw Another Sphere Using New Texture *)
                                                      (* Textures Will Mix Creating A MultiTexture Effect (Reflection) *)
  glDisable GL_TEXTURE_GEN_S;                         (* Disable Sphere Mapping *)
  glDisable GL_TEXTURE_GEN_T;                         (* Disable Sphere Mapping *)
  glDisable GL_BLEND;                                 (* Disable Blending *)
;;


let drawFloor ~texture =                              (* Draws The Floor *)
  glBindTexture BindTex.GL_TEXTURE_2D texture.(0);    (* Select Texture 1 (0) *)
  glBegin GL_QUADS;                                   (* Begin Drawing A Quad *)
    glNormal3 0.0 1.0 0.0;                            (* Normal Pointing Up *)
      glTexCoord2 0.0 1.0;                            (* Bottom Left Of Texture *)
      glVertex3 (-2.0) 0.0 2.0;                       (* Bottom Left Corner Of Floor *)

      glTexCoord2 0.0 0.0;                            (* Top Left Of Texture *)
      glVertex3 (-2.0) 0.0 (-2.0);                    (* Top Left Corner Of Floor *)

      glTexCoord2 1.0 0.0;                            (* Top Right Of Texture *)
      glVertex3 2.0 0.0 (-2.0);                       (* Top Right Corner Of Floor *)

      glTexCoord2 1.0 1.0;                            (* Bottom Right Of Texture *)
      glVertex3 2.0 0.0 2.0;                          (* Bottom Right Corner Of Floor *)
  glEnd();                                            (* Done Drawing The Quad *)
;;


let display ~q ~texture () =                          (* Draw Everything *)
  (* Clear Screen, Depth Buffer & Stencil Buffer *)
  glClear [GL_COLOR_BUFFER_BIT; GL_DEPTH_BUFFER_BIT; GL_STENCIL_BUFFER_BIT];

  (* Clip Plane Equations *)
  let eqr = [| 0.0; -1.0; 0.0; 0.0 |] in              (* Plane Equation To Use For The Reflected Objects *)

  glLoadIdentity();                                   (* Reset The Modelview Matrix *)
  glTranslate 0.0 (-0.6) !zoom;                       (* Zoom And Raise Camera Above The Floor (Up 0.6 Units) *)
  glColorMask false false false false;                (* Set Color Mask *)
  glEnable GL_STENCIL_TEST;                           (* Enable Stencil Buffer For "marking" The Floor *)
  glStencilFunc GL_ALWAYS 1 1;                        (* Always Passes, 1 Bit Plane, 1 As Mask *)
  glStencilOp GL_KEEP  GL_KEEP  GL_REPLACE;           (* We Set The Stencil Buffer To 1 Where We Draw Any Polygon *)
                                                      (* Keep If Test Fails, Keep If Test Passes But Buffer Test Fails *)
                                                      (* Replace If Test Passes *)
  glDisable GL_DEPTH_TEST;                            (* Disable Depth Testing *)
  drawFloor ~texture;                                 (* Draw The Floor (Draws To The Stencil Buffer) *)
                                                      (* We Only Want To Mark It In The Stencil Buffer *)
  glEnable GL_DEPTH_TEST;                             (* Enable Depth Testing *)
  glColorMask true true true true;                    (* Set Color Mask to true, true, true, true *)
  glStencilFunc GL_EQUAL 1 1;                         (* We Draw Only Where The Stencil Is 1 *)
                                                      (* (I.E. Where The Floor Was Drawn) *)
  glStencilOp GL_KEEP  GL_KEEP  GL_KEEP;              (* Don't Change The Stencil Buffer *)
  glEnable GL_CLIP_PLANE0;                            (* Enable Clip Plane For Removing Artifacts *)
                                                      (* (When The Object Crosses The Floor) *)
  glClipPlane Plane.GL_CLIP_PLANE0 eqr;               (* Equation For Reflected Objects *)
  glPushMatrix();                                     (* Push The Matrix Onto The Stack *)
    glScale 1.0 (-1.0) 1.0;                           (* Mirror Y Axis *)
    glLight (GL_LIGHT 0) (Light.GL_POSITION lightPos);(* Set Up Light0 *)
    glTranslate 0.0 !height 0.0;                      (* Position The Object *)
    glRotate !xrot 1.0 0.0 0.0;                       (* Rotate Local Coordinate System On X Axis *)
    glRotate !yrot 0.0 1.0 0.0;                       (* Rotate Local Coordinate System On Y Axis *)
    drawObject ~q ~texture;                           (* Draw The Sphere (Reflection) *)
  glPopMatrix();                                      (* Pop The Matrix Off The Stack *)
  glDisable GL_CLIP_PLANE0;                           (* Disable Clip Plane For Drawing The Floor *)
  glDisable GL_STENCIL_TEST;                          (* We Don't Need The Stencil Buffer Any More (Disable) *)
  glLight (GL_LIGHT 0) (Light.GL_POSITION lightPos);  (* Set Up Light0 Position *)
  glEnable GL_BLEND;                                  (* Enable Blending (Otherwise The Reflected Object Wont Show) *)
  glDisable GL_LIGHTING;                              (* Since We Use Blending, We Disable Lighting *)
  glColor4 1.0 1.0 1.0 0.8;                           (* Set Color To White With 80% Alpha *)
  glBlendFunc Sfactor.GL_SRC_ALPHA
              Dfactor.GL_ONE_MINUS_SRC_ALPHA;         (* Blending Based On Source Alpha And 1 Minus Dest Alpha *)
  drawFloor ~texture;                                 (* Draw The Floor To The Screen *)
  glEnable GL_LIGHTING;                               (* Enable Lighting *)
  glDisable GL_BLEND;                                 (* Disable Blending *)
  glTranslate 0.0 !height 0.0;                        (* Position The Ball At Proper Height *)
  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 *)
  drawObject ~q ~texture;                             (* Draw The Ball *)
  xrot += !xrotspeed;                                 (* Update X Rotation Angle By xrotspeed *)
  yrot += !yrotspeed;                                 (* Update Y Rotation Angle By yrotspeed *)
  glFlush();                                          (* Flush The GL Pipeline *)

  glutSwapBuffers();
;;


let key ~key ~x ~y =
  begin match key with
  | '\027' | 'q' ->
      exit(0);

  | 'A' ->
      zoom += 0.05;

  | 'Z' ->
      zoom -= 0.05;
  | _ -> ()
  end;
  glutPostRedisplay();
;;


let specialKey ~key ~x ~y =
  begin match key with
  | GLUT_KEY_UP ->
      xrotspeed += 0.08;
  | GLUT_KEY_DOWN ->
      xrotspeed -= 0.08;
  | GLUT_KEY_LEFT ->
      yrotspeed -= 0.08;
  | GLUT_KEY_RIGHT ->
      yrotspeed += 0.08;
  | GLUT_KEY_PAGE_UP ->
      height += 0.03;
  | GLUT_KEY_PAGE_DOWN ->
      height -= 0.03;
  | _ -> ()
  end;
  glutPostRedisplay();
;;


(* main *)
let () =
  let _ = glutInit Sys.argv in
  glutInitWindowPosition 0 0;
  glutInitWindowSize 640 480;
  glutInitDisplayMode [GLUT_RGB; GLUT_DOUBLE; GLUT_DEPTH; GLUT_STENCIL];
  let _ = glutCreateWindow Sys.argv.(0) in
  let texture, q = initGL() in
  glutReshapeFunc ~reshape;
  glutKeyboardFunc (key);
  glutSpecialFunc (specialKey);
  glutDisplayFunc (display ~q ~texture);
  glutMainLoop();
;;