Sophie

Sophie

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

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

(*
 *  This Code Was Created By Pet & Commented/Cleaned Up By Jeff Molofee
 *  If You've Found This Code Useful, Please Let Me Know.
 *  Visit NeHe Productions At http://nehe.gamedev.net
 *
 *  glut port by tsuraan
 *  ocaml port by Florent Monnier
 *)

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

let xrot, yrot, zrot = ref 0., ref 0., ref 0. ;;        (* X, Y & Z Rotation *)
let xspeed, yspeed, zspeed = ref 0., ref 0., ref 0. ;;  (* X, Y & Z Spin Speed *)
let cx, cy, cz = ref 0.0, ref 0.0, ref(-15.0) ;;        (* X, Y & Z Position *)

let key = ref 1                                         (* Used To Make Sure Same Morph Key Is Not Pressed *)
let step = ref 0 ;; let steps = 300                     (* Step Counter And Maximum Number Of Steps *)
let morph = ref false                                   (* Default morph To False (Not Morphing) *)

type vertex = {                                         (* Structure Called VERTEX For 3D Points *)
  mutable x: float;
  mutable y: float;                                     (* X, Y & Z Points *)
  mutable z: float;
}

type object_ = {                                        (* Structure Called OBJECT For An Object *)
  verts: int;                                           (* Number Of Vertices For The Object *)
  points: vertex array;                                 (* One Vertice (Vertex x,y & z) *)
}

let sour = ref { verts=0; points=[| |] }                (* Helper Object, Source Object, Destination Object *)
let dest = ref { verts=0; points=[| |] }
let helper = ref { verts=0; points=[| |] }

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

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


let objload ~name =                                     (* Loads Object From File (name) *)
  let ic = open_in name in
  let line = input_line ic in
  (* Scans Text For "Vertices: ".  Number After Is Stored In ver *)
  let nverts = Scanf.sscanf line "Vertices: %d" (fun n -> n) in
  let obj =
    { verts = nverts;
      points = Array.init nverts (fun _ ->
        let line = input_line ic in
        (* Searches For 3 Floating Point Numbers, Store In x,y & z *)
        let x, y, z = Scanf.sscanf line "%f %f %f" (fun x y z -> x,y,z) in
        { x=x; y=y; z=z; }
      );
    }
  in
  close_in ic;
  (obj)
;;


let calculate ~i =                                    (* Calculates Movement Of Points During Morphing *)
  { x = (!sour.points.(i).x -. !dest.points.(i).x) /. float steps;
    y = (!sour.points.(i).y -. !dest.points.(i).y) /. float steps;
    z = (!sour.points.(i).z -. !dest.points.(i).z) /. float steps; }
;;                                                    (* This Makes Points Move At A Speed So They All Get To Their *)
                                                      (* Destination At The Same Time *)

let resize ~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                                       (* Keep It Unchanged *)
  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 initGL() =                                        (* All Setup For OpenGL Goes Here *)
  glBlendFunc Sfactor.GL_SRC_ALPHA  Dfactor.GL_ONE;   (* Set The Blending Function For Translucency *)
  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 *)
  glHint GL_PERSPECTIVE_CORRECTION_HINT  GL_NICEST;   (* Really Nice Perspective Calculations *)

  let morph1 = objload "Data/lesson25/Sphere.txt" in  (* Load The First Object Into morph1 From File sphere.txt *)
  let morph2 = objload "Data/lesson25/Torus.txt" in   (* Load The Second Object Into morph2 From File torus.txt *)
  let morph3 = objload "Data/lesson25/Tube.txt" in    (* Load The Third Object Into morph3 From File tube.txt *)

  let morph4 = {
    verts = 486;
    points =
      Array.init 486 (fun _ ->                        (* Loop Through All 468 Vertices *)
        { x = (Random.float 14.0) -. 7.0;             (* morph4 x Point Becomes A Random Float Value From -7 to 7 *)
          y = (Random.float 14.0) -. 7.0;             (* morph4 y Point Becomes A Random Float Value From -7 to 7 *)
          z = (Random.float 14.0) -. 7.0; }           (* morph4 z Point Becomes A Random Float Value From -7 to 7 *)
      );
  } in

  helper := objload "Data/lesson25/Sphere.txt";       (* Load sphere.txt Object Into Helper (Used As Starting Point) *)
  sour := morph1;                                     (* Source & Destination Are Set To Equal First Object (morph1) *)
  dest := morph1;

  (morph1, morph2, morph3, morph4)
