Multiple viewport problem - c++

I'm setting up so I can switch between either one or four viewports but I got some trouble.
In my bottom right viewport I got camera view, the same camera that I can switch to full view on. The other three viewports are working with fixed locations but the bottom right viewport is compressed on the y scale and half of the picture on the x scale is missing.
void display(int what)
{
if(what==5){glViewport(0, 0, w, h);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
ca.lookAt();}
if(what==1){glViewport(0, 0, w/2, h/2);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(75,15,-5,0,5,-5,0,1,0);}
if(what==2){glViewport(w/2, h/2, w, h);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,110,0,20,0,20,1,0,0);}
if(what==3){glViewport(w/2, 0, w, h/2);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, float(320) / float(240), 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
ca.lookAt();}
if(what==4){glViewport(0, h/2, w/2, h);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(185,75,25,0,28,0,0,1,0);}
//glMatrixMode(GL_MODELVIEW);
//glLoadIdentity();
////gluLookAt(cos(shared.time) * shared.distance, 10, sin(shared.time) * shared.distance, 0, 0, 0, 0, 1, 0); // Roterar kameran kring origo genom att skapa en ny vymatris varje bildruta
////ca.orbitYaw(0.05);
//ca.lookAt();
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
drawScene();
drawCamera();
glutSwapBuffers();
}
void viewport(){
glEnable(GL_SCISSOR_TEST);
if(!divided_view_port)
{
glViewport(0, 0, w, h);
glScissor(0,0,640,480);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, w / h, 0.1f, 100.0f);
display(5);
}
else
{
////////////////////// bottom left - working
glViewport(0, 0, w/2, h/2);
glScissor(0,0,w/2,h/2);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, w / h, 0.1f, 300.0f);
display(1);
//////////////////////
////////////////////// top right - working
glViewport(w/2, h/2, w, h);
glScissor(w/2,h/2,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, w / h, 0.1f, 300.0f);
display(2);
//////////////////////
////////////////////// bottom right -working
glViewport(w/2, 0, w, h/2);
glScissor(w/2,0,w,h/2);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, w / h, 0.1f, 300.0f);
display(3);
////////////////////////
////////////////////////// top left
glViewport(0, h/2, w/2, h);
glScissor(0,h/2,w/2,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, w / h, 0.1f, 300.0f);
display(4);
///////////////////////////
}
glDisable(GL_SCISSOR_TEST);
glMatrixMode(GL_MODELVIEW);
}

glViewport() takes an offset and a size.
Your code seems to be passing lower-left and upper-right coordinates.
Try these:
glViewport( 0, 0, w/2, h/2); // lower-left
glViewport(w/2, 0, w/2, h/2); // lower-right
glViewport(w/2, h/2, w/2, h/2); // upper-right
glViewport( 0, h/2, w/2, h/2); // upper-left

Related

glViewport issue - getting stretched camera views

