// 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 class Renderer : protected QOpenGLFunctions_2_0{ public: float t; //time const float d0; // initial distance public: Renderer() : t(1.0), d0(3.0), width(0), height(0) {} public: void display() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective (dollyZoomFovy(), (float)width/(float)height, 0.1, 50.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // translate camera by 3 units glTranslatef(0.0f, 0.0f, -t*d0); // draw a cube in the local coordinate system drawCube(); // draw random lines drawRandomLines(); } void init() { initializeOpenGLFunctions(); glEnable(GL_DEPTH_TEST); // create random values between -1.0 and 1.0 for(unsigned r=0; r < 1000; r++) { int rval = rand(); randVals.push_back(2.0f*float(rval)/float(RAND_MAX)-1.0f); } } void resize(int w, int h) { // ignore this for now glViewport(0, 0, w, h); width = w; height = h; } void dispose() { } float dollyZoomFovy() { float fovyInit = 60.0f; // initial field of view float theta = fovyInit / 180.0f * M_PI; // degree to rad float f = 1.0f / tan(theta/2.0f); float fNew = f * (d0*t-1) / (d0-1); float thetaNew = atan(1.0f / fNew) * 2.0f; float val = 180.0f * thetaNew / M_PI; //rad to degree return val; } // implemention of gluPerspective to avoid GLU header void gluPerspective(double fovyInDegrees, double aspectRatio, double znear, double zfar) { double ymax = znear * tanf(fovyInDegrees * M_PI / 360.0); double xmax = ymax * aspectRatio; glFrustum(-xmax, xmax, -ymax, ymax, znear, zfar); } private: int width; int height; std::vector randVals; private: void drawCube() { glColor3f(1.0f, 1.0f, 1.0f); glLineWidth(3.0f); glBegin(GL_LINE_LOOP); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glVertex3f( 1.0f,-1.0f, 1.0f); glVertex3f(-1.0f,-1.0f, 1.0f); glEnd(); glBegin(GL_LINE_LOOP); glVertex3f(-1.0f, 1.0f,-1.0f); glVertex3f( 1.0f, 1.0f,-1.0f); glVertex3f( 1.0f,-1.0f,-1.0f); glVertex3f(-1.0f,-1.0f,-1.0f); glEnd(); glBegin(GL_LINE_LOOP); glVertex3f( 1.0f, 1.0f,-1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glVertex3f( 1.0f,-1.0f, 1.0f); glVertex3f( 1.0f,-1.0f,-1.0f); glEnd(); glBegin(GL_LINE_LOOP); glVertex3f(-1.0f, 1.0f,-1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f(-1.0f,-1.0f, 1.0f); glVertex3f(-1.0f,-1.0f,-1.0f); glEnd(); glLineWidth(1.0); } void drawRandomLines() { if(randVals.size() % 5) return; unsigned i = 0; while(i < randVals.size()) { glColor3f(fabs(randVals[i++]), fabs(randVals[i++]), fabs(randVals[i++])); float x = randVals[i++]; float y = randVals[i++]; glBegin(GL_LINES); glVertex3f(x, y, -1.0f); glVertex3f(x, y, 1.0f); glEnd(); } } }; class MyWidget : public QOpenGLWidget { private: Renderer *renderer; public: MyWidget(QWidget *parent = NULL) : QOpenGLWidget(parent) { this->setWindowTitle("Use the 1 key to perform a dolly zoom"); 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 = 0.02f; if(event->modifiers() & Qt::AltModifier) offset = -offset; switch(event->key()) { case '1': renderer->t += offset; if(renderer->t < 1.0f) renderer->t = 4.0f; if(renderer->t > 4.0f) renderer->t = 1.0f; redraw = true; break; case '0': renderer->t = 1.0f; redraw = true; break; } if(redraw) { float distance = renderer->t*renderer->d0; float fovy = renderer->dollyZoomFovy(); QString title = QString("Distance: %1 FieldofView: %2").arg(int(distance*10.0f)/10.0f, -4).arg(int(fovy*10.0f)/10.0f); this->setWindowTitle(title); 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 }