Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


cec19

Member Since 09 Jan 2012
Offline Last Active Feb 09 2012 08:33 AM

Topics I've Started

Mouse ray picking not working.

09 January 2012 - 03:35 PM

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[i]);
   Vector3d origin = nearPoint - parentBodyPos;

   CelestialBody *currentBody = sceneLayout->GetCelestialBody(parentNames[i]);
   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 Posted Image.

PARTNERS