;;

let ( <-= ) v1 v2 =
  v1.x <- v1.x -. v2.x;
  v1.y <- v1.y -. v2.y;
  v1.z <- v1.z -. v2.z;
;;

let drawGLScene (morph1, _, _, _) () =                (* Here's Where We Do All The Drawing *)
  glClear [GL_COLOR_BUFFER_BIT; GL_DEPTH_BUFFER_BIT]; (* Clear The Screen And The Depth Buffer *)
  glLoadIdentity();                                   (* Reset The View *)
  glTranslate !cx !cy !cz;                            (* Translate The The Current Position To Start Drawing *)
  glRotate !xrot 1.0 0.0 0.0;                         (* Rotate On The X Axis By xrot *)
  glRotate !yrot 0.0 1.0 0.0;                         (* Rotate On The Y Axis By yrot *)
  glRotate !zrot 0.0 0.0 1.0;                         (* Rotate On The Z Axis By zrot *)

  xrot += !xspeed; yrot += !yspeed; zrot += !zspeed;  (* Increase xrot,yrot & zrot by xspeed, yspeed & zspeed *)

  glBegin GL_POINTS;                                  (* Begin Drawing Points *)
    for i = 0 to pred morph1.verts do                 (* Loop Through All The Verts Of morph1 (All Objects Have *)
                                                      (* The Same Amount Of Verts For Simplicity *)
      let q = if !morph then calculate i
                        else { x=0.; y=0.; z=0.; } in (* If morph Is True Calculate Movement Otherwise Movement=0 *)
      !helper.points.(i).x <- !helper.points.(i).x -. q.x;  (* Subtract q.x Units From helper.points[i].x (Move On X Axis) *)
      !helper.points.(i).y <- !helper.points.(i).y -. q.y;  (* Subtract q.y Units From helper.points[i].y (Move On Y Axis) *)
      !helper.points.(i).z <- !helper.points.(i).z -. q.z;  (* Subtract q.z Units From helper.points[i].z (Move On Z Axis) *)
      let tx = ref !helper.points.(i).x in            (* Make Temp X Variable Equal To Helper's X Variable *)
      let ty = ref !helper.points.(i).y in            (* Make Temp Y Variable Equal To Helper's Y Variable *)
      let tz = ref !helper.points.(i).z in            (* Make Temp Z Variable Equal To Helper's Z Variable *)

      glColor3 0. 1. 1.;                              (* Set Color To A Bright Shade Of Off Blue *)
      glVertex3 !tx !ty !tz;                          (* Draw A Point At The Current Temp Values (Vertex) *)
      glColor3 0. 0.5 1.;                             (* Darken Color A Bit *)
      tx-=2.*.q.x; ty-=2.*.q.y; ty-=2.*.q.y;          (* Calculate Two Positions Ahead *)
      glVertex3 !tx !ty !tz;                          (* Draw A Second Point At The Newly Calculate Position *)
      glColor3 0. 0. 1.;                              (* Set Color To A Very Dark Blue *)
      tx-=2.*.q.x; ty-=2.*.q.y; ty-=2.*.q.y;          (* Calculate Two More Positions Ahead *)
      glVertex3 !tx !ty !tz;                          (* Draw A Third Point At The Second New Position *)
    done;                                             (* This Creates A Ghostly Tail As Points Move *)
  glEnd();                                            (* Done Drawing Points *)

  (* If We're Morphing And We Haven't Gone Through All 200 Steps Increase Our Step Counter
     Otherwise Set Morphing To False, Make Source=Destination And Set The Step Counter Back To Zero. *)
  if (!morph && !step <= steps)
  then incr step
  else ( morph := false;  sour := !dest;  step := 0 );

  glutSwapBuffers();
;;


let specialFunc ~key ~x ~y =
  match key with
  | GLUT_KEY_PAGE_UP ->                       (* Is Page Up Being Pressed? *)
      zspeed += 0.01;                         (* Increase zspeed *)

  | GLUT_KEY_PAGE_DOWN ->                     (* Is Page Down Being Pressed? *)
      zspeed -= 0.01;                         (* Decrease zspeed *)

  | GLUT_KEY_DOWN ->                          (* Is Down Being Pressed? *)
      xspeed += 0.01;                         (* Increase xspeed *)

  | GLUT_KEY_UP ->                            (* Is Up Being Pressed? *)
      xspeed -= 0.01;                         (* Decrease xspeed *)

  | GLUT_KEY_RIGHT ->                         (* Is Right Being Pressed? *)
      yspeed += 0.01;                         (* Increase yspeed *)

  | GLUT_KEY_LEFT ->                          (* Is Left Being Pressed? *)
      yspeed -= 0.01;                         (* Decrease yspeed *)
  | _ -> ()
;;


let keyFunc (morph1, morph2, morph3, morph4) ~key:k ~x ~y =
  match k with
  | 'Q' | 'q' ->                              (* Is Q Key Being Pressed? *)
      cz -= 0.01;                             (* Move Object Away From Viewer *)

  | 'Z' | 'z' ->                              (* Is Z Key Being Pressed? *)
      cz += 0.01;                             (* Move Object Towards Viewer *)

  | 'W' | 'w' ->                              (* Is W Key Being Pressed? *)
      cy += 0.01;                             (* Move Object Up *)

  | 'S' | 's' ->                              (* Is S Key Being Pressed? *)
      cy -= 0.01;                             (* Move Object Down *)

  | 'D' | 'd' ->                              (* Is D Key Being Pressed? *)
      cx += 0.01;                             (* Move Object Right *)

  | 'A' | 'a' ->                              (* Is A Key Being Pressed? *)
      cx -= 0.01;                             (* Move Object Left *)

  | '1' -> 
      if !key<>1 && not !morph then     (* Is 1 Pressed, key Not Equal To 1 And Morph False? *)
      begin
        key := 1;                             (* Sets key To 1 (To Prevent Pressing 1 2x In A Row) *)
        morph := true;                        (* Set morph To True (Starts Morphing Process) *)
        dest := morph1;                       (* Destination Object To Morph To Becomes morph1 *)
      end

  | '2' ->
      if !key<>2 && not !morph then     (* Is 2 Pressed, key Not Equal To 2 And Morph False? *)
      begin
        key := 2;                             (* Sets key To 2 (To Prevent Pressing 2 2x In A Row) *)
        morph := true;                        (* Set morph To True (Starts Morphing Process) *)
        dest := morph2;                       (* Destination Object To Morph To Becomes morph2 *)
      end

  | '3' ->
      if !key<>3 && not !morph then     (* Is 3 Pressed, key Not Equal To 3 And Morph False? *)
      begin
        key := 3;                             (* Sets key To 3 (To Prevent Pressing 3 2x In A Row) *)
        morph := true;                        (* Set morph To True (Starts Morphing Process) *)
        dest := morph3;                       (* Destination Object To Morph To Becomes morph3 *)
      end

  | '4' ->
      if !key<>4 && not !morph then     (* Is 4 Pressed, key Not Equal To 4 And Morph False? *)
      begin
        key := 4;                             (* Sets key To 4 (To Prevent Pressing 4 2x In A Row) *)
        morph := true;                        (* Set morph To True (Starts Morphing Process) *)
        dest := morph4;                       (* Destination Object To Morph To Becomes morph4 *)
      end

  | '\027' ->                           (* Escape key is pressed *)
      exit(0);

  | _ -> ()
;;


(* main *)
let () =
  let _ = glutInit Sys.argv in
  glutInitWindowSize 640 480;
  glutInitDisplayMode [GLUT_DOUBLE; GLUT_RGB; GLUT_DEPTH];
  let _ = glutCreateWindow "Piotr Cieslak & NeHe's Morphing Points Tutorial" in
  let morphs = initGL() in
  glutDisplayFunc (drawGLScene morphs);
  glutIdleFunc (drawGLScene morphs);
  glutKeyboardFunc (keyFunc morphs);
  glutSpecialFunc (specialFunc);
  glutReshapeFunc (resize);
  glutMainLoop();
;;