I've looked at a few tutorials about picking and the method Unproject, so I have an idea of how getting the mouse in 3d space is done. The code I have does display a mouse position, but it is way off of the actual position the mouse is at.

    public Vector3 FindWhereClicked(MouseState ms)
        Vector3 nearScreen = new Vector3(ms.X, ms.Y, 0);
        Vector3 farScreen = new Vector3(ms.X, ms.Y, 1);
        Vector3 nearWorld = device.Viewport.Unproject(nearScreen, cam.proj, cam.view, Matrix.Identity);
        Vector3 farWorld = device.Viewport.Unproject(farScreen, cam.proj, cam.view, Matrix.Identity);

        Vector3 direction = farWorld - nearWorld;

        float zFactor = -nearWorld.Y / direction.Y;

        Vector3 zeroWorldPoint = nearWorld + direction * zFactor;

        return zeroWorldPoint;

This code is from another thread I found on here. I'm guessing the problem is the near and far world variables.

    public ThirdPersonCam()
        proj = Matrix.CreatePerspectiveFieldOfView(0.78f, 1.7777f, 1f, 10000f);

    public void CameraUpdate(Matrix objectToFollow)
        Vector3 camPosition = objectToFollow.Translation + (objectToFollow.Backward * 10) + (objectToFollow.Up * 2);
        Vector3 camTarget = objectToFollow.Translation;

        view = Matrix.CreateLookAt(camPosition, camTarget, Vector3.Up);

The variables are grabbed from my camera class, but I don't know why it isn't working. A point that's supposed to be at 0, 0, 0 ends up being at something like 36, -1, 57


Basically I got all my information from Picking sample from microsoft.

This method creates a ray in world space that i can use to pick something:

private void RenewRay(){
    var camera = _cameraService.Current;
    //get mouse position in screen coordinates
    var mousePosition = _mouseInputProvider.Position;
    //calculate cursor points in screen space
    var cursorOnNearPlane = new Vector3(mousePosition, 0);
    var cursorOnFarPlane = new Vector3(mousePosition, 1);

    //calculate cursor points in world space.
    var nearPoint = _device.Viewport.Unproject(cursorOnNearPlane, camera.Projection, camera.View, Matrix.Identity);
    var farPoint = _device.Viewport.Unproject(cursorOnFarPlane, camera.Projection, camera.View, Matrix.Identity);

    var rayDirection = farPoint - nearPoint;

    Ray = new Ray(nearPoint, rayDirection);

This ray in world space can be used to intersect with bounding spheres in world space. So my picking looks like:

public float? PerformPicking(Ray rayInWorldSpace){
    if (WorldBoundingSphere.Intersects(rayInWorldSpace) == null) return null;

    var rayInObjectSpace = rayInWorldSpace.TransformToObjectSpace(ref _world);
    return PickableGeometry.PerformPicking(rayInObjectSpace);

As you can see, I first perform picking on the WorldBoundingSphere. This is extremly fast and so I don't have to perform TrainglePicking on every object I draw. If I picked the BoundingSphere, I should test weather I really the geometry so I have to transform the ray to the object space of my geometry. This is implemented in a extension method that looks like :

public static Ray TransformToObjectSpace(this Ray ray, ref Matrix worldMatrix){
    Matrix inverseWorld;
    Matrix.Invert(ref worldMatrix, out inverseWorld);
    Vector3 newRayStart, newRayDirection;
    Vector3.Transform(ref ray.Position, ref inverseWorld, out newRayStart);
    Vector3.TransformNormal(ref ray.Direction, ref inverseWorld, out newRayDirection);

    return new Ray(newRayStart, newRayDirection);

PickableGeometry.PerformPicking(rayInObjectSpace) simply uses a TrainglePicker class I wrote that adapts the algorithm written by microsoft that you can read in the triangle picking example from mircosft.

By the way, PickableGeometry.PerformPicking(rayInObjectSpace) gives you the distance from camera to object in object space. So if you use a world matrix with a scale!=1, you have to scale to distance value, too. Or you calculate the position of the intersection in object space and apply the world matrix to calculate the intersection point in world space. Its up to you!


Your Answer

