C++ OpenGL flickering Issues - c++

Im having a Problem, where when I just render 1 Cube it's all okay, but if I add multiple Cubes all of them start flickering.. might be because they are intefering each other but im using double dubbers so it shouldn't be that. here the code of the render method
for (std::vector<Entity *>::iterator iterator = entityArray->begin(); iterator != entityArray->end(); iterator++) {
Entity *entity = *iterator;
if (entity->getVertexBuffer() != NULL) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(entity->getVertexBuffer()->getShader()->getProgramHandle());
glLoadIdentity();
gluLookAt(_currentCamera->getPosition().x,
_currentCamera->getPosition().y,
_currentCamera->getPosition().z,
_currentCamera->getEyeVector().x,
_currentCamera->getEyeVector().y,
_currentCamera->getEyeVector().z,
_currentCamera->getUpVector().x,
_currentCamera->getUpVector().y,
_currentCamera->getUpVector().z);
glTranslatef(entity->getPosition().x, entity->getPosition().y, entity->getPosition().z);
glRotatef(entity->getRotation().x, 0.0f, 0.0f, 1.0f);
glRotatef(entity->getRotation().y, 0.0f, 1.0f, 0.0f);
glRotatef(entity->getRotation().z, 1.0f, 0.0f, 0.0f);
glScalef(entity->getScale().x, entity->getScale().y, entity->getScale().z);
glUniform4f(entity->getVertexBuffer()->getShader()->get_uColor(),
entity->getVertexBuffer()->getShaderData()->get_uColorValue().x,
entity->getVertexBuffer()->getShaderData()->get_uColorValue().y,
entity->getVertexBuffer()->getShaderData()->get_uColorValue().z,
entity->getVertexBuffer()->getShaderData()->get_uColorValue().w);
glUniform3f(entity->getVertexBuffer()->getShader()->get_uLightPosition(),
entity->getVertexBuffer()->getShaderData()->get_uLightPosition().x,
entity->getVertexBuffer()->getShaderData()->get_uLightPosition().y,
entity->getVertexBuffer()->getShaderData()->get_uLightPosition().z);
entity->getVertexBuffer()->configureVertexAttributes();
entity->getVertexBuffer()->renderVertexBuffer();
glfwSwapBuffers(_window);
glfwPollEvents();
}
}

Clear first, draw all cubes, then swap, like this:
glClear();
for (cube in cubes) { draw(cube); }
glfwSwapBuffers(_window);
glfwPollEvents();
That should solve it.

You're calling glClear and glSwapBuffers in the inner loop. So for everything you draw in the inner loop, it clears the picture, draws the thing (a single cube) swaps and then does the same for the next element in the array.
Everything that does not draw a cube must go outside of that loop.

Related

Adding gluPerspective and gluLookAt made my drawing disappear

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)

How to get the whole scene rotate around itself? (my code has a little bug which just lets the objects rotate around themselves)

