XNA Creators Club Online
Page 1 of 1 (6 items)
Sort Posts: Previous Next

mouse picking / ray-plane intersect issue

Last post 8/10/2009 7:36 PM by mathmos. 5 replies.
  • 3/31/2008 5:30 PM

    mouse picking / ray-plane intersect issue

    I have a picking function that translates 2D mouse coordinates to a 3D position in space. This process is somewhat simplified because in the application:

    - all objects are on the Y=0 plane, so the plane is always the same
    - the camera is fixed looking down (an RTS camera)
    - thus intersection is guaranteed

    It seems to work ok mostly, however I'm having a problem:

    - intersection works correctly near the XYZ=0 axis in the game world
    - when I move away from the axis, the picking becomes increasingly in-accurate (like say X or Z = 100,000+)

    Seems like I am forgetting to normalize something possibly? Anyway, here is the code. Anyone see any obvious reason why being far away from the XYZ=0 axis would cause problems?

    My code is based on the XNA Picking Sample on this site and the ray-plane intersect found here:

    http://www.ziggyware.com/readarticle.php?article_id=79

    //----------------------------------------------------------------
    // GetPickedPosition() - gets 3D position of 2D mouse pointer
    // - always on the the Y = 0 plane
    //----------------------------------------------------------------
    public Vector3 GetPickedPosition(Camera camera, Vector2 mousePosition)
    {

    // create 2 positions in screenspace using the cursor position. 0 is as
    // close as possible to the camera, 10 is as far away as possible
    Vector3 nearSource = new Vector3(mousePosition, 0f);
    Vector3 farSource = new Vector3(mousePosition, camera.nearClip);


    // find the two screen space positions in world space
    Vector3 nearPoint = graphicsDevMgr.GraphicsDevice.Viewport.Unproject(nearSource,
    camera.projectionMatrix, camera.viewMatrix, Matrix.Identity);
    Vector3 farPoint = graphicsDevMgr.GraphicsDevice.Viewport.Unproject(farSource,
    camera.projectionMatrix, camera.viewMatrix, Matrix.Identity);


    // normalized direction vector from nearPoint to farPoint
    Vector3 direction = farPoint - nearPoint;
    direction.Normalize();


    // create a ray using nearPoint as the source
    Ray r = new Ray(nearPoint, direction);


    // define the Y=0 plane
    Vector3 n = new Vector3(0f, 1f, 0f);
    Plane p = new Plane(n, 0f );


    // calcuate distance of plane intersection point from ray origin
    double denominator = Vector3.Dot(p.Normal, r.Direction);
    double numerator = Vector3.Dot(p.Normal, r.Position) + p.D;
    double t = -(numerator / denominator);


    // calculate the picked position on the y = 0 plane
    Vector3 pickedPosition = nearPoint + direction * (float)t;
    return pickedPosition;
    }

  • 3/31/2008 7:09 PM In reply to

    Re: mouse picking / ray-plane intersect issue

    Answer
    Reply Quote
    You may be encountering a mathematical situation similar to what contributes to z-fighting.

    Try setting the camera's nearClip value as high as possible. That would make the distance between your nearSource & farSource as big as possible and thus less prone to compounding inaccuracies.

    It's kind of like adding length to a gun barrel. Aiming with a rifle is more accurate for the long distances than aiming with a pistol.
    Unlock The *I don't use 3 angles in a Vector3 for rotations anymore* Achievement Here
  • 3/31/2008 7:39 PM In reply to

    Re: mouse picking / ray-plane intersect issue

    Huh wow that did fix it. Thanks a lot. =)

    My nearclip was 10 and my far clip was 100k. With nearclip increased to 1000 it works perfectly.

    Those default XNA models in the sample packs are huge, so you need a  huge gamespace. I just have to adjust my default aspect ratios and camera distances now, which will be trivial.
  • 3/31/2008 8:06 PM In reply to

    Re: mouse picking / ray-plane intersect issue

    Not sure if this method will be any more or less accurate than yours, but in case you (or anyone else reading this) didn't know, there is a Ray.Intersects(Plane) method built in to XNA. It returns a nullable float, so it will be null if no intersection occurs or it will contain the distance from the ray origin to the point of collision. Not sure if it does something different to solve for these situations, but I figured I'd just toss it out there.
  • 4/14/2008 4:42 AM In reply to

    Re: mouse picking / ray-plane intersect issue

    Hi,

    I just created a gamertag so I could comment in this thread.

    I am having two different problems.

    One is this "inaccuracy" of the Viewport.Unproject() method. It seems to mostly work ok, but it gets worse as I move the camera away from the origin, eventually the unprojected front point flips behind the camera and and starts moving away from the camera. My clip planes are set at 0.1 and 1000. I think that should be in a "normal" range.

    I have an "xyzwidget" which I can position in my scene with a vector. I can prove the unprojection is at least sort of working, by unprojecting a point in the bottom right of the screen (minus a bit), and placing an xyzwidget there. It appears as expected in the bottom right (apart from the problem described above). It's position is in world coordinates.

    Now, my second problem is that I'm trying to create an xyzwidget on the xz plane where the user clicks the mouse. Currently I'm using code almost identical to CookieFeathers' ray/plane intersection.

    I'm not sure if it's the dodgy unprojecting or what, but here's what happens. The ray correctly is projected through the scene and successfully hits the xz plane. but it's not where the user clicked, its in the center of the screen!!!!! It gets offset in the opposite direction that the user clicked, by the smallest amount. ie. if I multiply the resulting vector by -2000 (random i know!), it actually ends up being in roughly the right place....

    I also tried the Ray.Intersects(Plane) method, but no matter what I tried, it returned null.

    I hope someone can help me!! Or even has any ideas what's going on??

    I would post the whole source code, but it's quite a big app now. Anyway I checked about 5 times the unprojection code is identical to what appears on the forums and tutorials. And it seems to work (xyzwidget sucessfully placed at the bottom of the screen, in world coords).

    Thanks for reading.

    -dexy

     

    [edit:] after fiddling, I came to the conclusion that my mouse ray's direction vector seems to be wrong.... for some reason it always points towards the origin. The ray's position seems to be ok. But I can't for the life of me figure out why the direction would be pointing at the origin??

    {
    Vector3 screenNear = new Vector3((float)x, (float)y, 0f);
    Vector3 screenFar = new Vector3((float)x, (float)y, 1f);
    Vector3 worldNear = Unproject(camera, screenNear);
    Vector3 worldFar = Unproject(camera, screenFar);
    Vector3 direction = worldFar - worldNear;
    direction.Normalize();
    }
    public static Vector3 Unproject(Camera camera, Vector3 screenSpace)
    {
    return camera.Viewport.Unproject(screenSpace, camera.ProjectionMatrix, camera.ViewMatrix, Matrix.Identity);
    }
    open-source c++ and hlsl syntax highlighting for VS2010: http://highlighterr.codeplex.com/
  • 8/10/2009 7:36 PM In reply to

    Re: mouse picking / ray-plane intersect issue

    What is this Camera Class? Is it in the XNA framework? Is it howmade? How do i get it??
Page 1 of 1 (6 items) Previous Next