Skip to content

Instantly share code, notes, and snippets.

@StagPoint
Created December 2, 2020 23:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StagPoint/341a2da4c63c3c80bbee2e94773e172d to your computer and use it in GitHub Desktop.
Save StagPoint/341a2da4c63c3c80bbee2e94773e172d to your computer and use it in GitHub Desktop.
Small collection of utility functions for calculating screen size of objects, size of camera frustum at a distance, etc.
using System;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using Unity.Burst;
using Unity.Mathematics;
public static class CameraMath
{
/// <summary>
/// Get the screen size of an object in pixels, given its distance and diameter.
/// </summary>
/// <param name="distance">The distance from the desired camera to the object</param>
/// <param name="diameter">The diameter of the object's bounding sphere</param>
/// <param name="screenHeight">The height of the screen, in pixels</param>
/// <param name="fieldOfView">The Field of View (in degrees) of the desired camera</param>
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static float DistanceAndDiameterToPixelSize( float distance, float diameter, float screenHeight, float fieldOfView )
{
return math.degrees( diameter * screenHeight ) / ( distance * fieldOfView );
}
/// <summary>
/// Get the distance of an object, given its screen size in pixels and diameter.
/// </summary>
/// <param name="pixelSize">The size (in screen pixels) of the object</param>
/// <param name="diameter">The actual diameter of the object's bounding sphere</param>
/// <param name="screenHeight">The height of the screen, in pixels</param>
/// <param name="fieldOfView">The Field of View (in degrees) of the desired camera</param>
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static float PixelSizeAndDiameterToDistance( float pixelSize, float diameter, float screenHeight, float fieldOfView )
{
return math.degrees( diameter * screenHeight ) / ( pixelSize * fieldOfView );
}
/// <summary>
/// Returns the calculated diameter of an object, given its screen size in pixels and distance.
/// </summary>
/// <param name="pixelSize">The size (in screen pixels) of the object</param>
/// <param name="distance">The distance from the desired camera to the object</param>
/// <param name="screenHeight">The height of the screen, in pixels</param>
/// <param name="fieldOfView">The Field of View (in degrees) of the desired camera</param>
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static float PixelSizeAndDistanceToDiameter( float pixelSize, float distance, float screenHeight, float fieldOfView )
{
float diameter = ( pixelSize * distance * fieldOfView ) / math.degrees( screenHeight );
return diameter;
}
/// <summary>
/// Returns the distance required to give a specified frustum height at the given Field of View.
/// </summary>
/// <param name="frustumHeight">The diameter of the object's bounding sphere</param>
/// <param name="fieldOfView">The Field of View (in degrees) of the desired camera</param>
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static float DistanceForFrustumHeight( float frustumHeight, float fieldOfView )
{
float cameraView = math.tan( math.radians( fieldOfView * 0.5f ) );
float distance = ( frustumHeight * 0.5f ) / cameraView;
return distance;
}
/// <summary>
/// Returns the height of the frustum at a given distance.
/// </summary>
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static float FrustumHeightAtDistance( float distance, float fieldOfView )
{
return 2.0f * distance * math.tan( math.radians( fieldOfView * 0.5f ) );
}
/// <summary>
/// Returns the field of view when the distance and height are known.
/// </summary>
/// <param name="distance">Distance from camera to target position</param>
/// <param name="height">Height of target</param>
/// <returns></returns>
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static float FieldOfViewFromDistanceAndHeight( float distance, float height )
{
return 2.0f * math.degrees( math.atan( height * 0.5f / distance ) );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment