// This code example is created for educational purpose // by Thorsten Thormaehlen (contact: www.thormae.de). // It is distributed without any warranty. #include #include #include #include #include #include #ifndef M_PI #define M_PI 3.1415926535897932385f #endif #include #include #include using namespace std; class Renderer : protected QOpenGLFunctions_2_0 { public: Renderer() : rot1(0.0), rot2(0.0), rot3(0.0) {} public: void display() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // view scene from the side glTranslatef(0.0f,0.0f,-3.0f); glRotatef( -45.0f, 0.0f, 0.0f, 1.0f); glRotatef( -45.0f, 0.0f, 1.0f, 0.0f); glRotatef( 135.0f, 1.0f, 0.0f, 0.0f); // rotate around z glRotatef(rot1, 0.0f, 0.0f, 1.0f); glColor3f(0.0f, 0.0f, 1.0f); drawCoordinateAxisZ(); // rotate around local y glRotatef(rot2, 0.0f, 1.0f, 0.0f); glColor3f(0.0f, 1.0f, 0.0f); drawCoordinateAxisY(); // rotate around local x glRotatef(rot3, 1.0f, 0.0f, 0.0f); glColor3f(1.0f, 0.0f, 0.0f); drawCoordinateAxisX(); // draw the plane in the local coordinate system drawToyPlane(); } void init() { initializeOpenGLFunctions(); // read vertex data from file ifstream input(findFile("ToyPlaneData.txt", "qt", 5)); if(!input) { QMessageBox msgBox; msgBox.setText("Can not find vertex data file \"ToyPlaneData.txt\""); msgBox.exec(); } else { int vertSize; double vertData; if(input >> vertSize) { if(vertSize > 0) { toyPlaneData.resize(vertSize); int i = 0; while(input >> vertData && i < vertSize) { // store it in the vector. toyPlaneData[i] = vertData; i++; } if(i != vertSize || vertSize % 3) toyPlaneData.resize(0); } } input.close(); } glEnable(GL_DEPTH_TEST); } void resize(int w, int h) { // ignore this for now glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspectiveR (45.0, (float)w/(float)h, 0.1, 10.0); } void dispose() {} public: float rot1; float rot2; float rot3; std::vector toyPlaneData; private: void drawCoordinateAxisZ() { glBegin(GL_LINE_LOOP); // circle in x-y plane for(int a=0; a<360; a+=10) { float angle = M_PI / 180.0f * a; glVertex3f(cos(angle), sin(angle), 0.0); } glEnd(); glBegin(GL_LINES); glVertex3f(0.9f, 0.0f, 0.0f); // x-axis glVertex3f(1.0f, 0.0f, 0.0f); glVertex3f(0.0f, 0.9f, 0.0f); // y-axis glVertex3f(0.0f, 1.0f, 0.0f); glVertex3f(0.0f, 0.0f,-1.0f); // z-axis glVertex3f(0.0f, 0.0f, 1.0f); glEnd(); glBegin(GL_TRIANGLES); // z-axis tip glVertex3f(0.0f,-0.1f, 0.9f); glVertex3f(0.0f, 0.0f, 1.0f); glVertex3f(0.0f, 0.1f, 0.9f); glEnd(); } void drawCoordinateAxisX() { glPushMatrix(); glRotatef(90.0f, 0.0f, 1.0f, 0.0f); drawCoordinateAxisZ(); glPopMatrix(); } void drawCoordinateAxisY() { glPushMatrix(); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); drawCoordinateAxisZ(); glPopMatrix(); } void drawToyPlane() { glColor3f(0.5f, 0.5f, 0.5f); glBegin(GL_TRIANGLES); for(unsigned i=0; i < toyPlaneData.size(); i+=3) { glVertex3d(toyPlaneData[i],toyPlaneData[i+1], toyPlaneData[i+2]); } glEnd(); } // implemention of gluPerspective to avoid GLU header void gluPerspectiveR(float fovyInDegrees, float aspectRatio, float znear, float zfar) { float ymax = znear * tanf(fovyInDegrees * M_PI / 360.0); float xmax = ymax * aspectRatio; glFrustum(-xmax, xmax, -ymax, ymax, znear, zfar); } bool fileExists(const std::string& filename) { ifstream myfile(filename.c_str()); if (!myfile.is_open()) { return false; } myfile.close(); return true; } std::string findFile(const std::string& filename, const std::string& subdir, int depth) { int counter = 0; std::string path(""); while (counter < depth) { if (fileExists(path + filename)) return path + filename; if (fileExists(path + "/" + subdir + "/" + filename)) return path + "/" + subdir + "/" + filename; path += "../"; counter++; } return filename; } }; class MyWidget : public QOpenGLWidget { private: Renderer *renderer; public: MyWidget(QWidget *parent = NULL) : QOpenGLWidget(parent) { this->setWindowTitle("Use 1, 2, and 3 keys to rotate (ALT+key rotates in other direction)"); this->resize(320, 320); renderer = new Renderer(); } ~MyWidget() { makeCurrent(); renderer->dispose(); doneCurrent(); delete renderer; } protected: void initializeGL() { renderer->init(); } void resizeGL(int w, int h){ renderer->resize(w, h); } void paintGL() { renderer->display(); } void keyPressEvent(QKeyEvent* event){ bool redraw = false; float offset = 2.5f; if(event->modifiers() & Qt::AltModifier) offset = -offset; switch(event->key()) { case '1': renderer->rot1 += offset; redraw = true; break; case '2': renderer->rot2 += offset; redraw = true; break; case '3': renderer->rot3 += offset; redraw = true; break; case '0': renderer->rot1 = 0.0f; renderer->rot2 = 0.0f; renderer->rot3 = 0.0f; redraw = true; break; } if(redraw) { this->setWindowTitle(QString("Yaw %1, Pitch %2, Roll %3").arg(renderer->rot1).arg(renderer->rot2).arg(renderer->rot3)); this->update(); } } }; int main (int argc, char* argv[]) { // create a QApplication object that handles initialization, // finalization, and the main event loop QApplication appl(argc, argv); MyWidget widget; // create a widget widget.show(); //show the widget and its children return appl.exec(); // execute the application }