Hello I've tried to split a window in four viewports where I want to render a scene in each viewport.
For simplicity I have simplified the code to only contain a single camera view.
The code look roughly as follows:
void setup_trf(const PolarCoords& pc, double aspect)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, aspect, 0.01, 1000);
//glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
double eye_x, eye_y, eye_z;
pc.to_cartesian(eye_x, eye_y, eye_z);
double look_x = 0;
double look_y = 0;
double look_z = 0;
double up_x = 0;
double up_y = 0;
double up_z = 1;
gluLookAt(
eye_x, eye_y, eye_z,
look_x, look_y, look_z,
up_x, up_y, up_z);
}
void draw_scene(int w, int h) {
glClearColor(0.0f, 0.75f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
double aspect = w / double(h);
glViewport(0, h / 2, w / 2, h);
setup_trf(app_state.m_polar, aspect);
draw_sphere();
glViewport(w / 2, h / 2, w, h);
setup_trf(app_state.m_polar, aspect*0.5);
draw_sphere();
glViewport(0, 0, w / 2, h/2);
setup_trf(app_state.m_polar, aspect);
draw_sphere();
glViewport(w / 2, 0, w, h / 2);
setup_trf(app_state.m_polar, aspect);
draw_sphere();
}
And the result is the following:
view of the sphere
Anyone knows why the image gets stretched in the different viewports?
The 1st and 2nd parameter of glViewport are the bottom left coordinate (origin) of the viewport rectangle. But the 3rd and 4th parameter are the width and height of the viewport rectangle rather than the top right coordinate.
This means the 3rd and 4th parameter have to be the half of the window size (w/2, h/2) in each case:
glViewport(0, h/2, w/2, h/2);
setup_trf(app_state.m_polar, aspect);
draw_sphere();
glViewport(w/2, h/2, w/2, h/2);
setup_trf(app_state.m_polar, aspect);
draw_sphere();
glViewport(0, 0, w/2, h/2);
setup_trf(app_state.m_polar, aspect);
draw_sphere();
glViewport(w/2, 0, w/2, h/2);
setup_trf(app_state.m_polar, aspect);
draw_sphere();

draw two objects using openGL in a same time

I have several functions:
drawGrid() -> which draws a grid on the ground;
drawAxes() -> which is draw axes using the gluCylinder
Arrows() -> which is used in drawAxes to draw cones as arrows;
I cant understand why I can not call drawGrid and drawAxes in a same time; in this case the output is like this link:
http://www.4shared.com/photo/8YTsc17s/wrong.html
if I comment the drawGrid() I can see the axes fine; but I want to draw them simultaneously;
http://www.4shared.com/photo/KI3DER-5/Axis.html
this is the codes I used:
1. drawGrid
void Golsa::drawGrid(float size, float step)
{
// disable lighting
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
glColor3f(0.3f, 0.3f, 0.3f);
for(float i=step; i <= size; i+= step)
{
glVertex3f(-size, 0, i); // lines parallel to X-axis
glVertex3f( size, 0, i);
glVertex3f(-size, 0, -i); // lines parallel to X-axis
glVertex3f( size, 0, -i);
glVertex3f( i, 0, -size); // lines parallel to Z-axis
glVertex3f( i, 0, size);
glVertex3f(-i, 0, -size); // lines parallel to Z-axis
glVertex3f(-i, 0, size);
}
}
2. drawAxes:
void Golsa:: drawAxes(double length)
{
glPushMatrix();
glTranslatef(-length,0,0);
Arrow(0,0,0, 2*length,0,0,0.2);
glPopMatrix();
glPushMatrix();
glTranslatef(0,-length,0);
Arrow(0,0,0, 0,2*length,0,0.2);
glPopMatrix();
glPushMatrix();
glTranslatef(0,0,-length);
Arrow(0,0,0, 0,0,2*length,0.2);
glPopMatrix();
}
3. Arrow
void Golsa::Arrow(GLdouble x1,GLdouble y1,GLdouble z1,GLdouble x2,GLdouble y2,GLdouble z2,GLdouble D)
{
double x=x2-x1;
double y=y2-y1;
double z=z2-z1;
double L=sqrt(x*x+y*y+z*z);
GLUquadricObj *quadObj;
GLUquadric* cyl = gluNewQuadric();
GLUquadric* cy2 = gluNewQuadric();
GLUquadric* cy3 = gluNewQuadric();
glPushMatrix ();
glTranslated(x1,y1,z1);
if((x!=0.)||(y!=0.)) {
glRotated(atan2(y,x)/RADPERDEG,0.,0.,1.);
glRotated(atan2(sqrt(x*x+y*y),z)/RADPERDEG,0.,1.,0.);
} else if (z<0){
glRotated(180,1.,0.,0.);
}
//glTranslatef(0,0,L-4*D);
gluQuadricDrawStyle(cyl, GLU_FILL);
gluQuadricNormals(cyl, GLU_SMOOTH);
glTranslatef(0,0,0);
glColor3f(1,1,1);
gluQuadricDrawStyle(cyl, GLU_FILL);
//gluQuadricNormals(cyl, GLU_SMOOTH);
gluCylinder(cyl, 0.1, 0.1,4.0, 12,1);
//glColor3f (1,1,1);
glColor3f(1,1,1);
glTranslatef(0.0,0.0,4);
glColor3f(1,1,1);
gluQuadricNormals(cyl, GLU_SMOOTH);
gluCylinder(cy2, 0.2, 0,0.4, 12,1);
gluDeleteQuadric(cyl);
glPopMatrix();
}
this function call others :
void Golsa::drawSub()
{
float Xangle, Yangle, Zangle;
float Xposition, Yposition, Zposition;
/*Mat rvec1i = Mat(3,1,CV_64FC1,Scalar::all(0));
Mat tvec1i = Mat(3,1,CV_64FC1,Scalar::all(0));*/
// set bottom viewport (perspective)
glViewport(0, 0, windowWidth, windowHeight);
glScissor(0, 0, windowWidth, windowHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(FOV_Y, windowWidth/(windowHeight/2.0f), 1, 1000);
// switch to modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// clear buffer
glClearColor(bgColor[0], bgColor[1], bgColor[2], bgColor[3]); // background color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glPushMatrix();
// First, transform the camera (viewing matrix) from world space to eye space
glTranslatef(0, 0, -cameraDistance);
glRotatef(cameraAngleX, 1, 0, 0); // pitch
glRotatef(cameraAngleY, 0, 1, 0); // heading
// draw grid
drawGrid(10, 1);
FindingCameraPosition(Xposition,Yposition,Zposition,Xangle,Yangle,Zangle);
glPopMatrix();
}
Turning my comment into an answer.
drawGrid() has a call to glBegin(), but no matching call to glEnd().

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);
}

