Mouse ray picking not working.

Started by
0 comments, last by cec19 12 years, 3 months ago
Hello everyone!

Recently I have been trying to implement picking via mouse ray. I made a little project with three spheres in it and I simply check for ray-sphere intersection. If there is such, I have a sphere to pick. After I made everything to work fine with that little project I tried to implement this in a bigger one. The bigger project is a solar systems creator. However, when I try to select a sun(that is the only thing I need to be selected) the selection won't work. Below I am posting the code for the solution.

First, the intersection test:



bool CelestialBody::IsClickedOn(Ray mouseRay)
{
float a = DotProduct(mouseRay.GetDirection(), mouseRay.GetDirection());
float b = 2 * DotProduct(mouseRay.GetOrigin(), mouseRay.GetDirection());
float c = DotProduct(mouseRay.GetOrigin(), mouseRay.GetOrigin()) - this->radius * this->radius;

float discriminant = b * b - 4 * a * c;

std::cout<<discriminant<<std::endl;

if(discriminant < 0)
{
return false;
}
return true;
}


Second, the mouse click code:

if(userMouse.IsLeftButtonDown())
{
int cursorX = int(userMouse.GetCurrentPosition().GetX());
int cursorY = int(userMouse.GetCurrentPosition().GetY());

Vector3d nearPoint = userCamera.GetPosition();
Vector3d farPoint = MouseClass::ConvertMouseToOGLCoordinate(cursorX, cursorY, 1.0f);

Vector3d direction = farPoint - nearPoint;
direction.Normalize();

std::vector<std::string> parentNames = sceneLayout->GetParentNames();
int size = parentNames.size();
for(int i = 0; i < size; i++)
{
Vector3d parentBodyPos = sceneLayout->GetCelestialBodyPosition(parentNames);
Vector3d origin = nearPoint - parentBodyPos;

CelestialBody *currentBody = sceneLayout->GetCelestialBody(parentNames);
mouseRay = Ray(origin, direction);

bool isCollided = currentBody->IsClickedOn(mouseRay);
if(isCollided)
{
currentBody->SetColor(Color(0, 0, 255));
}
else
{
currentBody->SetColor(Color(255, 250, 255));
}
}
//userMouse.ReleaseLeftButton();
}


And at last, the ConvertMouseToOGLCoordinate() function code:

Vector3d MouseClass::ConvertMouseToOGLCoordinate(int mouseX, int mouseY, int mouseZ)
{
GLint viewport[4];
GLdouble modelMatrix[16];
GLdouble projectionMatrix[16];

glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix);float winY = float(viewport[3] - mouseY);

double x, y, z;
gluUnProject((double)mouseX, winY, mouseZ,
modelMatrix, projectionMatrix, viewport,
&x, &y, &z);

return Vector3d(x, y, z);
}


These are the snippets which correspond to the little project's code.

The thing I suspect to crash the algorithm is the position from which I view the scene. My camera coords are (0.0; 9000.0; 0.0) and when I switch from side view (0.0, 0.0, 9000.0) I am able to pick one of the planets. On the little project, however, I am able to pick from whatever position my camera is.

I know I haven't explained things good enough but that is all I can do... If you want the whole code of both projects, I will supply you with it smile.png.
Advertisement
I managed to fix the problem. The code, which made things not work was in the display function:


void Display()
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();


glPushMatrix();
ApplyCamera();
DrawGrid(10000, 200);
DrawObjects();

glPopMatrix();

DrawText();


glutSwapBuffers();
}


Simply, the push and pop funcs are making sth wrong in my code(I am not so experienced and I can't tell exactly what). By removing them I managed to get good results for the depth buffers.


void Display()
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();


DrawText();

ApplyCamera();
DrawGrid(10000, 200);
DrawObjects();


glutSwapBuffers();
}


Thats it! If anyone can explain me why the pushing and popping matrices screws the whole algorithm please post. :)

This topic is closed to new replies.

Advertisement