import torch


def ndc_to_camera_space(Xn, P):
    """Transform point(s) from normalised device coordinates to camera space.

    Args:
        Xn (torch.Tensor): homogeneous point(s) in normalised device coordinates.
        P (torch.Tensor): projection matrix.

    Returns:
        Xc (torch.Tensor): homogeneous point(s) in camera space.
    """
    # Normalised device coordinates -> homogeneous clip space
    z = Xn[..., 2:3]
    w = P[2, 3] / (z - P[2, 2])
    Xh = Xn * w
    # Homogeneous clip space -> camera space
    Xc = torch.matmul(Xh, P.inverse().t())
    return Xc