While attempting to render a 3D object using OpenGL (and the GLFW library), the model experiences lots of flickering. Im reading the .obj file using a library that I've written on my own.
Written below is my render function:
Unfortunately, in order to understand how faces and vertices are being inputted, I will have to provide all my code, which is linked:
Zipped code along with executable and sample .obj:
Source
Im using .obj files from here to test the program. Right now, the program doesn't support normals and textures, which isnt an issue since most of the models on the site dont have them. Also, (right now) it only reads from "123.obj" so the file should'nt be named anything else. And it only accepts a single space, not more than that.
float render()
{
glfwSetTime(0.0f);
int win_width;
int win_height;
glfwGetWindowSize(&win_width, &win_height);
float win_aspect = (float)win_width / (float)win_height;
glViewport(0, 0, win_width, win_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90, win_aspect, 0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, 50.0, 0, 0, 0, 0.0, 1.0, 0.0);
glEnable(GL_DEPTH);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_NORMALIZE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glRotatef(angle , 0 , 1, 0);
glColor3f(0.0f, 0.0f, 0.0f);
int index = 0;
for(int a = 0; a < faces.size(); a++)
{
if(faces[a].vertices.size() == 3)
{
glBegin(GL_TRIANGLES);
}
else
{
glBegin(GL_QUADS);
}
for(int b = 0; b < faces[a].vertices.size(); b++)
{
index = faces[a].vertices[b];
glVertex3f(vertices[index].Dimensions[_x], vertices[index].Dimensions[_y], vertices[index].Dimensions[_z]);
}
glEnd();
}
glfwSwapBuffers();
return (float)glfwGetTime();
Here's the problem
gluPerspective(90, win_aspect, 0, 100.0);
You cannot set 0 as your nearclip, set it to something larger like 0.1, or 1.0.
gluPerspective(90, win_aspect, 1.0, 100.0);
With nearclip at 0, all of your depths get mapped to z = 1, and you get z fighting.
EDIT : if you're interested, here's some theory on perspective depth:
For a given distance from the camera x, your perspective transform outputs a certian depth value z. At the farclip, this value will be the maximum of 1, and at nearclip it will be 0.
Between these values however, relationship is not linear like you may expect. The curve looks similar to the following diagrams:
Diagram
When you go to the extreme of setting your nearclip to 0, your curve is heavily warped, so now all distances map to z = 1.
Because of all this, you should also try to keep the ratio far:near smaller than 10000:1
Related
I draw many lines to form a grid. I want to see the grid rotated on its X-axis, but I never get the intended result. I tried glRotatef and gluLookAt which does not work the way I want. Please see the pictures below.
this is the grid
this is how I want to see it
Edit: geez, posting the code here is also hard, lol, anyway here it is.
Edit2: removed, only leave the code that has issues.
Please find the code below, no matter how I set the gluLookAt, the grid result won't be in the perspective I want.
#include <GL/glut.h>
void display() {
...
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINES);
for (int i = 0; i < 720; i += 3)
{
glColor3f(0, 1, 1);
glVertex3f(linePoints[i], linePoints[i + 1], linePoints[i + 2]);
}
glEnd();
glFlush();
}
void init() {
glClearColor(0.0, 0.0, 0.0, 1.0);
glColor3f(1.0, 1.0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, 4.0 / 3.0, 1, 40);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, -2, 1.25, 0, 0, 0, 0, 1, 0);
}
Lets assume, that you have a grid in the xy plane of the world:
glColor3f(0, 1, 1);
glBegin(GL_LINES);
for (int i = 0; i <= 10; i ++)
{
// horizontal
glVertex3f(-50.0f + i*10.0f, -50.0f, 0.0f);
glVertex3f(-50.0f + i*10.0f, 50.0f, 0.0f);
// vertical
glVertex3f(-50.0f, -50.0f + i*10.0f, 0.0f);
glVertex3f( 50.0f, -50.0f + i*10.0f, 0.0f);
}
glEnd();
Ensure that the distance of to the far plane of the projection is large enough (see gluPerspective). All the geometry which is not in between the near an far plane of the Viewing frustum is clipped.
Further more ensure that the aspect ratio (4.0 / 3.0) match the ratio of the viewport rectangle (window).
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, 4.0 / 3.0, 1, 200);
For the use of gluLookAt, the up vector of the view has to be perpendicular to the grid. If the grid is arranged parallel to the xy plane, then the up vector is z axis (0, 0, 1).
The target (center) is the center of the grid (0, 0, 0).
The point of view (eye position) is ought to be above and in front of the grid, for instance (0, -55, 50). Note the point of view is used for a grid with the bottom left of (-50, -50, 0) and a top right of (50, 50, 0).
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, -55.0, 50.0, 0, 0, 0, 0, 0, 1);
Okay, so my program opens a file, reads in xyz-points, then draws a line strip out of it. I originally had this program written in SharpGL (implemnted as WPF window) and it worked, but not well due to using immediate mode, so I have moved onto OpenGL in C++. I have (somewhat) figured out VBO's and I now I am trying to add mouse functionality now. My problem is I can't move the picture with my mouse, I want to be able to click and 'drag' the picture. My mouseClickFunc and mouseMotion work (my cout statements execute), however it seems like my translate call is never being executed (i.e. the picture starts partially 'clipped' in the scene and I would like the ability to drag it and center it). I know this is a shot in the dark but I am really not sure what to do.
MotionFunc:
void mouseMotion(int x, int y)
{
if (moveable)
{
xMove += xTransform(x) - xTransform(xDown);
yMove += yTransform(y) - yTransform(yDown);
xDown = x;
yDown = y;
cout << yMove << "---" << xMove << endl;
glutSwapBuffers();
glutPostRedisplay();
}
}
Display Function:
void RenderFunction(void)
{
++FrameCount;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glOrtho(xMin - 1, xMax + 1, yMin - 1, yMax + 1, -diameter * zScale, diameter * zScale);
// Reset the modelview matrix.
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glTranslatef(xMove, -yMove, 0);
//glViewport((GLint)xMove*100, (GLint)-yMove*100, CurrentWidth, CurrentHeight);
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_LINE_STRIP, 0, 29000);
glPopMatrix();
glutSwapBuffers();
glutPostRedisplay();
}
I am sure there is more code that I need to show, this is just where I think the problem is. Any help would be greatly appreciated.
Here is a picture of a console output and the screen (OpenGL context) as I see it.
UPDATE: Updated my code. It looks like my coordinates are moving, but the picture is not if that makes sense. If you look at my output, if I keep 'dragging' the picture, you can see in the console that the variable xMove and yMove can get as large or small as they want, again translate is just never moving it.
You pop your matrix before drawing things, which resets the matrix to the state of last push matrix. Move glPopMatrix(); below draw call
You're popping the matrix before you call glDrawArrays(), so this naturally negates the effect of the translation. It also negates the glOrtho() call, but that should be issued on the projection matrix and not on the modelview matrix in the first place.
And, of course, the problem is in your code, and not in OpenGL.
In this code excerpt :
glLoadIdentity();
glPushMatrix();
glTranslatef(xMove, -yMove, 0);
//glViewport((GLint)xMove*100, (GLint)-yMove*100, CurrentWidth, CurrentHeight);
glOrtho(xMin - 1, xMax + 1, yMin - 1, yMax + 1, -diameter * zScale, diameter * zScale);
glPopMatrix();
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_LINE_STRIP, 0, 29000);
you are :
setting the identity as the view matrix
push it into the queue
modify it by glTranslate
pop it of the stack
render the image
Therefore, your translation is ignored.
This is correct operation :
glLoadIdentity();
glPushMatrix();
glTranslatef(xMove, -yMove, 0);
//glViewport((GLint)xMove*100, (GLint)-yMove*100, CurrentWidth, CurrentHeight);
glOrtho(xMin - 1, xMax + 1, yMin - 1, yMax + 1, -diameter * zScale, diameter * zScale);
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_LINE_STRIP, 0, 29000);
glPopMatrix();
You are multiplying projection before translation, remember to always read matrix transformation from bottome to top in OpenGL 1.1 which you should upgrade IMO. Another issue is that you are poping the matrix before drawing.
Correct code:
//glViewport((GLint)xMove*100, (GLint)-yMove*100, CurrentWidth, CurrentHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(xMin - 1, xMax + 1, yMin - 1, yMax + 1, -diameter * zScale, diameter * zScale);
// Reset the modelview matrix.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glTranslatef(xMove, -yMove, 0);
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_LINE_STRIP, 0, 29000);
glPopMatrix();
I am attempting to make a simple drawing using openGL. However, the depth buffer doesn't appear to be working.
Other people with a similar problem are typically doing one of two things wrong:
Not including glEnable(GL_DEPTH_TEST)
Bad clipping values
However, my code does not have either of these problems.
...
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gluPerspective(25.0,1.0,10.0,200.0);
// Set the camera location
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(20.0, 10.0, 50.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
// Enable depth test
glEnable(GL_DEPTH_TEST);
// Cull backfacing polygons
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE)
drawCoordinateAxis();
drawBox(5.0,2.0,5.0,0.8,0.0,0.0);
glTranslated(1.0,-1.0,1.0); //The box is 5x2x5, it is shifted 1 unit down and 1 in the x and z directions
drawBox(5.0,2.0,5.0,0.0,1.0,1.0);
...
When I execute my code, this is drawn. http://imgur.com/G9y41O1
Note that the blue box and the red box collide, so the red box should be covering part of the blue box.
The functions drawCoordinateAxis() and drawBox() just draw a few primitives, nothing fancy inside.
I am running this on Debian squeeze.
void reshape(GLint width, GLint height)
{
g_Width = width;
g_Height = height;
glViewport(0, 0, g_Width, g_Height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(65.0, (float)g_Width / g_Height, g_nearPlane, g_farPlane);
glMatrixMode(GL_MODELVIEW);
}
So set Matrix Mode to GL_PROJECTION first, then gluPerspective.... and then back to MODELVIEW mode.
I have the following code that takes snapshots to the framebuffer. I verified the framebuffer works correctly and the camera is facing the object correctly. I used to get pictures done correctly, but it was based on faulty code, using the wrong frustum. So I decided to start fresh (with the frustums).
The object is centered at the middle and is 32*32 blocks with each block 2*2, so 64 * 64.
My distance is 100 and my viewport is 128x256. My frustum is 1 to 1000.0.
I'm relatively new to Opengl so I'm having trouble understanding the concepts of frustrums and perspectives fully.
I do not get a picture at all.
saveGLState();
const int nrPics = 360 / DEGREES_BETWEEN_PICTURES;
for (int i = 0; i < nrPics; i++) {
catchFbo->bind();
glViewport(0, 0, PICTURE_WIDTH, PICTURE_HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float rat = PICTURE_WIDTH / PICTURE_HEIGHT;
glFrustum(- 1.0, + 1.0, - rat, + rat, 1.0, 1000.0);
gluPerspective(90.0f,rat,CAPT_FRUSTRUM_NEAR,CAPT_FRUSTRUM_FAR);
glColorMask(true, true, true, true);
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_MULTISAMPLE);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
drawScreenshot(i);
catchFbo->release();
QImage catchImage = catchFbo->toImage();
catchImage.save("object/test" + QString::number(i) + ".png");
}
glDisable(GL_MULTISAMPLE);
restoreGLState();
void VoxelEditor::saveGLState()
{
glPushAttrib(GL_ALL_ATTRIB_BITS);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
}
void VoxelEditor::restoreGLState()
{
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPopAttrib();
}
EDIT: I tried using only glFrustum or glPerspective. No luck.
You shouldn't use both glFrustum and gluProjection. They both are operations which setup the projection matrix, and if you use them together you'll multiply them together and get a weird result. Generally you'd just apply glFrustum OR gluProjection on an identity matrix, not both.
If that doesn't solve the problem, what are your values of NEAR, FAR, WIDTH, and HEIGHT?
Also make sure you're not doing integer divide for your screen ratio (a common bug).
I have an object moving back and forth on the x axis, however i cant position it further right along the x axis.
this is my code, how do i do it?
float moveRad = 0.0;
moveRad = moveBee * (PI/180.0);
moveBee += 0.1;
glPushMatrix();
glTranslatef(50.0 * sinf(moveRad), -100,0);
e[0] = new Platform(0, 0, 0, 40, 33, 40, 33, 00, textures[23], (50.0 * sinf(moveRad)), -100);
glPopMatrix();
Platform.cpp creates the object like so:
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex2f(x1,y1);
glTexCoord2f(0.0, 1.0); glVertex2f(x2,y2);
glTexCoord2f(1.0, 1.0); glVertex2f(x3,y3);
glTexCoord2f(1.0, 0.0); glVertex2f(x4,y4);
glEnd();
I have the feeling you suffer from a misconception of how OpenGL works. You wrote "Platform.cpp creates the object like so:" and in the code snippet before I can see you're creating the instance of some Plattform class surrounded by OpenGL matrix stack operations. I suspect you assumed that OpenGL would somehow "store" this "object". This is not how OpenGL works You're thinking in terms of a scene graph. OpenGL is not a scene graph.
OpenGL is a drawing API. The calls
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex2f(x1,y1);
glTexCoord2f(0.0, 1.0); glVertex2f(x2,y2);
glTexCoord2f(1.0, 1.0); glVertex2f(x3,y3);
glTexCoord2f(1.0, 0.0); glVertex2f(x4,y4);
glEnd();
draw a quad to the screen. Again: They draw it. After those commands have been issued they are gone and forgotten by OpenGL. The OpenGL transformation matrices are used for transforming the drawing commands' input data. But again there's no persistency. The drawing commands have to be issued for every frame drawn. I first thought I could rewrite some of your code, but it needs to be rewritten ground up, if I may say so.
The typical OpenGL program looks like this (I liberally omit all the class and type definitions and expect some common sense interpreting the variable, member and method names).
/* draw_scene is called on every iteration of the program main loop or
the drawing callback handler to update the screen */
void Scene::draw_scene(ScreenInfo si)
{
glViewport(si.viewport.x, si.viewport.y, si.viewport.width, si.viewport.height);
glClearColor(this->clear.r, this->clear.g, this->clear.b, this->clear.a);
glClearDepth(this->clear.d);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_TRUE);
glClear( (this->clear.color ? GL_COLOR_BUFFER_BIT) |
(this->clear.depth ? GL_DEPTH_BUFFER_BTT) );
std::list<SceneObjects*> objects_by_distance =
sort_objects_by_direction(scene->objects,
scene->active_camera->position
scene->active_camera->direction);
SceneObjects *closest_object = objects_by_distance.front();
SceneObjects *farthest_object = objects_by_distance.back();
float near_clip = max(NEAR_CLIP_LIMIT,
length(closest_object->position - scene->active_camera->position)
- closest_object->bounding_sphere.radius );
float far_clip = min(FAR_CLIP_LIMIT,
length(farthest_object->position - scene->active_camera->position)
+ farthest_object->bounding_sphere.radius );
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
switch( scene->projection.type ) {
case Projection::perspective: {
gluPerspective( scene->projection.fov,
(float)si.viewport.width/(float)si.viewport.height,
near_clip, far_clip);
} break;
case Projection::orthographic: {
float aspect = (float)si.viewport.width/(float)si.viewport.height;
glOrtho( -0.5 * scene->projection.size * aspect, 0.5 * scene->projection.size * aspect
-0.5 * scene->projection.size 0.5 * scene->projection.size );
} break;
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
/* I normally disregard using gluLookAt, but in this case I use it
to show as much as possible! */
gluLookAt( scene->active_camera->position.x, scene->active_camera->position.y, scene->active_camera->position.z,
scene->active_camera->position.x + scene->active_camera->direction.x,
scene->active_camera->position.y + scene->active_camera->direction.y,
scene->active_camera->position.z + scene->active_camera->direction.z,
scene->active_camera->up.x, scene->active_camera->up.y, scene->active_camera->up.z );
for_each(scene->objects.begin(), scene->objects.end(), draw_object)
}
void draw_object(SceneObject *object)
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(object->position.x, object->position.y, object->position.z);
glRotatef(object->rotation.axis.angle, object->rotation.axis.x, object->rotation.axis.y, object->rotation.axis.z);
GLfloat *(vertex_ptr[3][3]) = object->mesh->vertices;
GLuint *vertex_indices = object->mesh->face_vertex_indices;
#ifdef USE_IMMEDIATE_MODE
glBegin(GL_TRIANGLES);
for(int i = 0; i < object->mesh->face_count; i++) {
glNormalfv(&vertex_ptr[vertex_indices[i]][0]);
glTexCoord3fv(&vertex_ptr[vertex_indices[i]][1]);
glVertex3fv(&vertex_ptr[vertex_indices[i]][2]);
glNormalfv(&vertex_ptr[vertex_indices[i+1]][0]);
glTexCoord3fv(&vertex_ptr[vertex_indices[i+1]][1]);
glVertex3fv(&vertex_ptr[vertex_indices[i+1]][2]);
glNormalfv(&vertex_ptr[vertex_indices[i+2]][0]);
glTexCoord3fv(&vertex_ptr[vertex_indices[i+2]][1]);
glVertex3fv(&vertex_ptr[vertex_indices[i+2]][2]);
}
glEnd();
#else
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
/* This is direct vertex array mode.
A more modern approach is using Vertex Buffer Objects, which reused this
API, but adds further function calls. */
glNormalPointer(GL_FLOAT, 3*3*sizeof(GLfloat), &vertex_ptr[0][0]);
glTexCoordPointer(3, GL_FLOAT, 3*3*sizeof(GLfloat), &vertex_ptr[0][1]);
glVertexPointer(3, GL_FLOAT, 3*3*sizeof(GLfloat), &vertex_ptr[0][2]);
glDrawElements(GL_TRIANGLES, object->mesh->face_count*3, GL_UNSIGNED_INT, vertex_indices);
#endif
glPopMatrix();
}
This is the most basic way use OpenGL seriously. I wrote it in this detail to give you the idea how to use it, and how it works.
Why don't you adjust the x-axis scaling in your call to glTranslatef?
glTranslatef(amplitude * sinf(moveRad), -100,0);
I have a feeling you don't know exactly what your code is doing (correct me if I'm wrong). If you want to move it to the right just add a number in here.
glTranslatef(50.0 * sinf(moveRad) + 30, -100,0);
I'll update my answer if neccesary.
I think your problem is the '50.0 * sinf(moveRad)' - that will oscilate between -50 and 50. Try adding a value instead of or as well as multiplying it.