opynsim
Unofficial C++ Documentation
Loading...
Searching...
No Matches
snorm.h
Go to the documentation of this file.
1#pragma once
2
4
5#include <compare>
6#include <concepts>
7#include <limits>
8#include <stdexcept>
9
10namespace osc
11{
12 // A normalized signed integer that can be used to store a floating-point
13 // number in the (clamped) range [-1.0f, 1.0f]
14 //
15 // see: https://www.khronos.org/opengl/wiki/Normalized_Integer
16 template<std::signed_integral T>
17 class Snorm final {
18 public:
19 using value_type = T;
20
21 constexpr Snorm() = default;
22
23 consteval Snorm(int literal) :
24 value_{static_cast<T>(literal)}
25 {
26 if (literal < std::numeric_limits<T>::min() or
27 literal > std::numeric_limits<T>::max()) {
28
29 throw std::runtime_error{"provided value is out of range"};
30 }
31 }
32
33 constexpr Snorm(T raw_value) :
34 value_{raw_value}
35 {}
36
37 constexpr Snorm(float normalized_value) :
38 value_{to_normalized_int(normalized_value)}
39 {}
40
41 friend auto operator<=>(const Snorm&, const Snorm&) = default;
42
43 explicit constexpr operator float() const
44 {
45 return normalized_value();
46 }
47
48 explicit constexpr operator T() const
49 {
50 return raw_value();
51 }
52
53 constexpr T raw_value() const
54 {
55 return value_;
56 }
57
58 constexpr float normalized_value() const
59 {
60 // remapping signed integers is trickier than unsigned ones, because
61 // `|MIN| > |MAX|`
62 //
63 // this implementation follows OpenGL 4.2+'s convention of mapping
64 // the integer range `[-MAX, MAX]` onto `[-1.0f, 1.0f]`, with
65 // the edge-case (MIN) mapping onto `-1.0f`, which ensures `0` maps
66 // onto `0.0f`
67 //
68 // see: https://www.khronos.org/opengl/wiki/Normalized_Integer
69
70 const float fvalue = static_cast<float>(value_) / static_cast<float>(std::numeric_limits<T>::max());
71 return fvalue >= -1.0f ? fvalue : -1.0f;
72 }
73
74 private:
75 static constexpr T to_normalized_int(float v)
76 {
77 const float saturated = v > -1.0f ? (v < 1.0f ? v : 1.0f) : -1.0f;
78 return static_cast<T>(127.0f * saturated);
79 }
80
81 T value_ = 0;
82 };
83
84 // tag `Snorm<T>` as scalar-like, so that other parts of the codebase (e.g.
85 // vectors, matrices) accept it
86 template<std::signed_integral T>
87 struct IsScalar<Snorm<T>> final {
88 static constexpr bool value = true;
89 };
90}
Definition snorm.h:17
constexpr float normalized_value() const
Definition snorm.h:58
consteval Snorm(int literal)
Definition snorm.h:23
constexpr Snorm()=default
constexpr T raw_value() const
Definition snorm.h:53
friend auto operator<=>(const Snorm &, const Snorm &)=default
constexpr Snorm(T raw_value)
Definition snorm.h:33
constexpr Snorm(float normalized_value)
Definition snorm.h:37
T value_type
Definition snorm.h:19
Definition custom_decoration_generator.h:5
constexpr U to(T &&value)
Definition conversion.h:56
Definition scalar.h:11
static constexpr bool value
Definition scalar.h:12