Added RGBA5551 tests file, changed template spec to use is_integral_v, implemented assignment operators, added casting operators

This commit is contained in:
Vladyslav Baranovskyi
2024-10-01 19:12:01 +03:00
parent fbd530a96e
commit dd3db1c079
2 changed files with 234 additions and 15 deletions

View File

@@ -13,7 +13,7 @@ namespace OpenVulkano::Math
{ {
class RGBA5551 class RGBA5551
{ {
static uint16_t Make5(uint8_t val) { return val * 31.0f / 255.0f; } static uint16_t Make5(uint8_t val) { return static_cast<uint16_t>(val * 31.0f / 255.0f); }
static uint8_t Unmake5(uint16_t val) { return static_cast<uint8_t>(val * 255.0f / 31.0f); } static uint8_t Unmake5(uint16_t val) { return static_cast<uint8_t>(val * 255.0f / 31.0f); }
static float Unmake5ToFloat(uint16_t val) { return std::clamp(val / 31.0f, 0.0f, 1.0f); } static float Unmake5ToFloat(uint16_t val) { return std::clamp(val / 31.0f, 0.0f, 1.0f); }
static uint16_t Make5FromFloat(float val) { return (uint16_t) std::clamp(val * 31.0f, 0.0f, 31.f); } static uint16_t Make5FromFloat(float val) { return (uint16_t) std::clamp(val * 31.0f, 0.0f, 31.f); }
@@ -33,29 +33,38 @@ namespace OpenVulkano::Math
RGBA5551() : r(0), g(0), b(0), a(1) {} RGBA5551() : r(0), g(0), b(0), a(1) {}
RGBA5551(Math::Vector4uc color) : b(Make5(color.b)), g(Make5(color.g)), r(Make5(color.r)), a(color.a > 128) {} template<typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
RGBA5551(const Math::Vector3<T>& color) : b(Make5(color.b)), g(Make5(color.g)), r(Make5(color.r)), a(1)
{
}
template<typename T, std::enable_if_t<std::is_unsigned_v<T> || std::is_signed_v<T>, bool> = true> template<typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
RGBA5551(const Math::Vector4<T>& color) RGBA5551(const Math::Vector4<T>& color)
: b(Make5(color.b)), g(Make5(color.g)), r(Make5(color.r)), a(color.a > 128) : b(Make5(color.b)), g(Make5(color.g)), r(Make5(color.r)), a(color.a > 128)
{ {
} }
template<typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
RGBA5551(const Math::Vector3<T>& color)
: b(Make5FromFloat(color.b)), g(Make5FromFloat(color.g)), r(Make5FromFloat(color.r)), a(1)
{
}
template<typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true> template<typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
RGBA5551(const Math::Vector4<T>& color) RGBA5551(const Math::Vector4<T>& color)
: b(Make5FromFloat(color.b)), g(Make5FromFloat(color.g)), r(Make5FromFloat(color.r)), a(color.a > 0.5f) : b(Make5FromFloat(color.b)), g(Make5FromFloat(color.g)), r(Make5FromFloat(color.r)), a(color.a > 0.5f)
{ {
} }
uint8_t GetR() { return Unmake5(r); } uint8_t GetR() const { return Unmake5(r); }
uint8_t GetG() { return Unmake5(g); } uint8_t GetG() const { return Unmake5(g); }
uint8_t GetB() { return Unmake5(b); } uint8_t GetB() const { return Unmake5(b); }
uint8_t GetA() { return a ? 255 : 0; } uint8_t GetA() const { return a ? 255 : 0; }
float GetR_Normalized() { return Unmake5ToFloat(r); } float GetR_Normalized() const { return Unmake5ToFloat(r); }
float GetG_Normalized() { return Unmake5ToFloat(g); } float GetG_Normalized() const { return Unmake5ToFloat(g); }
float GetB_Normalized() { return Unmake5ToFloat(b); } float GetB_Normalized() const { return Unmake5ToFloat(b); }
float GetA_Normalized() { return a ? 1.0f : 0.0f; } float GetA_Normalized() const { return a; }
void SetR(uint8_t red) { r = Make5(red); } void SetR(uint8_t red) { r = Make5(red); }
void SetG(uint8_t green) { g = Make5(green); } void SetG(uint8_t green) { g = Make5(green); }
@@ -67,18 +76,30 @@ namespace OpenVulkano::Math
void SetB_Normalized(float blue) { b = Make5FromFloat(blue); } void SetB_Normalized(float blue) { b = Make5FromFloat(blue); }
void SetA_Normalized(float alpha) { a = (alpha > 0.5f); } void SetA_Normalized(float alpha) { a = (alpha > 0.5f); }
template<typename T, std::enable_if_t<std::is_unsigned_v<T> || std::is_signed_v<T>, bool> = true> template<typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
Math::Vector4<T> Get4() Math::Vector3<T> Get3() const
{
return { GetR(), GetG(), GetB() };
}
template<typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
Math::Vector4<T> Get4() const
{ {
return { GetR(), GetG(), GetB(), GetA() }; return { GetR(), GetG(), GetB(), GetA() };
} }
template<typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true> template<typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
Math::Vector4<T> Get4Normalized() Math::Vector4<T> Get4Normalized() const
{ {
return { GetR_Normalized(), GetG_Normalized(), GetB_Normalized(), GetA_Normalized() }; return { GetR_Normalized(), GetG_Normalized(), GetB_Normalized(), GetA_Normalized() };
} }
template<typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
Math::Vector3<T> Get3Normalized() const
{
return { GetR_Normalized(), GetG_Normalized(), GetB_Normalized() };
}
RGBA5551& operator=(const RGBA5551& other) RGBA5551& operator=(const RGBA5551& other)
{ {
value = other.value; value = other.value;
@@ -88,6 +109,16 @@ namespace OpenVulkano::Math
bool operator==(const RGBA5551& other) const { return value == other.value; } bool operator==(const RGBA5551& other) const { return value == other.value; }
bool operator!=(const RGBA5551& other) const { return value != other.value; } bool operator!=(const RGBA5551& other) const { return value != other.value; }
template<typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
RGBA5551& operator=(const Math::Vector3<T>& color)
{
SetR_Normalized(color.r);
SetG_Normalized(color.g);
SetB_Normalized(color.b);
SetA_Normalized(1);
return *this;
}
template<typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true> template<typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
RGBA5551& operator=(const Math::Vector4<T>& color) RGBA5551& operator=(const Math::Vector4<T>& color)
{ {
@@ -98,7 +129,17 @@ namespace OpenVulkano::Math
return *this; return *this;
} }
template<typename T, std::enable_if_t<std::is_unsigned_v<T> || std::is_signed_v<T>, bool> = true> template<typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
RGBA5551& operator=(const Math::Vector3<T>& color)
{
SetR(color.r);
SetG(color.g);
SetB(color.b);
SetA(255);
return *this;
}
template<typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
RGBA5551& operator=(const Math::Vector4<T>& color) RGBA5551& operator=(const Math::Vector4<T>& color)
{ {
SetR(color.r); SetR(color.r);
@@ -107,6 +148,30 @@ namespace OpenVulkano::Math
SetA(color.a); SetA(color.a);
return *this; return *this;
} }
template<typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
operator Math::Vector3<T>() const
{
return Get3<T>();
}
template<typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
operator Math::Vector3<T>() const
{
return Get3Normalized<T>();
}
template<typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
operator Math::Vector4<T>() const
{
return Get4<T>();
}
template<typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
operator Math::Vector4<T>() const
{
return Get4Normalized<T>();
}
}; };
static_assert(sizeof(RGBA5551) == 2); static_assert(sizeof(RGBA5551) == 2);

154
tests/RGBA5551.cpp Normal file
View File

@@ -0,0 +1,154 @@
/*
* 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/.
*/
#include <catch2/catch_all.hpp>
#include <cmath>
#include "Math/RGBA5551.hpp"
using namespace OpenVulkano::Math;
bool almostEqual(float a, float b, float epsilon = 0.001f) { return std::fabs(a - b) < epsilon; }
TEST_CASE("test_rgba5551_default_ctor", "[RGBA5551]")
{
RGBA5551 color;
REQUIRE(color.GetR() == 0);
REQUIRE(color.GetG() == 0);
REQUIRE(color.GetB() == 0);
REQUIRE(color.GetA() == 255);
}
TEST_CASE("test_rgba5551_creation", "[RGBA5551]")
{
RGBA5551 color1(Vector4uc(255, 255, 255, 129));
REQUIRE(color1.r == 31);
REQUIRE(color1.g == 31);
REQUIRE(color1.b == 31);
REQUIRE(color1.a == 1);
RGBA5551 color2(Vector4f(1.0f, 1.0f, 1.0f, 1.0f));
REQUIRE(color2.r == 31);
REQUIRE(color2.g == 31);
REQUIRE(color2.b == 31);
REQUIRE(color2.a == 1);
RGBA5551 color3(Vector4i(128, 128, 128, 0));
REQUIRE(color3.r == 15);
REQUIRE(color3.g == 15);
REQUIRE(color3.b == 15);
REQUIRE(color3.a == 0);
}
TEST_CASE("test_rgba5551_conversion_to_vector3", "[RGBA5551]")
{
RGBA5551 color(Vector4i(255, 0, 0, 1));
Vector3f vec = color.Get3Normalized<float>();
REQUIRE(almostEqual(vec.x, 1.0f));
REQUIRE(almostEqual(vec.y, 0.0f));
REQUIRE(almostEqual(vec.z, 0.0f));
Vector3f vec3 { 0.1f, 0.5f, 1.0f };
RGBA5551 color2(vec3);
REQUIRE(almostEqual(color2.GetR_Normalized(), 0.096f));
REQUIRE(almostEqual(color2.GetG_Normalized(), 0.483f));
REQUIRE(almostEqual(color2.GetB_Normalized(), 1.0f));
REQUIRE(almostEqual(color2.GetA_Normalized(), 1.0f));
}
TEST_CASE("test_rgba5551_conversion_to_vector4", "[RGBA5551]")
{
RGBA5551 color(Vector4i(255, 0, 0, 129));
Vector4f vec = color.Get4Normalized<float>();
REQUIRE(almostEqual(vec.x, 1.0f));
REQUIRE(almostEqual(vec.y, 0.0f));
REQUIRE(almostEqual(vec.z, 0.0f));
REQUIRE(almostEqual(vec.w, 1.0f));
}
TEST_CASE("test_rgba5551_conversion_from_vector3", "[RGBA5551]")
{
Vector3f vec(1.0f, 0.5f, 0.25f);
RGBA5551 color(vec);
REQUIRE(color.r == 31);
REQUIRE(color.g == 15);
REQUIRE(color.b == 7);
REQUIRE(color.a == 1);
}
TEST_CASE("test_rgba5551_conversion_from_vector4", "[RGBA5551]")
{
Vector4f vec(0.0f, 1.0f, 0.5f, 0.0f);
RGBA5551 color(vec);
REQUIRE(color.r == 0);
REQUIRE(color.g == 31);
REQUIRE(color.b == 15);
REQUIRE(color.a == 0);
}
TEST_CASE("test_rgba5551_cast_to_vector4", "[RGBA5551]")
{
RGBA5551 color;
color.r = 31;
color.g = 15;
color.b = 7;
color.a = 1;
Vector4f casted = (Vector4f)color;
REQUIRE(almostEqual(casted.r, 1.0));
REQUIRE(almostEqual(casted.g, 0.483));
REQUIRE(almostEqual(casted.b, 0.225));
REQUIRE(almostEqual(casted.a, 1));
}
TEST_CASE("test_rgba5551_getters_setters", "[RGBA5551]")
{
RGBA5551 color;
color.SetR_Normalized(0.1f);
color.SetG_Normalized(0.5f);
color.SetB_Normalized(1.0f);
color.SetA_Normalized(0.7f);
REQUIRE(almostEqual(color.GetR_Normalized(), 0.096f));
REQUIRE(almostEqual(color.GetG_Normalized(), 0.483f));
REQUIRE(almostEqual(color.GetB_Normalized(), 1.0f));
REQUIRE(color.GetA() == 255);
color = RGBA5551(Vector3<uint8_t> { 255, 127, 63 });
Vector3<uint8_t> vec3 = color;
REQUIRE(vec3.r == 255);
REQUIRE(vec3.g == 123);
REQUIRE(vec3.b == 57);
}
TEST_CASE("test_rgba5551_comparison", "[RGBA5551]")
{
RGBA5551 color1(Vector4<uint8_t>{255, 127, 63, 255});
RGBA5551 color2(Vector4<uint8_t>{255, 127, 63, 255});
RGBA5551 color3(Vector4<uint8_t>{63, 127, 255, 255});
REQUIRE(color1 == color2);
REQUIRE(color1 != color3);
{
RGBA5551 color4 = color1;
REQUIRE(color4 == color1);
}
Vector3<uint8_t> vec3 { 255, 127, 63 };
color1 = vec3;
REQUIRE(color1.GetR() == 255);
REQUIRE(color1.GetG() == 123);
REQUIRE(color1.GetB() == 57);
REQUIRE(color1.GetA() == 255);
Vector4<float> vec4 { 0.1f, 0.5f, 1.0f, 0.7f };
color1 = vec4;
REQUIRE(almostEqual(color1.GetR_Normalized(), 0.096f));
REQUIRE(almostEqual(color1.GetG_Normalized(), 0.483f));
REQUIRE(almostEqual(color1.GetB_Normalized(), 1.0f));
REQUIRE(color1.GetA() == 255);
}