Adding gluPerspective and gluLookAt made my drawing disappear - c++

I'm currently working on a basic GUI that create and draw a robot in a 3d space, I'm using OpenGL and freeglut to deal with the 3d part.
Until last week, I was ignoring all the perspective stuff like 'gluLookAt' or 'gluPerspective' ...
Now, I would like to add those things in order to get basic camera movement (rotation, zoom, translation) with user input.
But i'm stuck cause whenever I try to add the perspective part to my code, I'm not able to get my beautiful robot anymore.
here's my current code :
void drawScene(void) {
glClearColor(1.0f,1.0f,1.0f,0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glMatrixMode(GL_MODELVIEW);
glColor3f(0.0f, 0.0f, 0.0f);
ortho();
robot.draw(); // only sone basic lines and quads
glLoadIdentity();
sprintf(title, "robot creation link:%i/joint:%i", robot.linkNumber, robot.jointNumber);
glutSetWindowTitle(title);
glFlush();
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA|GLUT_SINGLE|GLUT_MULTISAMPLE);
glutInitWindowPosition(0,0);
glutInitWindowSize(1360,768);
glEnable(GL_MULTISAMPLE_ARB | GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
id = glutCreateWindow("robot creation");
glutDisplayFunc (drawScene);
glutKeyboardFunc(keyboardHandler);
glutSpecialFunc (specialKeyHandler);
glutMouseFunc (mouseHandler);
glutReshapeFunc (reshapeHandler);
glutMainLoop();
return 0;
}
I wonder if my code need to be completly re-done to work properly with such things or if I'm not using them properly.
Atm I've tried to add this after the window creation :
glViewport(0, 0, 1360, 768);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(180.0f,1360.0f/768.0f,0.1f,1000.0f);
and this in the drawScene function after the drawing part :
gluLookAt(
10.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f
);
I know I'm facing the object because I can see a dot in the center of the screen that came from the robot.

You have both matrix modes (model view and projection. It is better to activate one. For gmu perspective try something like gluPerspective(170, 1.33, 0.00001, 1000); or put the camera closer to check if you can see a difference in the object. If you are not able to see the object your matrices are overwriting each other. You can check their values by:Gl.glGetDoublev(Gl.GL_MODELVIEW_MATRIX, modelMatrix);
Gl.glGetDoublev(Gl.GL_PROJECTION_MATRIX, projMatrix);.
Another option is also gluunproject which is easier to work than look at function (in my opinion)

Related

How to display 2D graphics in pangolin with panel

I can't figure out how to use pangolin to display 2D openGL graphics.
I'm am in internship in the research department of a school.
I am very novice at OpenGl and Pangolin.
I'm trying to add a monitoring window to an open_source program so that it is more user-friendly. This program is ORB_SLAM2, and it already uses pangolin as an openGL display manager. It has already some windows opening with panels and 3d openGL displays like thisby this piece of code
void Viewer::Run()
{
//...
pangolin::CreateWindowAndBind("ORB-SLAM2: Map Viewer",1024,768);
// 3D Mouse handler requires depth testing to be enabled
glEnable(GL_DEPTH_TEST);
// Issue specific OpenGl we might need
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
pangolin::CreatePanel("menu").SetBounds(0.0,1.0,0.0,pangolin::Attach::Pix(175));
// ... define elements of the menu (not important)
// Define Camera Render Object (for view / scene browsing)
pangolin::OpenGlRenderState s_cam(
pangolin::ProjectionMatrix(1024,768,mViewpointF,mViewpointF,512,389,0.1,1000),
pangolin::ModelViewLookAt(mViewpointX,mViewpointY,mViewpointZ, 0,0,0,0.0,-1.0, 0.0));
// Add named OpenGL viewport to window and provide 3D Handler
pangolin::View& d_cam = pangolin::CreateDisplay()
.SetBounds(0.0, 1.0, pangolin::Attach::Pix(175), 1.0, -1024.0f/768.0f)
.SetHandler(new pangolin::Handler3D(s_cam));
pangolin::OpenGlMatrix Twc;
Twc.SetIdentity();
//...
while(1)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
mpMapDrawer->GetCurrentOpenGLCameraMatrix(Twc);
//...
d_cam.Activate(s_cam);
glClearColor(1.0f,1.0f,1.0f,1.0f);
mpMapDrawer->DrawCurrentCamera(Twc);
if(menuShowKeyFrames || menuShowGraph)
mpMapDrawer->DrawKeyFrames(menuShowKeyFrames,menuShowGraph);
if(menuShowPoints)
mpMapDrawer->DrawMapPoints();
pangolin::FinishFrame();
//...
}
So I tried to copy that and remove the 3D handling part of it like this
void Monitor::Run()
{
//...
pangolin::CreateWindowAndBind("ORB-SLAM2: Monitoring",1024,768);
// Issue specific OpenGl we might need
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
pangolin::View& menu = pangolin::CreatePanel("vars").SetBounds(0.0,1.0,0.0,pangolin::Attach::Pix(175));
//...
// Add named OpenGL viewport to window
pangolin::View& graph = pangolin::CreateDisplay()
.SetBounds(0.0, 1.0, pangolin::Attach::Pix(175), 1.0, 1024.0f/768.0f);
while (1){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
graph.Activate();
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// 2D Basic test shape
glBegin(GL_QUADS);
glColor3f(0.4f, 0.05f, 0.05f);
glVertex2f(-0.5, 0.8f);
glVertex2f(-0.8f, -0.8f);
glVertex2f(0.8f, -0.8f);
glVertex2f(0.8f, 0.8f); glEnd();
pangolin::FinishFrame();
}
}
But The 2D Shape isn't apearing, it only shows the background color
I tried the followings:
Removing the Panel: it makes the shape appear but I want to keep the panel.
Changing zorders of the menu and the shape in both orders, didn't change anything
Not enclosing it in an infinite while loop: Both panel and shape appeared but obviously it is a static image. But it appears the render works the first call of FinishFrame() and then it doesn't anymore.
And other stuffs but i can't list it all here.
I'm wandering if it is because I didn't create OpenGlRenderState Object, But I don't understand why I would need it for 2D Rendering from my understanding of OpenGL and Pangolin.
I hope you guys can help me.

How to simply Scale an object in openGL?

I am trying to learn how to do scaling, rotating, and translating in openGL, but I am not sure exactly how to do so. I tried following an example but it is not working. Below is my sample code, which does not draw the object. Can anyone tell me what I am doing wrong?
#include <stdlib.h>
#include <GL/glut.h>
GLfloat vertices[][2] = { { -1.0,1.0 },{ -1.0,0.857 },
{ -0.857,0.857 },{ -0.857,1.0 } };
void drawObject() {
glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_POLYGON);
glVertex2fv(vertices[0]);
glVertex2fv(vertices[1]);
glVertex2fv(vertices[2]);
glVertex2fv(vertices[3]);
glEnd();
}
void display(void)
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glShadeModel(GL_SMOOTH);
glColor3f(0.0f, 0.0f, 0.0f);
glPushMatrix();
glLoadIdentity();
glScalef(2.0, 2.0, 0.0);
drawObject();
glPopMatrix();
glFlush();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(1600, 800);
glutInitWindowPosition(0, 0);
glutCreateWindow("Window");
glutDisplayFunc(display);
glutMainLoop();
}
With your current coordiantes and transformations, your object is just off the screen.
When setting all transformation matrices to identity, you are directly drawing in clip space. And if you do never use an input w value other than 1 (glVertex2* will always set w to 1), clip space equals normalized device space. In normalized device space, the viewing volume is defined as the cube [-1,1] along all dimensions.
However, by applying glScale(2.0, 2.0, 0.0), you scale the object by 2, with the center beeing the origin. As a result, the visible part of the scene is everything in the range [-0.5,0.5] in object space coordinates, and your object is completely outside of that range.
If you want to scale on a single object, you should first translate it to the center, and apply the scale afterwards.
The following sequence of transformations should make your object visible:
glScalef(2.0f, 2.0f, 1.0f);
glTranslatef(0.9285f, -0.9285f, 0.0f);
Also note that all of that is deprecated in modern GL. You are relying on the fixed function pipeline with the integrated matrix stack, immediate mode (Begin/End) rendering, GL_POLYGON primitive type, which is all removed from modern core profiles of OpenGL. If you are starting with GL nowadyays, I strongly recommend learning the new way.

