How to zoom and scroll in QGLWidget - c++

In a project where I use QGLWidget to create my own image viewer, I'm trying to add zooming and scrolling feature in displaying large images but I get a problem where the image is cut and cannot be wider than it's original size or the panel size.
Here i set up the viewport and glScalef. In implementing scrolling, I subclass QAbstractScrollArea and pass the coordinate of scrollbars into a variable.
// scrollOffset has the coordinates of horizontal and vertical scrollbars
// this->width() and this->height() are panel size
glViewport(0 - scrollOffset.x(), 0 + scrollOffset.y(), this->width(), this->height());
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, this->width(), this->height(), 0); // flip the y axis
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// if zoomFactor value is 1.0 means no zooming
glScalef(zoomFactor, zoomFactor, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
Render the image:
glBindTexture( GL_TEXTURE_2D, texId );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());
glBegin(GL_QUADS);
// text coords are flipped in y axis
// width and height are image's original size
glTexCoord2d(0,1); glVertex3d(0, 0, 0);
glTexCoord2d(1,1); glVertex3d(width, 0, 0);
glTexCoord2d(1,0); glVertex3d(width, height, 0);
glTexCoord2d(0,0); glVertex3d(0, height, 0);
glEnd();
in image below, i scroll down the image but the displayed image cannot be taller than the panel's height

You should not abuse glViewport for zooming. The viewport is used to set, to which part of the (visible) window NDC coordinates are mapped after projection. Usually you set glViewport to the size of the window you're drawing to.
Any zooming and scrolling should be done by adjustment of the projection matrix, by adjusting the left, right, bottom and top limits to what's to be shown.

Related

Vertically flip text

I'm using Fontstash to load and render my text. However when I draw, the text is vertically flipped:
flipped text
I cannot change the origin so I think I have to rotate the texture here, however I'm not sure how to do it or if it's the proper way.
I set the matrices like this:
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glViewport(0, 0, viewport[2], viewport[3]);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, viewport[2], viewport[3], 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Wyck pointed out that I had face culling enabled, disabling it resolved the issue just fine when flipping the orthographic matrix.

OpenGL immediate mode in window coordinates [duplicate]

I am having trouble setting the openGL origin to the upper left corner of the view. So, in my window resize handler, I do something as;
// ox and oy are some offsets and width and height are the
// required viewport width and height
glViewport(ox, oy, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, 0, height, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
This keeps the origin at bottom left and I can render my texture as:
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex2f(0, 0);
glTexCoord2f(1, 0); glVertex2f(width, 0);
glTexCoord2f(1, 1); glVertex2f(width, height);
glTexCoord2f(0, 1); glVertex2f(0, height);
glEnd();
As far as I can tell from reading the pages here, to flip the origin I simply need to replace the glOrtho call with
glOrtho(0, width, height, 0, -1, 1);
However, doing this and using the render code above does not render my texture anymore and I just see a blank screen.
By flipping around the y-axis you flipped the chirality of the world space. Which means that the winding of your faces comes out differently. CCW becomes CW and vice versa. Most likely you have face culling enabled, so to account for the chirality flip you have to swap CCW for CW face culling.

opengl: Change the origin to upper left corner

I am having trouble setting the openGL origin to the upper left corner of the view. So, in my window resize handler, I do something as;
// ox and oy are some offsets and width and height are the
// required viewport width and height
glViewport(ox, oy, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, 0, height, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
This keeps the origin at bottom left and I can render my texture as:
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex2f(0, 0);
glTexCoord2f(1, 0); glVertex2f(width, 0);
glTexCoord2f(1, 1); glVertex2f(width, height);
glTexCoord2f(0, 1); glVertex2f(0, height);
glEnd();
As far as I can tell from reading the pages here, to flip the origin I simply need to replace the glOrtho call with
glOrtho(0, width, height, 0, -1, 1);
However, doing this and using the render code above does not render my texture anymore and I just see a blank screen.
By flipping around the y-axis you flipped the chirality of the world space. Which means that the winding of your faces comes out differently. CCW becomes CW and vice versa. Most likely you have face culling enabled, so to account for the chirality flip you have to swap CCW for CW face culling.

OpenGL fill frustum with quad

I'm trying to write an OpenGL/GLSL app that will use GLSL for image processing. I've done some research and come to the conclusion that the right approach is to render to a framebuffer object and then retrieve the image from the gpu. Unfortunately I can't figure out how to set up the frustum and render the quadrilateral so that it fills it properly. Does anyone know how to do this?
You need to render with an orthogonal projection matrix.
glPushMatrix(GL_WORLDVIEW);
glLoadIdentity();
glPushMatrix(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, height, 0, 0, 1);
glBegin(GL_QUADS);
glVertex2i(0, 0);
glVertex2i(width, 0);
glVertex2i(width, height);
glVertex2i(0, height);
glEnd();
glPopMatrix();
glMatrixMode(GL_WORLDVIEW);
glPopMatrix();
Width and height are the dimensions of your FBO. Of course they could be both one if you don't need to address special parts of your FBO by drawing quads at pixel positions.

Why isn't this square in the middle of the screen?

I wrote some code, expecting to see a square in the middle of the screen, instead the square appears higher up, in some aspect ratios near the top of the screen, and slightly to the left.
With another aspect ratio:
Here's the relevant part of my code:
void resize(uint32_t height, uint32_t width){
glViewport(0, 0, width, height);
glMatrixMode (GL_PROJECTION); //set the matrix to projection
glLoadIdentity();
gluPerspective(60, (GLfloat)width / (GLfloat)height, 1.0, 1000.0);
}
void draw(){
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
//set up camera
glLoadIdentity();
gluLookAt(0,10,0,0,0,0,0.001,0.999,0);
//draw a square in the center of the screen
glBegin(GL_TRIANGLE_FAN);
glColor4f(0,1,1,1);
glVertex3f(-1,0,-1);
glVertex3f(-1,0,1);
glVertex3f(1,0,1);
glVertex3f(1,0,-1);
glEnd();
glPopMatrix();
}
Isn't 0,0,0 supposed to be the middle of the screen? And isn't gluLookAt supposed to put whatever coordinate i specify in the center of the screen?
Change the value of up vector
gluLookAt(0,10,0,0,0,0,0,0,1);
your eyes is at positive y-axis and reference point at center and up (head) vector must be along z-axis.
You have done another mistake in your resize function
void resize(uint32_t height, uint32_t width){
glViewport(0, 0, width, height);
.....................
gluPerspective(60, (GLfloat)width / (GLfloat)height, 1.0, 1000.0);
}
your variable height stores width of screen and variable width stores height, you have defined the glViewport and in gluPerspective you think your are taking ratio width by height, but actually you are taking ratio height by width, so it occurs the problem. Edit you code as follows:
void resize(uint32_t width, uint32_t height){
glViewport(0, 0, width, height);
..................
gluPerspective(60, (GLfloat)width / (GLfloat)height, 1.0, 1000.0);
}