From a72d2ca0d4b340e9e5aebfa989f3001b32ff1e9a Mon Sep 17 00:00:00 2001
From: Gilles Marckmann <gilles.marckmann@ec-nantes.fr>
Date: Fri, 26 Nov 2010 16:31:05 +0000
Subject: [PATCH] first implementation of camera mode in FLTK GUI

---
 Fltk/graphicWindow.cpp       |  96 +++++++----
 Fltk/openglWindow.cpp        |  31 +++-
 Fltk/optionWindow.cpp        |   5 +-
 Graphics/Camera.cpp          | 308 +++++++++++++++++++++--------------
 Graphics/Camera.h            | 172 +++++++++----------
 Graphics/drawContext.cpp     |  49 ++++--
 Graphics/drawContext.h       |   2 +
 utils/api_demos/mainGlut.cpp | 248 ++++++++--------------------
 8 files changed, 460 insertions(+), 451 deletions(-)

diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp
index bcabd7d010..70d674588f 100644
--- a/Fltk/graphicWindow.cpp
+++ b/Fltk/graphicWindow.cpp
@@ -2,7 +2,7 @@
 //
 // See the LICENSE.txt file for license information. Please report all
 // bugs and problems to <gmsh@geuz.org>.
-
+ 
 #include <string.h>
 #include <FL/fl_draw.H>
 #include <FL/fl_ask.H>
@@ -128,64 +128,90 @@ void status_xyz1p_cb(Fl_Widget *w, void *data)
                              ctx0->quaternion[2], ctx0->quaternion[3]);
         }
       }
-      else if(!Fl::event_state(FL_SHIFT))
+      else if(!Fl::event_state(FL_SHIFT)){
         ctx->addQuaternionFromAxisAndAngle(axis, -90.);
-      else
+	if (CTX::instance()->camera) ctx->camera.tiltHeadRight();
+      }
+      else{
         ctx->addQuaternionFromAxisAndAngle(axis, 90.);
+	if (CTX::instance()->camera) ctx->camera.tiltHeadLeft();
+      }
     }
     else if(!strcmp(str, "x")){
       // set X-axis pointing out or into (shift) the screen
-      if(!Fl::event_state(FL_SHIFT)){
-        ctx->r[0] = -90.; ctx->r[1] = 0.; ctx->r[2] = -90.;
-      }
+      if (CTX::instance()->camera) {
+	ctx->camera.alongX();}
       else{
-        ctx->r[0] = -90.; ctx->r[1] = 0.; ctx->r[2] = 90.;
+	if(!Fl::event_state(FL_SHIFT)){
+	  ctx->r[0] = -90.; ctx->r[1] = 0.; ctx->r[2] = -90.;
+	}
+	else{
+	  ctx->r[0] = -90.; ctx->r[1] = 0.; ctx->r[2] = 90.;
+	}
+	ctx->setQuaternionFromEulerAngles();
       }
-      ctx->setQuaternionFromEulerAngles();
     }
     else if(!strcmp(str, "y")){
       // set Y-axis pointing out or into (shift) the screen
-      if(!Fl::event_state(FL_SHIFT)){
-        ctx->r[0] = -90.; ctx->r[1] = 0.; ctx->r[2] = 180.;
-      }
+      if (CTX::instance()->camera) {
+	ctx->camera.alongY();}
       else{
-        ctx->r[0] = -90.; ctx->r[1] = 0.; ctx->r[2] = 0.;
+	if(!Fl::event_state(FL_SHIFT)){
+	  ctx->r[0] = -90.; ctx->r[1] = 0.; ctx->r[2] = 180.;
+	}
+	else{
+	  ctx->r[0] = -90.; ctx->r[1] = 0.; ctx->r[2] = 0.;
+	}
+	ctx->setQuaternionFromEulerAngles();
       }
-      ctx->setQuaternionFromEulerAngles();
     }
     else if(!strcmp(str, "z")){ 
       // set Z-axis pointing out or into (shift) the screen
-      if(!Fl::event_state(FL_SHIFT)){
-        ctx->r[0] = 0.; ctx->r[1] = 0.; ctx->r[2] = 0.;
-      }
+      if (CTX::instance()->camera) {
+	ctx->camera.alongZ();}
       else{
-        ctx->r[0] = 0.; ctx->r[1] = 180.; ctx->r[2] = 0.;
+	if(!Fl::event_state(FL_SHIFT)){
+	  ctx->r[0] = 0.; ctx->r[1] = 0.; ctx->r[2] = 0.;
+	}
+	else{
+	  ctx->r[0] = 0.; ctx->r[1] = 180.; ctx->r[2] = 0.;
+	}
+	ctx->setQuaternionFromEulerAngles();
       }
-      ctx->setQuaternionFromEulerAngles();
     }
     else if(!strcmp(str, "1:1")){
       // reset translation and scaling, or sync translation and
       // scaling with the first window (alt)
-      if(Fl::event_state(FL_ALT)){
-        if(i != 0){
-          drawContext *ctx0 = gls[0]->getDrawContext();
-          for(int j = 0; j < 3; j++){
-            ctx->t[j] = ctx0->t[j];
-            ctx->s[j] = ctx0->s[j];
-          }
-        }
-      }
+      if (CTX::instance()->camera) {
+	ctx->camera.lookAtCg();}
       else{
-        ctx->t[0] = ctx->t[1] = ctx->t[2] = 0.;
-        ctx->s[0] = ctx->s[1] = ctx->s[2] = 1.;
+
+	if(Fl::event_state(FL_ALT)){
+	  if(i != 0){
+	    drawContext *ctx0 = gls[0]->getDrawContext();
+	    for(int j = 0; j < 3; j++){
+	      ctx->t[j] = ctx0->t[j];
+	      ctx->s[j] = ctx0->s[j];
+	    }
+	  }
+	}
+	else{
+	  ctx->t[0] = ctx->t[1] = ctx->t[2] = 0.;
+	  ctx->s[0] = ctx->s[1] = ctx->s[2] = 1.;
+	}
       }
     }
-    else if(!strcmp(str, "reset")){ 
-      // reset everything
-      ctx->t[0] = ctx->t[1] = ctx->t[2] = 0.;
-      ctx->s[0] = ctx->s[1] = ctx->s[2] = 1.;
-      ctx->r[0] = ctx->r[1] = ctx->r[2] = 0.;
-      ctx->setQuaternionFromEulerAngles();
+    else if(!strcmp(str, "reset")){
+ 
+      if (CTX::instance()->camera) {
+	ctx->camera.init();}
+      else{
+	// reset everything
+	ctx->t[0] = ctx->t[1] = ctx->t[2] = 0.;
+	ctx->s[0] = ctx->s[1] = ctx->s[2] = 1.;
+	ctx->r[0] = ctx->r[1] = ctx->r[2] = 0.;
+	ctx->setQuaternionFromEulerAngles();
+      }
     }
   }
   drawContext::global()->draw();