What must be changed to let me see the impression of flying around the whole fixed scene? My current code just lets me look from a fixed viewpoint at objects each one rotating around itself. Enabling glLoadIdentity() just stops their rotation. Note that 3dWidget::paintGL() is permanently called by a timer every 20ms.
void 3dWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glTranslatef(0.5f, 0.5f, 0.5f);
glRotatef(3.0f, 1.0f, 1.0f, 1.0f);
glTranslatef(-0.5f, -0.5f, -0.5f);
glPushMatrix();
//glLoadIdentity();
for (int i = 0; i < m_cubes.count(); i++) {
m_cubes[i]->render();
}
glPopMatrix();
}
void Cube::render() {
glTranslatef(m_x, m_y, m_z); // local position of this object
glCallList(m_cubeId); // render code is in createRenderCode()
glTranslatef(-m_x, -m_y, -m_z);
}
void Cube::createRenderCode(int cubeId) {
m_cubeId = cubeId;
glVertexPointer(3, GL_FLOAT, 0, m_pCubePoints);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, m_pCubeColors);
glNewList(m_cubeId, GL_COMPILE);
{
glEnableClientState(GL_COLOR_ARRAY);
glDrawArrays(GL_TRIANGLE_STRIP, 0, m_numPoints);
glDisableClientState(GL_COLOR_ARRAY);
}
glEndList();
}
void 3dWidget::init(int w, int h)
{
...
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float aspect = w/(float)(h ? h : 1);
glFrustum(-aspect, aspect, -1, 1, 10, 100);
glTranslatef(0., 0., -12);
glMatrixMode(GL_MODELVIEW);
}
EDIT: It seems it's important to know that 2 cubes are created with the following 3D position coordinates (m_x, m_y, m_z):
void 3dWidget::createScene()
{
Cube* pCube = new Cube;
pCube->create(0.5 /*size*/, -0.5 /*m_x*/, -0.5 /*m_y*/, -0.5 /*m_z*/);
pCube = new Cube;
pCube->create(0.5 /*size*/, +0.5 /*m_x*/, +0.5 /*m_y*/, +0.5 /*m_z*/);
}
Use gluLookAt to position the camera. You apply it to the modelview matrix before any object transforms.
Obviously, you'll have to figure out a path for the camera to follow. That's up you and how you want the "flight" to proceed.
EDIT: Just to be clear, there's no camera concept, as such, in OpenGL. gluLookAt is just another transform that (when applied to the modelview matrix) has the effect of placing a camera at the prescribed location.
If you really are just trying to rotate the world, your code seems to perform the transforms in a reasonable order. I can't see why your objects rotate around themselves rather than as a group. It might help to present a SSCCE using glut.
Now I've found the reason by myself. It works as soon as I change method paintGL() to
void 3dWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
#if 0 // not working
glTranslatef(0.5f, 0.5f, 0.5f);
glRotatef(3.0f, 1.0f, 1.0f, 1.0f);
glTranslatef(-0.5f, -0.5f, -0.5f);
#else // this works properly, they rotate horizontally around (0,0,0)
glRotatef(3.0f, 0.0f, 1.0f, 0.0f);
#endif
for (int i = 0; i < m_cubes.count(); i++) {
m_cubes[i]->render();
}
}
I don't get it exactly why, but it obviously appeared that some transformations had compensated in a way that the objects just rotate around itself. Thanks for your help anyway.
I think it's always better to let the scene rotate than to move by gluLookAt (beside the issue that finding the right formula for the angle of view is more difficult).

OpenGL wireframe from x,y, and z text file

I have a file with 3 coordinates and I can render it as points, lines, triangles , or any primitive.
I want to construct a wireframe model of this file, what should I change or add to view it as a wireframe
sample:
void draw()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glOrtho(-50.0,50.0,-50.0,50.0,-50.0,50.0);
glColor4f(1.0f,1.0f,1.0f,1.0f);
glPointSize(3);
glLineWidth(3);
glColor3f(1.0f,1.0f,1.0f);
for(int i=0; i<points; i++)
{
glBegin(GL_LINES);
glNormal3f(0.0f, 0.0f, 1.0f);
glVertex3d(vList[i][0],vList[i][1],vList[i][2]);
glEnd();
}
}
This will never produce any output:
for(int i=0; i<points; i++)
{
glBegin(GL_LINES);
glNormal3f(0.0f, 0.0f, 1.0f);
glVertex3d(vList[i][0],vList[i][1],vList[i][2]);
glEnd();
}
GL_LINES requires two vertices per line, and you're only providing one between your glBegin and glEnd calls.
glBegin and glEnd should bookend particular pieces of geometry, not individual vertices.
However, simply moving the calls out of the for loop won't fix your problem:
glBegin(GL_LINES);
for(int i=0; i<points; i++)
{
glNormal3f(0.0f, 0.0f, 1.0f);
glVertex3d(vList[i][0],vList[i][1],vList[i][2]);
}
glEnd();
This would almost produce what you want, but will actually show every OTHER line, because it's treating each pair you send in as one line. So it will draw a line between point 1 and 2, and then between 3 and 4. This is because GL_LINES means "interpret each pair I send in as a completely new line, unrelated to the previous vertices.
What you really want is this:
glBegin(GL_LINE_STRIP);
for(int i=0; i<points; i++)
{
glNormal3f(0.0f, 0.0f, 1.0f);
glVertex3d(vList[i][0],vList[i][1],vList[i][2]);
}
glEnd();
Using GL_LINE_STRIP instructs OpenGL that it should take the first two vertices and draw a line, and then for each new vertex, draw another line from the end of the last line.
Caveat
All this assumes your file is actually designed to produce lines like this. Most 3D file formats include both vertices and indices. The vertices tell you the 3D positions, but the indices tell you which points should be connected to which. However, since this looks like a sort of homework assignment, I'm going to assume that the file is as described, a simple list of X-Y-Z coordinates that should be connected in sequence.

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.

