(* ============================================================================== *) (* === Projet ocamlpilot - CG version du 19/04/2005 === *) (* === === *) (* === Ce programme montre comment afficher un objet en utilisant les === *) (* === primitives begin/end et comment raffraichir l'ecran. Afin de bien voir === *) (* === les raffraichissements, ceux-ci ont lieu toutes les 3 secondes. === *) (* === A tester : faire passer une autre fenetre devant celle du programme === *) (* === puis faire passer cette derniere au premier plan. === *) (* ============================================================================== *) (* ============================================================================== *) (* === initialisation d'openGL a faire pour chaque programme === *) (* ============================================================================== *) (* on recupere les arguments specifiques a OpenGL transmis sur la ligne de commande *) ignore(Glut.init Sys.argv);; (* initialisation du mode d'affichage : alpha : permet de jouer sur la luminosite des objets double_buffer : on travaille en double buffering, comme en 2D depth : on utilise le Z-buffer pour supprimer les parties cachees *) Glut.initDisplayMode ~alpha:true ~double_buffer:true ~depth:true ();; (* taille de la fenetre a l'ouverture *) Glut.initWindowSize ~w:800 ~h:600;; (* creation de la fenetre et titre de la fenetre *) ignore(Glut.createWindow "OcamlPilot");; (* gestion du clavier : ESC = sortie du programme *) let manage_keyboard () = Glut.keyboardFunc ~cb:(fun ~key ~x ~y -> if key = 27 then exit 0);; (* ============================================================================== *) (* === affichage === *) (* ============================================================================== *) let dessine_fenetre () = (* on efface le buffer dans lequel on dessine *) GlClear.color (0.0, 0.0, 0.0); (* <- couleur de fond = noir *) GlClear.clear [`color;`depth]; (* on place la camera, l'oeil au centre des axes, on regarde selon l'axe des z, vers les z croissants, et le haut de notre tete est vers le haut. *) GlMat.mode `modelview; GlMat.load_identity(); GluMat.look_at ~eye:(0.,0.,0.) ~center:(0.,0.,1.) ~up:(0.,1.,0.); (* on affiche un triangle plein rouge *) GlDraw.color (1.0, 0.0, 0.0); (* <- rouge *) GlDraw.polygon_mode `both `fill; GlDraw.begins `triangles; GlDraw.vertex ~x:(-3.) ~y:0. ~z:10. (); GlDraw.vertex ~x:(-1.) ~y:0. ~z:10. (); GlDraw.vertex ~x:(-2.) ~y:1. ~z:10. (); GlDraw.ends (); (* on affiche un carre non rempli bleu *) GlDraw.color (0.0, 0.0, 1.0); (* <- bleu *) GlDraw.polygon_mode `both `line; GlDraw.begins `quads; GlDraw.vertex ~x:1. ~y:0. ~z:10. (); GlDraw.vertex ~x:2. ~y:0. ~z:10. (); GlDraw.vertex ~x:2. ~y:1. ~z:10. (); GlDraw.vertex ~x:1. ~y:1. ~z:10. (); GlDraw.ends (); (* on effectue la synchronisation du double buffering *) Gl.flush (); Glut.swapBuffers ();; (* fonction qui reaffiche tout toutes les 3 secondes *) let rec affichage ~value = dessine_fenetre (); Glut.timerFunc ~ms:3000 ~cb:affichage ~value:0;; (* ============================================================================== *) (* === changement de taille de la fenetre === *) (* ============================================================================== *) (* en cas de modification de la taille de la fenetre, il ne faut pas aplatir ou alonger l'image mais plutot diminuer ou augmenter le champ de vision. Ceci est calcule en utilisant une matrice de projection/perspective *) let reshape_window ~w ~h = (* w = nouvelle largeur de la fenetre h = nouvelle hauteur de la fenetre *) (* remise a jour de la matrice de projection *) GlMat.mode `projection; GlMat.load_identity(); (* changement de la matrice de perspective : fovy = l'angle de vision aspect = déformation aplatissement/alongement z = la coordonnee en Z du plan le plus proche et du plus eloigne ces parametres definissent le cone de ce qui est visible *) GluMat.perspective ~fovy:45.0 ~aspect:(float w /. float h) ~z:(7.,1500.0);; (* ============================================================================== *) (* ============================================================================== *) let main () = (* on binde le clavier *) manage_keyboard (); (* creation du timer pour effectuer les affichages regulierement *) Glut.timerFunc ~ms:1000 ~cb:affichage ~value:0; (* au cas ou la taille de la fenetre aurait change *) Glut.reshapeFunc ~cb:reshape_window; (* on appelle reshape de maniere a mettre en place la matrice de perspective *) reshape_window ~w:800 ~h:600; (* lancement de la boucle principale d'openGL. Ceci doit etre effectue en dernier car mainLoop ne rendra la main qu'a la fin de l'execution du programme. *) Glut.mainLoop ();; main ();;