Sunday, April 3, 2016

How To Zoom In in OpenGL + Qt


Recently I am working on a project which utilizes Qt5.3+OpenGL. I need to implement a function in which by spinning the mouse wheel, the 3D object in OpenGL view can be enlarged or shrunk. After some research, it is found that we can implement the function in two ways: glScaled or  glOrthof.

Approach 1: glScaled

glScaled function scales the x, y, z by a factor. In my implementation, all three axis are scaled by the same factor.

First, the mouse wheel function is written in such a way that wheel rotation changes a zoom factor named zoomScale. After that, it will call the paintGL() function where galScaled is embedded.

void GLWidget::wheelEvent(QWheelEvent *event)
{
QPoint numDegrees = event->angleDelta();
if (numDegrees.y() < 0)  zoomScale = zoomScale/1.1;
if (numDegrees.y() > 0)  zoomScale = zoomScale*1.1;

updateGL(); // call paintGL()
}

In paintGL() function, galScaled() is called and zoomScale is used to scale x, y, and z axis. We should note that in order to avoid unnecessary clipping, the near and far planes of OpenGL view need to be set with some redundancy.

void GLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glScaled(zoomScale, zoomScale, zoomScale);
    glRotatef(xRot / 16.0, 1.0, 0.0, 0.0);
    glRotatef(yRot / 16.0, 0.0, 1.0, 0.0);
    glRotatef(zRot / 16.0, 0.0, 0.0, 1.0);



Approach 2: glOrthof

glOrthof function defines a box where the objects are shown in OpenGL. The box has left, right, up, down, near, far boundaries. Again, we starts from the wheelEvent function which calls resizeGL().

void GLWidget::wheelEvent(QWheelEvent *event)
{
QPoint numDegrees = event->angleDelta();
if (numDegrees.y() < 0)  zoomScale = zoomScale/1.1;
if (numDegrees.y() > 0)  zoomScale = zoomScale*1.1;
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT,viewport); 
resizeGL(viewport[2], viewport[3]);

updateGL(); // call paintGL()
}

In resizeGL, zoomScale is used to adjust the boundaries in x and y directions. In this way, we can also implement the zoom in/out functions.

void GLWidget::resizeGL(int width, int height)
{
    int side = qMin(width, height);
int range = 1000;
    //glViewport((width - side) / 2, (height - side) / 2, side, side);
glViewport(0, 0, width, height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glOrthof(-0.5*range*zoomScale, +0.5*range*zoomScale, -0.5*height/width*range*zoomScale, +0.5*height/width*range*zoomScale, -5*range, +5*range);

    glMatrixMode(GL_MODELVIEW);
}


2 comments: