1
0
mirror of https://github.com/borgesdan/xn65 synced 2024-12-29 21:54:47 +01:00
xn65/framework/common/packedvalue.hpp
2024-04-14 16:11:15 -03:00

84 lines
2.1 KiB
C++

#ifndef CXNA_COMMON_PACKEDVECTOR_HPP
#define CXNA_COMMON_PACKEDVECTOR_HPP
#include "vectors.hpp"
#include <cmath>
#include "../default.hpp"
namespace xna {
class IPackedVector {
virtual Vector4 ToVector4() const = 0;
virtual void PackFromVector4(Vector4 const& vector) = 0;
};
template <typename T>
class IPackedVectorT {
virtual T PackedValue() const = 0;
virtual void PackedValue(T const& value) = 0;
};
struct PackUtils {
static Uint PackUnsigned(float bitmask, float value) {
return static_cast<Uint>(ClampAndRound(value, 0.0f, bitmask));
}
static Uint PackSigned(Uint bitmask, float value) {
const auto max = static_cast<float>(bitmask >> 1);
const auto min = -max - 1.0F;
return static_cast<Uint>(ClampAndRound(value, min, max)) & bitmask;
}
static Uint PackUNorm(float bitmask, float value) {
value *= bitmask;
return static_cast<Uint>(ClampAndRound(value, 0.0f, bitmask));
}
static constexpr float UnpackUNorm(Uint bitmask, Uint value) {
value &= bitmask;
return static_cast<float>(value) / static_cast<float>(bitmask);
}
static Uint PackSNorm(Uint bitmask, float value) {
const auto max = static_cast<float>(bitmask >> 1);
value *= max;
return static_cast<Uint>(ClampAndRound(value, -max, max)) & bitmask;
}
static constexpr float UnpackSNorm(Uint bitmask, Uint value) {
const auto num1 = (bitmask + 1U) >> 1;
const auto ivalue = static_cast<Int>(value);
const auto inum1 = static_cast<Int>(num1);
const auto ibitmask = static_cast<Int>(bitmask);
if ((ivalue & inum1) != 0) {
if ((ivalue & ibitmask) == inum1)
return -1.0f;
value |= ~bitmask;
}
else
value &= bitmask;
const auto num2 = static_cast<float>(bitmask >> 1);
return static_cast<Int>(value) / num2;
}
static double ClampAndRound(float value, float min, float max) {
if (isnan(value))
return 0.0;
if (isinf(value))
return value < 0 ? static_cast<double>(min) : static_cast<double>(max);
if (value < min)
return static_cast<double>(min);
return value > max ? static_cast<double>(max) : std::round(static_cast<double>(value));
}
};
}
#endif