Perspective projection (misunderstood gluPerspective)

I want to clarify things with gluPerspective near and far parameters, I know
that they define the range in z axis for all objects - so objects closer/away than near/far will be clipped by the clipping algorithms. And when lets say near = 0.1, and far = 100*winWid, we are not seeing anything because objects are behind of the viewer (and camera by default is at (0.0, 0.0, 0.0) plus openGL user coordinates system is right handed), so then we call (see code below) translate(0.0, 0.0, -winWid) to move back by -z axis objects to place them in front of the camera.
But if we set far = -100*winWid; everything works same as with positive far value.
So what's being changed when far is negative ??
Why in that case nothing is clipped too ??
#include <gl/glut.h>
#include <math.h>
const float winWid = 1000.0f;
const float winHei = 800.0f;
GLfloat cube_side = 200.0f;
GLfloat ALPHA = 0.7f;
void render();
void updateDisplay()
{
render(cubeAngle, rotx, roty, rotz);
}
void drawCube(const GLfloat& a)
{
glBegin(GL_QUADS);
// back face
glColor4f(0.0f, 1.0f, 0.0f, ALPHA);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, a, 0.0f);
glVertex3f(a, a, 0.0f);
glVertex3f(a, 0.0f, 0.0f);
// and other cube faces here ...
glEnd();
}
void render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
drawCube(cube_side);
glPopMatrix();
glutSwapBuffers();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_ALPHA);
glutInitWindowSize(winWid, winHei);
glutInitWindowPosition(100, 100);
glutCreateWindow("window");
glutDisplayFunc(updateDisplay);
glEnable(GL_DEPTH_TEST); // depth buffer setup
glEnable(GL_BLEND); // transparency setup
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(55.0f, winWid/winHei, 0.1f, 100*winWid);
glMatrixMode(GL_MODELVIEW);
glTranslatef(0.0f, 0.0f, -winWid); // move back to see drawing objects
glRotatef(75.0f, -1.0f, 0.0f, 0.0f); // make z+ axis point up to emphasize 3D (wihout this rotate z+ points towards the viewer)
glutMainLoop();
return 0;
}
Negative far-plane values are not supported by gluPerspective. The documentation states:
zFar: Specifies the distance from the viewer to the far clipping plane (always positive). (source)
By default, the camera in OpenGL looks along the negative z-axis. So the visible area is [-near, -far] in world coordinates. In your code example, the object is located at z=-1000, while the visible range is from [-0.01, -100*1000], which means that the object is clearly in view.
One additional thing to mention is the depth-buffer precision: This is mainly defined by the range given by nearPlane and farPlane. Assuming, that you have a precision of 16-bit (can be more or less depending on the setup), one can store 2^16 different depth values. This means with your setup, objects can be relative far away from each other and will still be treated as being at the same depth. You may think about whether this huge depth range is really necessary for the application.

Why is my HUD not rendering in OpenGL?

I'm new to OpenGL, and I've been going through NeHe's tutorials and various other web sources, and I'm testing some things to render text as a HUD of sorts over everything else.
After a very long night, I can't get this to work and I can't find any solutions here that work, so I thought I'd ask.
My code:
GLvoid glLoadHUD(GLvoid)
{
glPushAttrib(GL_LIGHTING_BIT |
GL_DEPTH_BUFFER_BIT |
GL_TEXTURE_BIT);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
glRasterPos2f(0.1f, 0.6f);
glColor3f(1.0f,1.0f,1.0f);
glPrint("Test.");
glRasterPos2f(0.0f, 0.0f);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopAttrib();
glEnable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
}
Which is the code to render the text, and this is the code for drawing the scene:
int DrawGLScene(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clears buffers
glLoadIdentity();
// If I put glLoadHUD(); here, it renders but the models render over it,
// which is useless.
for (xloop = 0; xloop < 3;)
{
glLoadIdentity();
glTranslatef(-4.0f+(float(xloop)*4.0f),0.0f,-12.0f);
glCallList(dlstBox); // This is the call to create a box.
xloop++;
}
glLoadHUD(); // If I put it here though, it doesn't render at all.
return TRUE;
}
Thank you in advance for any help you could give, I know I'm pretty green and I'm sure it's staring me right in the face, but this is driving me mad and I'm not sure how to make it work.
With glLoadHud after the rest of the scene, your MODELVIEW matrix is still on the stack, and you do not clear it as part of glLoadHud. Thus all of the glTranslatef translations that you accumulate during the scene are still active when you're drawing the hud, which translates it right out of your viewable window.
Clear the MODELVIEW matrix as part of the start of glLoadHud and see if that makes a difference.
It might be printing inside your z-clipping so it will not show up on your screen. So, move out of the screen a little bit and see if it shows up.

