diff --git a/glm/gtc/packing.hpp b/glm/gtc/packing.hpp index f44a48b0..089e74f6 100644 --- a/glm/gtc/packing.hpp +++ b/glm/gtc/packing.hpp @@ -515,6 +515,34 @@ namespace glm template class vecType> GLM_FUNC_DECL vecType unpackHalf(vecType const & p); + /// Convert each component of the normalized floating-point vector into unsigned integer values. + /// + /// @see gtc_packing + /// @see vecType unpackUnorm(vecType const & p); + template class vecType> + GLM_FUNC_DECL vecType packUnorm(vecType const & v); + + /// Convert each unsigned integer components of a vector to normalized floating-point values. + /// + /// @see gtc_packing + /// @see vecType packUnorm(vecType const & v) + template class vecType> + GLM_FUNC_DECL vecType unpackUnorm(vecType const & v); + + /// Convert each component of the normalized floating-point vector into signed integer values. + /// + /// @see gtc_packing + /// @see vecType unpackSnorm(vecType const & p); + template class vecType> + GLM_FUNC_DECL vecType packSnorm(vecType const & v); + + /// Convert each signed integer components of a vector to normalized floating-point values. + /// + /// @see gtc_packing + /// @see vecType packSnorm(vecType const & v) + template class vecType> + GLM_FUNC_DECL vecType unpackSnorm(vecType const & v); + /// @} }// namespace glm diff --git a/glm/gtc/packing.inl b/glm/gtc/packing.inl index e390fffc..30ecade5 100644 --- a/glm/gtc/packing.inl +++ b/glm/gtc/packing.inl @@ -36,6 +36,7 @@ #include "../vec4.hpp" #include "../detail/type_half.hpp" #include +#include namespace glm{ namespace detail @@ -391,7 +392,7 @@ namespace detail Unpack * 0.00787401574803149606299212598425f, // 1.0f / 127.0f -1.0f, 1.0f); } - + GLM_FUNC_QUALIFIER uint16 packUnorm1x16(float s) { return static_cast(round(clamp(s, 0.0f, 1.0f) * 65535.0f)); @@ -616,4 +617,40 @@ namespace detail { return detail::compute_half::unpack(v); } + + template class vecType> + GLM_FUNC_QUALIFIER vecType packUnorm(vecType const & v) + { + static_assert(std::numeric_limits::is_integer, "uintType must be an integer type"); + static_assert(std::numeric_limits::is_iec559, "floatType must be a floating point type"); + + return vecType(round(clamp(v, static_cast(0), static_cast(1)) * static_cast(std::numeric_limits::max()))); + } + + template class vecType> + GLM_FUNC_QUALIFIER vecType unpackUnorm(vecType const & v) + { + static_assert(std::numeric_limits::is_integer, "uintType must be an integer type"); + static_assert(std::numeric_limits::is_iec559, "floatType must be a floating point type"); + + return vecType(v) * (static_cast(1) / static_cast(std::numeric_limits::max())); + } + + template class vecType> + GLM_FUNC_QUALIFIER vecType packSnorm(vecType const & v) + { + static_assert(std::numeric_limits::is_integer, "uintType must be an integer type"); + static_assert(std::numeric_limits::is_iec559, "floatType must be a floating point type"); + + return vecType(round(clamp(v , static_cast(-1), static_cast(1)) * static_cast(std::numeric_limits::max()))); + } + + template class vecType> + GLM_FUNC_QUALIFIER vecType unpackSnorm(vecType const & v) + { + static_assert(std::numeric_limits::is_integer, "uintType must be an integer type"); + static_assert(std::numeric_limits::is_iec559, "floatType must be a floating point type"); + + return clamp(vecType(v) * (static_cast(1) / static_cast(std::numeric_limits::max())), static_cast(-1), static_cast(1)); + } }//namespace glm diff --git a/test/gtc/gtc_packing.cpp b/test/gtc/gtc_packing.cpp index 11bf457c..5514ee36 100644 --- a/test/gtc/gtc_packing.cpp +++ b/test/gtc/gtc_packing.cpp @@ -529,10 +529,54 @@ int test_packSnorm4x8() return Error; } +int test_packUnorm() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec2(1.0f, 0.7f)); + A.push_back(glm::vec2(0.5f, 0.1f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec2 B(A[i]); + glm::u16vec2 C = glm::packUnorm(B); + glm::vec2 D = glm::unpackUnorm(C); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 255.f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packSnorm() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec2( 1.0f, 0.0f)); + A.push_back(glm::vec2(-0.5f,-0.7f)); + A.push_back(glm::vec2(-0.1f, 0.1f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec2 B(A[i]); + glm::i16vec2 C = glm::packSnorm(B); + glm::vec2 D = glm::unpackSnorm(C); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 32767.0f * 2.0f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + int main() { int Error(0); + Error += test_packUnorm(); + Error += test_packSnorm(); + Error += test_packSnorm1x16(); Error += test_packSnorm2x16(); Error += test_packSnorm4x16();