Member function projection() for projection transformation. Projection() is the most critical function in the class. It creates a projection transformation matrix based on the data in the class, and defines the viewpoint transformation through the OpenGL utility library function gluLookAt(). Its implementation is as follows: void GCamera::projection() { // Switch to the projection transformation matrix setting glMatrixMode(GL_PROJECTION); // Initialize the projection matrix glLoadIdentity(); // Rendering mode glRenderMode(GL_RENDER); // Create projection matrix double left = - m_width/2.0; double right = m_width/2.0; double bottom = - m_height/2.0; double top = m_height/2.0; // Right angle projection glOrtho(left,right,bottom,top,m_near,m_far); // Switch to view transformation matrix settings glMatrixMode(GL_MODELVIEW ); // Initialize the view transformation matrix glLoadIdentity( ); // Set viewpoint position and viewing direction gluLookAt(m_eye.x,m_eye.y,m_eye.z,m_ref.x,m_ref.y,m_ref.z,m_vecUp.dx, m_vecUp.dy, m_vecUp.dz); } void GCamera::selection(int xPos,int yPos) { GLint vp[4]; glGetIntegerv(GL_VIEWPORT,vp); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glRenderMode(GL_SELECT); gluPickMatrix(xPos,vp[3]-yPos, 1, 1, vp ); //apply projective matrix double left = - m_width/2.0; double right = m_width/2.0; double bottom = - m_height/2.0; double top = m_height/2.0; glOrtho(left,right,bottom,top,m_near,m_far); glMatrixMode( GL_MODELVIEW ); glLoadIdentity( ); gluLookAt(m_eye.x,m_eye.y,m_eye.z,m_ref.x,m_ref.y,m_ref.z, m_vecUp.dx, m_vecUp.dy, m_vecUp.dz); } (2) The member function set_screen() for viewport settings. When the size of the Windows window changes, you need to reset the size of the viewport. At the same time, in order to keep the display scale of the graphics from changing with the window size, the width and height of the viewing body need to be recalculated according to the new window size. The function set_screen() is used when the size of the Windows window changes. Called to reset the viewport and viewing volume. void GCamera::set_screen( int x, int y) { glViewport(0,0,x,y); // Set viewport if(y==0) y=1; double ratio = (double)x/(double)y; // Update the width and height of the viewing volume according to the change of the window size m_width *= (double)x/m_screen[0]; m_height *= (double)y/m_screen[1]; // Keep the ratio of the width and height of the viewing field consistent with the window m_width = m_height*ratio; m_screen[0] = x; m_screen[1] = y; } Member functions used to set the viewpoint and the viewing volume. GCamera also defines functions for setting viewpoint and viewing volume respectively. Set the viewpoint position and direction: void GCamera::set_eye(double eye_x,double eye_y,double eye_z) { m_eye.x = eye_x; m_eye.y = eye_y; m_eye.z = eye_z; } void GCamera::set_ref(double ref_x,double ref_y,double ref_z) { m_ref.x = ref_x; m_ref.y = ref_y; m_ref.z = ref_z; } void GCamera::set_vecUp(double up_dx,double up_dy,double up_dz) { m_vecUp.dx = up_dx; m_vecUp.dy = up_dy; m_vecUp.dz = up_dz; } Set the viewing volume: void GCamera::set_view_rect(double width,double height) { m_width = width; m_height = height; double aspect = m_screen[0]/m_screen[1]; m_width = m_height*aspect; } void GCamera::get_view_rect(double& width,double& height) { width = m_width; height = m_height; } void GCamera::zoom(double scale) { ASSERT(scale > 0.0); m_width *= scale; m_height *= scale; } void GCamera::zoom_all(double x0,double y0,double z0,double x1,double y1,double z1) { double width,height; double xl, yl, zl; xl = x1-x0; yl = y1-y0; zl = z1-z0; width = max(max(xl,yl),zl); height= max(max(xl,yl),zl); set_view_rect(width,height); CVector3D vec = m_eye - m_ref; m_ref.x = (x0+x1)/2; m_ref.y = (y0+y1)/2; m_ref.z = (z0+z1)/2; m_eye = m_ref + vec; } void GCamera::set_view_type( int type ) { double r; CVector3D vec; vec = m_ref - m_eye; r = vec.GetMagnitude(); if(IS_ZERO(r)) r = 50.0; if( r > 10000) r = 10000; switch(type){ case VIEW_FRONT: m_eye = m_ref + CVector3D(0,-r,0); m_vecUp = CVector3D(0,0,1); break; case VIEW_BACK: m_eye = m_ref + CVector3D(0,r,0); m_vecUp = CVector3D(0,0,1); break; case VIEW_TOP: m_eye = m_ref + CVector3D(0,0,r); m_vecUp = CVector3D(0,1,0); break; case VIEW_BOTTOM: m_eye = m_ref + CVector3D(0,0,-r); m_vecUp = CVector3D(0,1,0); break; case VIEW_RIGHT: m_eye = m_ref + CVector3D(r,0,0); m_vecUp = CVector3D(0,0,1); break; case VIEW_LEFT: m_eye = m_ref + CVector3D(-r,0,0); m_vecUp = CVector3D(0,0,1); break; case VIEW_SW_ISOMETRIC: m_eye = m_ref + CVector3D(-1,-1,1).GetNormal()*r; update_upVec(); break; case VIEW_SE_ISOMETRIC: m_eye = m_ref + CVector3D(1,-1,1).GetNormal()*r; update_upVec(); break; case VIEW_NE_ISOMETRIC: m_eye = m_ref + CVector3D(1,1,1).GetNormal()*r; update_upVec(); break; case VIEW_NW_ISOMETRIC: m_eye = m_ref + CVector3D(-1,1,1).GetNormal()*r; update_upVec(); break; } } void GCamera::move_view_by_percent(double dpx, double dpy) { CVector3D vec; CVector3D xUp, yUp; vec = m_ref - m_eye; vec.Normalize(); xUp = vec*m_vecUp; yUp = xUp*vec; m_eye -= xUp*m_width*dpx + yUp*m_height*dpy; m_ref -= xUp*m_width*dpx + yUp*m_height*dpy; } void GCamera::move_view_by_space(double dx, double dy) { CVector3D vec; CVector3D xUp, yUp; vec = m_ref - m_eye; vec.Normalize(); xUp = vec*m_vecUp; yUp = xUp*vec; m_eye -= xUp*dx + yUp*dy; m_ref -= xUp*dx + yUp*dy; } void GCamera::move_screen(int dx,int dy) { double dxvw = dx*m_width/m_screen[0]; double dyvw = dy*m_height/m_screen[1]; move_view_by_space(dxvw,dyvw); } void GCamera::update_upVec() { CVector3D vec = m_ref - m_eye; CVector3D zVec(0,0,1); CVector3D vec0; vec.Normalize(); vec0 = vec*zVec; m_vecUp = vec0*vec; } void GCamera::turnLeft(double angle) { angle /= 180/PI; CMatrix3D mat = CMatrix3D::CreateRotateMatrix(angle,m_vecUp); CVector3D vec = m_eye-m_ref; vec = vec*mat; m_eye = m_ref + vec; update_upVec(); } void GCamera::turnRight(double angle) { angle /= 180/PI; CMatrix3D mat = CMatrix3D::CreateRotateMatrix(-angle,m_vecUp); CVector3D vec = m_eye-m_ref; vec = vec*mat; m_eye = m_ref + vec; update_upVec(); } void GCamera::turnUp(double angle) { angle /= 180/PI; CVector3D xDir = (m_ref-m_eye)*m_vecUp; CMatrix3D mat = CMatrix3D::CreateRotateMatrix(angle,xDir); CVector3D vec = m_eye-m_ref; vec = vec*mat; m_eye = m_ref + vec; update_upVec(); } void GCamera::turnDown(double angle) { angle /= 180/PI; CVector3D xDir = (m_ref-m_eye)*m_vecUp; CMatrix3D mat = CMatrix3D::CreateRotateMatrix(-angle,xDir); CVector3D vec = m_eye-m_ref; vec = vec*mat; m_eye = m_ref + vec; update_upVec(); }