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);
Related
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().
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
I am trying to create two viewports in my window: a main, full screen view and a smaller view in the upper left corner. I've looked the issue up and looked at the solutions: I am using glScissor() and glViewport(), clearing my depth buffer bit, enabling my depth buffer bit, and rendering only once (after a for loop). But clearly, I am missing something. Here is my code. Thank you in advance.
Edit:
link to screenshots: http://imgur[dot]com/a/sdoUy
Basically, the upper left mini viewport flickers, disappearing and reappearing very quickly.
void viewports() {
float width = wWidth;
float height = wHeight;
for (int i = 0; i < 2; i++) {
glClearColor(.392,.584,.929,0.0f);
if (i == 0) {
//main view
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0,0,(GLsizei)width,(GLsizei)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60,(GLfloat)width/(GLfloat)height,1.0,100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
keyOp();
camera();
} else if (i == 1) {
glScissor(0,height - height/3,(GLsizei)height/3,(GLsizei)height/3);
glEnable(GL_SCISSOR_TEST);
glClear(GL_DEPTH_BUFFER_BIT);
glViewport(0,height - height/3,(GLsizei)height/3,(GLsizei)height/3);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60,1,1.0,100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,40,-15,0,-1,-15,1,0,0);
glDisable(GL_SCISSOR_TEST);
}
renderScene();
}
}
Don't call glutSwapBuffers in renderscene. You call renderscene twice per frame (for i==0 and i==1), so you're drawing main screen, swap, draw minimap, swap, repeat.
You need to draw both main and minimap, and then swap.
Also don't bother calling glClearColor so many times, you only need to call it once at init.
Not sure if it will help with your flickering problem but I notice you have written:
glClearColor(.392,.584,929,0.0f);
With the third parameter being 929 instead of what I assume you wanted, .929
I hope you can help me with a little problem...
I know how to draw a circle, that's not a problem - here is the code in c#
void DrawEllipse()
{
GL.Color3(0.5, 0.6, 0.2);
float x, y, z;
double t;
GL.Begin(BeginMode.Points);
for (t = 0; t <= 360; t += 0.25)
{
x = (float)(3*Math.Sin(t));
y = (float)(3*Math.Cos(t));
z = (float)0;
GL.Vertex3(x, y, z);
}
GL.End();
}
But there is a problem - when I Rotate 'Gl.Rotate(angle, axis)' and then redraw a circle - yeah, it's still circle in the 3D, but I want a circle in the screen - I mean static circle which is not rotating with 3D object in it... Is that possible? How to repair the code?
Are you trying to draw a 2D circle on top of a 3D scene to create a HUD or similar? If you are then you should research 2D OpenGL, glOrtho and using multiple viewports in a scene. There is a discussion around this here:
http://www.gamedev.net/topic/388298-opengl-hud/
Just draw it at a position before the camera!
Use pushMatrix() and popMatrix().
Or you can draw the other things between pushMatrix() and popMatrix(). Then draw the circle.
HUD (heads-up display): http://en.wikipedia.org/wiki/HUD_(video_gaming)
void setupScene ()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// set the perspective
glFrustum(...) // or glu's perspective
}
void loop ()
{
// main scene
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport (...)
// push the camera position into GL_MODELVIEW
// (i.e. the inverse matrix of its object position)
// draw your normal 3D objects
// switch to 2D projection (for the HUD)
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(....)
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// draw the objects onto the HUD
// switch back to 3d projection (i.e. restore GL_PROJECTION)
// glEnable (GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
// glMatrixMode(GL_MODELVIEW);
// swap buffers
}
The commented code is optional, depending on what you're gonna do in the end. Take it as hints.
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.