I'm trying to get world coordinates from any of my rendered vertices in OpenGL window (I prefer to use GLUT library). The problem is when I'm calling glReadPixels function to get depth value of a vertex, it always returns a 1 value, when I'm clicking my mouse anywhere.
I am stuck on this point, have already read a ton of articles, but didn't get any answer.
Here is my code:
display function
void display(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH | GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDepthRange(200, 2000);
//here i put some glBegins and glEnds
glutSwapBuffers();}
main function
int main(int argc, char **argv){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(1280, 720);
glutInitWindowPosition(50, 86);
glutCreateWindow("2D correlation function");
glClearColor(1,1,1,1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glFrustum(-150, 150, -150, 150, 200, 2000);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutKeyboardFunc(keyboard);
gluLookAt(200,400,200,0,0.0,0.0,0.0,0.0,1.0);
glScalef(0.4, 0.4, 0.4);
glutDisplayFunc(display);
timer();
glutMainLoop();
return 0;}
mouse clicking function
void mouse(int button, int state, int x, int y){
GLdouble objX, objY, objZ;
GLdouble matModelView[16], matProjection[16];
GLint viewport[4];
glGetDoublev(GL_MODELVIEW_MATRIX, matModelView);
glGetDoublev(GL_PROJECTION_MATRIX, matProjection);
glGetIntegerv(GL_VIEWPORT, viewport);
GLfloat winX = x;
GLfloat winY = viewport[3] - y;
GLfloat winZ = 0;
glReadPixels(winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);
cout << winX << " " << winY << " " << winZ << " " <<endl;
gluUnProject(winX, winY, winZ, matModelView, matProjection, viewport, &objX, &objY, &objZ);
cout << objX << " " << objY << " " << objZ << " " <<endl;}
Because of this, my world coordinates are displayed incorrectly:
example of mouse clicking
another example
I think i'm doing something wrong in display procedure
The parameter to glEnable has to be a single enumerator constant. The parameter is not a bit field.
The following is not valid and will generate a GL_INVALID_ENUM error, which can be detected by glGetError or Debug Output:
glEnable(GL_DEPTH | GL_DEPTH_TEST);
It has to be
glEnable(GL_DEPTH_TEST);
Anyway GL_DEPTH is not a valid parameter for glEnable, but it is possibly an parameter to glCopyPixels.
Note, the value of the enumerator constant GL_DEPTH_TEST is 0x0B71 and the value of GL_DEPTH is 0x1801. A binary or (|) operation of the both constants won't make any sense.
Because of this the depth test has never been enabled and nothing was written to the depth buffer.
Further note, that the values which are accepted for the depth range glDepthRange have to be in the range [0, 1]. The values which are passed to the glDepthRange are both clamped to this range before they are accepted.
This means, that
glDepthRange(200, 2000);
is equal to
glDepthRange(1, 1);
so the depth range is [1, 1] and all values returned by glReadPixels are 1, too.
Skip glDepthRange(200, 2000); to solve the issue.
glGetDoublev(GL_MODELVIEW_MATRIX, matModelView) gets the current model view matrix from the GL_MODELVIEW matrix stack.
glGetDoublev(GL_PROJECTION_MATRIX, matProjection) gets the current projection matrix from the GL_PROJECTION matrix stack.
So you should put the projection matrix on the GL_PROJECTION matrix stack and the view matrix on the GL_MODELVIEW matrix stack (see glMatrixMode):
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-150, 150, -150, 150, 200, 2000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(200,400,200,0,0.0,0.0,0.0,0.0,1.0);
Have you tried passing GLUT_DEPTH to glutInitDisplayMode?
According to GLUT documentation that flag is needed to create a depth buffer.
Related
I am using QGLWidget and QtOpenGL to display my point clouds and glReadPixels and gluUnProject to pick a point from a poiint cloud. The problem is that the glReadPixels does not seem to pick pixels of my points.
I've tried to use different point sizes as well as different block sizes in glReadPixels but the "ray" seems to go through the points. Im wondering if I need to calculate the closes point to the ray since its almost impossible to click right on the point.
The points are drawn with (just and example of a point in origon )
`
GLuint list = glGenLists(1);
glNewList(list, GL_COMPILE);
glPointSize(10.0f);
glBegin(GL_POINTS);
glColor3f(0.0f, 255.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glEnd();
glEndList();
updateScene();`
The point picking is done by the getObejctCoords function below.
`
void pclView::getObjectCoords(QMouseEvent *event)
GLdouble projection[16];
GLdouble modelView[16];
GLint viewPort[4];
GLdouble obj_coords0, obj_coords1, obj_coords2;
GLdouble pt_coords0, pt_coords1, pt_coords2;
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glGetDoublev(GL_MODELVIEW_MATRIX, modelView);
glGetIntegerv(GL_VIEWPORT, viewPort);
// Window parameters
winX = event->pos().x();
winY = viewPort[3] - event->pos().y();
// get Window Z
glReadPixels( event->pos().x(), int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);
// Unproject 2D click to 3D location
gluUnProject( winX, winY, winZ, modelView, projection, viewPort, &obj_coords0, &obj_coords1, &obj_coords2);
std::cout << "x: " << obj_coords0;
std::cout << " y: " << obj_coords1;
std::cout << " z: " << obj_coords2 << std::endl;
`
At camera position (0,0,-50) rotation: (0, 0) (By clicking at the point at almost at origon (but on the point ) the function produces the following output
´ x: 0 y: -0.578724 z: -950 `
And the actual result should (as I've understood it) should be something like
x: 0 y: -0.578724 z: -0
I made a simple OpenGL program that draws a 2D texture to the screen. When you resize the window, it doesn't adjust properly, so to fix that, I would just run the projection matrix code again:
if (windowSizeChange)
{
std::cout << "Window resized." << std::endl;
std::cout << windowWidth << " " << windowHeight << std::endl;
windowSizeChange = false;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, windowWidth, windowHeight, 0.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
However, running this code warps the image. To my understanding, to make it so I can draw 2D-like on the screen, my texture is drawn using an orthographic projection matrix which means there is a plane that is "parallel" with the window port or something like that which I draw on. When I try to re-make it to accommodate for the new window size, it doesn't adjust properly. What's going wrong with this code?
In your code you're changing the ortho matrix, but you also need to change the glViewport:
if (windowSizeChange)
{
glViewport(0, 0, windowWidth, windowHeight); // <-- Add this
std::cout << "Window resized." << std::endl;
std::cout << windowWidth << " " << windowHeight << std::endl;
windowSizeChange = false;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, windowWidth, windowHeight, 0.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
Orthographic matrices are, like you said, just a matrix that in this case is parallel to the screen. When we call glOrtho, it changes the size of the matrix we're working with, and glViewport tells openGL the size of the viewport (in this case, our window) we're working with. You'll generally want glOrtho and glViewport to be the same dimensions
When the size of the window and the framebuffer has been changed, then you have to adjust the viewport rectangle.
The viewport rectangle can be set by glViewport and specifies how the normalized device coordinates are mapped to window coordinates. It defines the area of the framebuffer, where the normalized device coordinates from (-1, -1) to (1, 1) are mapped to.
glViewport(0, 0, windowWidth, windowHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, windowWidth, windowHeight, 0.0, -1.0, 1.0);
I want to draw a model of a chair that I exported from 3ds max as a txt file. I read the file and display it in OpenGL (using Visual Studio -> C++). My problem is that I have to multiplicate the chair many times (10). I did try to multiplicate it twice but it does not work. The program crashes with these "Program is not responding" Windows errors. I have a main class that calls all of the nessessery methods from CDrawModel like that:
CDrawModel mModel;
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB);
glutInitWindowSize( 1000, 600 );
glutInitWindowPosition(100, 100);
glutCreateWindow("Georgi Koemdzhiev - 1306794");
glutKeyboardFunc(KeyResponse);
glutDisplayFunc(DrawGLScene);
glutReshapeFunc(ReSizeGLScene);
mModel.initGL();
glutMainLoop();
}
void DrawGLScene(void) {
mModel.myDrawGLScene();
}
GLvoid ReSizeGLScene(GLsizei fwidth, GLsizei fheight) {
mModel.MyReSizeGLScene(fwidth, fheight);
}
CDrawModal initialises an object of type CPolygonMesh which handles the reading from the file and drawing on the screen functionality. I know my code works since I am getting my modal drawn on the screen:
this is my CDrawModal class:
oid CDrawModel::initGL(void) {
glClearColor(1.0, 1.0, 1.0, 1.0);
near = 1.0;
far = 1000.0;
height = 1.5;
glCullFace(GL_BACK); // don’t draw back facing faces
glEnable(GL_CULL_FACE); // enable face culling
glPolygonMode(GL_FRONT, GL_LINE); // select front polygons and draw edges only
}
void CDrawModel::MyReSizeGLScene(int fwidth, int fheight) // Resize And Initialize The GL Window{
// Store window size so it can be accessed in myDrawGLScene()
wWidth = fwidth;
wHeight = fheight;
// Set fovy so that the viewing frustum has the specified height at the
// near clipping plane
fovy = (360 / PI) * atan(height / (2.0 * near));
// Calculate the aspect ratio of the VIEWPORT
// so that we can set the camera’s aspect ratio to the same value
aspect_ratio = (double)fwidth / (double)fheight;
glMatrixMode(GL_PROJECTION); // Select The Projection Stack
glLoadIdentity();
/* void glOrtho( GLdouble left,
GLdouble right,
GLdouble bottom,
GLdouble top,
GLdouble nearVal,
GLdouble farVal);*/
gluPerspective(90, aspect_ratio, near, far); // perspective view
//glOrtho(-130.0,130.0,-130.0,130.0,near,far);
glViewport(0, 0, wWidth, wHeight); // Viewport fills the window
// Print values of parameters
cout << fixed; // Use fixed-point notation
cout.precision(3); // Number of digits after the decimal point
cout << "fovy = " << fovy << endl;
cout << "aspect_ratio = " << aspect_ratio << endl;
cout << "near = " << near << endl;
cout << "far = " << far << endl;
}
void CDrawModel::myDrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the drawing area
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -200);
mesh.draw_model();
glutSwapBuffers(); // Needed if we're running an animation
glFlush();
}
What I need to do in order to draw it twice.This is my drawModal method in CPolugonMesh:
void CPolygonMesh::draw_model(void){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0, 0.0, 0.0); // draw red things
glBegin(GL_TRIANGLES);
for (int i = 0; i < Mesh_NumFaces; i++) {
// Look up the coordinates of each vertex
// in vertex_list[]
glVertex3fv(vertex_list[ face_list[i][0] ]);
glVertex3fv(vertex_list[ face_list[i][1] ]);
glVertex3fv(vertex_list[ face_list[i][2] ]);
//cout << "Drawing face: " << i << endl;
}
glEnd();
}
Your CPolygonMesh::draw_model(void) method actually clears the screen each time you draw a model, so only the last call will leave anything on the screen.
The line
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
is totally wrong there. You already do clear the screen at the beginning of your frame.
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'm using a vertex with three floats for the position (XYZ) and three other for the color (RGB):
XYZ RGB
XYZ RGB
...
I'm currently trying to plot a red triangle. Unfortunately I end up with a white window. I think there's a problem with the stride but I can't figure it out. I've tried many values for the stride and the size, still it doesn't seem to display anything.
//main.cpp
#include "data.h"
GLuint ID;
int size,el_size;
void init(){
vector<float>data_vector(18);
data_vector[0]=0; //x
data_vector[1]=0; //y
data_vector[2]=0; //z
data_vector[3]=1;
data_vector[4]=0;
data_vector[5]=0;
data_vector[6]=1; //x
data_vector[7]=0; //y
data_vector[8]=0; //z
data_vector[9]=1;
data_vector[10]=0;
data_vector[11]=0;
data_vector[12]=0; //x
data_vector[13]=1; //y
data_vector[14]=0; //z
data_vector[15]=1;
data_vector[16]=0;
data_vector[17]=0;
size=data_vector.size();
// Init GLEW
if ( glewInit() != GLEW_OK ){
cerr << "Failed to initialize GLEW." << endl;
exit(-1);
}
if ( !glewIsSupported("GL_VERSION_1_5") && !glewIsSupported( "GL_ARB_vertex_buffer_object" ) ){
cerr << "ARB_vertex_buffer_object not supported!" << endl;
exit(-2);
}
glOrtho(-1, 1,1,-1, -5.0f, 5.0f);
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glShadeModel(GL_SMOOTH);
glEnableClientState(GL_VERTEX_ARRAY);
glGenBuffers(1,&ID);
glBindBuffer(GL_ARRAY_BUFFER, ID);
glBufferData(GL_ARRAY_BUFFER,size*sizeof(float), &data_vector[0], GL_STATIC_DRAW);
el_size=3*sizeof(data_vector[0]);
}
void reshape(int w, int h){
cout<<"reshape"<<endl;
glViewport(0,0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0f, (GLdouble) w, 0.0f, (GLdouble) h);
}
void display(){
cout<<"display"<<endl;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindBuffer(GL_ARRAY_BUFFER, ID);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, el_size, 0);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3,GL_FLOAT, el_size,(void*)(el_size));
glDrawArrays(GL_TRIANGLES,0,size/6);
glFlush();
}
int main(int argc, char **argv){
cout<<"main"<<endl;
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500,500);
glutInitWindowPosition(300,300);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
// glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
You do appear to be using the incorrect stride. The stride should be the distance from the start of one vertex to the start of the next vertex, or in your case 6 floats.
You've set the stride as el_size, which is only 3 floats.
Also take care that your resize function is using an ortho matrix from 0 to screen width, and your init function is setting it from -1 to 1. If resize ever gets called your scene will become radically different.
One problem I see is that call to glOrtho in the init function. Whatever you intend to do, this surely doesn't do what you want. As a general rule, put all drawing state related commands only into the display function, nowhere else. Setting transformation matrices (and the viewport) should happen there. Doing so saves a lot of headaches later.
The other problem is, that the stride you define is to short. The stride is the distance from vertex to vertex in an interlaced array, not the length of a single attribute. el_size is calculated wrong.