How to scale glDrawPixels?

I need to scale the result of glDrawPixels image.
I'm drawing a 640x480 pixels image buffer with glDrawPixels in a Qt QGLWidget.
I tryed to do the following in PaintGL:
glScalef(windowWidth/640, windowHeight/480, 0);
glDrawPixels(640,480,GL_RGB,GL_UNSIGNED_BYTE,frame);
But it doesn't work.
I am setting the OpenGL viewport and glOrtho with the size of the widget as:
void WdtRGB::paintGL() {
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Setup the OpenGL viewpoint
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, windowWidth, windowHeight, 0, -1.0, 1.0);
glDepthMask(0);
//glRasterPos2i(0, 0);
glScalef(windowWidth/640, windowHeight/480, 0);
glDrawPixels(640,480,GL_RGB,GL_UNSIGNED_BYTE,frame);
}
//where windowWidth and windowHeight corresponds to the widget size.
/the init functions are:
void WdtRGB::initializeGL() {
glClearColor ( 0.8, 0.8, 0.8, 0.0); // Background to a grey tone
/* initialize viewing values */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, windowWidth, windowHeight, 0, -1.0, 1.0);
glEnable (GL_DEPTH_TEST);
}
void WdtRGB::resizeGL(int w, int h) {
float aspect=(float)w/(float)h;
windowWidth = w;
windowHeight = h;
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
if( w <= h )
glOrtho ( -5.0, 5.0, -5.0/aspect, 5.0/aspect, -5.0, 5.0);
else
glOrtho (-5.0*aspect, 5.0*aspect, -5.0, 5.0, -5.0, 5.0);
//printf("\nresize");
emit changeSize ( );
}
It sounds like what you actually need to do instead of calling glDrawPixels () is to load your image data into a texture and draw a textured quad the size of the window. So something like this:
glGenTextures (1, &texID);
glBindTextures (GL_TEXTURE_RECTANGLE_EXT, texID);
glTexImage2D (GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, 640, 480, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, frame);
glBegin (GL_QUADS);
glTexCoord2f (0, 0);
glVertex2f (0, 0);
glTexCoord2f (640, 0);
glVertex2f (windowWidth, 0);
glTexCoord2f (640, 480);
glVertex2f (windowWidth, windowHeight);
glTexCoord2f (0, 480);
glVertex2f (0, windowHeight);
glEnd();
Or if that's too much work, glPixelZoom (windowWidth / 640, windowHeight / 480), might do the trick, too.
Just for further reference: Instead of doing the glScalef(windowWidth/640, windowHeight/480, 0); before the glDrawPixels you should do a pixel zoom:
glRasterPos2i(0,0);
GLint iViewport[4];
glGetIntegerv(GL_VIEWPORT, iViewport);
glPixelZoom(iViewport[2]/640, iViewport[3]/480);
glDrawPixels(640,480,GL_RGB,GL_UNSIGNED_BYTE,frame);
I need to scale the result of glDrawPixels image.
glDrawPixels directly goes to the framebuffer. So every incoming pixel is mapped 1:1 to the output. There is a function (ah, why am I telling you this) glPixelZoom, which allows you to zoom glDrawPixels.
BUT I urge you, not to use glDrawPixels!
Use textures quads instead. glDrawPixels is a depreciated function, no longer supported by modern OpenGL-3. And even when it was not deprecated it still is a very slow function. Textured quads are better in every regard.

Displaying not moving text not in 3D (eg. displaying HUD or frame rate)

I want to make something to display text on the screen. But I want something like FPS displayer - wherever you are text is in the same place (eg. in corner) and have the same height. Something like drawing HUD.
I'd like to see code.
That kind of thing is usually done in the a way like this:
void render_frame()
{
glViewport(0, 0, win_width, win_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
set_perspective_projection(); // glFrustum, gluPerspective, etc.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
render_scene();
glViewport(0, 0, lower_left_HUD_width, lower_left_HUD_height);
glEnable(GL_SCISSOR_TEST);
glScissor(0, 0, lower_left_HUD_width, lower_left_HUD_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 1, 0, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_DEPTH_BUFFER_BIT);
render_lower_left_HUD();
glViewport(win_width - upper_right_HUD_width, win_height - upper_right_HUD_height, upper_right_HUD_width, upper_right_HUD_height);
glEnable(GL_SCISSOR_TEST);
glScissor(win_width - upper_right_HUD_width, win_height - upper_right_HUD_height, upper_right_HUD_width, upper_right_HUD_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 1, 0, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_DEPTH_BUFFER_BIT);
render_upper_right_HUD();
SwapBuffers();
}
Just to give you the general idea. You can expand this concept as far as you want, placing mini-views instead of HUDs or similar.