📄 qglobe.cc
字号:
//-----------------------------------------------------------------------------// qglobe.cc : implementation of QGlobe class//// - programmed by Boyoon Jung (boyoon@robotics.usc.edu)//-----------------------------------------------------------------------------#include "qglobe.h"#include "qglobe_texture.h"#include <cstdlib>// for Icosahedron#define X 0.525731112119133606#define Z 0.850650808352039932static GLfloat vdata[12][3] = { {-X, 0.0, Z}, {X, 0.0, Z}, {-X, 0.0, -Z}, {X, 0.0, -Z}, {0.0, Z, X}, {0.0, Z, -X}, {0.0, -Z, X}, {0.0, -Z, -X}, {Z, X, 0.0}, {-Z, X, 0.0}, {Z, -X, 0.0}, {-Z, -X, 0.0}};static GLint tindices[20][3] = { {0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1}, {8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3}, {7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6}, {6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11}};// constructorQGlobe::QGlobe( QWidget* parent, const char* name ) : QGLWidget( parent, name ){ model_globe = model_position = 0; latitude = longitude = altitude = geoid = 0.0f; hrot = vrot = 0.0f; mb_pressed = false; flag_shown = false; // change the size policy setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);}// destructorQGlobe::~QGlobe(){ makeCurrent(); glDeleteLists(model_globe, 1); glDeleteLists(model_position, 1);}// set up the OpenGL rendering state, and define display listvoid QGlobe::initializeGL(){ // set texture info texture = QGLWidget::convertToGLFormat(qembed_findImage("earth_map")); glTexImage2D(GL_TEXTURE_2D, 0, 3, texture.width(), texture.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, texture.bits()); // configure OpenGL for texture mapping glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // construct models model_globe = buildGlobeModel(); model_position = buildPositionModel(); // initialize OpenGL qglClearColor(black); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);}// paint void QGlobe::paintGL(){ GLfloat angle, naxis[2]; // clear glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // initialize a global transformation glLoadIdentity(); glTranslatef(0.0, 0.0, -10.0); glRotatef(vrot, 1.0, 0.0, 0.0); glRotatef(hrot, 0.0, 1.0, 0.0); // draw the globe model glEnable(GL_TEXTURE_2D); glCallList(model_globe); // compute the height from the center of the Earth float sl = sin(latitude * M_PI/180); float N = GA / sqrt(1 - GE*GE * sl*sl); float height = N + altitude + geoid; // draw the position indicator glRotatef(longitude+180, 0.0, 1.0, 0.0); // longitude glRotatef(latitude, 0.0, 0.0, 1.0); // latitude glTranslatef(height/GB, 0.0, 0.0); // altitude glScalef(0.025, 0.025, 0.025); glDisable(GL_TEXTURE_2D); if (flag_shown) glCallList(model_position); // done glFlush();}// set up the OpenGL view port, matrix mode, etc.void QGlobe::resizeGL(int w, int h){ if (w < h) glViewport(0, (h-w)/2, (GLint)w, (GLint)w); else glViewport((w-h)/2, 0, (GLint)h, (GLint)h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 8.0, 12.0); glMatrixMode(GL_MODELVIEW);}// normalize a 3D vectorinline void normalize(float* v){ float d = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); if (d != 0.0) for (int i=0; i<3; i++) v[i] /= d;}// convert a 3D vector to a 2D texture coordinatesinline void vertex2texture(float* v, float* t){ t[0] = -atan2(v[2],v[0]) / (2*M_PI); t[1] = -asin(v[1]) / M_PI + 0.5;}// improve a sphere model recursivelyvoid subdivide(float* v1, float* v2, float* v3, int depth){ GLfloat v12[3], v23[3], v31[3]; GLfloat t1[2], t2[2], t3[2]; if (depth <= 0) { // compute the texture coordinates vertex2texture(v1, t1); vertex2texture(v2, t2); vertex2texture(v3, t3); // correct boundary error if (fabs(t1[0]-t2[0]) > 0.5 || fabs(t2[0]-t3[0]) > 0.5 || fabs(t3[0]-t1[0]) > 0.5) { while (t1[0] < 0) t1[0] += 1.0; while (t2[0] < 0) t2[0] += 1.0; while (t3[0] < 0) t3[0] += 1.0; } // add a triangle glNormal3fv(v1); glTexCoord2fv(t1); glVertex3fv(v1); glNormal3fv(v2); glTexCoord2fv(t2); glVertex3fv(v2); glNormal3fv(v3); glTexCoord2fv(t3); glVertex3fv(v3); return; } for (int i=0; i<3; i++) { v12[i] = v1[i] + v2[i]; v23[i] = v2[i] + v3[i]; v31[i] = v3[i] + v1[i]; } normalize(v12); normalize(v23); normalize(v31); subdivide(v1, v12, v31, depth-1); subdivide(v2, v23, v12, depth-1); subdivide(v3, v31, v23, depth-1); subdivide(v12, v23, v31, depth-1);}// construct a 3D model for a globeGLuint QGlobe::buildGlobeModel(){ GLuint list = glGenLists(1); glNewList(list, GL_COMPILE); glBegin(GL_TRIANGLES); qglColor(white); for (int i=0; i<20; i++) subdivide(&vdata[tindices[i][0]][0], &vdata[tindices[i][1]][0], &vdata[tindices[i][2]][0], 3); glEnd(); glEndList(); return list;}// construct a 3D model for a globeGLuint QGlobe::buildPositionModel(){ GLuint list = glGenLists(1); glNewList(list, GL_COMPILE); glBegin(GL_TRIANGLES); for (int i=0; i<20; i++) { qglColor(red); glNormal3fv(&vdata[tindices[i][0]][0]); glVertex3fv(&vdata[tindices[i][0]][0]); glNormal3fv(&vdata[tindices[i][1]][0]); glVertex3fv(&vdata[tindices[i][1]][0]); glNormal3fv(&vdata[tindices[i][2]][0]); glVertex3fv(&vdata[tindices[i][2]][0]); } glEnd(); glEndList(); return list;}// convert a ECEF position to a geodetic positionvoid QGlobe::ecef2geo(float x, float y, float z, float& latitude, float& longitude, float& altitude, float& geoid){ float p = sqrt(x*x + y*y); float th = atan2(z*GA, p*GB); float sth = sin(th); float cth = cos(th); latitude = atan2(z + GEP*GEP * GB * sth*sth*sth, p - GE*GE * GA * cth*cth*cth) * 180/M_PI; longitude = atan2(y, x) * 180/M_PI; float sl = sin(latitude * M_PI/180); float cl = cos(latitude * M_PI/180); float N = GA / sqrt(1 - GE*GE * sl*sl); altitude = p/cl - N; geoid = 0.0f;}// start to rotate a globe when a mouse button is clickedvoid QGlobe::mousePressEvent(QMouseEvent* e){ if (e->button() == LeftButton) { orig_cursor = cursor(); setCursor(SizeAllCursor); prev_x = e->x(); prev_y = e->y(); mb_pressed = true; }}// rotate a globe during the button is pressedvoid QGlobe::mouseMoveEvent(QMouseEvent* e){ if (mb_pressed) { hrot -= (prev_x - e->x()) * 1.0f; vrot -= (prev_y - e->y()) * 1.0f; prev_x = e->x(); prev_y = e->y(); updateGL(); }}// stop rotating a globe when a mouse button is releasedvoid QGlobe::mouseReleaseEvent(QMouseEvent* e){ if (e->button() == LeftButton) { setCursor(orig_cursor); mb_pressed = false; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -