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