Adds documentation for the `omath::ViewAngles` struct, clarifying its purpose, common usage patterns, and the definition of the types of pitch, yaw and roll. Also, adds short explanations of how to use ViewAngles and what tradeoffs exist between using raw float types and strongly typed Angle<> types.
3.4 KiB
omath::angles — angle conversions, FOV helpers, and wrapping
Header:
omath/trigonometry/angles.hppNamespace:omath::anglesAll functions are[[nodiscard]]andnoexceptwhere applicable.
A small set of constexpr-friendly utilities for converting between degrees/radians, converting horizontal/vertical field of view, and wrapping angles into a closed interval.
API
// Degrees ↔ Radians (Type must be floating-point)
template<class Type>
requires std::is_floating_point_v<Type>
constexpr Type radians_to_degrees(const Type& radians) noexcept;
template<class Type>
requires std::is_floating_point_v<Type>
constexpr Type degrees_to_radians(const Type& degrees) noexcept;
// FOV conversion (inputs/outputs in degrees, aspect = width/height)
template<class Type>
requires std::is_floating_point_v<Type>
Type horizontal_fov_to_vertical(const Type& horizontal_fov, const Type& aspect) noexcept;
template<class Type>
requires std::is_floating_point_v<Type>
Type vertical_fov_to_horizontal(const Type& vertical_fov, const Type& aspect) noexcept;
// Wrap angle into [min, max] (any arithmetic type)
template<class Type>
requires std::is_arithmetic_v<Type>
Type wrap_angle(const Type& angle, const Type& min, const Type& max) noexcept;
Usage
Degrees ↔ Radians
float rad = omath::angles::degrees_to_radians(180.0f); // π
double deg = omath::angles::radians_to_degrees(std::numbers::pi); // 180
Horizontal ↔ Vertical FOV
aspect= width / height.- Inputs/outputs are degrees.
float hdeg = 90.0f;
float aspect = 16.0f / 9.0f;
float vdeg = omath::angles::horizontal_fov_to_vertical(hdeg, aspect); // ~58.0°
float hdeg2 = omath::angles::vertical_fov_to_horizontal(vdeg, aspect); // ≈ 90.0°
Formulas (in radians):
v = 2 * atan( tan(h/2) / aspect )h = 2 * atan( tan(v/2) * aspect )
Wrapping angles (or any periodic value)
Wrap any numeric angle into [min, max]:
// Wrap degrees into [0, 360]
float a = omath::angles::wrap_angle( 370.0f, 0.0f, 360.0f); // 10
float b = omath::angles::wrap_angle( -15.0f, 0.0f, 360.0f); // 345
// Signed range [-180,180]
float c = omath::angles::wrap_angle( 200.0f, -180.0f, 180.0f); // -160
Notes & edge cases
-
Type requirements
- Converters & FOV helpers require floating-point
Type. wrap_angleaccepts any arithmeticType(floats or integers).
- Converters & FOV helpers require floating-point
-
Aspect ratio must be positive and finite. For
aspect == 0the FOV helpers are undefined. -
Units: FOV functions accept/return degrees but compute internally in radians.
-
Wrapping interval: Behavior assumes
max > min. The result lies in the closed interval[min, max]with modulo arithmetic; if you need half-open behavior (e.g.,[min,max)), adjust your range or post-process endpoint cases. -
constexpr: Converters are
constexpr; FOV helpers are runtime constexpr-compatible except forstd::atan/std::tanconstraints on some standard libraries.
Quick tests
using namespace omath::angles;
static_assert(degrees_to_radians(180.0) == std::numbers::pi);
static_assert(radians_to_degrees(std::numbers::pi_v<float>) == 180.0f);
float v = horizontal_fov_to_vertical(90.0f, 16.0f/9.0f);
float h = vertical_fov_to_horizontal(v, 16.0f/9.0f);
assert(std::abs(h - 90.0f) < 1e-5f);
assert(wrap_angle(360.0f, 0.0f, 360.0f) == 0.0f || wrap_angle(360.0f, 0.0f, 360.0f) == 360.0f);