Rendering from SDL and OpenGL at the Same Time

Hey all, I'm very new to OpenGL (just started seriously programming with it today) and I'm trying to use it to give my SDL games a 3D boost. I've setup a small test program below:
#include <SDL/SDL.h>
#include <gl/gl.h>
int main(int argc, char *argv[])
{
SDL_Event event;
float theta = 0.0f;
SDL_Init(SDL_INIT_VIDEO);
SDL_Surface *screen = SDL_SetVideoMode(800, 600, 32, SDL_OPENGL | SDL_HWSURFACE | SDL_RESIZABLE | SDL_FULLSCREEN);
glViewport(0, 0, 800, 600);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glMatrixMode(GL_PROJECTION);
glMatrixMode(GL_MODELVIEW);
int done;
for(done = 0; !done;)
{
SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 255, 0, 0));
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.0f,0.0f);
glRotatef(theta, 0.0f, 0.0f, 1.0f);
glBegin(GL_TRIANGLES);
glColor3f(0.83f, 0.83f, 0.0f);
glVertex2f(0.0f, 1.0f);
glColor3f(0.83f, 0.83f, 0.0f);
glVertex2f(0.87f, -0.5f);
glColor3f(0.83f, 0.83f, 0.0f);
glVertex2f(-0.87f, -0.5f);
glEnd();
theta += 10.0f;
SDL_Flip(screen);
SDL_GL_SwapBuffers();
SDL_PollEvent(&event);
if(event.key.keysym.sym == SDLK_ESCAPE)
done = 1;
}
}
My problem is that the red background I'm trying to rendered is never rendered, only the OpenGL Triangle is rendered.
Thanks in advance to anyone who can help me. It's much appreciated.
There's one simple rule about OpenGL: It doesn't play well with others. What happens in your case is, that the double buffer swap (initiated by SDL_GL_SwapBuffers) will in some way replace everything in the window, not being rendered by OpenGL.
Just draw everything using OpenGL.
You fill the back buffer on one line with SDL_FillRect then you clear it on the next with glClear. Have you tried swapping the order of the operations?
Not that I disagree with the accepted answer; in general trying to mix software rendering methods with OpenGL is a recipe for confusion at best, but you might get lucky in this case.
As for rending textured quads, you should be able to work it out from NeHe lesson 6. People complain about NeHe but it's a reasonable guide for getting started. Just don't use it as an example of good coding or of efficient modern OpenGL usage. Start here and move to more complex stuff later.
If you're using C++, SFML library might be a better option (it has C bindings though, but haven't tried those). It plays nicely with OpenGL and has functions to cooperatively work alongside GL. As far as I understood it, SFML functions themselves use GL to render. Although, I do suggest that you do rendering only with GL calls as noted above.
your SDL_FillRect isn't show as red, because you call glClear with GL_COLOR_BUFFER_BIT set afterwards