Browse Source

Math: finally implemented precise signed/unsigned normalization.

(De)normalization from/to [0, 1] for unsigned types and from/to [-1, 1]
for signed types. -1.0 is always denormalized to min+1.

Also updated some tests for Color, as they depended on previous
imprecise implementation.
pull/7/head
Vladimír Vondruš 14 years ago
parent
commit
cade175304
  1. 51
      src/Math/Functions.h
  2. 140
      src/Math/Test/FunctionsTest.cpp
  3. 34
      src/Test/ColorTest.cpp

51
src/Math/Functions.h

@ -75,14 +75,18 @@ std::uint32_t MAGNUM_EXPORT log2(std::uint32_t number);
std::uint32_t MAGNUM_EXPORT log(std::uint32_t base, std::uint32_t number); std::uint32_t MAGNUM_EXPORT log(std::uint32_t base, std::uint32_t number);
/** /**
@brief Normalize floating-point value @brief Normalize integral value
Converts integral value from full range of given (signed/unsigned) integral Converts integral value from full range of given *unsigned* integral type to
type to value in range @f$ [0, 1] @f$. value in range @f$ [0, 1] @f$ or from *signed* integral to range @f$ [-1, 1] @f$.
@note For best precision, `FloatingPoint` type should be always larger that
resulting `Integral` type (e.g. `double` to `std::int32_t`, `long double`
to `std::int64_t`).
@attention To ensure the integral type is correctly detected when using @attention To ensure the integral type is correctly detected when using
literals, this function should be called with both template parameters literals, this function should be called with both template parameters
explicit, e.g.: explicit, e.g.:
@code @code
// Even if this is character literal, integral type is 32bit, thus a != 1.0f // Even if this is character literal, integral type is 32bit, thus a != 1.0f
float a = normalize<float>('\127'); float a = normalize<float>('\127');
@ -91,32 +95,43 @@ float a = normalize<float>('\127');
float b = normalize<float, std::int8_t>('\127'); float b = normalize<float, std::int8_t>('\127');
@endcode @endcode
@todo Signed normalization to [-1.0, 1.0] like in OpenGL? @see denormalize()
*/ */
template<class FloatingPoint, class Integral> inline constexpr typename std::enable_if<std::is_floating_point<FloatingPoint>::value && std::is_integral<Integral>::value, FloatingPoint>::type normalize(Integral value) { #ifdef DOXYGEN_GENERATING_OUTPUT
return (FloatingPoint(value)-FloatingPoint(std::numeric_limits<Integral>::min()))/ template<class FloatingPoint, class Integral> inline constexpr FloatingPoint normalize(Integral value);
(FloatingPoint(std::numeric_limits<Integral>::max()) - FloatingPoint(std::numeric_limits<Integral>::min())); #else
template<class FloatingPoint, class Integral> inline constexpr typename std::enable_if<std::is_floating_point<FloatingPoint>::value && std::is_integral<Integral>::value && std::is_unsigned<Integral>::value, FloatingPoint>::type normalize(Integral value) {
return value/FloatingPoint(std::numeric_limits<Integral>::max());
} }
template<class FloatingPoint, class Integral> inline constexpr typename std::enable_if<std::is_floating_point<FloatingPoint>::value && std::is_integral<Integral>::value && std::is_signed<Integral>::value, FloatingPoint>::type normalize(Integral value) {
return std::max(value/FloatingPoint(std::numeric_limits<Integral>::max()), FloatingPoint(-1));
}
#endif
/** /**
@brief Denormalize floating-point value @brief Denormalize floating-point value
Converts floating-point value in range @f$ [0, 1] @f$ to full range of given Converts floating-point value in range @f$ [0, 1] @f$ to full range of given
unsigned integral type or range @f$ [-1, 1] @f$ to full range of given signed
integral type. integral type.
@note For best precision, `FloatingPoint` type should be always larger that @note For best precision, `FloatingPoint` type should be always larger that
resulting `Integral` type (e.g. `double` to `std::int32_t`, `long double` to resulting `Integral` type (e.g. `double` to `std::int32_t`, `long double`
`std::int64_t`). to `std::int64_t`).
@todo Signed normalization to [-1.0, 1.0] like in OpenGL? @see normalize()
@todo Stable behavior (working/broken) for long double and long long
(currently fails in Debug builds, but passes in Release on GCC 4.7)
*/ */
template<class Integral, class FloatingPoint> inline constexpr typename std::enable_if<std::is_floating_point<FloatingPoint>::value && std::is_integral<Integral>::value, Integral>::type denormalize(FloatingPoint value) { #ifdef DOXYGEN_GENERATING_OUTPUT
return std::numeric_limits<Integral>::min() + template<class Integral, class FloatingPoint> inline constexpr typename Integral denormalize(FloatingPoint value);
round(FloatingPoint(value*std::numeric_limits<Integral>::max()) - #else
FloatingPoint(value*std::numeric_limits<Integral>::min())); template<class Integral, class FloatingPoint> inline constexpr typename std::enable_if<std::is_floating_point<FloatingPoint>::value && std::is_integral<Integral>::value && std::is_unsigned<Integral>::value, Integral>::type denormalize(FloatingPoint value) {
return value*std::numeric_limits<Integral>::max();
}
template<class Integral, class FloatingPoint> inline constexpr typename std::enable_if<std::is_floating_point<FloatingPoint>::value && std::is_integral<Integral>::value && std::is_signed<Integral>::value, Integral>::type denormalize(FloatingPoint value) {
return value*std::numeric_limits<Integral>::max();
} }
#endif
/** @brief Clamp value */ /** @brief Clamp value */
template<class T> inline T clamp(T value, T min, T max) { template<class T> inline T clamp(T value, T min, T max) {

140
src/Math/Test/FunctionsTest.cpp

@ -23,8 +23,12 @@ class FunctionsTest: public Corrade::TestSuite::Tester {
public: public:
FunctionsTest(); FunctionsTest();
void normalize(); void normalizeUnsigned();
void denormalize(); void normalizeSigned();
void denormalizeUnsigned();
void denormalizeSigned();
void renormalizeUnsinged();
void renormalizeSinged();
void clamp(); void clamp();
void pow(); void pow();
void log(); void log();
@ -32,62 +36,124 @@ class FunctionsTest: public Corrade::TestSuite::Tester {
}; };
FunctionsTest::FunctionsTest() { FunctionsTest::FunctionsTest() {
addTests(&FunctionsTest::normalize, addTests(&FunctionsTest::normalizeUnsigned,
&FunctionsTest::denormalize, &FunctionsTest::normalizeSigned,
&FunctionsTest::denormalizeUnsigned,
&FunctionsTest::denormalizeSigned,
&FunctionsTest::renormalizeUnsinged,
&FunctionsTest::renormalizeSinged,
&FunctionsTest::clamp, &FunctionsTest::clamp,
&FunctionsTest::pow, &FunctionsTest::pow,
&FunctionsTest::log, &FunctionsTest::log,
&FunctionsTest::log2); &FunctionsTest::log2);
} }
void FunctionsTest::normalize() { void FunctionsTest::normalizeUnsigned() {
/* Range for signed and unsigned */
CORRADE_COMPARE((Math::normalize<float, std::int8_t>(-128)), 0.0f);
CORRADE_COMPARE((Math::normalize<float, std::int8_t>(127)), 1.0f);
CORRADE_COMPARE((Math::normalize<float, std::uint8_t>(0)), 0.0f); CORRADE_COMPARE((Math::normalize<float, std::uint8_t>(0)), 0.0f);
CORRADE_COMPARE((Math::normalize<float, std::uint8_t>(255)), 1.0f); CORRADE_COMPARE((Math::normalize<float, std::uint8_t>(255)), 1.0f);
/* Between */ CORRADE_COMPARE((Math::normalize<double, std::uint32_t>(0)), 0.0);
CORRADE_COMPARE((Math::normalize<float, std::int16_t>(16384)), 0.750011f); CORRADE_COMPARE((Math::normalize<double, std::uint32_t>(std::numeric_limits<std::uint32_t>::max())), 1.0);
CORRADE_COMPARE((Math::normalize<float, std::int16_t>(-16384)), 0.250004f);
CORRADE_COMPARE((Math::normalize<long double, std::uint64_t>(0)), 0.0);
CORRADE_COMPARE((Math::normalize<long double, std::uint64_t>(std::numeric_limits<std::uint64_t>::max())), 1.0);
/* Test overflow for large types */ CORRADE_COMPARE((Math::normalize<float, std::uint16_t>(0)), 0.0f);
CORRADE_COMPARE((Math::normalize<float, std::int32_t>(std::numeric_limits<std::int32_t>::min())), 0.0f); CORRADE_COMPARE((Math::normalize<float, std::uint16_t>(std::numeric_limits<std::uint16_t>::max())), 1.0f);
CORRADE_COMPARE((Math::normalize<float, std::int32_t>(std::numeric_limits<std::int32_t>::max())), 1.0f);
CORRADE_COMPARE((Math::normalize<float, std::uint32_t>(0)), 0.0f);
CORRADE_COMPARE((Math::normalize<float, std::uint32_t>(std::numeric_limits<std::uint32_t>::max())), 1.0f);
CORRADE_COMPARE((Math::normalize<double, std::int64_t>(std::numeric_limits<std::int64_t>::min())), 0.0); CORRADE_COMPARE((Math::normalize<float, std::uint16_t>(8192)), 0.125002f);
CORRADE_COMPARE((Math::normalize<double, std::int64_t>(std::numeric_limits<std::int64_t>::max())), 1.0); CORRADE_COMPARE((Math::normalize<float, std::uint16_t>(49152)), 0.750011f);
CORRADE_COMPARE((Math::normalize<double, std::uint64_t>(0)), 0.0);
CORRADE_COMPARE((Math::normalize<double, std::uint64_t>(std::numeric_limits<std::uint64_t>::max())), 1.0);
} }
void FunctionsTest::denormalize() { void FunctionsTest::normalizeSigned() {
/* Range for signed and unsigned */ CORRADE_COMPARE((Math::normalize<float, std::int8_t>(127)), 1.0f);
CORRADE_COMPARE(Math::denormalize<std::int8_t>(0.0f), -128); CORRADE_COMPARE((Math::normalize<float, std::int8_t>(0)), 0.0f);
CORRADE_COMPARE(Math::denormalize<std::int8_t>(1.0f), 127); CORRADE_COMPARE((Math::normalize<float, std::int8_t>(-128)), -1.0f);
CORRADE_COMPARE((Math::normalize<float, std::int16_t>(std::numeric_limits<std::int16_t>::min())), -1.0f);
CORRADE_COMPARE((Math::normalize<float, std::int16_t>(0)), 0.0f);
CORRADE_COMPARE((Math::normalize<float, std::int16_t>(std::numeric_limits<std::int16_t>::max())), 1.0f);
CORRADE_COMPARE((Math::normalize<double, std::int32_t>(std::numeric_limits<std::int32_t>::min())), -1.0);
CORRADE_COMPARE((Math::normalize<double, std::int32_t>(0)), 0.0);
CORRADE_COMPARE((Math::normalize<double, std::int32_t>(std::numeric_limits<std::int32_t>::max())), 1.0);
CORRADE_COMPARE((Math::normalize<long double, std::int64_t>(std::numeric_limits<std::int64_t>::min())), -1.0);
CORRADE_COMPARE((Math::normalize<long double, std::int64_t>(0)), 0.0);
CORRADE_COMPARE((Math::normalize<long double, std::int64_t>(std::numeric_limits<std::int64_t>::max())), 1.0);
CORRADE_COMPARE((Math::normalize<float, std::int16_t>(16384)), 0.500015f);
CORRADE_COMPARE((Math::normalize<float, std::int16_t>(-16384)), -0.500015f);
}
void FunctionsTest::denormalizeUnsigned() {
CORRADE_COMPARE(Math::denormalize<std::uint8_t>(0.0f), 0); CORRADE_COMPARE(Math::denormalize<std::uint8_t>(0.0f), 0);
CORRADE_COMPARE(Math::denormalize<std::uint8_t>(1.0f), 255); CORRADE_COMPARE(Math::denormalize<std::uint8_t>(1.0f), 255);
/* Between */ CORRADE_COMPARE(Math::denormalize<std::uint16_t>(0.0f), 0);
CORRADE_COMPARE(Math::denormalize<std::int16_t>(0.33f), -11141); CORRADE_COMPARE(Math::denormalize<std::uint16_t>(1.0f), std::numeric_limits<std::uint16_t>::max());
CORRADE_COMPARE(Math::denormalize<std::int16_t>(0.66f), 10485);
CORRADE_COMPARE(Math::denormalize<std::uint32_t>(0.0), 0);
CORRADE_COMPARE(Math::denormalize<std::uint32_t>(1.0), std::numeric_limits<std::uint32_t>::max());
/* Test overflow for large types */
CORRADE_COMPARE(Math::denormalize<std::int32_t>(0.0f), std::numeric_limits<std::int32_t>::min());
CORRADE_COMPARE(Math::denormalize<std::uint32_t>(0.0f), 0);
CORRADE_COMPARE(Math::denormalize<std::int64_t>(0.0), std::numeric_limits<std::int64_t>::min());
CORRADE_COMPARE(Math::denormalize<std::uint64_t>(0.0), 0); CORRADE_COMPARE(Math::denormalize<std::uint64_t>(0.0), 0);
CORRADE_COMPARE(Math::denormalize<std::uint64_t>(1.0), std::numeric_limits<std::uint64_t>::max());
CORRADE_COMPARE(Math::denormalize<std::uint16_t>(0.33f), 21626);
CORRADE_COMPARE(Math::denormalize<std::uint16_t>(0.66f), 43253);
}
void FunctionsTest::denormalizeSigned() {
CORRADE_COMPARE(Math::denormalize<std::int8_t>(-1.0f), -127);
CORRADE_COMPARE(Math::denormalize<std::int8_t>(0.0f), 0);
CORRADE_COMPARE(Math::denormalize<std::int8_t>(1.0f), 127);
CORRADE_COMPARE(Math::denormalize<std::int16_t>(-1.0f), std::numeric_limits<std::int16_t>::min()+1);
CORRADE_COMPARE(Math::denormalize<std::int16_t>(0.0f), 0);
CORRADE_COMPARE(Math::denormalize<std::int16_t>(1.0f), std::numeric_limits<std::int16_t>::max());
CORRADE_COMPARE(Math::denormalize<std::int32_t>(-1.0), std::numeric_limits<std::int32_t>::min()+1);
CORRADE_COMPARE(Math::denormalize<std::int32_t>(0.0), 0);
CORRADE_COMPARE(Math::denormalize<std::int32_t>(1.0), std::numeric_limits<std::int32_t>::max()); CORRADE_COMPARE(Math::denormalize<std::int32_t>(1.0), std::numeric_limits<std::int32_t>::max());
CORRADE_COMPARE(Math::denormalize<std::uint32_t>(1.0), std::numeric_limits<std::uint32_t>::max());
// { CORRADE_COMPARE(Math::denormalize<std::int64_t>(-1.0l), std::numeric_limits<std::int64_t>::min()+1);
// CORRADE_EXPECT_FAIL("Denormalize doesn't work for large types well"); CORRADE_COMPARE(Math::denormalize<std::int64_t>(0.0l), 0);
// CORRADE_COMPARE((Math::denormalize<long long, long double>(1.0)), numeric_limits<long long>::max()); CORRADE_COMPARE(Math::denormalize<std::int64_t>(1.0l), std::numeric_limits<std::int64_t>::max());
// CORRADE_COMPARE((Math::denormalize<unsigned long long, long double>(1.0)), numeric_limits<unsigned long long>::max());
// } CORRADE_COMPARE(Math::denormalize<std::int16_t>(-0.33f), -10813);
CORRADE_COMPARE(Math::denormalize<std::int16_t>(0.66f), 21626);
}
void FunctionsTest::renormalizeUnsinged() {
CORRADE_COMPARE(Math::normalize<float>(Math::denormalize<std::uint8_t>(0.0f)), 0.0f);
CORRADE_COMPARE(Math::normalize<float>(Math::denormalize<std::uint8_t>(1.0f)), 1.0f);
CORRADE_COMPARE(Math::normalize<float>(Math::denormalize<std::uint16_t>(0.0f)), 0.0f);
CORRADE_COMPARE(Math::normalize<float>(Math::denormalize<std::uint16_t>(1.0f)), 1.0f);
CORRADE_COMPARE(Math::normalize<double>(Math::denormalize<std::uint32_t>(0.0)), 0.0);
CORRADE_COMPARE(Math::normalize<double>(Math::denormalize<std::uint32_t>(1.0)), 1.0);
CORRADE_COMPARE(Math::normalize<long double>(Math::denormalize<std::uint64_t>(0.0l)), 0.0l);
CORRADE_COMPARE(Math::normalize<long double>(Math::denormalize<std::uint64_t>(1.0l)), 1.0l);
}
void FunctionsTest::renormalizeSinged() {
CORRADE_COMPARE(Math::normalize<float>(Math::denormalize<std::int8_t>(-1.0f)), -1.0f);
CORRADE_COMPARE(Math::normalize<float>(Math::denormalize<std::int8_t>(0.0f)), 0.0f);
CORRADE_COMPARE(Math::normalize<float>(Math::denormalize<std::int8_t>(1.0f)), 1.0f);
CORRADE_COMPARE(Math::normalize<float>(Math::denormalize<std::int16_t>(-1.0f)), -1.0f);
CORRADE_COMPARE(Math::normalize<float>(Math::denormalize<std::int16_t>(0.0f)), 0.0f);
CORRADE_COMPARE(Math::normalize<float>(Math::denormalize<std::int16_t>(1.0f)), 1.0f);
CORRADE_COMPARE(Math::normalize<double>(Math::denormalize<std::int32_t>(-1.0)), -1.0);
CORRADE_COMPARE(Math::normalize<double>(Math::denormalize<std::int32_t>(0.0)), 0.0);
CORRADE_COMPARE(Math::normalize<double>(Math::denormalize<std::int32_t>(1.0)), 1.0);
CORRADE_COMPARE(Math::normalize<long double>(Math::denormalize<std::int64_t>(-1.0l)), -1.0l);
CORRADE_COMPARE(Math::normalize<long double>(Math::denormalize<std::int64_t>(0.0l)), 0.0l);
CORRADE_COMPARE(Math::normalize<long double>(Math::denormalize<std::int64_t>(1.0l)), 1.0l);
} }
void FunctionsTest::clamp() { void FunctionsTest::clamp() {

34
src/Test/ColorTest.cpp

@ -104,16 +104,16 @@ void ColorTest::fromDenormalized() {
} }
void ColorTest::fromNormalized() { void ColorTest::fromNormalized() {
CORRADE_COMPARE(Color3::fromNormalized(Color3f(0.294118, 0.45098, 0.878431)), Color3(75, 115, 224)); CORRADE_COMPARE(Color3::fromNormalized(Color3f(0.294118, 0.45098, 0.878431)), Color3(75, 114, 223));
} }
void ColorTest::fromHue() { void ColorTest::fromHue() {
CORRADE_COMPARE(Color3::fromHSV(27.0f, 1.0f, 1.0f), Color3(255, 115, 0)); CORRADE_COMPARE(Color3::fromHSV(27.0f, 1.0f, 1.0f), Color3(255, 114, 0));
CORRADE_COMPARE(Color3::fromHSV(86.0f, 1.0f, 1.0f), Color3(145, 255, 0)); CORRADE_COMPARE(Color3::fromHSV(86.0f, 1.0f, 1.0f), Color3(144, 255, 0));
CORRADE_COMPARE(Color3::fromHSV(134.0f, 1.0f, 1.0f), Color3(0, 255, 60)); CORRADE_COMPARE(Color3::fromHSV(134.0f, 1.0f, 1.0f), Color3(0, 255, 59));
CORRADE_COMPARE(Color3::fromHSV(191.0f, 1.0f, 1.0f), Color3(0, 208, 255)); CORRADE_COMPARE(Color3::fromHSV(191.0f, 1.0f, 1.0f), Color3(0, 208, 255));
CORRADE_COMPARE(Color3::fromHSV(269.0f, 1.0f, 1.0f), Color3(123, 0, 255)); CORRADE_COMPARE(Color3::fromHSV(269.0f, 1.0f, 1.0f), Color3(123, 0, 255));
CORRADE_COMPARE(Color3::fromHSV(317.0f, 1.0f, 1.0f), Color3(255, 0, 183)); CORRADE_COMPARE(Color3::fromHSV(317.0f, 1.0f, 1.0f), Color3(255, 0, 182));
} }
void ColorTest::hue() { void ColorTest::hue() {
@ -126,7 +126,7 @@ void ColorTest::hue() {
} }
void ColorTest::fromSaturation() { void ColorTest::fromSaturation() {
CORRADE_COMPARE(Color3::fromHSV(0.0f, 0.702f, 1.0f), Color3(255, 76, 76)); CORRADE_COMPARE(Color3::fromHSV(0.0f, 0.702f, 1.0f), Color3(255, 75, 75));
} }
void ColorTest::saturation() { void ColorTest::saturation() {
@ -143,7 +143,7 @@ void ColorTest::value() {
} }
void ColorTest::hsv() { void ColorTest::hsv() {
CORRADE_COMPARE(Color3::fromHSV(230.0f, 0.749f, 0.427f), Color3(27, 41, 109)); CORRADE_COMPARE(Color3::fromHSV(230.0f, 0.749f, 0.427f), Color3(27, 40, 108));
float hue, saturation, value; float hue, saturation, value;
std::tie(hue, saturation, value) = Color3(27, 41, 109).toHSV(); std::tie(hue, saturation, value) = Color3(27, 41, 109).toHSV();
@ -153,24 +153,24 @@ void ColorTest::hsv() {
} }
void ColorTest::hsvOverflow() { void ColorTest::hsvOverflow() {
CORRADE_COMPARE(Color3::fromHSV(27.0f-360.0f, 1.0f, 1.0f), Color3(255, 115, 0)); CORRADE_COMPARE(Color3::fromHSV(27.0f-360.0f, 1.0f, 1.0f), Color3(255, 114, 0));
CORRADE_COMPARE(Color3::fromHSV(86.0f-360.0f, 1.0f, 1.0f), Color3(145, 255, 0)); CORRADE_COMPARE(Color3::fromHSV(86.0f-360.0f, 1.0f, 1.0f), Color3(144, 255, 0));
CORRADE_COMPARE(Color3::fromHSV(134.0f-360.0f, 1.0f, 1.0f), Color3(0, 255, 60)); CORRADE_COMPARE(Color3::fromHSV(134.0f-360.0f, 1.0f, 1.0f), Color3(0, 255, 59));
CORRADE_COMPARE(Color3::fromHSV(191.0f-360.0f, 1.0f, 1.0f), Color3(0, 208, 255)); CORRADE_COMPARE(Color3::fromHSV(191.0f-360.0f, 1.0f, 1.0f), Color3(0, 208, 255));
CORRADE_COMPARE(Color3::fromHSV(269.0f-360.0f, 1.0f, 1.0f), Color3(123, 0, 255)); CORRADE_COMPARE(Color3::fromHSV(269.0f-360.0f, 1.0f, 1.0f), Color3(123, 0, 255));
CORRADE_COMPARE(Color3::fromHSV(317.0f-360.0f, 1.0f, 1.0f), Color3(255, 0, 183)); CORRADE_COMPARE(Color3::fromHSV(317.0f-360.0f, 1.0f, 1.0f), Color3(255, 0, 182));
CORRADE_COMPARE(Color3::fromHSV(360.0f+27.0f, 1.0f, 1.0f), Color3(255, 115, 0)); CORRADE_COMPARE(Color3::fromHSV(360.0f+27.0f, 1.0f, 1.0f), Color3(255, 114, 0));
CORRADE_COMPARE(Color3::fromHSV(360.0f+86.0f, 1.0f, 1.0f), Color3(145, 255, 0)); CORRADE_COMPARE(Color3::fromHSV(360.0f+86.0f, 1.0f, 1.0f), Color3(144, 255, 0));
CORRADE_COMPARE(Color3::fromHSV(360.0f+134.0f, 1.0f, 1.0f), Color3(0, 255, 60)); CORRADE_COMPARE(Color3::fromHSV(360.0f+134.0f, 1.0f, 1.0f), Color3(0, 255, 59));
CORRADE_COMPARE(Color3::fromHSV(360.0f+191.0f, 1.0f, 1.0f), Color3(0, 208, 255)); CORRADE_COMPARE(Color3::fromHSV(360.0f+191.0f, 1.0f, 1.0f), Color3(0, 208, 255));
CORRADE_COMPARE(Color3::fromHSV(360.0f+269.0f, 1.0f, 1.0f), Color3(123, 0, 255)); CORRADE_COMPARE(Color3::fromHSV(360.0f+269.0f, 1.0f, 1.0f), Color3(123, 0, 255));
CORRADE_COMPARE(Color3::fromHSV(360.0f+317.0f, 1.0f, 1.0f), Color3(255, 0, 183)); CORRADE_COMPARE(Color3::fromHSV(360.0f+317.0f, 1.0f, 1.0f), Color3(255, 0, 182));
} }
void ColorTest::hsvAlpha() { void ColorTest::hsvAlpha() {
CORRADE_COMPARE(Color4::fromHSV(std::make_tuple(230.0f, 0.749f, 0.427f), 23), Color4(27, 41, 109, 23)); CORRADE_COMPARE(Color4::fromHSV(std::make_tuple(230.0f, 0.749f, 0.427f), 23), Color4(27, 40, 108, 23));
CORRADE_COMPARE(Color4::fromHSV(230.0f, 0.749f, 0.427f, 23), Color4(27, 41, 109, 23)); CORRADE_COMPARE(Color4::fromHSV(230.0f, 0.749f, 0.427f, 23), Color4(27, 40, 108, 23));
} }
void ColorTest::debug() { void ColorTest::debug() {

Loading…
Cancel
Save