Mouse Pick Dead Zones

srbosu

12-02-2009 00:36:38

I've scoured the forums all day when I should have been working, and everything I've encountered hasn't been able to solve my problem. Perhaps the real problem is I don't exactly know what the problem is and cannot search well for it. Anyway, I am using Mogre with MogreNewt. When I add entities to the scene, I either build a convex hull or tree collision depending on the precision that I need for my project. I am using, what I thought at the time of implementation, a simple and obvious method for mouse selecting. Please, if you have time, take a look at my code, I know it's probably something in Newton that I just don't understand. Most likely something obvious. I've also made some screenshots illustrating my problem.

Mouse Select Code

if (e.Button == MouseButtons.Left)
{

float mX = (float)e.X / (float)mogrePanel.Width;
float mY = (float)e.Y / (float)mogrePanel.Height;

Vector3 start, end;

// A MogreObject is a class i built to store all my user defined data, like whether to build a convex hull or tree collision
MogreObject mObject = null;


Camera mCamera = mogreWin.sceneMgr.GetCamera("SimpleCamera");

Ray mouseRay = mCamera.GetCameraToViewportRay(mX, mY);


start = mouseRay.Origin;
end = mouseRay.GetPoint(1000f);

BasicRaycast ray = new BasicRaycast(newtWorld, start, end);
BasicRaycast.BasicRaycastInfo info = ray.FirstHit;




try
{
mObject = myResources.GetObject(info.mBody.OgreNode.Name);
}
catch { }


try
{

// SelectObject just hides one AABB and draws another one
this.SelectObject(info.mBody.OgreNode.Name);

}
catch
{
// SelectObject("null") just hides one AABB
this.SelectObject("null");

}


}


Code for adding an object to the scene

private void BuildObject(MogreObject mObject)
{
Entity ent = sceneMgr.CreateEntity(mObject.ObjectID, mObject.Resource);

SceneNode parentNode = sceneMgr.GetSceneNode(mObject.Parent);
SceneNode objectNode = sceneMgr.CreateSceneNode(mObject.ObjectID);

objectNode.Orientation = mObject.Orientation;
objectNode.Position = mObject.Position;
objectNode.SetScale(mObject.Scale);

parentNode.AddChild(objectNode);
objectNode.AttachObject(ent);


if (mObject.CollisionType == CollisionPrecisionTypes.Rough)
{
Collision ObjectCollisionPrimitive = new MogreNewt.CollisionPrimitives.ConvexHull(NewtWorld, objectNode);

Body ObjectBody = new Body(NewtWorld, ObjectCollisionPrimitive);

ObjectBody.AttachToNode(objectNode);
ObjectBody.SetPositionOrientation(objectNode.Position, objectNode.Orientation);


ObjectCollisionPrimitive.Dispose();
}
else // there are only two types of CollisionPrecisionTypes
{
Collision ObjectCollisionPrimitive = new MogreNewt.CollisionPrimitives.TreeCollision(NewtWorld, ent, false);

Body ObjectBody = new Body(NewtWorld, ObjectCollisionPrimitive);

ObjectBody.AttachToNode(objectNode);
ObjectBody.SetPositionOrientation(mObject.Position, mObject.Orientation);


ObjectCollisionPrimitive.Dispose();
}


Areas shaded in red are selectable





I'll be checking up frequently, so if I need to post some more details don't hesitate to ask. I'll be more than grateful for anyone's help.

srbosu

13-02-2009 02:50:29

I think I may have solved the problem. What I did was take the original ray, and grab new begining points along that ray. Hard to explain in little words, here is my new selection code:



if (e.Button == MouseButtons.Left)
{

float mX = (float)e.X / (float)mogrePanel.Width;
float mY = (float)e.Y / (float)mogrePanel.Height;

Vector3 start, end;

// A MogreObject is a class i built to store all my user defined data, like whether to build a convex hull or tree collision
MogreObject mObject = null;


Camera mCamera = mogreWin.sceneMgr.GetCamera("SimpleCamera");

Ray mouseRay = mCamera.GetCameraToViewportRay(mX, mY);


start = mouseRay.Origin;
end = mouseRay.GetPoint(1000f);

BasicRaycast ray = new BasicRaycast(newtWorld, start, end);
BasicRaycast.BasicRaycastInfo info = ray.FirstHit;

/************************************************* Iterate down the ray for 1000 units
for (int i = 0; i< 1000; i++)
{
ray.Go(newtWorld, mouseRay.GetPoint(i), end);
info = ray.FirstHit;
if (info != null) i = 1001;
}
/*************************************************

try
{
mObject = myResources.GetObject(info.mBody.OgreNode.Name);
}
catch { }


try
{

// SelectObject just hides one AABB and draws another one
this.SelectObject(info.mBody.OgreNode.Name);

}
catch
{
// SelectObject("null") just hides one AABB
this.SelectObject("null");

}


}



I haven't really toyed with the number of times i should loop, and I would imagine that 1000 times is a bit of overkill, but the delay is almost nonexistent so I'll keep it where it is for now.