Line get duplicated instead of moved - c++

I'm using qWidget which inherits QGLWidget and below the widget I have 2 buttons.
button1: +
button2: -
this is my code:
void GLWidget::paintGL() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,_w,0,_h,-1,1);
glViewport(_camera_pos_x,0,_w,_h);
glBegin(GL_LINES);
glVertex2i(50,50);
glVertex2i(200,200);
glEnd();
update();
}
I want each time I'm pressing the + button, the screen will move 10 pixels to the right which means the line should move to the left by 10 pixels.
This is the code when im pressing the button:
void right() {_camera_pos_x += 10;}
_camera_pos_X is just a member int which is initialized to 0.
When I'm pressing the button another line is rendered 10 pixels to the right and I see 2 lines
What's wrong with my code?
By the way, I think im using old code of OpenGL, is there a better way to render a line?

First of all note, that drawing with glBegin/glEnd sequences is deprecated since more than 10 years.
Read about Fixed Function Pipeline and see Vertex Specification for a state of the art way of rendering.
glViewport specifies the transformation from normalized device coordinates to window coordinates. If you want to change the position of the line, then you have to draw the line at a different position, but that doesn't change the size of the viewport. Keep your viewport as large as the window:
glViewport(0, 0, _w, _h);
The default frame buffer is never cleared, so the rendering is always drawn on the rendering of the previous frames. Because of that, you can "see 2 lines". Use glClear to clear the framebuffer at the begine of the rendering:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Change the model view matrix to set the positon of the line:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,_w,0,_h,-1,1);
glViewport(0, 0, _w, _h);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(_camera_pos_x, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_LINES);
glVertex2i(50,50);
glVertex2i(200,200);
glEnd();

You must clear the old contents of the framebuffer, before drawing the new image. Put a glClear(GL_COLOR_BUFFER_BIT) at the beginning of paintGL().

Related

Saving a specific Camera View in OpenGL as Image

I have a 3D scene with an object and I would like to save a view of that object that is different from the one of the current screen I look at.
So I thought I'd just have to do something like this (pseudo code):
PushMatrix()
LoadIdentity()
TranslateAndRotate()
gluperspective()
setViewport()
DrawScene()
saveScreenshot()
PopMatrix()
But I only get a picture of the current view of my camera, not the one I specified.
Did I forget something?
EDIT:
Because of the answer below, I tried the following code:
void ScenePhotograph(GLubyte* Target, float *Translation, float RotationAroundY)
{
glMatrixMode(GL_PROJECTION);
gluPerspective(54.0f, (GLfloat)openGLControl1->Width / (GLfloat)openGLControl1->Height, 1.0f, 3000.0f);
glViewport(0,0,openGLControl1->Width, openGLControl1->Height);
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(Translation[0],Translation[1],Translation[2]);
glRotatef(RotationAroundY, 0,1,0);
openGLControl1_OnDrawGL(NULL,System::EventArgs::Empty);
openGLControl1->Refresh();
glReadPixels(0, 0, openGLControl1->Width, openGLControl1->Height, GL_RGB, GL_UNSIGNED_BYTE, Target);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
cam->SetView();
openGLControl1_OnDrawGL(NULL,System::EventArgs::Empty);
openGLControl1->Refresh();
glutSwapBuffers();
}
That is giving me an access violation at glutSwapBuffers();
Any Ideas?
First, make sure you are not mixing diferent matrix in your code. To get a screenshot, you will need to position your camera exactly as you normally do to view it on your sccreen, but, before you swap the buffers, you read the pixels from the current framebuffer and store it as an image.
So, what you need is something like this:
glMatrixMode(GL_PROJECTION);
gluPerspective();
glMatrixMode(GL_MODELVIEW);
glClear(); // clear buffers here
loadIdendity();
setCameraPosition();
TranslateRotate();
DrawScene();
screenShot();
// do again to set your camera to correct position
glClear(); // clear buffers here
loadIdendity();
setCameraPosition();
TranslateRotate();
DrawScene();
swapBuffers();
as you can see, screenShot take care of reading the pixels from your current framebuffer and save it as an image. So do everything again to position your camera to the correct place

OpenGL does not update the drawview

I have the following drawScene function which draws a sphere. The coords of X,Y are being updated all the time. As far as I can see from the printf the values changed for sure.
The problem is that the sphere does not change position according to the coords but is always drawn at the same place...
void drawScene(void){
//Clear information from last draw
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
glLoadIdentity(); //Reset the drawing perspective
glColor3d(1,0,0);
//glPushMatrix();///
glTranslated(X,Y,-7);//xyz//(X%5)-2.5,Y%5//(((X%6)-3),0,-7)
printf("\n\n\nCOORDS(X)%d (Y):%d\n\n\n\n",X,Y);
glutSolidSphere(0.3, 25, 20);//3,20,20
//glPopMatrix();///
glutSwapBuffers(); //Send the 3D scene to the screen
}
PS. I am not sure if this is right but every time I want my openGL window to be updated I call the drawScene() or else it is drawn only once.
Either call glutPostRedisplay() when you update the X and Y or enable the idleFunc like this:
void idle()
{
glutPostRedisplay();
}
and add this in your main:
glutIdleFunc(idle);

Untextured Quads appear dark

