diff --git a/Graphics/CMakeLists.txt b/Graphics/CMakeLists.txt index 2f2d72cd3770074af87a9130eb72d1b124d26ad8..ad73469ee614e94c6fae69f34a133252b50764e0 100644 --- a/Graphics/CMakeLists.txt +++ b/Graphics/CMakeLists.txt @@ -4,6 +4,7 @@ # bugs and problems to <gmsh@geuz.org>. set(SRC + Camera.cpp Trackball.cpp ReadImg.cpp drawContext.cpp diff --git a/Graphics/Camera.cpp b/Graphics/Camera.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ff46c372bf0dbfd40ba58639c46e628a1762105a --- /dev/null +++ b/Graphics/Camera.cpp @@ -0,0 +1,196 @@ +#include <string> +#include <iostream> +#include "Camera.h" +#include "Gmsh.h" +#include "GmshConfig.h" +#include "GmshMessage.h" +#include "Trackball.h" +#include "Context.h" +#include "drawContext.h" + +#if defined(HAVE_FLTK) +#include <FL/Fl_JPEG_Image.H> +#include <FL/Fl_PNG_Image.H> +#endif + +using namespace std; + + +Camera::Camera( ) { + 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; + ref_distance=distance; + this->update(); +} + +Camera::~Camera(){}; + + +void Camera::lookAtCg(){ + target.x=CTX::instance()->cg[0]; + target.y=CTX::instance()->cg[1]; + target.z=CTX::instance()->cg[2]; + 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(); + focallength=distance; + ref_distance=distance; + eyesep=focallength*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::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); +} + +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; + 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; + 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 ; + 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 + double sina=sin(acos(omega.w)); + double length; + if (sina != 0.){ + length=(omega.x*omega.x+omega.y*+omega.y+omega.z*omega.z)/(sina*sina); + } + else{ + length=0.; + } + 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; + + } + this->update(); +} + diff --git a/Graphics/Camera.cpp~ b/Graphics/Camera.cpp~ new file mode 100644 index 0000000000000000000000000000000000000000..fa53fb57f8e97d0c4ef074e10f0a8b5c5bfed590 --- /dev/null +++ b/Graphics/Camera.cpp~ @@ -0,0 +1,194 @@ +#include <string> +#include <iostream> +#include "Camera.h" +#include "Gmsh.h" +#include "GmshConfig.h" +#include "GmshMessage.h" +#include "Trackball.h" +#include "Context.h" +#include "drawContext.h" + +#if defined(HAVE_FLTK) +#include <FL/Fl_JPEG_Image.H> +#include <FL/Fl_PNG_Image.H> +#endif + +using namespace std; + + +Camera::Camera( ) { + aperture = 40; + focallength = 100.; + distance=focallength; + // eyesep =0.88 ; + ratio=1./50.; + 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; + ref_distance=distance; + this->update(); +} + +Camera::~Camera(){}; + + +void Camera::lookAtCg(){ + target.x=CTX::instance()->cg[0]; + target.y=CTX::instance()->cg[1]; + target.z=CTX::instance()->cg[2]; + 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.)); + // 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(); + focallength=distance; + eyesep=focallength*ratio; +} + + +void Camera::init(){ + aperture = 40; + focallength = 100; + ratio=1./50.; + target = origin; + distance=focallength*1.4; + 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=focallength*ratio; + // closeness=distance/focallength; + lookAtCg(); +} + +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); +} + +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; + 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; + 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 ; + 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 + double sina=sin(acos(omega.w)); + double length; + if (sina != 0.){ + length=(omega.x*omega.x+omega.y*+omega.y+omega.z*omega.z)/(sina*sina); + } + else{ + length=0.; + } + 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; + + } + this->update(); +} + diff --git a/Graphics/Camera.h b/Graphics/Camera.h new file mode 100644 index 0000000000000000000000000000000000000000..390030da75983be2c6e23aeb7d73fe2788cfcf98 --- /dev/null +++ b/Graphics/Camera.h @@ -0,0 +1,138 @@ + +#ifndef _CAMERA_H_ +#define _CAMERA_H_ + +#include <stdio.h> +#include <math.h> +# + + +typedef struct { + double x,y,z; +} XYZ; +typedef struct { + double x,y,z,w; +} quaternion; + +XYZ origin = {0.0,0.0,0.0}; + +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 */ + int screenwidth,screenheight; + double distance; + double ref_distance; + bool button_left_down; + bool button_middle_down; + bool button_right_down; + bool stereoEnable; + double Lc; + double ratio; + double closeness; + Camera(); + ~Camera(); + void lookAtCg(); + void init(); + void rotate(double* q); + void moveRight(double theta); + void moveUp(double theta); + void update(); +private: +}; + + + +class mouseAndKeyboard { +public: + bool button_left_down; + bool button_middle_down; + bool button_right_down; + int key; + int mode; + mouseAndKeyboard() {}; + ~mouseAndKeyboard() {}; +}; + + + + +// 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/Camera.h~ b/Graphics/Camera.h~ new file mode 100644 index 0000000000000000000000000000000000000000..ff5bf4ffc1c9e9de198e8f25a3fe86622ac2309a --- /dev/null +++ b/Graphics/Camera.h~ @@ -0,0 +1,138 @@ + +#ifndef _CAMERA_H_ +#define _CAMERA_H_ + +#include <stdio.h> +#include <math.h> +# + + +typedef struct { + double x,y,z; +} XYZ; +typedef struct { + double x,y,z,w; +} quaternion; + +XYZ origin = {0.0,0.0,0.0}; + +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 */ + int screenwidth,screenheight; + double distance; + double ref_distance; + bool button_left_down; + bool button_middle_down; + bool button_right_down; + bool stereoEnable; + double Lc; + double ratio; + double closeness; + Camera(); + ~Camera(); + void lookAtCg(); + void init(); + void rotate(double* q); + void moveRight(double theta); + void moveUp(double theta); +private: + void update(); +}; + + + +class mouseAndKeyboard { +public: + bool button_left_down; + bool button_middle_down; + bool button_right_down; + int key; + int mode; + mouseAndKeyboard() {}; + ~mouseAndKeyboard() {}; +}; + + + + +// 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/Trackball.cpp b/Graphics/Trackball.cpp index 302059b0457469632ed7aceae3e341fd2a740604..209a37f0e9fee0d390a21f0a4ed9b3263e49163e 100644 --- a/Graphics/Trackball.cpp +++ b/Graphics/Trackball.cpp @@ -54,7 +54,8 @@ */ #include <math.h> #include "Trackball.h" - +#include "Gmsh.h" +#include <iostream> /* * This size should really be based on the distance from the center of * rotation to the point on the object underneath the mouse. That @@ -62,13 +63,14 @@ * simple example, though, so that is left as an Exercise for the * Programmer. */ -#define TRACKBALLSIZE (0.8) +#define TRACKBALLSIZE (.8) /* * Local function prototypes (not defined in trackball.h) */ static double tb_project_to_sphere(double, double, double); static void normalize_quat(double [4]); +using namespace std ; void vzero(double *v) @@ -162,40 +164,45 @@ vadd(const double *src1, const double *src2, double *dst) void trackball(double q[4], double p1x, double p1y, double p2x, double p2y) { - double a[3]; /* Axis of rotation */ - double phi; /* how much to rotate about axis */ - double p1[3], p2[3], d[3]; - double t; - - if (p1x == p2x && p1y == p2y) { - /* Zero rotation */ - vzero(q); - q[3] = 1.0; - return; - } - - /* - * First, figure out z-coordinates for projection of P1 and P2 to - * deformed sphere - */ - vset(p1,p1x,p1y,tb_project_to_sphere(TRACKBALLSIZE,p1x,p1y)); - vset(p2,p2x,p2y,tb_project_to_sphere(TRACKBALLSIZE,p2x,p2y)); - - /* - * Now, we want the cross product of P1 and P2 - */ - vcross(p2,p1,a); - - /* - * Figure out how much to rotate around that axis. - */ - vsub(p1,p2,d); - t = vlength(d) / (2.0*TRACKBALLSIZE); - - /* - * Avoid problems with out-of-control values... - */ - if (t > 1.0) t = 1.0; + double a[3]; /* Axis of rotation */ + double phi; /* how much to rotate about axis */ + double p1[3], p2[3], d[3]; + double t; + + if (p1x == p2x && p1y == p2y) { + /* Zero rotation */ + vzero(q); + q[3] = 1.0; + return; + } + + /* + * First, figure out z-coordinates for projection of P1 and P2 to + * deformed sphere + */ + vset(p1,p1x,p1y,tb_project_to_sphere(TRACKBALLSIZE,p1x,p1y)); + vset(p2,p2x,p2y,tb_project_to_sphere(TRACKBALLSIZE,p2x,p2y)); + /* + * Now, we want the cross product of P1 and P2 + */ + vcross(p2,p1,a); + + /* + * Figure out how much to rotate around that axis. + */ + vsub(p1,p2,d); + //t = vlength(d); + t = vlength(d) / (2.0*TRACKBALLSIZE); + /* + * Avoid problems with out-of-control values... + */ + if (t > 1.0) t = 1.0; + if (t < -1.0) t = -1.0; + phi = 2.0 * asin(t); + /* + * Avoid problems with out-of-control values... + */ + if (t > 1.0) t = 1.0; if (t < -1.0) t = -1.0; phi = 2.0 * asin(t); @@ -221,16 +228,36 @@ axis_to_quat(double a[3], double phi, double q[4]) static double tb_project_to_sphere(double r, double x, double y) { - double d, t, z; - - d = sqrt(x*x + y*y); - if (d < r * 0.70710678118654752440) { /* Inside sphere */ - z = sqrt(r*r - d*d); - } else { /* On hyperbola */ - t = r / 1.41421356237309504880; - z = t*t / d; + double d, t, z; + + d = sqrt(x*x + y*y); + + double _camera; + GmshGetOption("General", "Camera",_camera ); + if (_camera ) { + if (d < r ) { + z = sqrt(r*r - d*d); + } else { + z = 0.; + } + } + else{ + if (d < r * 0.70710678118654752440) { + // Inside sphere + z = sqrt(r*r - d*d); + } else { + // On hyperbola + t = r / 1.41421356237309504880; + z = t*t / d; } - return z; + } + + + + +return z; + + } /* @@ -325,3 +352,7 @@ build_rotmatrix(double m[16], double q[4]) m[15] = 1.0; } + +double trackballsize(){ + return TRACKBALLSIZE; +} diff --git a/Graphics/Trackball.h b/Graphics/Trackball.h index d6f4f144ca21c6e1019629be1915ff1fba118e58..6a4683202243686c3c87572f23f37ca3de9846e4 100644 --- a/Graphics/Trackball.h +++ b/Graphics/Trackball.h @@ -76,3 +76,4 @@ build_rotmatrix(double m[16], double q[4]); void axis_to_quat(double a[3], double phi, double q[4]); +double trackballsize() ; diff --git a/Graphics/drawAxes.cpp b/Graphics/drawAxes.cpp index ae8092a3be9b19509f41060122f669570753ac23..26e78bde20e202dc627f418de4ce7d79b4208de9 100644 --- a/Graphics/drawAxes.cpp +++ b/Graphics/drawAxes.cpp @@ -4,8 +4,11 @@ // bugs and problems to <gmsh@geuz.org>. #include <string> +#include <iostream> +#include "Gmsh.h" #include <string.h> #include "drawContext.h" +#include "Trackball.h" #include "GModel.h" #include "Context.h" #include "Numeric.h" @@ -275,7 +278,7 @@ void drawContext::drawAxes() break; } } - + if(geometryExists && (CTX::instance()->drawBBox || !CTX::instance()->mesh.draw)) { glColor4ubv((GLubyte *) & CTX::instance()->color.fg); glLineWidth((float)CTX::instance()->lineWidth); @@ -325,6 +328,8 @@ void drawContext::drawAxes() CTX::instance()->geom.light); } + + } void drawContext::drawSmallAxes() @@ -335,17 +340,36 @@ void drawContext::drawSmallAxes() double cx = CTX::instance()->smallAxesPos[0]; double cy = CTX::instance()->smallAxesPos[1]; fix2dCoordinates(&cx, &cy); + double _camera ; + GmshGetOption("General", "Camera", _camera); + double xx, xy, yx, yy , zx, zy; - double xx = l * rot[0]; - double xy = l * rot[1]; - double yx = l * rot[4]; - double yy = l * rot[5]; - double zx = l * rot[8]; - double zy = l * rot[9]; + if (_camera) { + + glPopMatrix(); + float fvViewMatrix[ 16 ]; + glGetFloatv( GL_MODELVIEW_MATRIX, fvViewMatrix ); + glLoadIdentity(); + + xx = l * fvViewMatrix[0]; + xy = l * fvViewMatrix[1]; + yx = l * fvViewMatrix[4]; + yy = l * fvViewMatrix[5]; + zx = l * fvViewMatrix[8]; + zy = l * fvViewMatrix[9]; + } + else { /* if NOT STEREO */ + xx = l * rot[0]; + xy = l * rot[1]; + yx = l * rot[4]; + yy = l * rot[5]; + zx = l * rot[8]; + zy = l * rot[9]; + } glLineWidth((float)CTX::instance()->lineWidth); gl2psLineWidth((float)(CTX::instance()->lineWidth * - CTX::instance()->print.epsLineWidthFactor)); + CTX::instance()->print.epsLineWidthFactor)); glColor4ubv((GLubyte *) & CTX::instance()->color.smallAxes); glBegin(GL_LINES); @@ -362,4 +386,8 @@ void drawContext::drawSmallAxes() drawString("Y"); glRasterPos2d(cx + zx + o, cy + zy + o); drawString("Z"); + + + + } diff --git a/Graphics/drawContext.cpp b/Graphics/drawContext.cpp index 437ff8516dd37a333e103d2b43aeb9ec91d46d71..a0e49511eb75c832bf0c0aec6356b4f82436ec31 100644 --- a/Graphics/drawContext.cpp +++ b/Graphics/drawContext.cpp @@ -4,6 +4,7 @@ // bugs and problems to <gmsh@geuz.org>. #include <string> +#include "Gmsh.h" #include "GmshConfig.h" #include "GmshMessage.h" #include "drawContext.h" @@ -16,12 +17,13 @@ #include "PViewOptions.h" #include "VertexArray.h" #include "gl2ps.h" - + #if defined(HAVE_FLTK) #include <FL/Fl_JPEG_Image.H> #include <FL/Fl_PNG_Image.H> #endif - +using namespace std; + drawContextGlobal *drawContext::_global = 0; drawContext::drawContext(drawTransform *transform) @@ -48,6 +50,7 @@ drawContext::drawContext(drawTransform *transform) _quadric = 0; // cannot create it here: needs valid opengl context _displayLists = 0; + } drawContext::~drawContext() @@ -226,7 +229,6 @@ void drawContext::draw3d() // much simpler to deal with option changes, e.g. arrow shape // changes) createQuadricsAndDisplayLists(); - // We should only enable the polygon offset when there is a mix of // lines and polygons to be drawn; enabling it all the time can lead // to very small but annoying artifacts in the picture. Since there @@ -245,19 +247,27 @@ void drawContext::draw3d() else CTX::instance()->polygonOffset = 0; + glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); initProjection(); initRenderModel(); - initPosition(); + + double _camera; + GmshGetOption("General", "Camera", _camera); + if (!_camera) initPosition(); drawAxes(); drawGeom(); drawMesh(); drawPost(); + + + } void drawContext::draw2d() { + glDisable(GL_DEPTH_TEST); for(int i = 0; i < 6; i++) glDisable((GLenum)(GL_CLIP_PLANE0 + i)); @@ -266,44 +276,54 @@ void drawContext::draw2d() glLoadIdentity(); glOrtho((double)viewport[0], (double)viewport[2], (double)viewport[1], (double)viewport[3], - -100., 100.); // in pixels, so we can draw some 3D glyphs + -1000., 1000.); // in pixels, so we can draw some 3D glyphs // hack to make the 2D primitives appear "in front" in GL2PS glTranslated(0., 0., CTX::instance()->clipFactor > 1. ? 1. / CTX::instance()->clipFactor : CTX::instance()->clipFactor); glMatrixMode(GL_MODELVIEW); + + + //++++ + glPushMatrix(); + //++++ glLoadIdentity(); drawGraph2d(); drawText2d(); - if(CTX::instance()->post.draw) - drawScales(); - if(CTX::instance()->smallAxes) - drawSmallAxes(); + double _stereo; + GmshGetOption("General", "Stereo", _stereo); + if (!_stereo) { + if(CTX::instance()->post.draw) drawScales(); + } + if(CTX::instance()->smallAxes) drawSmallAxes(); + } void drawContext::initProjection(int xpick, int ypick, int wpick, int hpick) { + double Va = (double) (viewport[3] - viewport[1]) / (double) (viewport[2] - viewport[0]); double Wa = (CTX::instance()->max[1] - CTX::instance()->min[1]) / (CTX::instance()->max[0] - CTX::instance()->min[0]); + // compute the viewport in World coordinates (with margins) if(Va > Wa) { vxmin = CTX::instance()->min[0]; vxmax = CTX::instance()->max[0]; vymin = 0.5 * (CTX::instance()->min[1] + CTX::instance()->max[1] - - Va * (CTX::instance()->max[0] - CTX::instance()->min[0])); + Va * (CTX::instance()->max[0] - CTX::instance()->min[0])); vymax = 0.5 * (CTX::instance()->min[1] + CTX::instance()->max[1] + - Va * (CTX::instance()->max[0] - CTX::instance()->min[0])); + Va * (CTX::instance()->max[0] - CTX::instance()->min[0])); } else { vxmin = 0.5 * (CTX::instance()->min[0] + CTX::instance()->max[0] - - (CTX::instance()->max[1] - CTX::instance()->min[1]) / Va); + (CTX::instance()->max[1] - CTX::instance()->min[1]) / Va); vxmax = 0.5 * (CTX::instance()->min[0] + CTX::instance()->max[0] + - (CTX::instance()->max[1] - CTX::instance()->min[1]) / Va); + (CTX::instance()->max[1] - CTX::instance()->min[1]) / Va); vymin = CTX::instance()->min[1]; vymax = CTX::instance()->max[1]; } @@ -324,42 +344,33 @@ void drawContext::initProjection(int xpick, int ypick, int wpick, int hpick) // (otherwise the z-buffer resolution e.g. with Mesa can become // insufficient) double zmax = std::max(fabs(CTX::instance()->min[2]), - fabs(CTX::instance()->max[2])); + fabs(CTX::instance()->max[2])); if(zmax < CTX::instance()->lc) zmax = CTX::instance()->lc; + + double _camera; + GmshGetOption("General", "Camera", _camera); - double clip_near, clip_far; - if(CTX::instance()->ortho) { - clip_near = -zmax * s[2] * CTX::instance()->clipFactor; - clip_far = -clip_near; - } - else { - clip_near = 0.75 * CTX::instance()->clipFactor * zmax; - clip_far = 75. * CTX::instance()->clipFactor * zmax; - } - // setup projection matrix - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - // restrict picking to a rectangular region around xpick,ypick - if(render_mode == GMSH_SELECT) - gluPickMatrix((GLdouble)xpick, (GLdouble)(viewport[3] - ypick), - (GLdouble)wpick, (GLdouble)hpick, (GLint *)viewport); + if (_camera) { /* if Camera */ - // draw background if not in selection mode - if(render_mode != GMSH_SELECT && (CTX::instance()->bgGradient || - CTX::instance()->bgImageFileName.size())){ + double clip_near, clip_far; + clip_near = 0.75 * CTX::instance()->clipFactor * zmax; + clip_far = 75. * CTX::instance()->clipFactor * zmax; + // draw background if not in selection mode glDisable(GL_DEPTH_TEST); glPushMatrix(); glLoadIdentity(); // the z values and the translation are only needed for GL2PS, // which does not understand "no depth test" (hence we must make // sure that we draw the background behind the rest of the scene) + glOrtho((double)viewport[0], (double)viewport[2], - (double)viewport[1], (double)viewport[3], - clip_near, clip_far); - glTranslated(0., 0., -0.99 * clip_far); - + (double)viewport[1], (double)viewport[3], + clip_near, clip_far); + + // glTranslated(0., 0., clip_near); + // glScaled(1.2,1.2,1.); // background gradient if(CTX::instance()->bgGradient == 1){ // vertical glBegin(GL_QUADS); @@ -385,7 +396,7 @@ void drawContext::initProjection(int xpick, int ypick, int wpick, int hpick) double cx = 0.5 * (viewport[0] + viewport[2]); double cy = 0.5 * (viewport[1] + viewport[3]); double r = 0.5 * std::max(viewport[2] - viewport[0], - viewport[3] - viewport[1]); + viewport[3] - viewport[1]); glBegin(GL_TRIANGLE_FAN); glColor4ubv((GLubyte *) & CTX::instance()->color.bgGrad); glVertex2d(cx, cy); @@ -393,173 +404,342 @@ void drawContext::initProjection(int xpick, int ypick, int wpick, int hpick) glVertex2d(cx + r, cy); int ntheta = 36; for(int i = 1; i < ntheta + 1; i ++){ - double theta = i * 2 * M_PI / (double)ntheta; - glVertex2d(cx + r * cos(theta), cy + r * sin(theta)); + double theta = i * 2 * M_PI / (double)ntheta; + glVertex2d(cx + r * cos(theta), cy + r * sin(theta)); } glEnd(); } - // hack for GL2PS (to make sure that the image is in front of the // gradient) glTranslated(0., 0., 0.01 * clip_far); // background image if(CTX::instance()->bgImageFileName.size()){ -#if defined(HAVE_FLTK) - if(_bgImage.empty()){ - int idot = CTX::instance()->bgImageFileName.find_last_of('.'); - std::string ext; - if(idot > 0 && idot < (int)CTX::instance()->bgImageFileName.size()) - ext = CTX::instance()->bgImageFileName.substr(idot + 1); - Fl_RGB_Image *img = 0; - if(ext == "jpg" || ext == "JPG" || ext == "jpeg" || ext == "JPEG") - img = new Fl_JPEG_Image(CTX::instance()->bgImageFileName.c_str()); - else if(ext == "png" || ext == "PNG") - img = new Fl_PNG_Image(CTX::instance()->bgImageFileName.c_str()); - if(img && img->d() >= 3){ - const unsigned char *data = img->array; - for(int j = img->h() - 1; j >= 0; j--) { - for(int i = 0; i < img->w(); i++) { - int idx = j * img->w() * img->d() + i * img->d(); - _bgImage.push_back((GLfloat)data[idx] / 255.F); - _bgImage.push_back((GLfloat)data[idx + 1] / 255.F); - _bgImage.push_back((GLfloat)data[idx + 2] / 255.F); - } - } - _bgImageSize[0] = img->w(); - _bgImageSize[1] = img->h(); - } - if(!_bgImageSize[0] || !_bgImageSize[1]){ - Msg::Error("Could not load valid background image"); - // make sure we don't try to load it again - for(int i = 0; i < 3; i++) _bgImage.push_back(0); - _bgImageSize[0] = _bgImageSize[1] = 1; - } - if(img) delete img; - } - double x = CTX::instance()->bgImagePosition[0]; - double y = CTX::instance()->bgImagePosition[1]; - int c = fix2dCoordinates(&x, &y); - if(c & 1) x -= _bgImageSize[0] / 2.; - if(c & 2) y -= _bgImageSize[1] / 2.; - if(x < viewport[0]) x = viewport[0]; - if(y < viewport[1]) y = viewport[1]; - glRasterPos2d(x, y); - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glDrawPixels(_bgImageSize[0], _bgImageSize[1], GL_RGB, GL_FLOAT, - (void*)&_bgImage[0]); - gl2psDrawPixels(_bgImageSize[0], _bgImageSize[1], 0, 0, GL_RGB, GL_FLOAT, - (void*)&_bgImage[0]); -#endif } - glPopMatrix(); - glEnable(GL_DEPTH_TEST); - } + glEnable(GL_DEPTH_TEST); + } - if(CTX::instance()->ortho) { - glOrtho(vxmin, vxmax, vymin, vymax, clip_near, clip_far); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - } - else { - // recenter the model such that the perspective is always at the - // center of gravity (we should maybe add an option to choose - // this, as we do for the rotation center) - t_init[0] = CTX::instance()->cg[0]; - t_init[1] = CTX::instance()->cg[1]; - vxmin -= t_init[0]; - vxmax -= t_init[0]; - vymin -= t_init[1]; - vymax -= t_init[1]; - glFrustum(vxmin, vxmax, vymin, vymax, clip_near, clip_far); - glMatrixMode(GL_MODELVIEW); + else { /* if NOT Camera */ + + double clip_near, clip_far; + if(CTX::instance()->ortho) { + clip_near = -zmax * s[2] * CTX::instance()->clipFactor; + clip_far = -clip_near; + } + else { + clip_near = 0.75 * CTX::instance()->clipFactor * zmax; + clip_far = 75. * CTX::instance()->clipFactor * zmax; + } + // setup projection matrix + glMatrixMode(GL_PROJECTION); glLoadIdentity(); - double coef = (clip_far / clip_near) / 3.; - glTranslated(-coef * t_init[0], -coef * t_init[1], -coef * clip_near); - glScaled(coef, coef, coef); - } + + // restrict picking to a rectangular region around xpick,ypick + if(render_mode == GMSH_SELECT) + gluPickMatrix((GLdouble)xpick, (GLdouble)(viewport[3] - ypick), + (GLdouble)wpick, (GLdouble)hpick, (GLint *)viewport); + // draw background if not in selection mode + if(render_mode != GMSH_SELECT && (CTX::instance()->bgGradient || + CTX::instance()->bgImageFileName.size())){ + glDisable(GL_DEPTH_TEST); + glPushMatrix(); + glLoadIdentity(); + // the z values and the translation are only needed for GL2PS, + // which does not understand "no depth test" (hence we must make + // sure that we draw the background behind the rest of the scene) + glOrtho((double)viewport[0], (double)viewport[2], + (double)viewport[1], (double)viewport[3], + clip_near, clip_far); + glTranslated(0., 0., -0.99 * clip_far); + // background gradient + if(CTX::instance()->bgGradient == 1){ // vertical + glBegin(GL_QUADS); + glColor4ubv((GLubyte *) & CTX::instance()->color.bg); + glVertex2i(viewport[0], viewport[1]); + glVertex2i(viewport[2], viewport[1]); + glColor4ubv((GLubyte *) & CTX::instance()->color.bgGrad); + glVertex2i(viewport[2], viewport[3]); + glVertex2i(viewport[0], viewport[3]); + glEnd(); + } + else if(CTX::instance()->bgGradient == 2){ // horizontal + glBegin(GL_QUADS); + glColor4ubv((GLubyte *) & CTX::instance()->color.bg); + glVertex2i(viewport[2], viewport[1]); + glVertex2i(viewport[2], viewport[3]); + glColor4ubv((GLubyte *) & CTX::instance()->color.bgGrad); + glVertex2i(viewport[0], viewport[3]); + glVertex2i(viewport[0], viewport[1]); + glEnd(); + } + else if(CTX::instance()->bgGradient == 3){ // radial + double cx = 0.5 * (viewport[0] + viewport[2]); + double cy = 0.5 * (viewport[1] + viewport[3]); + double r = 0.5 * std::max(viewport[2] - viewport[0], + viewport[3] - viewport[1]); + glBegin(GL_TRIANGLE_FAN); + glColor4ubv((GLubyte *) & CTX::instance()->color.bgGrad); + glVertex2d(cx, cy); + glColor4ubv((GLubyte *) & CTX::instance()->color.bg); + glVertex2d(cx + r, cy); + int ntheta = 36; + for(int i = 1; i < ntheta + 1; i ++){ + double theta = i * 2 * M_PI / (double)ntheta; + glVertex2d(cx + r * cos(theta), cy + r * sin(theta)); + } + glEnd(); + } + // hack for GL2PS (to make sure that the image is in front of the + // gradient) + glTranslated(0., 0., 0.01 * clip_far); + // background image + if(CTX::instance()->bgImageFileName.size()){ +#if defined(HAVE_FLTK) + if(_bgImage.empty()){ + int idot = CTX::instance()->bgImageFileName.find_last_of('.'); + std::string ext; + if(idot > 0 && idot < (int)CTX::instance()->bgImageFileName.size()) + ext = CTX::instance()->bgImageFileName.substr(idot + 1); + Fl_RGB_Image *img = 0; + if(ext == "jpg" || ext == "JPG" || ext == "jpeg" || ext == "JPEG") + img = new Fl_JPEG_Image(CTX::instance()->bgImageFileName.c_str()); + else if(ext == "png" || ext == "PNG") + img = new Fl_PNG_Image(CTX::instance()->bgImageFileName.c_str()); + if(img && img->d() >= 3){ + const unsigned char *data = img->array; + for(int j = img->h() - 1; j >= 0; j--) { + for(int i = 0; i < img->w(); i++) { + int idx = j * img->w() * img->d() + i * img->d(); + _bgImage.push_back((GLfloat)data[idx] / 255.F); + _bgImage.push_back((GLfloat)data[idx + 1] / 255.F); + _bgImage.push_back((GLfloat)data[idx + 2] / 255.F); + } + } + _bgImageSize[0] = img->w(); + _bgImageSize[1] = img->h(); + } + if(!_bgImageSize[0] || !_bgImageSize[1]){ + Msg::Error("Could not load valid background image"); + // make sure we don't try to load it again + for(int i = 0; i < 3; i++) _bgImage.push_back(0); + _bgImageSize[0] = _bgImageSize[1] = 1; + } + if(img) delete img; + } + double x = CTX::instance()->bgImagePosition[0]; + double y = CTX::instance()->bgImagePosition[1]; + int c = fix2dCoordinates(&x, &y); + if(c & 1) x -= _bgImageSize[0] / 2.; + if(c & 2) y -= _bgImageSize[1] / 2.; + if(x < viewport[0]) x = viewport[0]; + if(y < viewport[1]) y = viewport[1]; + glRasterPos2d(x, y); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glDrawPixels(_bgImageSize[0], _bgImageSize[1], GL_RGB, GL_FLOAT, + (void*)&_bgImage[0]); + gl2psDrawPixels(_bgImageSize[0], _bgImageSize[1], 0, 0, GL_RGB, GL_FLOAT, + (void*)&_bgImage[0]); +#endif + } + glPopMatrix(); + glEnable(GL_DEPTH_TEST); + } + if(CTX::instance()->ortho) { + glOrtho(vxmin, vxmax, vymin, vymax, clip_near, clip_far); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + } + else { + // recenter the model such that the perspective is always at the + // center of gravity (we should maybe add an option to choose + // this, as we do for the rotation center) + t_init[0] = CTX::instance()->cg[0]; + t_init[1] = CTX::instance()->cg[1]; + vxmin -= t_init[0]; + vxmax -= t_init[0]; + vymin -= t_init[1]; + vymax -= t_init[1]; + glFrustum(vxmin, vxmax, vymin, vymax, clip_near, clip_far); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + double coef = (clip_far / clip_near) / 3.; + glTranslated(-coef * t_init[0], -coef * t_init[1], -coef * clip_near); + glScaled(coef, coef, coef); + } + } /*end if NOT Camera */ } void drawContext::initRenderModel() { - glPushMatrix(); - glLoadIdentity(); - glScaled(s[0], s[1], s[2]); - glTranslated(t[0], t[1], t[2]); + double _camera; + GmshGetOption("General", "Camera", _camera); + if (_camera) { + glPushMatrix(); + glLoadIdentity(); + glScaled(s[0], s[1], s[2]); + glTranslated(t[0], t[1], t[2]); - for(int i = 0; i < 6; i++) { - if(CTX::instance()->light[i]) { - GLfloat position[4] = {(GLfloat)CTX::instance()->lightPosition[i][0], - (GLfloat)CTX::instance()->lightPosition[i][1], - (GLfloat)CTX::instance()->lightPosition[i][2], - (GLfloat)CTX::instance()->lightPosition[i][3]}; - glLightfv((GLenum)(GL_LIGHT0 + i), GL_POSITION, position); - - GLfloat r = (GLfloat)(CTX::instance()->unpackRed - (CTX::instance()->color.ambientLight[i]) / 255.); - GLfloat g = (GLfloat)(CTX::instance()->unpackGreen - (CTX::instance()->color.ambientLight[i]) / 255.); - GLfloat b = (GLfloat)(CTX::instance()->unpackBlue - (CTX::instance()->color.ambientLight[i]) / 255.); - GLfloat ambient[4] = {r, g, b, 1.0F}; - glLightfv((GLenum)(GL_LIGHT0 + i), GL_AMBIENT, ambient); - - r = (GLfloat)(CTX::instance()->unpackRed - (CTX::instance()->color.diffuseLight[i]) / 255.); - g = (GLfloat)(CTX::instance()->unpackGreen - (CTX::instance()->color.diffuseLight[i]) / 255.); - b = (GLfloat)(CTX::instance()->unpackBlue - (CTX::instance()->color.diffuseLight[i]) / 255.); - GLfloat diffuse[4] = {r, g, b, 1.0F}; - glLightfv((GLenum)(GL_LIGHT0 + i), GL_DIFFUSE, diffuse); - - r = (GLfloat)(CTX::instance()->unpackRed - (CTX::instance()->color.specularLight[i]) / 255.); - g = (GLfloat)(CTX::instance()->unpackGreen - (CTX::instance()->color.specularLight[i]) / 255.); - b = (GLfloat)(CTX::instance()->unpackBlue - (CTX::instance()->color.specularLight[i]) / 255.); - GLfloat specular[4] = {r, g, b, 1.0F}; - glLightfv((GLenum)(GL_LIGHT0 + i), GL_SPECULAR, specular); - - glEnable((GLenum)(GL_LIGHT0 + i)); - } - else{ - glDisable((GLenum)(GL_LIGHT0 + i)); + for(int i = 0; i < 6; i++) { + if(CTX::instance()->light[i]) { + GLfloat position[4] = {(GLfloat)CTX::instance()->lightPosition[i][0], + (GLfloat)CTX::instance()->lightPosition[i][1], + (GLfloat)CTX::instance()->lightPosition[i][2], + (GLfloat)CTX::instance()->lightPosition[i][3]}; + glLightfv((GLenum)(GL_LIGHT0 + i), GL_POSITION, position); + + GLfloat r = (GLfloat)(CTX::instance()->unpackRed + (CTX::instance()->color.ambientLight[i]) / 255.); + GLfloat g = (GLfloat)(CTX::instance()->unpackGreen + (CTX::instance()->color.ambientLight[i]) / 255.); + GLfloat b = (GLfloat)(CTX::instance()->unpackBlue + (CTX::instance()->color.ambientLight[i]) / 255.); + GLfloat ambient[4] = {r, g, b, 1.0F}; + glLightfv((GLenum)(GL_LIGHT0 + i), GL_AMBIENT, ambient); + + r = (GLfloat)(CTX::instance()->unpackRed + (CTX::instance()->color.diffuseLight[i]) / 255.); + g = (GLfloat)(CTX::instance()->unpackGreen + (CTX::instance()->color.diffuseLight[i]) / 255.); + b = (GLfloat)(CTX::instance()->unpackBlue + (CTX::instance()->color.diffuseLight[i]) / 255.); + GLfloat diffuse[4] = {r, g, b, 1.0F}; + glLightfv((GLenum)(GL_LIGHT0 + i), GL_DIFFUSE, diffuse); + + r = (GLfloat)(CTX::instance()->unpackRed + (CTX::instance()->color.specularLight[i]) / 255.); + g = (GLfloat)(CTX::instance()->unpackGreen + (CTX::instance()->color.specularLight[i]) / 255.); + b = (GLfloat)(CTX::instance()->unpackBlue + (CTX::instance()->color.specularLight[i]) / 255.); + GLfloat specular[4] = {r, g, b, 1.0F}; + glLightfv((GLenum)(GL_LIGHT0 + i), GL_SPECULAR, specular); + + glEnable((GLenum)(GL_LIGHT0 + i)); + } + else{ + glDisable((GLenum)(GL_LIGHT0 + i)); + } } + + glPopMatrix(); + + // ambient and diffuse material colors track glColor automatically + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + glEnable(GL_COLOR_MATERIAL); + // "white"-only specular material reflection color + GLfloat spec[4] = {(GLfloat)CTX::instance()->shine, + (GLfloat)CTX::instance()->shine, + (GLfloat)CTX::instance()->shine, 1.0F}; + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec); + // specular exponent in [0,128] (larger means more "focused" + // reflection) + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, + (GLfloat)CTX::instance()->shineExponent); + + glShadeModel(GL_SMOOTH); + + // Normalize the normals automatically. We could use the more + // efficient glEnable(GL_RESCALE_NORMAL) instead (since we initially + // specify unit normals), but GL_RESCALE_NORMAL does only work with + // isotropic scalings (and we allow anistotropic scalings in + // myZoom). Note that GL_RESCALE_NORMAL is only available in + // GL_VERSION_1_2. + glEnable(GL_NORMALIZE); + + // lighting is enabled/disabled for each particular primitive later + glDisable(GL_LIGHTING); } + else { + glPushMatrix(); + glLoadIdentity(); + glScaled(s[0], s[1], s[2]); + glTranslated(t[0], t[1], t[2]); + + for(int i = 0; i < 6; i++) { + if(CTX::instance()->light[i]) { + GLfloat position[4] = {(GLfloat)CTX::instance()->lightPosition[i][0], + (GLfloat)CTX::instance()->lightPosition[i][1], + (GLfloat)CTX::instance()->lightPosition[i][2], + (GLfloat)CTX::instance()->lightPosition[i][3]}; + glLightfv((GLenum)(GL_LIGHT0 + i), GL_POSITION, position); + + GLfloat r = (GLfloat)(CTX::instance()->unpackRed + (CTX::instance()->color.ambientLight[i]) / 255.); + GLfloat g = (GLfloat)(CTX::instance()->unpackGreen + (CTX::instance()->color.ambientLight[i]) / 255.); + GLfloat b = (GLfloat)(CTX::instance()->unpackBlue + (CTX::instance()->color.ambientLight[i]) / 255.); + GLfloat ambient[4] = {r, g, b, 1.0F}; + glLightfv((GLenum)(GL_LIGHT0 + i), GL_AMBIENT, ambient); + + r = (GLfloat)(CTX::instance()->unpackRed + (CTX::instance()->color.diffuseLight[i]) / 255.); + g = (GLfloat)(CTX::instance()->unpackGreen + (CTX::instance()->color.diffuseLight[i]) / 255.); + b = (GLfloat)(CTX::instance()->unpackBlue + (CTX::instance()->color.diffuseLight[i]) / 255.); + GLfloat diffuse[4] = {r, g, b, 1.0F}; + glLightfv((GLenum)(GL_LIGHT0 + i), GL_DIFFUSE, diffuse); + + r = (GLfloat)(CTX::instance()->unpackRed + (CTX::instance()->color.specularLight[i]) / 255.); + g = (GLfloat)(CTX::instance()->unpackGreen + (CTX::instance()->color.specularLight[i]) / 255.); + b = (GLfloat)(CTX::instance()->unpackBlue + (CTX::instance()->color.specularLight[i]) / 255.); + GLfloat specular[4] = {r, g, b, 1.0F}; + glLightfv((GLenum)(GL_LIGHT0 + i), GL_SPECULAR, specular); + + glEnable((GLenum)(GL_LIGHT0 + i)); + } + else{ + glDisable((GLenum)(GL_LIGHT0 + i)); + } + } - glPopMatrix(); + glPopMatrix(); + + // ambient and diffuse material colors track glColor automatically + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + glEnable(GL_COLOR_MATERIAL); + // "white"-only specular material reflection color + GLfloat spec[4] = {(GLfloat)CTX::instance()->shine, + (GLfloat)CTX::instance()->shine, + (GLfloat)CTX::instance()->shine, 1.0F}; + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec); + // specular exponent in [0,128] (larger means more "focused" + // reflection) + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, + (GLfloat)CTX::instance()->shineExponent); + + glShadeModel(GL_SMOOTH); + + // Normalize the normals automatically. We could use the more + // efficient glEnable(GL_RESCALE_NORMAL) instead (since we initially + // specify unit normals), but GL_RESCALE_NORMAL does only work with + // isotropic scalings (and we allow anistotropic scalings in + // myZoom). Note that GL_RESCALE_NORMAL is only available in + // GL_VERSION_1_2. + glEnable(GL_NORMALIZE); + + // lighting is enabled/disabled for each particular primitive later + glDisable(GL_LIGHTING); + } - // ambient and diffuse material colors track glColor automatically - glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); - glEnable(GL_COLOR_MATERIAL); - // "white"-only specular material reflection color - GLfloat spec[4] = {(GLfloat)CTX::instance()->shine, - (GLfloat)CTX::instance()->shine, - (GLfloat)CTX::instance()->shine, 1.0F}; - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec); - // specular exponent in [0,128] (larger means more "focused" - // reflection) - glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, - (GLfloat)CTX::instance()->shineExponent); - - glShadeModel(GL_SMOOTH); - - // Normalize the normals automatically. We could use the more - // efficient glEnable(GL_RESCALE_NORMAL) instead (since we initially - // specify unit normals), but GL_RESCALE_NORMAL does only work with - // isotropic scalings (and we allow anistotropic scalings in - // myZoom). Note that GL_RESCALE_NORMAL is only available in - // GL_VERSION_1_2. - glEnable(GL_NORMALIZE); - - // lighting is enabled/disabled for each particular primitive later - glDisable(GL_LIGHTING); } + + + + + + + + + + void drawContext::initPosition() { glScaled(s[0], s[1], s[2]); diff --git a/Graphics/drawContext.h b/Graphics/drawContext.h index 750e25c2542b8f88a0580118964d6f62ddccf582..fd65ddf972ee9644449da794be52d2af493b4065 100644 --- a/Graphics/drawContext.h +++ b/Graphics/drawContext.h @@ -25,6 +25,7 @@ #include <GL/glu.h> #endif + class PView; class GModel; class GVertex; @@ -47,6 +48,7 @@ class drawTransformScaled : public drawTransform { private: double _mat[3][3]; double _tra[3]; + public: drawTransformScaled(double mat[3][3], double tra[3]=0) : drawTransform() @@ -76,7 +78,7 @@ class drawTransformScaled : public drawTransform { z += _tra[2]; } }; - + // global drawing functions, which need to be redefined for each // widget toolkit (FLTK, Qt, etc.) class drawContextGlobal { @@ -121,7 +123,6 @@ class drawContext { // at the time of the last InitPosition() call enum RenderMode {GMSH_RENDER=1, GMSH_SELECT=2, GMSH_FEEDBACK=3}; int render_mode; // current rendering mode - public: drawContext(drawTransform *transform=0); ~drawContext(); @@ -190,6 +191,7 @@ class drawContext { std::string label[3], SBoundingBox3d &bb, int mikado); void drawAxes(); void drawSmallAxes(); + void drawTrackball(); void drawScales(); void drawString(const std::string &s, const std::string &font_name, int font_enum, int font_size, int align);