diff --git a/Fltk/openglWindow.cpp b/Fltk/openglWindow.cpp
index d79f4cb619..2a4b44d158 100644
--- a/Fltk/openglWindow.cpp
+++ b/Fltk/openglWindow.cpp
@@ -3,6 +3,7 @@
 // See the LICENSE.txt file for license information. Please report all
 // bugs and problems to <gmsh@geuz.org>.
 
+#include "stdio.h"
 #include "openglWindow.h"
 #include "graphicWindow.h"
 #include "manipWindow.h"
@@ -14,8 +15,9 @@
 #include "MElement.h"
 #include "Numeric.h"
 #include "FlGui.h"
+#include <GL/glu.h>
 #include "Context.h"
-
+ 
 static void lassoZoom(drawContext *ctx, mousePosition &click1, mousePosition &click2)
 {
   if(click1.win[0] == click2.win[0] || click1.win[1] == click2.win[1])
@@ -165,13 +167,16 @@ void openglWindow::draw()
       CTX::instance()->mesh.draw = 0;
       CTX::instance()->post.draw = 0;
     }
+    
     glClearColor
       ((GLclampf)(CTX::instance()->unpackRed(CTX::instance()->color.bg) / 255.),
        (GLclampf)(CTX::instance()->unpackGreen(CTX::instance()->color.bg) / 255.),
        (GLclampf)(CTX::instance()->unpackBlue(CTX::instance()->color.bg) / 255.), 
        0.0F);
+    
     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
-    _ctx->draw3d();
+
+     _ctx->draw3d();
     glColor4ubv((GLubyte *) & CTX::instance()->color.fg);
     glPointSize((float)CTX::instance()->geom.pointSize);
     glBegin(GL_POINTS);
@@ -185,18 +190,36 @@ void openglWindow::draw()
   }
   else{
     // draw the whole scene
+    /*
     glClearColor
       ((GLclampf)(CTX::instance()->unpackRed(CTX::instance()->color.bg) / 255.),
        (GLclampf)(CTX::instance()->unpackGreen(CTX::instance()->color.bg) / 255.),
        (GLclampf)(CTX::instance()->unpackBlue(CTX::instance()->color.bg) / 255.), 
        0.0F);
+    */
     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+
+    if(CTX::instance()->camera){
+      Camera *  cam= &(_ctx->camera);      
+      if (!cam->on) cam->init();
+      cam->giveViewportDimension(_ctx->viewport[2],_ctx->viewport[3]);  
+      glMatrixMode(GL_PROJECTION);
+      glLoadIdentity();
+      glFrustum(cam->glFleft,cam->glFright,cam->glFbottom,cam->glFtop,cam->near,cam->far); 
+      glMatrixMode(GL_MODELVIEW);
+      glLoadIdentity();
+      glDrawBuffer(GL_BACK);
+      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+      glLoadIdentity();
+      gluLookAt(cam->position.x,cam->position.y,cam->position.z,
+		cam->target.x,cam->target.y,cam->target.z,
+		cam->up.x,cam->up.y,cam->up.z);      
+    }
     _ctx->draw3d();
     _ctx->draw2d();
     _drawScreenMessage();
     _drawBorder();
   }
-
   _lock = false;
 }
 
@@ -407,7 +430,7 @@ int openglWindow::handle(int event)
       // find line in real space corresponding to current cursor position
       double p[3], d[3];
       _ctx->unproject(_curr.win[0], _curr.win[1], p, d);
-      // fin closest point to the center of gravity
+      // fin closest point to the center of graity
       double r[3] = {CTX::instance()->cg[0] - p[0], CTX::instance()->cg[1] - p[1], 
                      CTX::instance()->cg[2] - p[2]}, t;
       prosca(r, d, &t);
diff --git a/Fltk/optionWindow.cpp b/Fltk/optionWindow.cpp
index 2766d0db7b..21b5b678b5 100644
--- a/Fltk/optionWindow.cpp
+++ b/Fltk/optionWindow.cpp
@@ -255,9 +255,9 @@ static void general_options_ok_cb(Fl_Widget *w, void *data)
     }
     else    o->general.butt[18]->activate(); 
   }
-  if(opt_general_camera_mode(0, GMSH_GET, 0) != o->general.butt[18]->value())
+  if(opt_general_camera_mode(0, GMSH_GET, 0) != o->general.butt[18]->value()) {
     opt_general_camera_mode(0, GMSH_SET, o->general.butt[18]->value()); 
-
+  }
 
   opt_general_trackball(0, GMSH_SET, o->general.butt[5]->value());
   opt_general_terminal(0, GMSH_SET, o->general.butt[7]->value());
@@ -1328,6 +1328,7 @@ optionWindow::optionWindow(int deltaFontSize)
       general.butt[18]->type(FL_TOGGLE_BUTTON);
       general.butt[18]->callback(general_options_ok_cb);
 
+
       general.butt[17] = new Fl_Check_Button
         (L + width / 2, 2 * WB + 11 * BH, width/2-WB, BH, "Enable stereo");
       general.butt[17]->type(FL_TOGGLE_BUTTON);
diff --git a/Graphics/Camera.cpp b/Graphics/Camera.cpp
index ff46c372bf..722bbbf81f 100644
--- a/Graphics/Camera.cpp
+++ b/Graphics/Camera.cpp
@@ -1,5 +1,7 @@
 #include <string>
 #include <iostream>
+#include <stdio.h>
+#include <math.h>
 #include "Camera.h"
 #include "Gmsh.h"
 #include "GmshConfig.h"
@@ -15,31 +17,52 @@
 
 using namespace std;
   
