Repository: FlaxEngine/FlaxEngine
File: Source/Engine/Level/Actors/Camera.cpp (C++)

Code before:
}

bool Camera::IsPointOnView(const Vector3& worldSpaceLocation) const
{
    Camera* mainCamera = Camera::GetMainCamera();

    if (!mainCamera)
    {
        return false;
    }

    Vector3 cameraUp = mainCamera->GetTransform().GetUp();
    Vector3 cameraForward = mainCamera->GetTransform().GetForward();
    Vector3 directionToPosition = (worldSpaceLocation- mainCamera->GetPosition()).GetNormalized();

    if (Vector3::Dot(cameraForward, directionToPosition) < 0)
    {
        return false;
    }

    Quaternion lookAt = Quaternion::LookRotation(directionToPosition, cameraUp);
    Vector3 lookAtDirection = lookAt * Vector3::Forward;
    Vector3 newWorldLocation = mainCamera->GetPosition() + lookAtDirection;

    Float2 windowSpace = Float2();
    Float2 screenSize = Screen::GetSize();

    mainCamera->ProjectPoint(newWorldLocation, windowSpace);

    return (windowSpace.X >= 0 && windowSpace.X <= screenSize.X) &&
           (windowSpace.Y >= 0 && windowSpace.Y <= screenSize.Y);
}

Ray Camera::ConvertMouseToRay(const Float2& mousePosition) const
{
    return ConvertMouseToRay(mousePosition, GetViewport());
}

Ray Camera::ConvertMouseToRay(const Float2& mousePosition, const Viewport& viewport) const
{
#if 1
    // Gather camera properties
    Matrix v, p, ivp;
    GetMatrices(v, p, viewport);
    Matrix::Multiply(v, p, ivp);
    ivp.Invert();

    // Create near and far points
    Vector3 nearPoint(mousePosition, 0.0f);
    Vector3 farPoint(mousePosition, 1.0f);
    viewport.Unproject(nearPoint, ivp, nearPoint);

Review comment (performance):
This could use `GetViewport()` of the camera instead and then pass the viewport to `ProjectPoint(newWorldLocation, windowSpace, viewport)` to be more optimized.

Code after:

bool Camera::IsPointOnView(const Vector3& worldSpaceLocation) const
{
    Vector3 cameraUp = GetTransform().GetUp();
    Vector3 cameraForward = GetTransform().GetForward();
    Vector3 directionToPosition = (worldSpaceLocation - GetPosition()).GetNormalized();

    if (Vector3::Dot(cameraForward, directionToPosition) < 0)
    {
        return false;
    }

    Quaternion lookAt = Quaternion::LookRotation(directionToPosition, cameraUp);
    Vector3 lookAtDirection = lookAt * Vector3::Forward;
    Vector3 newWorldLocation = GetPosition() + lookAtDirection;

    Float2 windowSpace = Float2();
    Float2 screenSize = GetViewport().Size;

    ProjectPoint(newWorldLocation, windowSpace);

    return (windowSpace.X >= 0 && windowSpace.X <= screenSize.X) &&
           (windowSpace.Y >= 0 && windowSpace.Y <= screenSize.Y);
}

Ray Camera::ConvertMouseToRay(const Float2& mousePosition) const
{
    return ConvertMouseToRay(mousePosition, GetViewport());
}

Ray Camera::ConvertMouseToRay(const Float2& mousePosition, const Viewport& viewport) const
{
#if 1
    // Gather camera properties
    Matrix v, p, ivp;
    GetMatrices(v, p, viewport);
    Matrix::Multiply(v, p, ivp);
    ivp.Invert();

    // Create near and far points
    Vector3 nearPoint(mousePosition, 0.0f);
    Vector3 farPoint(mousePosition, 1.0f);
    viewport.Unproject(nearPoint, ivp, nearPoint);
    viewport.Unproject(farPoint, ivp, farPoint);

    // Create direction vector
    Vector3 direction = farPoint - nearPoint;
    direction.Normalize();

    return Ray(nearPoint, direction);
#else