Begun learning OpenGL, need help figuring out this problem

So I have begun learning OpenGL, reading from the book "OpenGL Super Bible 5 ed.". It's explains things really well, and I have been able to create my first gl program myself! Just something simple, a rotating 3d pyramid.
Now for some reason one of the faces are not rendering. I checked the vertecies (plotted it on paper first) and it seemed to be right. Found out if I changed the shader to draw a line loop, it would render. However it would not render a triangle. Can anyone explain why?
void setupRC()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
shaderManager.InitializeStockShaders();
M3DVector3f vVerts1[] = {-0.5f,0.0f,-0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,-0.5f};
M3DVector3f vVerts2[] = {-0.5f,0.0f,-0.5f,0.0f,0.5f,0.0f,-0.5f,0.0f,0.5f};
M3DVector3f vVerts3[] = {-0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,0.5f};
M3DVector3f vVerts4[] = {0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,-0.5f};
triangleBatch1.Begin(GL_LINE_LOOP, 3);
triangleBatch1.CopyVertexData3f(vVerts1);
triangleBatch1.End();
triangleBatch2.Begin(GL_TRIANGLES, 3);
triangleBatch2.CopyVertexData3f(vVerts2);
triangleBatch2.End();
triangleBatch3.Begin(GL_TRIANGLES, 3);
triangleBatch3.CopyVertexData3f(vVerts3);
triangleBatch3.End();
triangleBatch4.Begin(GL_TRIANGLES, 3);
triangleBatch4.CopyVertexData3f(vVerts4);
triangleBatch4.End();
glEnable(GL_CULL_FACE);
}
float rot = 1;
void renderScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
GLfloat vRed[] = {1.0f, 0.0f, 0.0f, 0.5f};
GLfloat vBlue[] = {0.0f, 1.0f, 0.0f, 0.5f};
GLfloat vGreen[] = {0.0f, 0.0f, 1.0f, 0.5f};
GLfloat vWhite[] = {1.0f, 1.0f, 1.0f, 0.5f};
M3DMatrix44f transformMatrix;
if (rot >= 360)
rot = 0;
else
rot = rot + 1;
m3dRotationMatrix44(transformMatrix,m3dDegToRad(rot),0.0f,1.0f,0.0f);
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, vRed);
triangleBatch1.Draw();
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, vBlue);
triangleBatch2.Draw();
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, vGreen);
triangleBatch3.Draw();
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, vWhite);
triangleBatch4.Draw();
glutSwapBuffers();
glutPostRedisplay();
Sleep(10);
}
You've most likely defined the vertices in clockwise order for the triangle that isn't showing, and in counterclockwise order (normally the default) for those that are. Clockwise winding essentially creates an inward facing normal and thus OpenGL won't bother to render it when culling is enabled.
The easiest way to check this is to set glCullFace(GL_FRONT)--that should toggle it so you see the missing triangle and no longer see the other three.
The only thing I see that affects polygons here is glEnable(GL_CULL_FACE);.
You shouldn't have that, because if you plot your vertices backwards, the polygon won't render.
Remove it or actually call glDisable(GL_CULL_FACE); to be sure.
In your case, it's not likely that you want to draw a polygon that you can see from one side only.