I just started working with OpenGL, but I ran into a problem after implementing a Font system.
My plan is to simply visualize several Pathfinding Algorithms.
Currently OpenGL gets set up like this (OnSize gets called once on window creation manually):
void GLWindow::OnSize(GLsizei width, GLsizei height)
{
// set size
glViewport(0,0,width,height);
// orthographic projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0,width,height,0.0,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
m_uiWidth = width;
m_uiHeight = height;
}
void GLWindow::InitGL()
{
// enable 2D texturing
glEnable(GL_TEXTURE_2D);
// choose a smooth shading model
glShadeModel(GL_SMOOTH);
// set the clear color to black
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.0f);
}
In theory I don't need blending, because I will only use untextured Quads to visualize obstacles and line etc to draw paths... So everything will be untextured, except the fonts...
The Font Class has a push and pop function, that look like this (if I remember right my Font system is based on a NeHe Tutorial that I was following quite a while ago):
inline void GLFont::pushScreenMatrix()
{
glPushAttrib(GL_TRANSFORM_BIT);
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(viewport[0],viewport[2],viewport[1],viewport[3], -1.0, 1.0);
glPopAttrib();
}
inline void GLFont::popProjectionMatrix()
{
glPushAttrib(GL_TRANSFORM_BIT);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
}
So the Problem:
If I don't draw a Text I can see the Quads I want to draw, but they are quite dark, so there must be something wrong with my general OpenGL Matrix Properties.
If I draw Text (so the font related push and pop functions get called) I can't see any Quads.
The question:
How do I solve this problem and some background information why this happened would also be nice, because I am still a beginner/student, who just started.
If your quads are untextured, you will run into undefined behaviour. What will probably happen is that any previous texture will be used, and the colour at point (0,0) will be used, which could be what is causing them to be invisible.
Really, you need to disable texturing before trying to draw untextured quads using glDisable(GL_TEXTURE_2D). Again, if you don't, it'll just use the previous texture and texture co-ordinates, which without seeing your draw() loop, I'm assuming to be undefined.

Draw camera position in specific view port

Most of this code should be fairly self explanatory. I got an display function and my view port function. There are two modes which is 4 small view ports in the window or one large.
I got one camera which can be moved and if in 4 view port mode just 3 fixed angles. The thing is I want the free moving cameras position to be displayed in the 3 other view ports. I tried doing it by drawing spheres using opengl but the problem is that then the position gets draw in the free roaming camera too as it shows the same scene.
It doesn't have to be a sphere, just something simple that represents the cameras spacial position in these three other views.
Drawing the scene once with camera object showing for the three viewports, render to texture. Clear and draw scene without camera object render to texture and then stitch these together before actually drawing the scene seems like a lot o work for something that should be easy.
void display(int what)
{
if(what==5){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
camControll();}
if(what==1){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(75,15,-5,0,5,-5,0,1,0);}
if(what==2){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,110,0,0,0,0,1,0,0);}
if(what==3){
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, float(320) / float(240), 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
camControll();}
if(what==4){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(185,75,25,0,28,0,0,1,0);}
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/2, h/2);
glScissor(w/2,h/2,w/2,h/2);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, w / h, 0.1f, 300.0f);
display(2);
//////////////////////
////////////////////// bottom right -working
glViewport(w/2, 0, w/2, h/2);
glScissor(w/2,0,w/2,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/2);
glScissor(0,h/2,w/2,h/2);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, w / h, 0.1f, 300.0f);
display(4);
///////////////////////////
}
glDisable(GL_SCISSOR_TEST);
glMatrixMode(GL_MODELVIEW);
}
So what I basically need is to hide this object in specific viewport.
Why not make that single Sphere object (or the entity responsible for drawing the sphere) aware of the "current viewport" (which happens to be the what variable in your code) and let it be invisible if it's the given viewport?
This solution exactly corresponds to the logic involved here sounds both simple and correct.
A more general solution would be to give each "camera" a GUID and make it available for the entity responsible for drawing Cameras to check the GUID of the "camera" bound to the viewport which is being rendered at the moment. If they happen to be equal, ignore the camera object during this draw pass.
I think that should be easy if you would just draw point, because if you want to see point in viewport, its center have to be in viewport, otherwise nothing of it is displayed even if you set huge point size. Then you have 2 options to eliminate flickering effect (as when you put 2 squares in the very same possition they will flicker one over another). You can just move that point little behind camera, or use nonzero value for near clipping plane in glFrustrum/gluPerspective call.. and well if you update point position every time you move camera you have no chance of seeing that point in your moving camera and you can use single scene.
And second option, I don't know if you can update just single viewport, but maybe just setting scene, displaying it to moving camera, drawing camera position and displaying it for other 3 viewports should be easy also..
Why don't you draw the sphere behind the moving camera's near plane? That should ensure that the moving camera doesn't see the sphere at all, but its position is clearly marked for the others.

Display object in just a certain viewport

Hi I got 4 viewports and one large that I can switch between now I got an object namely the camera and the cameras target position that I show with rendering a sphere at those locations. I want to show the cameras position in 3 of my viewports but not in the last which is the camera display but at the moment I got an all or nothing scenario.
void display(int what)
{
if(what==5){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
camControll();}
if(what==1){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(75,15,-5,0,5,-5,0,1,0);}
if(what==2){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,110,0,0,0,0,1,0,0);}
if(what==3){
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, float(320) / float(240), 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
camControll();}
if(what==4){
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);
////ca.orbitYaw(0.05);
//ca.lookAt();
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
drawScene(); // scene that all views should render
drawCamera(); / camera position that only certain views should render
glutSwapBuffers();
}
I'm thinking that perhaps I could do one sweep for first the 3 viewports and then call glutSwapBuffers() and then do the other viewport without the camera position but some stuttering I previously had was traced to glutSwapBuffers() being called for each viewport so I guess there has to be another way only that I cant figure it out.
You have to render everything before swapping buffers.
As you do it - it is not going to work. Actually, it will work, but not you want.
EDIT
To render to a texture take a look into one of the links here.
After changing a view, render the image for the specific view to a texture. Then for the final image, set the final view and render all 3 textures. Only when the final image is rendered, swap buffers.
On the 2nd thought, it would be much better if you could set the vertices of all objects to render and render whole image in one pass.