i tried almost everything, copied a lot of codes from different forums but nothing works. What the issue.
I have loop where i draw object from vector. i want to create object where user clicked in 3D space. This is code where i'm trying to do this:
if(glfwGetKey( window, GLFW_KEY_F ) == GLFW_PRESS && glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT)==GLFW_PRESS && check==false) {
double x, y;
glfwGetCursorPos(window, &x, &y);
double mvmatrix[16];
double projmatrix[16];
int viewport[4];
double dX, dY, dZ, dClickY; // glUnProject uses doubles, but I'm using floats for these 3D vectors
glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);
glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);
dClickY = double (1080 - y); // OpenGL renders with (0,0) on bottom, mouse reports with (0,0) on top
gluUnProject ((double) x, dClickY, 0.0, mvmatrix, projmatrix, viewport, &dX, &dY, &dZ);
bricks.push_back(new Cube(0,0,0,1110));
bricks[bricks.size()-1]->translate(dX, dY, dZ);
check=true;
}
After that operation dX, dY and dZ is -1.#IND. What am i doing wrong?
Related
I'm trying to move objects with the mouse using the Gluunproject method with openGL 2.1 , but i'm really struggling here; here's the code i wrote :
int viewport[4];
double modelview[16],
projection[16],
X1, Y1, Z1;
double realY;
GLfloat depth[2];
for(_compt=_OjebctScene.begin();_compt!=_OjebctScene.end();_compt++)
{
if ((*_compt)->IsSelected())
{
GLdouble mouseX=event.x;
GLdouble mouseY=event.y;
glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
realY = viewport[3] - (GLint) mouseY - 1;
glReadPixels(mouseX, realY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, depth);
gluUnProject(mouseX, realY, 0, modelview, projection, viewport, &X1, &Y1, &Z1);
(*_compt)->setX(X1);
(*_compt)->setY(Y1);
(*_compt)->setZ(Z1);
}
}
I use a loop to check all the objects on the scene (I've pushed them into a vector) , then when i find the selected object , i try to move it using the mouse.
I then set the coordinates of my object to the position of the mouse in the 3D space (X1 , Y1 , Z1); but this doesn't really work.
I think I've fixed it just by passing the depth[0] to the gluunproject method.
here's what I've done , change this :
gluUnProject(mouseX, realY, 0, modelview, projection, viewport, &X1, &Y1, &Z1);
by this :
gluUnProject(mouseX, realY,depth[0], modelview, projection, viewport, &X1, &Y1, &Z1);
I don't understand what this means though , if someone could explain it to me it would be nice.
I am trying to get the coordinates that the user clicks on on the plane y=0
I'm doing this by unprojecting the mouse coordinates to get the world coordinates on the near and far planes then using linear interpolation to find the coordinates on the plane but it's not giving me the correct coordinates.
My unprojection code:
int viewport[4];
double modelview[16];
double projection[16];
glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
double x, y, z;
//x_ and y_ are the x and y coordinates of the mouse
gluUnProject(x_, viewport[3] - y_, 0.0, modelview, projection, viewport, &x, &y, &z);
near.x = x;
near.y = y;
near.z = z;
gluUnProject(x_, viewport[3] - y_, 100.0, modelview, projection, viewport, &x, &y, &z);
far.x = x;
far.y = y;
far.z = z;
float t = -near.y / (far.y - near.y);
target_.y = 0.0f;
target_.x = near.x - t * (far.x - near.x);
target_.z = near.z - t * (far.z - near.z);
std::cout << target_ << std::endl;
but this always outputs:
x: a value between +-1 which seems to have a correlation to the click position just normalized even though I'm not normalizing anywhere
y: 0
z: -2
which I can't make sense of
Edit
Sorry, the error was me doing the unprojections before my transformations which you can't tell from the above code. I have solved it now.
Sorry, the error was me doing the unprojections before my transformations which you can't tell from the above code.
To zoom into the mouse position I was using:
glTranslatef(current.ScalePoint.x,current.ScalePoint.y,0);
glScalef(current.ScaleFactor,current.ScaleFactor,current.ScaleFactor);
glTranslatef(-current.ScalePoint.x,-current.ScalePoint.y,0);
so basically I translate to the new origin (the mouse position) then scale by the current scale factor, then translate back.
This kind of works generally well, but it can be a bit buggy. My issue is really that now I'v introduced a camera offset so I tried something like this:
glTranslatef(controls.MainGlFrame.GetCameraX(),
controls.MainGlFrame.GetCameraY(),0);
glTranslatef(current.ScalePoint.x,current.ScalePoint.y,0);
glScalef(current.ScaleFactor,current.ScaleFactor,current.ScaleFactor);
glTranslatef(-current.ScalePoint.x,-current.ScalePoint.y,0);
But this did not work as I intended. How could I properly do this knowing that:
The matrix's origin is the top left corner (0,0)
1 unit == 1 pixel
My scale factor
My camera's position relative to how far it is from (0,0) (the origin) and
the mouse position (screen to client).
Thanks
It is more safe (and also for code reuse) to un-project the mouse coordinate point (from window coordinates to model coordinates) first even though you know how projection is done.
You can use the following function:
void unProject(int ix, int iy, int &ox, int &oy)
{
// First, ensure that your OpenGL context is the selected one
GLint viewport[4];
GLdouble projection[16];
GLdouble modelview[16];
glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
int xx = ix;
int yy = viewport[3] - iy;
GLdouble x, y, z;
gluUnProject(xx, yy, 0 /*check*/, modelview, projection, viewport, &x, &y, &z);
ox = (int) x;
oy = (int) y;
}
The output then is the correct point on the model coordinates for your zooming
The following piece of code gives me an error and I'm not able to understand it.
GLdouble objX,objY,objZ;
GLdouble modelview1[4][4], projection1[4][4];
GLint viewport1[4];
glGetDoublev( GL_MODELVIEW_MATRIX, *modelview1 );
glGetDoublev( GL_PROJECTION_MATRIX, *projection1 );
glGetIntegerv( GL_VIEWPORT, viewport1 );
gluUnProject(x, y, z, modelview1, projection1, viewport1, objX , objY , objZ);`
The error :
error C2664: 'gluUnProject' : cannot convert parameter 4 from 'GLdouble [4][4]' to 'const GLdouble []'
It seems that variables modelview1 and projection1 have wrong type.
I found following snippet (here http://www.3dkingdoms.com/selection.html ):
// This function will find 2 points in world space that are on the line into the screen defined by screen-space( ie. window-space ) point (x,y)
double mvmatrix[16];
double projmatrix[16];
int viewport[4];
double dX, dY, dZ, dClickY; // glUnProject uses doubles, but I'm using floats for these 3D vectors
glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);
glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);
dClickY = double (g_WindowHeight - y); // OpenGL renders with (0,0) on bottom, mouse reports with (0,0) on top
gluUnProject ((double) x, dClickY, 0.0, mvmatrix, projmatrix, viewport, &dX, &dY, &dZ);
ClickRayP1 = Vector3 ( (float) dX, (float) dY, (float) dZ );
gluUnProject ((double) x, dClickY, 1.0, mvmatrix, projmatrix, viewport, &dX, &dY, &dZ);
ClickRayP2 = Vector3 ( (float) dX, (float) dY, (float) dZ );
I have this view set:
glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
glLoadIdentity(); //Reset the drawing perspective
and I get a screen position (sx, sy) from a mouse click.
Given a value of z, how can I calculate x and y in 3d-space from sx and sy?
You should use gluUnProject:
First, compute the "unprojection" to the near plane:
GLdouble modelMatrix[16];
GLdouble projMatrix[16];
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
GLdouble x, y, z;
gluUnProject(sx, viewport[1] + viewport[3] - sy, 0, modelMatrix, projMatrix, viewport, &x, &y, &z);
and then to the far plane:
// replace the above gluUnProject call with
gluUnProject(sx, viewport[1] + viewport[3] - sy, 1, modelMatrix, projMatrix, viewport, &x, &y, &z);
Now you've got a line in world coordinates that traces out all possible points you could have been clicking on. So now you just need to interpolate: suppose you're given the z-coordinate:
GLfloat nearv[3], farv[3]; // already computed as above
if(nearv[2] == farv[2]) // this means we have no solutions
return;
GLfloat t = (nearv[2] - z) / (nearv[2] - farv[2]);
// so here are the desired (x, y) coordinates
GLfloat x = nearv[0] + (farv[0] - nearv[0]) * t,
y = nearv[1] + (farv[1] - nearv[1]) * t;