Download

How to measure frustum at a given distance from camera?

Is there a way to get the bounds / frustum coordinates of a UE4 scenecap2d at a given focal distance?

I’m not seeing a way of getting either 6 vectors for the frustum volume coordinates or 4 vectors for a plane at a given distance from camera. There’s “Draw Debug Frustum” BP node, but when I plug the transform of a camera into it just draws a square at the camera position, not a frustum / truncated pyramid.

Also, in the “show” menu I’m able to turn on “camera frustums”, but I only see this in-editor, not during play. I have both scenecap2d’s and cameras in the level and “ShowFlag.CameraFrustums 1” has no effect on either of them.

Would greatly appreciate any help you can provide. Hopefully there’s something that can be done in BP, I’m hoping to hold off on cpp until I finish my prototype.

Using the “DrawFrustumComponent.cpp” as a reference I developed a set of methods for calculating frustum height and width, as well as calculating camera distance or field of view relative to a height / width;

Obs.: The editor uses a constant aspect ratio, so when tested on the editor, it is necessary to call methods with FixedAspectRatio as true, but at runtime, use it as false.



float UCameraFunctionLibrary::GetFrustumWidth( UCameraComponent* Camera, float Distance )
{
    FMinimalViewInfo info;
    Camera->GetCameraView(0, info);
    const float FrustumAngle = info.FOV;
    const float HozHalfAngleInRadians = FMath::DegreesToRadians(FrustumAngle * 0.5f);
    return Distance * FMath::Tan(HozHalfAngleInRadians) * 2.0f;
}

float UCameraFunctionLibrary::GetFrustumHeight( UCameraComponent* Camera, float Distance, bool FixedAspectRatio/* = false*/ )
{
    const float AspectRatio = GetAspectRatio(Camera, FixedAspectRatio);
    return GetFrustumWidth(Camera, Distance) / AspectRatio;
}

float UCameraFunctionLibrary::GetDistanceByFrustumWidth( UCameraComponent* Camera, float FrustumWidth )
{
    FMinimalViewInfo info;
    Camera->GetCameraView(0, info);
    const float FrustumAngle = info.FOV;
    const float HozHalfAngleInRadians = FMath::DegreesToRadians(FrustumAngle * 0.5f);
    return FrustumWidth * 0.5f / FMath::Tan(HozHalfAngleInRadians);
}

float UCameraFunctionLibrary::GetDistanceByFrustumHeight( UCameraComponent* Camera, float FrustumHeight, bool FixedAspectRatio/* = false*/ )
{
    const float AspectRatio = GetAspectRatio(Camera, FixedAspectRatio);
    return GetDistanceByFrustumWidth( Camera, FrustumHeight*AspectRatio );
}

float UCameraFunctionLibrary::GetFieldOfViewByFrustumWidth( UCameraComponent* Camera, float Distance, float FrustumWidth )
{
    Distance = FMath::Abs(Distance);
    float Radians = 2.0f * FMath::Atan(FrustumWidth * 0.5f / Distance);
    return FMath::RadiansToDegrees(Radians);
}

float UCameraFunctionLibrary::GetFieldOfViewByFrustumHeight( UCameraComponent* Camera, float Distance, float FrustumHeight, bool FixedAspectRatio/* = false*/ )
{
    const float AspectRatio = GetAspectRatio(Camera, FixedAspectRatio);
    return GetFieldOfViewByFrustumWidth( Camera, Distance, FrustumHeight*AspectRatio );
}

float UCameraFunctionLibrary::GetAspectRatio( UCameraComponent* Camera, bool FixedAspectRatio/* = false*/ ) 
{
    float AspectRatio;
    if( FixedAspectRatio )
    {
        FMinimalViewInfo info;
        Camera->GetCameraView(0, info);
        AspectRatio = info.AspectRatio;
    }
    else
    {
        FVector2D Size = UWidgetLayoutLibrary::GetViewportSize(Camera->GetWorld());
        AspectRatio = Size.X/Size.Y;
    }

    return AspectRatio;
}