Plasma Engine  2.0
Loading...
Searching...
No Matches
Math_inl.h
1#pragma once
2
3#include <algorithm>
4
5namespace plMath
6{
7 template <typename T>
8 constexpr PL_ALWAYS_INLINE T Square(T f)
9 {
10 return (f * f);
11 }
12
13 template <typename T>
14 constexpr PL_ALWAYS_INLINE T Sign(T f)
15 {
16 return (f < 0 ? T(-1) : f > 0 ? T(1)
17 : 0);
18 }
19
20 template <typename T>
21 constexpr PL_ALWAYS_INLINE T Abs(T f)
22 {
23 return (f < 0 ? -f : f);
24 }
25
26 template <typename T>
27 constexpr PL_ALWAYS_INLINE T Min(T f1, T f2)
28 {
29 return (f2 < f1 ? f2 : f1);
30 }
31
32 template <typename T, typename... ARGS>
33 constexpr PL_ALWAYS_INLINE T Min(T f1, T f2, ARGS... f)
34 {
35 return Min(Min(f1, f2), f...);
36 }
37
38 template <typename T>
39 constexpr PL_ALWAYS_INLINE T Max(T f1, T f2)
40 {
41 return (f1 < f2 ? f2 : f1);
42 }
43
44 template <typename T, typename... ARGS>
45 constexpr PL_ALWAYS_INLINE T Max(T f1, T f2, ARGS... f)
46 {
47 return Max(Max(f1, f2), f...);
48 }
49
50 template <typename T>
51 constexpr PL_ALWAYS_INLINE T Clamp(T value, T min_val, T max_val)
52 {
53 return value < min_val ? min_val : (max_val < value ? max_val : value);
54 }
55
56 template <typename T>
57 constexpr PL_ALWAYS_INLINE T Saturate(T value)
58 {
59 return Clamp(value, T(0), T(1));
60 }
61
62 template <typename Type>
63 constexpr Type Invert(Type f)
64 {
65 static_assert(std::is_floating_point_v<Type>);
66
67 return ((Type)1) / f;
68 }
69
70 PL_ALWAYS_INLINE plUInt32 FirstBitLow(plUInt32 value)
71 {
72 PL_ASSERT_DEBUG(value != 0, "FirstBitLow is undefined for 0");
73
74#if PL_ENABLED(PL_PLATFORM_WINDOWS)
75 unsigned long uiIndex = 0;
76 _BitScanForward(&uiIndex, value);
77 return uiIndex;
78#elif PL_ENABLED(PL_COMPILER_GCC) || PL_ENABLED(PL_COMPILER_CLANG)
79 return __builtin_ctz(value);
80#else
81 PL_ASSERT_NOT_IMPLEMENTED;
82 return 0;
83#endif
84 }
85
86 PL_ALWAYS_INLINE plUInt32 FirstBitLow(plUInt64 value)
87 {
88 PL_ASSERT_DEBUG(value != 0, "FirstBitLow is undefined for 0");
89
90#if __castxml__
91 return 0;
92#elif PL_ENABLED(PL_PLATFORM_WINDOWS)
93 unsigned long uiIndex = 0;
94# if PL_ENABLED(PL_PLATFORM_64BIT)
95
96 _BitScanForward64(&uiIndex, value);
97# else
98 uint32_t lower = static_cast<uint32_t>(value);
99 unsigned char returnCode = _BitScanForward(&uiIndex, lower);
100 if (returnCode == 0)
101 {
102 uint32_t upper = static_cast<uint32_t>(value >> 32);
103 returnCode = _BitScanForward(&uiIndex, upper);
104 if (returnCode > 0) // Only can happen in Release build when PL_ASSERT_DEBUG(value != 0) would fail.
105 {
106 uiIndex += 32; // Add length of lower to index.
107 }
108 }
109# endif
110 return uiIndex;
111#elif PL_ENABLED(PL_COMPILER_GCC) || PL_ENABLED(PL_COMPILER_CLANG)
112 return __builtin_ctzll(value);
113#else
114 PL_ASSERT_NOT_IMPLEMENTED;
115 return 0;
116#endif
117 }
118
119 PL_ALWAYS_INLINE plUInt32 FirstBitHigh(plUInt32 value)
120 {
121 PL_ASSERT_DEBUG(value != 0, "FirstBitHigh is undefined for 0");
122
123#if PL_ENABLED(PL_PLATFORM_WINDOWS)
124 unsigned long uiIndex = 0;
125 _BitScanReverse(&uiIndex, value);
126 return uiIndex;
127#elif PL_ENABLED(PL_COMPILER_GCC) || PL_ENABLED(PL_COMPILER_CLANG)
128 return 31 - __builtin_clz(value);
129#else
130 PL_ASSERT_NOT_IMPLEMENTED;
131 return 0;
132#endif
133 }
134
135 PL_ALWAYS_INLINE plUInt32 FirstBitHigh(plUInt64 value)
136 {
137 PL_ASSERT_DEBUG(value != 0, "FirstBitHigh is undefined for 0");
138
139#if __castxml__
140 return 0;
141#elif PL_ENABLED(PL_PLATFORM_WINDOWS)
142 unsigned long uiIndex = 0;
143# if PL_ENABLED(PL_PLATFORM_64BIT)
144 _BitScanReverse64(&uiIndex, value);
145# else
146 uint32_t upper = static_cast<uint32_t>(value >> 32);
147 unsigned char returnCode = _BitScanReverse(&uiIndex, upper);
148 if (returnCode == 0)
149 {
150 uint32_t lower = static_cast<uint32_t>(value);
151 returnCode = _BitScanReverse(&uiIndex, lower);
152 }
153 else
154 {
155 uiIndex += 32; // Add length of upper to index.
156 }
157# endif
158 return uiIndex;
159#elif PL_ENABLED(PL_COMPILER_GCC) || PL_ENABLED(PL_COMPILER_CLANG)
160 return 63 - __builtin_clzll(value);
161#else
162 PL_ASSERT_NOT_IMPLEMENTED;
163 return 0;
164#endif
165 }
166
167 PL_ALWAYS_INLINE plUInt32 CountTrailingZeros(plUInt32 uiBitmask)
168 {
169 return (uiBitmask == 0) ? 32 : FirstBitLow(uiBitmask);
170 }
171
172 PL_ALWAYS_INLINE plUInt32 CountTrailingZeros(plUInt64 uiBitmask)
173 {
174 const plUInt32 numLow = CountTrailingZeros(static_cast<plUInt32>(uiBitmask & 0xFFFFFFFF));
175 const plUInt32 numHigh = CountTrailingZeros(static_cast<plUInt32>((uiBitmask >> 32u) & 0xFFFFFFFF));
176
177 return (numLow == 32) ? (32 + numHigh) : numLow;
178 }
179
180 PL_ALWAYS_INLINE plUInt32 CountLeadingZeros(plUInt32 uiBitmask)
181 {
182 return (uiBitmask == 0) ? 32 : (31u - FirstBitHigh(uiBitmask));
183 }
184
185
186 PL_ALWAYS_INLINE plUInt32 CountBits(plUInt32 value)
187 {
188#if PL_ENABLED(PL_COMPILER_MSVC) && (PL_ENABLED(PL_PLATFORM_ARCH_X86) || (PL_ENABLED(PL_PLATFORM_ARCH_ARM) && PL_ENABLED(PL_PLATFORM_32BIT)))
189# if PL_ENABLED(PL_PLATFORM_ARCH_X86)
190 return __popcnt(value);
191# else
192 return _CountOneBits(value);
193# endif
194#elif PL_ENABLED(PL_COMPILER_GCC) || PL_ENABLED(PL_COMPILER_CLANG)
195 return __builtin_popcount(value);
196#else
197 value = value - ((value >> 1) & 0x55555555u);
198 value = (value & 0x33333333u) + ((value >> 2) & 0x33333333u);
199 return ((value + (value >> 4) & 0xF0F0F0Fu) * 0x1010101u) >> 24;
200#endif
201 }
202
203 PL_ALWAYS_INLINE plUInt32 CountBits(plUInt64 value)
204 {
205 plUInt32 result = 0;
206 result += CountBits(plUInt32(value));
207 result += CountBits(plUInt32(value >> 32));
208 return result;
209 }
210
211 template <typename Type>
212 PL_ALWAYS_INLINE Type Bitmask_LowN(plUInt32 uiNumBitsToSet)
213 {
214 return (uiNumBitsToSet >= sizeof(Type) * 8) ? ~static_cast<Type>(0) : ((static_cast<Type>(1) << uiNumBitsToSet) - static_cast<Type>(1));
215 }
216
217 template <typename Type>
218 PL_ALWAYS_INLINE Type Bitmask_HighN(plUInt32 uiNumBitsToSet)
219 {
220 return (uiNumBitsToSet == 0) ? 0 : ~static_cast<Type>(0) << ((sizeof(Type) * 8) - plMath::Min<plUInt32>(uiNumBitsToSet, sizeof(Type) * 8));
221 }
222
223 template <typename T>
224 PL_ALWAYS_INLINE void Swap(T& ref_f1, T& ref_f2)
225 {
226 std::swap(ref_f1, ref_f2);
227 }
228
229 template <typename T>
230 PL_FORCE_INLINE T Lerp(T f1, T f2, float fFactor)
231 {
232 // value is not included in format string, to prevent requirement on FormatString.h, to break #include cycles
233 PL_ASSERT_DEBUG((fFactor >= -0.00001f) && (fFactor <= 1.0f + 0.00001f), "lerp: factor is not in the range [0; 1]");
234
235 return (T)(f1 + (fFactor * (f2 - f1)));
236 }
237
238 template <typename T>
239 PL_FORCE_INLINE T Lerp(T f1, T f2, double fFactor)
240 {
241 // value is not included in format string, to prevent requirement on FormatString.h, to break #include cycles
242 PL_ASSERT_DEBUG((fFactor >= -0.00001) && (fFactor <= 1.0 + 0.00001), "lerp: factor is not in the range [0; 1]");
243
244 return (T)(f1 + (fFactor * (f2 - f1)));
245 }
246
247 template <typename T>
248 PL_FORCE_INLINE constexpr float Unlerp(T fMin, T fMax, T fValue)
249 {
250 return static_cast<float>(fValue - fMin) / static_cast<float>(fMax - fMin);
251 }
252
254 template <typename T>
255 constexpr PL_FORCE_INLINE T Step(T value, T edge)
256 {
257 return (value >= edge ? T(1) : T(0));
258 }
259
260 constexpr PL_FORCE_INLINE bool IsPowerOf2(plInt32 value)
261 {
262 return (value < 1) ? false : ((value & (value - 1)) == 0);
263 }
264
265 constexpr PL_FORCE_INLINE bool IsPowerOf2(plUInt32 value)
266 {
267 return (value < 1) ? false : ((value & (value - 1)) == 0);
268 }
269
270 constexpr PL_FORCE_INLINE bool IsPowerOf2(plUInt64 value)
271 {
272 return (value < 1) ? false : ((value & (value - 1)) == 0);
273 }
274
275 template <typename Type>
276 constexpr bool IsEqual(Type lhs, Type rhs, Type fEpsilon)
277 {
278 return ((rhs >= lhs - fEpsilon) && (rhs <= lhs + fEpsilon));
279 }
280
281 template <typename T>
282 constexpr inline bool IsInRange(T value, T minVal, T maxVal)
283 {
284 return minVal < maxVal ? (value >= minVal) && (value <= maxVal) : (value <= minVal) && (value >= maxVal);
285 }
286
287 template <typename Type>
288 bool IsZero(Type f, Type fEpsilon)
289 {
290 PL_ASSERT_DEBUG(fEpsilon >= 0, "Epsilon may not be negative.");
291
292 return ((f >= -fEpsilon) && (f <= fEpsilon));
293 }
294
295 template <typename Type>
296 PL_ALWAYS_INLINE Type Trunc(Type f)
297 {
298 if (f > 0)
299 return Floor(f);
300
301 return Ceil(f);
302 }
303
304 template <typename Type>
305 PL_ALWAYS_INLINE Type Fraction(Type f)
306 {
307 return (f - Trunc(f));
308 }
309
310 template <typename Type>
311 inline Type SmoothStep(Type x, Type edge1, Type edge2)
312 {
313 const Type divider = edge2 - edge1;
314
315 if (divider == (Type)0)
316 {
317 return (x >= edge2) ? 1 : 0;
318 }
319
320 x = Saturate((x - edge1) / divider);
321
322 return (x * x * ((Type)3 - ((Type)2 * x)));
323 }
324
325 template <typename Type>
326 inline Type SmootherStep(Type x, Type edge1, Type edge2)
327 {
328 const Type divider = edge2 - edge1;
329
330 if (divider == (Type)0)
331 {
332 return (x >= edge2) ? 1 : 0;
333 }
334
335 x = Saturate((x - edge1) / divider);
336
337 return (x * x * x * (x * ((Type)6 * x - (Type)15) + (Type)10));
338 }
339
340 inline plUInt8 ColorFloatToByte(float value)
341 {
342 // Implemented according to
343 // https://docs.microsoft.com/windows/desktop/direct3d10/d3d10-graphics-programming-guide-resources-data-conversion
344 if (IsNaN(value))
345 {
346 return 0;
347 }
348 else
349 {
350 return static_cast<plUInt8>(Saturate(value) * 255.0f + 0.5f);
351 }
352 }
353
354 inline plUInt16 ColorFloatToShort(float value)
355 {
356 // Implemented according to
357 // https://docs.microsoft.com/windows/desktop/direct3d10/d3d10-graphics-programming-guide-resources-data-conversion
358 if (IsNaN(value))
359 {
360 return 0;
361 }
362 else
363 {
364 return static_cast<plUInt16>(Saturate(value) * 65535.0f + 0.5f);
365 }
366 }
367
368 inline plInt8 ColorFloatToSignedByte(float value)
369 {
370 // Implemented according to
371 // https://docs.microsoft.com/windows/desktop/direct3d10/d3d10-graphics-programming-guide-resources-data-conversion
372 if (IsNaN(value))
373 {
374 return 0;
375 }
376 else
377 {
378 value = Clamp(value, -1.0f, 1.0f) * 127.0f;
379 if (value >= 0.0f)
380 {
381 value += 0.5f;
382 }
383 else
384 {
385 value -= 0.5f;
386 }
387 return static_cast<plInt8>(value);
388 }
389 }
390
391 inline plInt16 ColorFloatToSignedShort(float value)
392 {
393 // Implemented according to
394 // https://docs.microsoft.com/windows/desktop/direct3d10/d3d10-graphics-programming-guide-resources-data-conversion
395 if (IsNaN(value))
396 {
397 return 0;
398 }
399 else
400 {
401 value = Clamp(value, -1.0f, 1.0f) * 32767.0f;
402 if (value >= 0.0f)
403 {
404 value += 0.5f;
405 }
406 else
407 {
408 value -= 0.5f;
409 }
410 return static_cast<plInt16>(value);
411 }
412 }
413
414 constexpr inline float ColorByteToFloat(plUInt8 value)
415 {
416 // Implemented according to
417 // https://docs.microsoft.com/windows/desktop/direct3d10/d3d10-graphics-programming-guide-resources-data-conversion
418 return value * (1.0f / 255.0f);
419 }
420
421 constexpr inline float ColorShortToFloat(plUInt16 value)
422 {
423 // Implemented according to
424 // https://docs.microsoft.com/windows/desktop/direct3d10/d3d10-graphics-programming-guide-resources-data-conversion
425 return value * (1.0f / 65535.0f);
426 }
427
428 constexpr inline float ColorSignedByteToFloat(plInt8 value)
429 {
430 // Implemented according to
431 // https://docs.microsoft.com/windows/desktop/direct3d10/d3d10-graphics-programming-guide-resources-data-conversion
432 return (value == -128) ? -1.0f : value * (1.0f / 127.0f);
433 }
434
435 constexpr inline float ColorSignedShortToFloat(plInt16 value)
436 {
437 // Implemented according to
438 // https://docs.microsoft.com/windows/desktop/direct3d10/d3d10-graphics-programming-guide-resources-data-conversion
439 return (value == -32768) ? -1.0f : value * (1.0f / 32767.0f);
440 }
441
442 template <typename T, typename T2>
443 T EvaluateBezierCurve(T2 t, const T& startPoint, const T& controlPoint1, const T& controlPoint2, const T& endPoint)
444 {
445 const T2 mt = 1 - t;
446
447 const T2 f1 = mt * mt * mt;
448 const T2 f2 = 3 * mt * mt * t;
449 const T2 f3 = 3 * mt * t * t;
450 const T2 f4 = t * t * t;
451
452 return f1 * startPoint + f2 * controlPoint1 + f3 * controlPoint2 + f4 * endPoint;
453 }
454} // namespace plMath
455
456constexpr PL_FORCE_INLINE plAngle plAngle::AngleBetween(plAngle a, plAngle b)
457{
458 // taken from http://gamedev.stackexchange.com/questions/4467/comparing-angles-and-working-out-the-difference
459 return plAngle(Pi<float>() - plMath::Abs(plMath::Abs(a.GetRadian() - b.GetRadian()) - Pi<float>()));
460}
461
462constexpr PL_FORCE_INLINE plInt32 plMath::FloatToInt(float value)
463{
464 return static_cast<plInt32>(value);
465}
466
467#if PL_DISABLED(PL_PLATFORM_ARCH_X86) || (_MSC_VER <= 1916)
468constexpr PL_FORCE_INLINE plInt64 plMath::FloatToInt(double value)
469{
470 return static_cast<plInt64>(value);
471}
472#endif
473
474PL_ALWAYS_INLINE plResult plMath::TryConvertToSizeT(size_t& out_uiResult, plUInt64 uiValue)
475{
476#if PL_ENABLED(PL_PLATFORM_32BIT)
477 if (uiValue <= MaxValue<size_t>())
478 {
479 out_uiResult = static_cast<size_t>(uiValue);
480 return PL_SUCCESS;
481 }
482
483 return PL_FAILURE;
484#else
485 out_uiResult = static_cast<size_t>(uiValue);
486 return PL_SUCCESS;
487#endif
488}
489
490#if PL_ENABLED(PL_PLATFORM_64BIT)
491PL_ALWAYS_INLINE size_t plMath::SafeConvertToSizeT(plUInt64 uiValue)
492{
493 return uiValue;
494}
495#endif
Float wrapper struct for a safe usage and conversions of angles.
Definition Angle.h:10
constexpr plAngle()
Standard constructor, initializing with 0.
Definition Angle.h:40
constexpr float GetRadian() const
Returns the radian value. (No need for any conversion)
Definition Angle_inl.h:48
static constexpr plAngle AngleBetween(plAngle a, plAngle b)
Computes the smallest angle between the two given angles. The angle will always be a positive value.
Definition Math_inl.h:456
This namespace provides common math-functionality as functions.
Definition Constants.h:6
plInt8 ColorFloatToSignedByte(float value)
Converts a color value from float [-1;1] range to signed byte [-127;127] range, with proper rounding.
Definition Math_inl.h:368
constexpr plInt32 FloatToInt(float value)
Casts the float to an integer, removes the fractional part.
Definition Math_inl.h:462
PL_FORCE_INLINE constexpr float Unlerp(T fMin, T fMax, T fValue)
Returns the interpolation factor such that Lerp(fMin, fMax, factor) == fValue.
Definition Math_inl.h:248
T EvaluateBezierCurve(T2 t, const T &startPoint, const T &controlPoint1, const T &controlPoint2, const T &endPoint)
Evaluates the cubic spline defined by four control points at time t and returns the interpolated resu...
Definition Math_inl.h:443
constexpr PL_ALWAYS_INLINE T Square(T f)
Returns f * f.
Definition Math_inl.h:8
PL_FORCE_INLINE T Lerp(T f1, T f2, float fFactor)
Returns the linear interpolation of f1 and f2. factor is a value between 0 and 1.
Definition Math_inl.h:230
constexpr PL_ALWAYS_INLINE T Min(T f1, T f2)
Returns the smaller value, f1 or f2.
Definition Math_inl.h:27
PL_ALWAYS_INLINE plUInt32 FirstBitHigh(plUInt32 value)
Returns the index of the most significant bit set.
Definition Math_inl.h:119
PL_ALWAYS_INLINE Type Fraction(Type f)
Returns the fraction-part of f.
Definition Math_inl.h:305
constexpr Type Invert(Type f)
Returns 1 / f.
Definition Math_inl.h:63
constexpr PL_ALWAYS_INLINE T Clamp(T value, T min_val, T max_val)
Clamps "value" to the range [min; max]. Returns "value", if it is inside the range already.
Definition Math_inl.h:51
plUInt8 ColorFloatToByte(float value)
Converts a color value from float [0;1] range to unsigned byte [0;255] range, with proper rounding.
Definition Math_inl.h:340
PL_ALWAYS_INLINE plUInt32 FirstBitLow(plUInt32 value)
Returns the index of the least significant bit set.
Definition Math_inl.h:70
constexpr float ColorSignedByteToFloat(plInt8 value)
Converts a color value from signed byte [-128;127] range to float [-1;1] range, with proper rounding.
Definition Math_inl.h:428
PL_FOUNDATION_DLL size_t SafeConvertToSizeT(plUInt64 uiValue)
Checks whether the given 64bit value actually fits into size_t, If it doesn't the program is terminat...
plInt16 ColorFloatToSignedShort(float value)
Converts a color value from float [-1;1] range to signed short [-32767;32767] range,...
Definition Math_inl.h:391
constexpr bool IsInRange(T value, T minVal, T maxVal)
Checks whether the value of the first parameter lies between the value of the second and third.
Definition Math_inl.h:282
plUInt16 ColorFloatToShort(float value)
Converts a color value from float [0;1] range to unsigned short [0;65535] range, with proper rounding...
Definition Math_inl.h:354
constexpr float ColorByteToFloat(plUInt8 value)
Converts a color value from unsigned byte [0;255] range to float [0;1] range, with proper rounding.
Definition Math_inl.h:414
constexpr float ColorSignedShortToFloat(plInt16 value)
Converts a color value from signed short [-32768;32767] range to float [0;1] range,...
Definition Math_inl.h:435
Type SmootherStep(Type x, Type edge1, Type edge2)
Returns 0, if value is <= edge1, 1 if value >= edge2 and the second order hermite interpolation in be...
Definition Math_inl.h:326
PL_ALWAYS_INLINE plUInt32 CountBits(plUInt32 value)
Returns the number of bits set.
Definition Math_inl.h:186
PL_ALWAYS_INLINE Type Bitmask_LowN(plUInt32 uiNumBitsToSet)
Creates a bitmask in which the low N bits are set. For example for N=5, this would be '0000 ....
Definition Math_inl.h:212
PL_ALWAYS_INLINE plUInt32 CountLeadingZeros(plUInt32 uiBitmask)
Definition Math_inl.h:180
constexpr PL_ALWAYS_INLINE T Sign(T f)
Returns the sign of f (i.e: -1, 1 or 0)
Definition Math_inl.h:14
bool IsZero(Type f, Type fEpsilon)
Checks whether the given number is close to zero.
Definition Math_inl.h:288
constexpr bool IsEqual(Type lhs, Type rhs, Type fEpsilon)
Checks, whether fValue is in the range [fDesired - fMaxImprecision; fDesired + fMaxImprecision].
Definition Math_inl.h:276
PL_ALWAYS_INLINE Type Trunc(Type f)
Returns the integer-part of f (removes the fraction).
Definition Math_inl.h:296
PL_ALWAYS_INLINE void Swap(T &ref_f1, T &ref_f2)
Swaps the values in the two variables f1 and f2.
Definition Math_inl.h:224
constexpr PL_ALWAYS_INLINE T Abs(T f)
Returns the absolute value of f.
Definition Math_inl.h:21
plResult TryConvertToSizeT(size_t &out_uiResult, plUInt64 uiValue)
Checks whether the given 64bit value actually fits into size_t, If it doesn't PL_FAILURE is returned.
Definition Math_inl.h:474
constexpr PL_ALWAYS_INLINE T Saturate(T value)
Clamps "value" to the range [0; 1]. Returns "value", if it is inside the range already.
Definition Math_inl.h:57
constexpr PL_ALWAYS_INLINE T Max(T f1, T f2)
Returns the greater value, f1 or f2.
Definition Math_inl.h:39
PL_ALWAYS_INLINE plUInt32 CountTrailingZeros(plUInt32 uiBitmask)
Definition Math_inl.h:167
Type SmoothStep(Type x, Type edge1, Type edge2)
Returns 0, if value is <= edge1, 1 if value >= edge2 and the hermite interpolation in between.
Definition Math_inl.h:311
constexpr PL_FORCE_INLINE bool IsPowerOf2(plInt32 value)
Returns true, if there exists some x with 2^x == value.
Definition Math_inl.h:260
PL_ALWAYS_INLINE Type Bitmask_HighN(plUInt32 uiNumBitsToSet)
Creates a bitmask in which the high N bits are set. For example for N=5, this would be '1111 1000 ....
Definition Math_inl.h:218
constexpr float ColorShortToFloat(plUInt16 value)
Converts a color value from unsigned short [0;65535] range to float [0;1] range, with proper rounding...
Definition Math_inl.h:421
constexpr PL_FORCE_INLINE T Step(T value, T edge)
Returns 0, if value < edge, and 1, if value >= edge.
Definition Math_inl.h:255
Default enum for returning failure or success, instead of using a bool.
Definition Types.h:54