opynsim
Unofficial C++ Documentation
Loading...
Searching...
No Matches
unorm.h
Go to the documentation of this file.
1#pragma once
2
4
5#include <cmath>
6#include <compare>
7#include <concepts>
8#include <functional>
9#include <limits>
10#include <ostream>
11#include <stdexcept>
12
13namespace osc
14{
15 // A normalized unsigned integer that can be used to store a floating-point
16 // number in the (clamped) range [0.0f, 1.0f]
17 //
18 // see: https://www.khronos.org/opengl/wiki/Normalized_Integer
19 template<std::unsigned_integral T>
20 class Unorm {
21 public:
22 using value_type = T;
23
24 constexpr Unorm() = default;
25
26 template<std::integral U>
27 constexpr Unorm(U integral_value) :
29 {}
30
31 constexpr Unorm(T raw_value) :
32 value_{raw_value}
33 {}
34
35 template<std::floating_point U>
37 value_{to_normalized_uint(normalized_value)}
38 {}
39
40 friend auto operator<=>(const Unorm&, const Unorm&) = default;
41
42 explicit constexpr operator float() const
43 {
44 return normalized_value();
45 }
46
47 explicit constexpr operator T() const
48 {
49 return raw_value();
50 }
51
52 constexpr T raw_value() const
53 {
54 return value_;
55 }
56
57 constexpr float normalized_value() const
58 {
59 return (1.0f/static_cast<float>(std::numeric_limits<T>::max())) * static_cast<float>(value_);
60 }
61
62 private:
63 template<std::floating_point U>
64 static constexpr T to_normalized_uint(U v)
65 {
66 const U saturated = v > U{0.0} ? (v < U{1.0} ? v : U{1.0}) : U{0.0};
67 return static_cast<T>(static_cast<U>(std::numeric_limits<T>::max()) * saturated);
68 }
69
70 T value_ = 0;
71 };
72
73 // tag `Unorm<T>` as scalar-like, so that other parts of the codebase (e.g.
74 // vectors, matrices) accept it
75 template<std::unsigned_integral T>
76 struct IsScalar<Unorm<T>> final {
77 static constexpr bool value = true;
78 };
79
80 template<std::unsigned_integral T>
81 std::ostream& operator<<(std::ostream& o, const Unorm<T>& unorm)
82 {
83 return o << unorm.normalized_value();
84 }
85
86 // returns the equivalent of `a + t(b - a)` (linear interpolation with extrapolation),
87 // with clamping for under-/over-flow
88 template<std::unsigned_integral T, std::floating_point TInterpolant>
90 {
91 return Unorm<T>{std::lerp(a.normalized_value(), b.normalized_value(), t)};
92 }
93
94 // returns a copy of the provided `Unorm<T>`.
95 //
96 // the reason it returns a direct copy is because `saturate` for floating-point numbers
97 // clamps the number into the interval [0.0f, 1.0f]. `Unorm<T>`'s storage (unsigned
98 // integers) already map into that floating point range.
99 template<std::unsigned_integral T>
100 constexpr Unorm<T> saturate(const Unorm<T>& v)
101 {
102 return v;
103 }
104}
105
106template<std::unsigned_integral T>
107struct std::hash<osc::Unorm<T>> final {
108 size_t operator()(const osc::Unorm<T>& unorm) const
109 {
110 return std::hash<T>{}(unorm.raw_value());
111 }
112};
Definition unorm.h:20
friend auto operator<=>(const Unorm &, const Unorm &)=default
constexpr float normalized_value() const
Definition unorm.h:57
T value_type
Definition unorm.h:22
constexpr Unorm(U normalized_value)
Definition unorm.h:36
constexpr Unorm(T raw_value)
Definition unorm.h:31
constexpr Unorm(U integral_value)
Definition unorm.h:27
constexpr T raw_value() const
Definition unorm.h:52
constexpr Unorm()=default
Definition custom_decoration_generator.h:5
std::ostream & operator<<(std::ostream &, const Object &)
constexpr auto lerp(const Rgba< T > &x, const Rgba< T > &y, TInterpolant t)
Definition rgba.h:230
constexpr Rgba< T > saturate(const Rgba< T > &x)
Definition rgba.h:237
constexpr U to(T &&value)
Definition conversion.h:56
Definition scalar.h:11
static constexpr bool value
Definition scalar.h:12
size_t operator()(const osc::Unorm< T > &unorm) const
Definition unorm.h:108