Search code examples
math3d2dprojection

How do I take a 2D point, and project it into a 3D Vector by a perspective camera


I have a 2D Point (x,y) and I want to project it to a Vector, so that I can perform a ray-trace to check if the user clicked on a 3D Object, I have written all the other code, Except when I got back to my function to get the Vector from the xy cords of the mouse, I was not accounting for Field-Of-View, and I don't want to guess what the factor would be, as 'voodoo' fixes are not a good idea for a library. any math-magicians wanna help? :-).

Heres my current code, that needs FOV of the camera applied:

sf::Vector3<float> Camera::Get3DVector(int Posx, int Posy, sf::Vector2<int> ScreenSize){
    //not using a "wide lens", and will maintain the aspect ratio of the viewport
    int window_x = Posx - ScreenSize.x/2;
    int window_y = (ScreenSize.y - Posy) - ScreenSize.y/2;
    float Ray_x = float(window_x)/float(ScreenSize.x/2);
    float Ray_y = float(window_y)/float(ScreenSize.y/2);

    sf::Vector3<float> Vector(Ray_x,Ray_y, -_zNear);
    // to global cords
    return MultiplyByMatrix((Vector/LengthOfVector(Vector)), _XMatrix, _YMatrix, _ZMatrix);
}

Solution

  • You're not too fart off, one thing is to make sure your mouse is in -1 to 1 space (not 0 to 1) Then you create 2 vectors:

    Vector3 orig = Vector3(mouse.X,mouse.Y,0.0f);
    Vector3 far = Vector3(mouse.X,mouse.Y,1.0f);
    

    You also need to use the inverse of your perspective tranform (or viewprojection if you want world space)

    Matrix ivp = Matrix::Invert(Projection)
    

    Then you do:

    Vector3 rayorigin = Vector3::TransformCoordinate(orig,ivp);
    Vector3 rayfar = Vector3::TransformCoordinate(far,ivp);
    

    If you want a ray, you also need direction, which is simply:

    Vector3 raydir = Normalize(rayfar-rayorigin);