-  
-Camera::Camera( ) {
+
+   
+Camera::~Camera(){};
+
+void Camera::init(){
+  on=true;  
+  near=0.1 ; 
+  far=10000;
+  eye_sep_ratio=.015;
   aperture = 40;
   focallength = 100.;
-  distance=focallength;
-  //  eyesep =0.88 ;
-  ratio=.015;
-  closeness=1.;
-  target = origin;
-  position = origin;
-  position.z = focallength ;
-  view.x =0.; 
-  view.y =0.; 
-  view.z =-1.;
-  up.x = 0;  
-  up.y = 1; 
-  up.z = 0;
-  screenwidth=400;
-  screenheight=400;
-  stereoEnable=false;
+  alongZ();
+  this->lookAtCg();
+  eyesep=distance*eye_sep_ratio;
   ref_distance=distance;
   this->update();
+   
+}
+
+void Camera::alongX(){ 
+  view.set(-1.,0.,0.);
+  up.set(0., 0., 1);
+  position=target-distance*view;
+  this->update();
+}
+void Camera::alongY(){ 
+  view.set(0.,-1.,0.);
+  up.set(1., 0., 0);
+  position=target-distance*view;
+  this->update();
+}
+void Camera::alongZ(){ 
+  view.set(0.,0.,-1.);
+  up.set(0., 1., 0);
+  position=target-distance*view;
+  this->update();
+}
+void Camera::tiltHeadLeft(){
+  up=-1.*right;
+  update();
+}
+void Camera::tiltHeadRight(){
+  up=right;
+  update();
 }
-  
-Camera::~Camera(){};
+
 
 
 void Camera::lookAtCg(){
@@ -49,93 +72,94 @@ void Camera::lookAtCg(){
   double W=CTX::instance()->max[0]-CTX::instance()->min[0];
   double H=CTX::instance()->max[1]-CTX::instance()->min[1];
   double P=CTX::instance()->max[2]-CTX::instance()->min[2];
-  //    cout<<" H "<<H << " W"<< W <<endl;
   Lc=sqrt(1.*W*W+1.*H*H+1.*P*P);
-  //    cout<<"  "<< 1.*W*W+1.*H*H <<endl;
-  //    cout<<"  "<< tan(aperture) <<endl;
-  distance=fabs(.5*Lc*4./3./tan(aperture*.01745329/2.));
-  distance=Lc*1.8;
-  //    cout<<" RC "<<RC << " distance"<< distance <<endl;
-  position.x=target.x-distance*view.x;
-  position.y=target.y-distance*view.y;
-  position.z=target.z-distance*view.z;
-  //  cout<<" cg "<<target.x << " "<< target.y  << " "<<target.z<<endl;
-  update();
+  //distance=fabs(.5*Lc*4./3./tan(aperture*.01745329/2.));
+  distance=Lc*1.45;
+   position=target-distance*view;
+  this->update();
   focallength=distance;
   ref_distance=distance;
-  eyesep=focallength*ratio;
+  eyesep=focallength*eye_sep_ratio;
 }
 
-
-void Camera::init(){  
-  aperture = 40;
-  ratio=.015;
-  focallength = 100;
-  //  ratio=1./50.;
-  target = origin;
-  distance=focallength;
-  position = origin;
-  position.z = distance ;
-  view.x =0.; 
-  view.y =0.; 
-  view.z =-1.;
-  up.x = 0;  
-  up.y = 1; 
-  up.z = 0;
-  ref_distance=distance;
-  eyesep=distance*ratio;
-  lookAtCg();
+void Camera::giveViewportDimension(const int& W,const int& H){
+  screenwidth=W;
+  screenheight=H;
+  screenratio=(double)W/(double)H;
+  glFleft  =-screenratio*wd2;
+  glFright = screenratio*wd2;
+  glFtop   = wd2;
+  glFbottom =-wd2;
 }
 
 void Camera::update() {
   right.x=view.y*up.z-view.z*up.y;
   right.y=view.z*up.x-view.x*up.z;
   right.z=view.x*up.y-view.y*up.x;
-  up.x=right.y*view.z-right.z*view.y;
-  up.y=right.z*view.x-right.x*view.z;
-  up.z=right.x*view.y-right.y*view.x;
   ref_distance=distance;
   normalize(up);
   normalize(right);
   normalize(view);
+  radians =  0.0174532925 * aperture / 2;
+  wd2 = near * tan(radians);
+  ndfl    = near / focallength;
 }
 
+
+void Camera::affiche() {
+  cout<<"  ------------ CAMERA PARAMETERS ------------"   <<endl ;         
+  cout<<"  position "<<  position.x<<","<<position.y<<","<<position.z <<endl ;    
+  cout<<"  view "<<  view.x<<","<<view.y<<","<<view.z <<endl;              
+  cout<<"  up "<< up.x<<","<<up.y<<","<<up.z <<endl;                 
+  cout<<"  right "<< right.x<<","<<right.y<<","<<right.z  <<endl;              
+  cout<<"  target "<<  target.x<<","<<target.y<<","<<target.z <<endl;   
+  cout<<"  focallength "<<focallength <<endl;  
+  cout<<"  aperture "<<aperture <<endl;     
+  cout<<"  eyesep "<<eyesep <<endl;       
+  cout<<"  screenwidth "<<screenwidth <<endl;
+  cout<<"  screenheight "<<screenheight <<endl;
+  cout<<"  distance "<<distance <<endl;
+  cout<<"  ref_distance "<<ref_distance <<endl;
+  cout<<"  button_left_down "<<button_left_down <<endl;
+  cout<<"  button_middle_down "<< button_middle_down  <<endl;
+  cout<<"  button_right_down "<< button_right_down  <<endl;
+  cout<<"  stereoEnable "<< stereoEnable <<endl;
+  cout<<"  Lc "<< Lc<<endl;
+  cout<<"  eye_sep_ratio "<<eye_sep_ratio <<endl;
+  cout<<"  closeness "<< closeness<<endl;
+  cout<<"  near "<< near <<endl; 
+  cout<<"  far "<<far <<endl;
+  cout<<"  radians "<<radians <<endl;
+  cout<<"  wd2 "<<wd2 <<endl;
+}
+
+
+
 void Camera::moveRight(double theta) {
   this->update();
-
-  position.x=position.x-distance*tan(theta)*right.x;
-  position.y=position.y-distance*tan(theta)*right.y;
-  position.z=position.z-distance*tan(theta)*right.z;
-  target.x=position.x+distance*view.x;
-  target.y=position.y+distance*view.y;
-  target.z=position.z+distance*view.z;
+  position=position-distance*tan(theta)*right;
+  target=position+distance*view;
   this->update();
 }
 
+
 void Camera::moveUp(double theta) {
   this->update();
-  position.x=position.x+distance*tan(theta)*up.x;
-  position.y=position.y+distance*tan(theta)*up.y;
-  position.z=position.z+distance*tan(theta)*up.z;
-  target.x=position.x+distance*view.x;
-  target.y=position.y+distance*view.y;
-  target.z=position.z+distance*view.z;
+   position=position+distance*tan(theta)*up;
+  target=position+distance*view;
   this->update();
 }
 
+
 void Camera::rotate(double* q) {
   this->update();
   // rotation projection in global coordinates  
-  quaternion omega;
-  omega.x=-q[0]*right.x+q[1]*up.x+q[2]*view.x ;
-  omega.y=-q[0]*right.y+q[1]*up.y+q[2]*view.y ;
-  omega.z=-q[0]*right.z+q[1]*up.z+q[2]*view.z ;
+  Quaternion omega;
+  omega.x=q[0]*right.x+q[1]*up.x-q[2]*view.x ;
+  omega.y=q[0]*right.y+q[1]*up.y-q[2]*view.y ;
+  omega.z=q[0]*right.z+q[1]*up.z-q[2]*view.z ;
   omega.w=q[3];
-
-  quaternion q_view,q_position,new_q_view,new_q_position;
-  quaternion q_right,q_up,new_q_right,new_q_up;
-
-  // normalize the axe of rotation in the quaternion omega if not null
+  // normalize the axe of rotation in the Quaternion omega if not null
   double sina=sin(acos(omega.w));
   double length;
   if (sina != 0.){
@@ -146,51 +170,95 @@ void Camera::rotate(double* q) {
   }
   length=sqrt(length);
   if (length!=0.){
-
-    omega.x=omega.x/length;
-    omega.y=omega.y/length;
-    omega.z=omega.z/length;
-    //  rotation of the camera (view,up and right vectors) 
-    // arround 0 0 0  the CenterOfRotation  
-    //normalize(camera.view);
-  
-    //rotate view direction
-    q_view.x=view.x;
-    q_view.y=view.y;
-    q_view.z=view.z;
-    q_view.w=0.;
-    normalize(q_view);
-    new_q_view=mult(mult(omega,q_view),conjugate(omega));
-    view.x=new_q_view.x ;
-    view.y=new_q_view.y;
-    view.z=new_q_view.z;
-    //rotate up direction
-    q_up.x=up.x;
-    q_up.y=up.y;
-    q_up.z=up.z;
-    q_up.w=0.;
-    normalize(q_up);
-    new_q_up=mult(mult(omega,q_up),conjugate(omega));
-    up.x=new_q_up.x ;
-    up.y=new_q_up.y;
-    up.z=new_q_up.z;
-    //rotate right direction
-    q_right.x=right.x;
-    q_right.y=right.y;
-    q_right.z=right.z;
-    q_right.w=0.;
-    normalize(q_right);
-    new_q_right=mult(mult(omega,q_right),conjugate(omega));
-    right.x=new_q_right.x ;
-    right.y=new_q_right.y;
-    right.z=new_q_right.z;
-
-     //actualize camera position 
-    position.x=target.x-view.x*distance;
-    position.y=target.y-view.y*distance;
-    position.z=target.z-view.z*distance;
-      
+    omega.x/=length;
+    omega.y/=length;
+    omega.z/=length;
+    Quaternion conj=conjugate(omega);  
+    view=omega*view*conj;
+    up=omega*up*conj;
+    right=omega*right*conj;
+    normalize(view);
+    normalize(up);
+    normalize(right);
+    //actualize camera position 
+    position=target-distance*view;
   }
   this->update();
 }
 
+
+
+
+
+// Quaternion and XYZ functions
+double length(Quaternion &q) {  return sqrt(q.x*q.x+q.y*q.y+q.z*q.z+q.w*q.w); }
+
+double length(XYZ &p) {  return sqrt(p.x*p.x+p.y*p.y+p.z*p.z);}
+
+void normalize(Quaternion &quat)
+{
+  double L = length(quat);
+  quat.x /= L;   quat.y /= L;   quat.z /= L;   quat.w /= L;
+}
+
+void normalize(XYZ &p){
+  double L = length(p);
+  p.x /= L;   p.y /= L;   p.z /= L;
+}
+
+XYZ::XYZ (const Quaternion &R):x(R.x), y(R.y), z(R.z){} 
+
+XYZ::XYZ(double _x,double _y,double _z):x(_x),y(_y),z(_z){}
+
+void XYZ::set(const double&  _x,const double&  _y,const double&  _z){x=_x;y=_y;z=_z;}
+
+void rotate(Quaternion omega,XYZ axe) {
+  XYZ new_axe;
+  Quaternion qaxe,new_qaxe;
+  qaxe.x=axe.x;    qaxe.y=axe.y;   qaxe.z=axe.z;   qaxe.w=0.;
+  new_qaxe=mult(mult(omega,qaxe),conjugate(omega));
+  axe.x=new_qaxe.x ;   axe.y=new_qaxe.y;   axe.z=new_qaxe.z;
+}
+
+XYZ operator* (const double &a,const XYZ &T){ 
+  XYZ res(T);
+  res.x*=a;
+  res.y*=a;
+  res.z*=a;
+  return res;
+}
+XYZ operator+ (const XYZ &L,const XYZ &R){ 
+  XYZ res(L);
+  res.x+=R.x;
+  res.y+=R.y;
+  res.z+=R.z;
+  return res;
+}
+XYZ operator- (const XYZ &L,const XYZ &R){ 
+  XYZ res(L);
+  res.x-=R.x;
+  res.y-=R.y;
+  res.z-=R.z;
+  return res;
+}
+
+Quaternion::Quaternion(const XYZ &R):x(R.x), y(R.y), z(R.z),w(0.){}
+
+Quaternion mult(const Quaternion& A,const Quaternion& B)
+{
+  Quaternion C;
+  C.x = A.w*B.x + A.x*B.w + A.y*B.z - A.z*B.y;
+  C.y = A.w*B.y - A.x*B.z + A.y*B.w + A.z*B.x;
+  C.z = A.w*B.z + A.x*B.y - A.y*B.x + A.z*B.w;
+  C.w = A.w*B.w - A.x*B.x - A.y*B.y - A.z*B.z;
+  return C;
+}
+
+Quaternion operator *(const Quaternion& A,const Quaternion& B){
+  return mult(A,B);
+}
+
+Quaternion conjugate(Quaternion quat) {
+  quat.x = -quat.x;   quat.y = -quat.y;   quat.z = -quat.z;
+  return quat;
+}
diff --git a/Graphics/Camera.h b/Graphics/Camera.h
index 390030da75..fe55bec61e 100644
--- a/Graphics/Camera.h
+++ b/Graphics/Camera.h
@@ -2,53 +2,97 @@
 #ifndef _CAMERA_H_
 #define _CAMERA_H_
 
-#include <stdio.h>
-#include <math.h>
-#
-
 
+/*
 typedef struct {
+  double x,y,z,w;
+} Quaternion;
+*/ 
+class Quaternion;
+
+class XYZ {
+public: 
+  XYZ(){};
+  ~XYZ(){};
+  XYZ(double _x,double _y,double _z);
   double x,y,z;
-} XYZ;
-typedef struct {
+  //  double length(XYZ &p);
+  //  void normalize(XYZ &p);
+  //  void rotate(Quaternion omega,XYZ axe) ; 
+  void set(const  double & _x, const double & _y ,const  double & _z);
+  XYZ (const Quaternion &R);
+};
+double length(XYZ &p);
+void normalize(XYZ &p);
+void rotate(Quaternion omega,XYZ axe) ; 
+XYZ operator* (const double &a,const XYZ &T);
+XYZ operator+ (const XYZ &L,const XYZ &R);
+XYZ operator- (const XYZ &L,const XYZ &R);
+
+
+class Quaternion{
+public:
   double x,y,z,w;
-} quaternion;
+  Quaternion(){}; 
+  ~Quaternion(){};
+  Quaternion (const XYZ &R);
+};
+
+double length(Quaternion &quat);
+void normalize(Quaternion &quat);
+Quaternion conjugate(Quaternion quat);
+Quaternion mult(const Quaternion& A,const Quaternion& B);
+Quaternion operator *(const Quaternion &A, const Quaternion &B);
+
+
+
+
+
+
+
+
+
+
+
+
 
-XYZ origin = {0.0,0.0,0.0};
+using namespace std; 
 
 class Camera {
 public:
-  XYZ position;          /* camera position           */
-  XYZ view;              /* View direction vector   */
-  XYZ up;                /* View up direction       */
-  XYZ right;              /* View right direction       */
-  XYZ target;   /* center of rotation and screen   */
-  double focallength;  /* Focal Length along vd   */
-  double aperture;     /* Camera aperture         */
-  double eyesep;       /* Eye separation          */
+  bool on;
+  XYZ position;           /* camera position         */
+  XYZ view;               /* View direction vector   */
+  XYZ up;                 /* View up direction       */
+  XYZ right;              /* View right direction    */
+  XYZ target;             /* center of rotation and screen   */
+  double focallength;     /* Focal Length along vd   */
+  double aperture;        /* Camera aperture         */
+  double eyesep;          /* Eye separation          */
   int screenwidth,screenheight;
-  double distance;
-  double ref_distance;
-  bool button_left_down;
-  bool button_middle_down;
-  bool button_right_down;
+  double screenratio, distance, ref_distance;
+  bool button_left_down, button_middle_down, button_right_down;
   bool stereoEnable;
-  double Lc;
-  double ratio;
-  double closeness;
-  Camera();
+  double Lc, eye_sep_ratio, closeness, near , ndfl, far, radians,wd2 ;
+  double glFleft,glFright,glFtop,glFbottom;
+  Camera():stereoEnable(false),on(false){};
   ~Camera();
+  void giveViewportDimension(const int& W,const int& H);
   void lookAtCg();
   void init();
   void rotate(double* q);
   void moveRight(double theta);
   void moveUp(double theta);
   void update();
-private:
+  void affiche();
+  void alongX();
+  void alongY();
+  void alongZ();
+  void tiltHeadLeft();
+  void tiltHeadRight();
 };  
 
 
-
 class mouseAndKeyboard {
 public:
   bool button_left_down;
@@ -61,78 +105,8 @@ public:
 };
 
 
-
-
-// Quaternion and XYZ functions
-double length(quaternion quat)
-{
-  return sqrt(quat.x * quat.x + quat.y * quat.y +
-              quat.z * quat.z + quat.w * quat.w);
-}
-double length(XYZ p)
-{
-  return sqrt(p.x * p.x + p.y * p.y + p.z * p.z);
-}
-quaternion normalize(quaternion &quat)
-{
-  double L = length(quat);
-
-  quat.x /= L;
-  quat.y /= L;
-  quat.z /= L;
-  quat.w /= L;
-
-  return quat;
-}
-
-XYZ normalize(XYZ &p)
-{
-  double L = length(p);
-
-  p.x /= L;
-  p.y /= L;
-  p.z /= L;
-
-  return p;
-}
-quaternion conjugate(quaternion quat)
-{
-  quat.x = -quat.x;
-  quat.y = -quat.y;
-  quat.z = -quat.z;
-  return quat;
-}
-quaternion mult(quaternion A, quaternion B)
-{
-  quaternion C;
-
-  C.x = A.w*B.x + A.x*B.w + A.y*B.z - A.z*B.y;
-  C.y = A.w*B.y - A.x*B.z + A.y*B.w + A.z*B.x;
-  C.z = A.w*B.z + A.x*B.y - A.y*B.x + A.z*B.w;
-  C.w = A.w*B.w - A.x*B.x - A.y*B.y - A.z*B.z;
-  return C;
-}
-
-XYZ rotate(quaternion omega,XYZ axe) {
-  XYZ new_axe;
-  quaternion qaxe,new_qaxe;
-  qaxe.x=axe.x;
-  qaxe.y=axe.y;
-  qaxe.z=axe.z;
-  qaxe.w=0.;
-  new_qaxe=mult(mult(omega,qaxe),conjugate(omega));
-  axe.x=new_qaxe.x ;
-  axe.y=new_qaxe.y;
-  axe.z=new_qaxe.z;
-
-}
-
-
-
-
-
-
-
+ 
+ 
 
 
 #endif
diff --git a/Graphics/drawContext.cpp b/Graphics/drawContext.cpp
index 903f666e1e..0fa39d8ec7 100644
--- a/Graphics/drawContext.cpp
+++ b/Graphics/drawContext.cpp
@@ -4,6 +4,7 @@
 // bugs and problems to <gmsh@geuz.org>.
 
 #include <string>
+#include <stdio.h>
 #include "Gmsh.h"
 #include "GmshConfig.h"
 #include "GmshMessage.h"
@@ -151,6 +152,8 @@ void drawContext::addQuaternion(double p1x, double p1y, double p2x, double p2y)
   double quat[4];
   trackball(quat, p1x, p1y, p2x, p2y);
   add_quats(quat, quaternion, quaternion);
+  if (CTX::instance()->camera)   camera.rotate(quat); 
+
 }
 
 void drawContext::addQuaternionFromAxisAndAngle(double axis[3], double angle)
@@ -267,12 +270,17 @@ void drawContext::draw3d()
   initProjection();
   initRenderModel();
 
-  if(!CTX::instance()->camera)
+  if(CTX::instance()->camera)  {
+
+  }
+  else{
     initPosition();
-  drawAxes();
-  drawGeom();
-  drawMesh();
-  drawPost();
+  }
+    drawAxes();
+    drawGeom();
+    drawMesh();
+    drawPost();
+
 }
 
 void drawContext::draw2d()
@@ -445,26 +453,37 @@ void drawContext::initProjection(int xpick, int ypick, int wpick, int hpick)
   double zmax = std::max(fabs(CTX::instance()->min[2]),
 			 fabs(CTX::instance()->max[2]));
   if(zmax < CTX::instance()->lc) zmax = CTX::instance()->lc;
- 
+  
   if (CTX::instance()->camera) { // if we use the new camera mode
-
+      
     double clip_near, clip_far;
     clip_near = 0.75 * CTX::instance()->clipFactor * zmax;
-    clip_far = 75. * CTX::instance()->clipFactor * zmax;
-
+    clip_far = 75. * CTX::instance()->clipFactor * zmax;   
     glDisable(GL_DEPTH_TEST);
     glPushMatrix();
     glLoadIdentity();
-    glOrtho((double)viewport[0], (double)viewport[2],
-	    (double)viewport[1], (double)viewport[3], 
-	    clip_near, clip_far);
-    drawBackgroundGradient();
+    double w=(double)viewport[2];
+    double h=(double)viewport[3];
+    double ratio=w/h; 
+    double dx=.5*w*ratio;
+    double dy=.5*w;
+    double dz=-w*1.25;
+    glBegin(GL_QUADS);
+    //glColor4ubv((GLubyte *) & CTX::instance()->color.bg);
+    glColor3d(.8,.8,.95);
+    glVertex3i(-dx,-dy,dz);
+    glVertex3i( dx,-dy,dz);
+    //    glColor4ubv((GLubyte *) & CTX::instance()->color.bgGrad);
+    glColor3d(.1,.1,.3);
+    glVertex3i( dx, dy,dz);
+    glVertex3i(-dx, dy,dz);
+    glEnd();
     glPopMatrix();
     glEnable(GL_DEPTH_TEST);   
-
   } 
+  
   else{ // if not in camera mode
-
+  
     double clip_near, clip_far;
     if(CTX::instance()->ortho) {
       clip_near = -zmax * s[2] * CTX::instance()->clipFactor;
diff --git a/Graphics/drawContext.h b/Graphics/drawContext.h
index f72b9f0ccc..036d5729d9 100644
--- a/Graphics/drawContext.h
+++ b/Graphics/drawContext.h
@@ -10,6 +10,7 @@
 #include <vector>
 #include <set>
 #include "SBoundingBox3d.h"
+#include "Camera.h"
 
 #if defined(WIN32)
 #include <windows.h>
@@ -110,6 +111,7 @@ class drawContext {
   int _bgImageSize[2];
 
  public:
+  Camera camera;
   double r[3]; // current Euler angles (in degrees!) 
   double t[3], s[3]; // current translation and scale 
   double quaternion[4]; // current quaternion used for "trackball" rotation
diff --git a/utils/api_demos/mainGlut.cpp b/utils/api_demos/mainGlut.cpp
index e16a0dbfaf..3a1cad8a87 100644
--- a/utils/api_demos/mainGlut.cpp
+++ b/utils/api_demos/mainGlut.cpp
@@ -30,7 +30,7 @@ typedef struct {
 
 using namespace std; 
 drawContext *ctx = 0;
-Camera camera;
+Camera *camera;
 mouseAndKeyboard mouseandkeys;
 
 
@@ -57,131 +57,75 @@ public:
 
 
 
-
-
-
-
-
-
 // GLUT callbacks
-
 void display()
 {
 
-  if (!camera.stereoEnable) {
-    //    cout<<" display();"<<endl;
+  if (!camera->stereoEnable) {
     glViewport(ctx->viewport[0], ctx->viewport[1],
 	       ctx->viewport[2], ctx->viewport[3]);
     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
-    double dist,ratio,radians,scale,wd2,ndfl,left,right,top,bottom ;
-    double near=0.1 ;  double far=10000;
-    double h=  1.*( ctx->viewport[3]-ctx->viewport[1]);
-    double w= 1.*( ctx->viewport[2]-ctx->viewport[0]) ;
-    ratio  =w/h ;
-    radians =  0.0174532925 * camera.aperture / 2;
-    wd2     = near * tan(radians);
-    ndfl    = near / camera.focallength;
-    ndfl=1;
-    
-    // fill the background
-    //      ctx->initProjection();
-    // defines the lights
-    //     ctx->initRenderModel();
-    // defines screen plane and frame
+    camera->giveViewportDimension(ctx->viewport[2],ctx->viewport[3]);  
+
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
-    left  = - ratio * wd2;
-    right =   ratio * wd2;
-    top    =   wd2;
-    bottom = - wd2;
-    glFrustum(left,right,bottom,top,near,far); 
+    glFrustum(camera->glFleft,camera->glFright,camera->glFbottom,camera->glFtop,camera->near,camera->far); 
     glMatrixMode(GL_MODELVIEW);
     glDrawBuffer(GL_BACK);
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     glLoadIdentity();
-    gluLookAt(camera.position.x,
-	      camera.position.y,
-	      camera.position.z,
-	      camera.target.x,
-	      camera.target.y,
-	      camera.target.z,
-	      camera.up.x,
-	      camera.up.y,
-	      camera.up.z); 
-    drawContext::global()->draw();
+    gluLookAt(camera->position.x, camera->position.y, camera->position.z,
+	      camera->target.x, camera->target.y, camera->target.z,
+	      camera->up.x, camera->up.y, camera->up.z); 
+    ctx->draw3d();
+    ctx->draw2d();
     glutSwapBuffers(); 
+	
   }
   else {
     //    cout<<" display3D();"<<endl;
     glViewport(ctx->viewport[0], ctx->viewport[1],
 	       ctx->viewport[2], ctx->viewport[3]);
     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
-    double dist,ratio,radians,scale,wd2,ndfl,left,right,top,bottom ;
-    double near=0.1 ;  double far=10000;
-    double h=  1.*( ctx->viewport[3]-ctx->viewport[1]);
-    double w= 1.*( ctx->viewport[2]-ctx->viewport[0]) ;
-    // 4:3 , 16:9, ... 
-    ratio  =w/h ;
-    // demi angle de vue (en radian)
-    radians =  0.0174532925 * camera.aperture / 2;
-
-    wd2     = near * tan(radians);
-    ndfl    = near / camera.focallength;
-    
-    XYZ eye;
-    // fill the background
-    //    ctx->initProjection();
-    // defines the lights
-    //    ctx->initRenderModel();
-    //right eye
-    eye.x = camera.right.x*camera.eyesep / 2.0;
-    eye.y = camera.right.y*camera.eyesep / 2.0;
-    eye.z = camera.right.z*camera.eyesep / 2.0;
+    camera->giveViewportDimension(ctx->viewport[2],ctx->viewport[3]);
+     
+     //right eye
+    XYZ eye =camera->eyesep / 2.0* camera->right;
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
-    left  = - ratio * wd2 - 0.5 * camera.eyesep * ndfl;
-    right =   ratio * wd2 - 0.5 * camera.eyesep * ndfl;
-    top    =   wd2;
-    bottom = - wd2;
-    glFrustum(left,right,bottom,top,near,far);
+    double left  = - camera->screenratio * camera->wd2 - 0.5 * camera->eyesep * camera->ndfl;
+    double right =   camera->screenratio * camera->wd2 - 0.5 * camera->eyesep * camera->ndfl;
+    double top    =   camera->wd2;
+    double  bottom = - camera->wd2;
+    glFrustum(left,right,bottom,top,camera->near,camera->far);
     glMatrixMode(GL_MODELVIEW);
     glDrawBuffer(GL_BACK_RIGHT);
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     glLoadIdentity();
-    gluLookAt(camera.position.x+eye.x,
-	      camera.position.y+eye.y,
-	      camera.position.z+eye.z,
-	      camera.target.x+eye.x,
-	      camera.target.y+eye.y,
-	      camera.target.z+eye.z,
-	      camera.up.x,
-	      camera.up.y,
-	      camera.up.z); 
-    drawContext::global()->draw();
+    gluLookAt(camera->position.x+eye.x, camera->position.y+eye.y,  camera->position.z+eye.z,
+	      camera->target.x+eye.x,  camera->target.y+eye.y,  camera->target.z+eye.z,
+	      camera->up.x,  camera->up.y,  camera->up.z); 
+    ctx->draw3d();
+    ctx->draw2d();
     
     //left eye
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
-    left  = - ratio * wd2 + 0.5 * camera.eyesep * ndfl;
-    right =   ratio * wd2 + 0.5 * camera.eyesep * ndfl;
-    top    =   wd2;
-    bottom = - wd2;
-    glFrustum(left,right,bottom,top,near,far);
+    left  = - camera->screenratio * camera->wd2 + 0.5 * camera->eyesep * camera->ndfl;
+    right =   camera->screenratio * camera->wd2 + 0.5 * camera->eyesep * camera->ndfl;
+    top    =   camera->wd2;
+    bottom = - camera->wd2;
+    glFrustum(left,right,bottom,top,camera->near,camera->far);
     
     glMatrixMode(GL_MODELVIEW);
     glDrawBuffer(GL_BACK_LEFT);
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     glLoadIdentity();
-    gluLookAt(camera.position.x-eye.x,
-	      camera.position.y-eye.y,
-	      camera.position.z-eye.z,
-	      camera.target.x-eye.x,
-	      camera.target.y-eye.y,
-	      camera.target.z-eye.z,
-	      camera.up.x,
-	      camera.up.y,
-	      camera.up.z); 
-    drawContext::global()->draw();
+    gluLookAt(camera->position.x-eye.x, camera->position.y-eye.y, camera->position.z-eye.z,
+	      camera->target.x-eye.x, camera->target.y-eye.y, camera->target.z-eye.z,
+	      camera->up.x, camera->up.y, camera->up.z); 
+    ctx->draw3d();
+    ctx->draw2d();
     
     glutSwapBuffers(); 
   }
@@ -189,26 +133,15 @@ void display()
 }
 
 
-
-
-
-
 void reshape(int w, int h)
 {
   ctx->viewport[2] = w;
   ctx->viewport[3] = h;
-   display();
-}
-
-
-
-
-void keyboard(unsigned char key, int x, int y)
-{
   display();
 }
 
 
+void keyboard(unsigned char key, int x, int y) {  display();}
 
 
 void motion(int x, int y)
@@ -218,12 +151,12 @@ void motion(int x, int y)
   //rotate
   if (mouseandkeys.button_left_down && (mouseandkeys.mode!= GLUT_ACTIVE_CTRL) ){
     double x_r = 2.*(1.*x - w/2.)/w;
-    double y_r = 2.*(1.*y - h/2.)/h;
+    double y_r = 2.*(-1.*y + h/2.)/h;
     double xprev_r=2.*(1.*xprev - w/2.)/w;
-    double yprev_r=2.*(1.*yprev - h/2.)/h;
+    double yprev_r=2.*(-1.*yprev + h/2.)/h;
     double q[4];
     trackball(q,xprev_r,yprev_r,x_r,y_r);
-    camera.rotate(q); 
+      camera->rotate(q); 
     xprev = x;
     yprev = y;
   }
@@ -232,27 +165,21 @@ void motion(int x, int y)
     double dy= y-yprev;
     double factor =( CTX::instance()->zoomFactor * fabs(dy) +(double) h) / (double)h;
     factor = ((dy > 0) ? factor : 1./factor);
-    //    cout<<" zoom factor: "<<factor<<endl;
-    camera.distance=fabs(1./factor*camera.ref_distance);
-    camera.position.x=camera.target.x-camera.distance*camera.view.x;
-    camera.position.y=camera.target.y-camera.distance*camera.view.y;
-    camera.position.z=camera.target.z-camera.distance*camera.view.z;
+    camera->distance=fabs(1./factor*camera->ref_distance);
+    camera->position.x=camera->target.x-camera->distance*camera->view.x;
+    camera->position.y=camera->target.y-camera->distance*camera->view.y;
+    camera->position.z=camera->target.z-camera->distance*camera->view.z;
  }
   // translate
   if (mouseandkeys.button_right_down ){
-    //    cout<<" prev: "<<xprev<<" "<<yprev<<"-> x,y: "<<x<<" "<<y<<endl;
     double x_r = 2.*(1.*x - w/2.)/w;
     double y_r = 2.*(1.*y - h/2.)/h;
     double xprev_r=2.*(1.*xprev - w/2.)/w;
-    double yprev_r=2.*(1.*yprev - h/2.)/h;
-    
-    double theta_x=camera.aperture*(x_r-xprev_r)*0.0174532925/2. ;
-    double theta_y=camera.aperture*(y_r-yprev_r)*0.0174532925/2. ;
-    //    cout<<" theta_x : "<<theta_x<<endl;
-    //    cout<<" theta_y : "<<theta_y<<endl;
-
-    camera.moveRight(theta_x); 
-    camera.moveUp(theta_y); 
+    double yprev_r=2.*(1.*yprev - h/2.)/h;   
+    double theta_x=camera->aperture*(x_r-xprev_r)*0.0174532925/2. ;
+    double theta_y=camera->aperture*(y_r-yprev_r)*0.0174532925/2. ;
+    camera->moveRight(theta_x); 
+    camera->moveUp(theta_y); 
     xprev = x;
     yprev = y;
   }
@@ -264,13 +191,9 @@ void motion(int x, int y)
 }
 
 
-
-
-
 void mouse(int button, int state, int x, int y)
 {
-  specialkey = glutGetModifiers();
-  
+  specialkey = glutGetModifiers(); 
   xprev = x;
   yprev = y;
   if (button == GLUT_LEFT_BUTTON) {
@@ -282,29 +205,24 @@ void mouse(int button, int state, int x, int y)
   else {
     mouseandkeys.button_right_down=!state;
   }
-  camera.ref_distance=camera.distance;
+  camera->ref_distance=camera->distance;
 }
 
 
 
-
-
 void processSpecialKeys(int key, int x, int y) {
 
   mouseandkeys.mode = glutGetModifiers();
   if (mouseandkeys.mode == GLUT_ACTIVE_CTRL)    {
-    //    cout<<"CTRL "<<key<<endl;
     switch(key){
     case 100 : /* 'left' */
-      //  camera.closeness*=.99; 
       display();
-      camera.focallength=camera.focallength*.99;
-      camera.eyesep=(camera.focallength/camera.distance)*camera.distance*camera.ratio;
+      camera->focallength=camera->focallength*.99;
+      camera->eyesep=(camera->focallength/camera->distance)*camera->distance*camera->screenratio;
       break; 
     case 102 :  /* 'right' */
-      //camera.closeness*=1.01;
-      camera.focallength=camera.focallength*1.01;
-      camera.eyesep=(camera.focallength/camera.distance)*camera.distance*camera.ratio;
+      camera->focallength=camera->focallength*1.01;
+      camera->eyesep=(camera->focallength/camera->distance)*camera->distance*camera->screenratio;
       display();
       break; 
     }
@@ -312,72 +230,58 @@ void processSpecialKeys(int key, int x, int y) {
   else{
     switch(key){
       mouseandkeys.key= key ;
-      //      cout<<"special  key "<<key<<endl;
-      //  cout<<"move in special key :"<<x<<" "<<y<<endl;
     case 101 : /* 'up' */
-      camera.focallength*=1.1;
-      // display();
+      camera->focallength*=1.1;
       break; 
     case 103 : /* 'down' */
-      camera.focallength*=0.9;
-      // display();
+      camera->focallength*=0.9;
       break; 
     case 100 : /* 'left' */
-      camera.eyesep*=.9;
-      //  display();
+      camera->eyesep*=.9;
       break; 
     case 102 :  /* 'right' */
-      camera.eyesep*=1.1;
-      //  display();
+      camera->eyesep*=1.1;
       break; 
     }
   }
-  //  camera.ratio=camera.eyesep/camera.focallength;
-  //  camera.closeness= camera.distance/camera.focallength;
-  camera.update();
+  camera->update();
   display();
     
-    cout<<"eyesep = "<< camera.eyesep<<" / focallength = "<< camera.focallength<<" / ratio = ";
-    cout<< camera.ratio<<" / distance = "<< camera.distance<<" / closeness = "<< camera.closeness<<endl;
+    cout<<"eyesep = "<< camera->eyesep<<" / focallength = "<< camera->focallength<<" / screenratio = ";
+    cout<< camera->screenratio<<" / distance = "<< camera->distance<<" / closeness = "<< camera->closeness<<endl;
   mouseandkeys.mode = 0;
 }
 
 
 
-
 void processNormalKeys(unsigned char key, int x, int y) {
   double def;
 
   if (key != 0) {
-    //    cout<<"normal key "<<key; 
     mouseandkeys.key= key ;
-    //    cout<<" = "<<mouseandkeys.key<<endl;
-    //    cout<<"move in normal key :"<<x<<" "<<y<<endl;
     mouseandkeys.mode = glutGetModifiers();
-    //  if (mouseandkeys.mode == GLUT_ACTIVE_CTRL)      cout<<"CTRL "<<key<<endl;
-    if (mouseandkeys.mode == GLUT_ACTIVE_CTRL && key==17)     exit(0);
- 
+    if (mouseandkeys.mode == GLUT_ACTIVE_CTRL && key==17)     exit(0); 
   } 
   switch(key){
   case 49: GModel::current()->mesh(1); break;  /* '1' */
   case 50: GModel::current()->mesh(2); break;  /* '2' */
   case 51: GModel::current()->mesh(3); break;  /* '3' */
   case 48 :  /* '0' */ 
-    camera.lookAtCg(); 
+    camera->lookAtCg(); 
     display();
     break;
   case 114 : /* 'R' */ 
-    camera.init(); 
+    camera->init(); 
     display();
     break;
   case 'f' :  /* 'F' */
-    camera.screenwidth=ctx->viewport[2]; 
-    camera.screenheight=ctx->viewport[3]; 
+    camera->screenwidth=ctx->viewport[2]; 
+    camera->screenheight=ctx->viewport[3]; 
     glutFullScreen(); 
     display();
     break;  
   case 27 : /* 'ech' */
-        glutReshapeWindow(camera.screenwidth ,camera.screenheight );
+        glutReshapeWindow(camera->screenwidth ,camera->screenheight );
 	//glutReshapeWindow(500,500 );
     display(); 
     break; 
@@ -397,16 +301,11 @@ void processNormalKeys(unsigned char key, int x, int y) {
     GmshSetOption("View","DisplacementFactor",def);
     display(); 
     break; 
-    case 112 :  /* 'p' */
-      //      cout<<"*--*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*--*-*-*-*-*-*-*-*-*-*-***-*---*-***-"<<endl;
-      break; 
   }
 
 }
 
 
-
-
 //*******************************************************
 //*******************************************************
 //*******************************************************
@@ -422,22 +321,21 @@ int main(int argc, char **argv)
   GmshSetOption("General", "TrackballHyperbolicSheet", 0.);
 
   if (strstr(argv[1],"-s") != NULL){
-   camera.stereoEnable = true;
+   camera->stereoEnable = true;
    cout<<"mode STEREO"<<endl;
    GmshSetOption("General", "Stereo", 1.);
   } 
 
   for(int i = 1; i < argc; i++) GmshMergeFile(argv[i]);
 
-  camera.lookAtCg();
-
   ctx = new drawContext();
   drawContext::setGlobal(new drawContextGlut);
-  
+
+  camera= &(ctx->camera);
+  camera->init();
   glutInit(&argc, argv);
-  if (camera.stereoEnable) {
+  if (camera->stereoEnable) {
     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STEREO);
-    //   GmshSetOption("General", "BackgroundGradient", 0.);
   }
   else  {   
     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
@@ -474,9 +372,7 @@ int main(int argc, char **argv)
   cout<<" left                 eye sep -"<<endl;  
   cout<<" right                eye sep +"<<endl;  
   cout<<"-------------------------------------"<<endl;  
-
   glutMainLoop();
-
   GmshFinalize();
   return 0;
 }
-- 
GitLab