From b7c11b1e6aad0cfdeffb00f24ff727a9e96a8aad Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Fri, 30 Sep 2011 15:36:55 +0100 Subject: [PATCH] Added GLM_GTX_constants extension --- glm/gtx/constants.hpp | 177 ++++++++++ glm/gtx/constants.inl | 792 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 969 insertions(+) create mode 100644 glm/gtx/constants.hpp create mode 100644 glm/gtx/constants.inl diff --git a/glm/gtx/constants.hpp b/glm/gtx/constants.hpp new file mode 100644 index 00000000..d8ea4f05 --- /dev/null +++ b/glm/gtx/constants.hpp @@ -0,0 +1,177 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2011 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref constants +/// @file glm/gtx/constants.hpp +/// @date 2011-09-30 / 2011-09-30 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtc_half_float (dependence) +/// +/// @defgroup gtx_constants GLM_GTX_constants: Provide build-in constants +/// @ingroup gtx +/// +/// @brief Allow to perform bit operations on integer values +/// +/// need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef GLM_GTX_constants +#define GLM_GTX_constants GLM_VERSION + +// Dependency: +#include "../glm.hpp" +#include "../gtc/half_float.hpp" + +#if(defined(GLM_MESSAGES) && !defined(glm_ext)) +# pragma message("GLM: GLM_GTX_constants extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_constants + /// @{ + + template + T pi(); + + template + GLM_FUNC_QUALIFIER T pi() + { + return T(3.14159265358979323846264338327950288); + } + + template + GLM_FUNC_QUALIFIER T root_pi() + { + return T(1.772453850905516027); + } + + template + GLM_FUNC_QUALIFIER T half_pi() + { + return T(1.57079632679489661923132169163975144); + } + + template + GLM_FUNC_QUALIFIER T quarter_pi() + { + return T(0.785398163397448309615660845819875721); + } + + template + GLM_FUNC_QUALIFIER T one_over_pi() + { + return T(0.318309886183790671537767526745028724); + } + + template + GLM_FUNC_QUALIFIER T two_over_pi() + { + return T(0.636619772367581343075535053490057448); + } + + template + GLM_FUNC_QUALIFIER T two_over_root_pi() + { + return T(1.12837916709551257389615890312154517); + } + + template + GLM_FUNC_QUALIFIER T one_over_root_two() + { + return T(0.707106781186547524400844362104849039); + } + + template + GLM_FUNC_QUALIFIER T root_half_pi() + { + return T(1.253314137315500251); + } + + template + GLM_FUNC_QUALIFIER T root_two_pi() + { + return T(2.506628274631000502); + } + + template + GLM_FUNC_QUALIFIER T root_ln_four() + { + return T(1.17741002251547469); + } + + template + GLM_FUNC_QUALIFIER T e() + { + return T(2.71828182845904523536); + } + + template + GLM_FUNC_QUALIFIER T euler() + { + return T(0.577215664901532860606); + } + + template + GLM_FUNC_QUALIFIER T root_two() + { + return T(1.41421356237309504880168872420969808); + } + + template + GLM_FUNC_QUALIFIER T ln_two() + { + return T(0.693147180559945309417232121458176568); + } + + template + GLM_FUNC_QUALIFIER T ln_ten(2.30258509299404568401799145468436421) + { + return T(); + } + + template + GLM_FUNC_QUALIFIER T ln_ln_two() + { + return T(-0.3665129205816643); + } + + template + GLM_FUNC_QUALIFIER T third() + { + return T(0.333333333333333333); + } + + template + GLM_FUNC_QUALIFIER T twothirds() + { + return T(0.666666666666666666); + } + + /// @} +} //namespace glm + +#include "constants.inl" + +#endif//GLM_GTX_constants diff --git a/glm/gtx/constants.inl b/glm/gtx/constants.inl new file mode 100644 index 00000000..885c66af --- /dev/null +++ b/glm/gtx/constants.inl @@ -0,0 +1,792 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2011 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_half_float +/// @file glm/gtc/half_float.inl +/// @date 2009-04-29 / 2011-06-05 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include "../core/_detail.hpp" + +namespace glm{ + +template +GLM_FUNC_QUALIFIER genIType mask +( + genIType const & count +) +{ + return ((genIType(1) << (count)) - genIType(1)); +} + +template +GLM_FUNC_QUALIFIER detail::tvec2 mask +( + detail::tvec2 const & count +) +{ + return detail::tvec2( + mask(count[0]), + mask(count[1])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec3 mask +( + detail::tvec3 const & count +) +{ + return detail::tvec3( + mask(count[0]), + mask(count[1]), + mask(count[2])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec4 mask +( + detail::tvec4 const & count +) +{ + return detail::tvec4( + mask(count[0]), + mask(count[1]), + mask(count[2]), + mask(count[3])); +} + +// extractField +template +GLM_FUNC_QUALIFIER genIType extractField +( + half const & value, + genIType const & first, + genIType const & count +) +{ + assert(first + count < sizeof(half)); + return (value._data() << first) >> ((sizeof(half) << 3) - count); +} + +template +GLM_FUNC_QUALIFIER genIType extractField +( + float const & value, + genIType const & first, + genIType const & count +) +{ + assert(first + count < sizeof(float)); + return (detail::uif32(value).i << first) >> ((sizeof(float) << 3) - count); +} + +template +GLM_FUNC_QUALIFIER genIType extractField +( + double const & value, + genIType const & first, + genIType const & count +) +{ + assert(first + count < sizeof(double)); + return (detail::uif64(value).i << first) >> ((sizeof(double) << genIType(3)) - count); +} + +template +GLM_FUNC_QUALIFIER genIUType extractField +( + genIUType const & Value, + sizeType const & First, + sizeType const & Count +) +{ + sizeType GenSize = sizeof(genIUType) << 3; + + assert(First + Count <= GenSize); + + genIUType ShiftLeft = Count ? Value << (GenSize - (Count + First)) : 0; + genIUType ShiftBack = ShiftLeft >> genIUType(GenSize - Count); + + return ShiftBack; +} + +template +GLM_FUNC_QUALIFIER detail::tvec2 extractField +( + detail::tvec2 const & value, + sizeType const & first, + sizeType const & count +) +{ + return detail::tvec2( + extractField(value[0], first, count), + extractField(value[1], first, count)); +} + +template +GLM_FUNC_QUALIFIER detail::tvec3 extractField +( + detail::tvec3 const & value, + sizeType const & first, + sizeType const & count +) +{ + return detail::tvec3( + extractField(value[0], first, count), + extractField(value[1], first, count), + extractField(value[2], first, count)); +} + +template +GLM_FUNC_QUALIFIER detail::tvec4 extractField +( + detail::tvec4 const & value, + sizeType const & first, + sizeType const & count +) +{ + return detail::tvec4( + extractField(value[0], first, count), + extractField(value[1], first, count), + extractField(value[2], first, count), + extractField(value[3], first, count)); +} + +template +GLM_FUNC_QUALIFIER detail::tvec2 extractField +( + detail::tvec2 const & value, + detail::tvec2 const & first, + detail::tvec2 const & count +) +{ + return detail::tvec2( + extractField(value[0], first[0], count[0]), + extractField(value[1], first[1], count[1])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec3 extractField +( + detail::tvec3 const & value, + detail::tvec3 const & first, + detail::tvec3 const & count +) +{ + return detail::tvec3( + extractField(value[0], first[0], count[0]), + extractField(value[1], first[1], count[1]), + extractField(value[2], first[2], count[2])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec4 extractField +( + detail::tvec4 const & value, + detail::tvec4 const & first, + detail::tvec4 const & count +) +{ + return detail::tvec4( + extractField(value[0], first[0], count[0]), + extractField(value[1], first[1], count[1]), + extractField(value[2], first[2], count[2]), + extractField(value[3], first[3], count[3])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec2 extractField +( + genIUType const & value, + detail::tvec2 const & first, + detail::tvec2 const & count +) +{ + return detail::tvec2( + extractField(value, first[0], count[0]), + extractField(value, first[1], count[1])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec3 extractField +( + genIUType const & value, + detail::tvec3 const & first, + detail::tvec3 const & count +) +{ + return detail::tvec3( + extractField(value, first[0], count[0]), + extractField(value, first[1], count[1]), + extractField(value, first[2], count[2])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec4 extractField +( + genIUType const & value, + detail::tvec4 const & first, + detail::tvec4 const & count +) +{ + return detail::tvec4( + extractField(value, first[0], count[0]), + extractField(value, first[1], count[1]), + extractField(value, first[2], count[2]), + extractField(value, first[3], count[3])); +} + +// lowestBit +template +GLM_FUNC_QUALIFIER int lowestBit +( + genType const & Value +) +{ + assert(Value != genType(0)); // not valid call + + genType Bit; + for(Bit = genType(0); !(Value & (1 << Bit)); ++Bit){} + return Bit; +} + +template +GLM_FUNC_QUALIFIER detail::tvec2 lowestBit +( + detail::tvec2 const & value +) +{ + return detail::tvec2( + lowestBit(value[0]), + lowestBit(value[1])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec3 lowestBit +( + detail::tvec3 const & value +) +{ + return detail::tvec3( + lowestBit(value[0]), + lowestBit(value[1]), + lowestBit(value[2])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec4 lowestBit +( + detail::tvec4 const & value +) +{ + return detail::tvec4( + lowestBit(value[0]), + lowestBit(value[1]), + lowestBit(value[2]), + lowestBit(value[3])); +} + +// highestBit +template +GLM_FUNC_QUALIFIER int highestBit +( + genType const & value +) +{ + assert(value != genType(0)); // not valid call + + genType bit = genType(-1); + for(genType tmp = value; tmp; tmp >>= 1, ++bit){} + return bit; +} + +//template <> +//GLM_FUNC_QUALIFIER int highestBit +//( +// int value +//) +//{ +// int bit = -1; +// for(int tmp = value; tmp; tmp >>= 1, ++bit); +// return bit; +//} + +template +GLM_FUNC_QUALIFIER detail::tvec2 highestBit +( + detail::tvec2 const & value +) +{ + return detail::tvec2( + highestBit(value[0]), + highestBit(value[1])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec3 highestBit +( + detail::tvec3 const & value +) +{ + return detail::tvec3( + highestBit(value[0]), + highestBit(value[1]), + highestBit(value[2])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec4 highestBit +( + detail::tvec4 const & value +) +{ + return detail::tvec4( + highestBit(value[0]), + highestBit(value[1]), + highestBit(value[2]), + highestBit(value[3])); +} + +// highestBitValue +template +GLM_FUNC_QUALIFIER genType highestBitValue +( + genType const & value +) +{ + genType tmp = value; + genType result = genType(0); + while(tmp) + { + result = (tmp & (~tmp + 1)); // grab lowest bit + tmp &= ~result; // clear lowest bit + } + return result; +} + +template +GLM_FUNC_QUALIFIER detail::tvec2 highestBitValue +( + detail::tvec2 const & value +) +{ + return detail::tvec2( + highestBitValue(value[0]), + highestBitValue(value[1])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec3 highestBitValue +( + detail::tvec3 const & value +) +{ + return detail::tvec3( + highestBitValue(value[0]), + highestBitValue(value[1]), + highestBitValue(value[2])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec4 highestBitValue +( + detail::tvec4 const & value +) +{ + return detail::tvec4( + highestBitValue(value[0]), + highestBitValue(value[1]), + highestBitValue(value[2]), + highestBitValue(value[3])); +} + +// isPowerOfTwo +template +GLM_FUNC_QUALIFIER bool isPowerOfTwo(genType const & Value) +{ + //detail::If::is_signed>::apply(abs, Value); + //return !(Value & (Value - 1)); + + // For old complier? + genType Result = Value; + if(std::numeric_limits::is_signed) + Result = abs(Result); + return !(Result & (Result - 1)); +} + +template +GLM_FUNC_QUALIFIER detail::tvec2 isPowerOfTwo +( + detail::tvec2 const & value +) +{ + return detail::tvec2( + isPowerOfTwo(value[0]), + isPowerOfTwo(value[1])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec3 isPowerOfTwo +( + detail::tvec3 const & value +) +{ + return detail::tvec3( + isPowerOfTwo(value[0]), + isPowerOfTwo(value[1]), + isPowerOfTwo(value[2])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec4 isPowerOfTwo +( + detail::tvec4 const & value +) +{ + return detail::tvec4( + isPowerOfTwo(value[0]), + isPowerOfTwo(value[1]), + isPowerOfTwo(value[2]), + isPowerOfTwo(value[3])); +} + +// powerOfTwoAbove +template +GLM_FUNC_QUALIFIER genType powerOfTwoAbove(genType const & value) +{ + return isPowerOfTwo(value) ? value : highestBitValue(value) << 1; +} + +template +GLM_FUNC_QUALIFIER detail::tvec2 powerOfTwoAbove +( + detail::tvec2 const & value +) +{ + return detail::tvec2( + powerOfTwoAbove(value[0]), + powerOfTwoAbove(value[1])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec3 powerOfTwoAbove +( + detail::tvec3 const & value +) +{ + return detail::tvec3( + powerOfTwoAbove(value[0]), + powerOfTwoAbove(value[1]), + powerOfTwoAbove(value[2])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec4 powerOfTwoAbove +( + detail::tvec4 const & value +) +{ + return detail::tvec4( + powerOfTwoAbove(value[0]), + powerOfTwoAbove(value[1]), + powerOfTwoAbove(value[2]), + powerOfTwoAbove(value[3])); +} + +// powerOfTwoBelow +template +GLM_FUNC_QUALIFIER genType powerOfTwoBelow +( + genType const & value +) +{ + return isPowerOfTwo(value) ? value : highestBitValue(value); +} + +template +GLM_FUNC_QUALIFIER detail::tvec2 powerOfTwoBelow +( + detail::tvec2 const & value +) +{ + return detail::tvec2( + powerOfTwoBelow(value[0]), + powerOfTwoBelow(value[1])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec3 powerOfTwoBelow +( + detail::tvec3 const & value +) +{ + return detail::tvec3( + powerOfTwoBelow(value[0]), + powerOfTwoBelow(value[1]), + powerOfTwoBelow(value[2])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec4 powerOfTwoBelow +( + detail::tvec4 const & value +) +{ + return detail::tvec4( + powerOfTwoBelow(value[0]), + powerOfTwoBelow(value[1]), + powerOfTwoBelow(value[2]), + powerOfTwoBelow(value[3])); +} + +// powerOfTwoNearest +template +GLM_FUNC_QUALIFIER genType powerOfTwoNearest +( + genType const & value +) +{ + if(isPowerOfTwo(value)) + return value; + + genType prev = highestBitValue(value); + genType next = prev << 1; + return (next - value) < (value - prev) ? next : prev; +} + +template +GLM_FUNC_QUALIFIER detail::tvec2 powerOfTwoNearest +( + detail::tvec2 const & value +) +{ + return detail::tvec2( + powerOfTwoNearest(value[0]), + powerOfTwoNearest(value[1])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec3 powerOfTwoNearest +( + detail::tvec3 const & value +) +{ + return detail::tvec3( + powerOfTwoNearest(value[0]), + powerOfTwoNearest(value[1]), + powerOfTwoNearest(value[2])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec4 powerOfTwoNearest +( + detail::tvec4 const & value +) +{ + return detail::tvec4( + powerOfTwoNearest(value[0]), + powerOfTwoNearest(value[1]), + powerOfTwoNearest(value[2]), + powerOfTwoNearest(value[3])); +} + +template +GLM_FUNC_QUALIFIER genType bitRevert(genType const & In) +{ + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitRevert' only accept integer values"); + + genType Out = 0; + std::size_t BitSize = sizeof(genType) * 8; + for(std::size_t i = 0; i < BitSize; ++i) + if(In & (genType(1) << i)) + Out |= genType(1) << (BitSize - 1 - i); + return Out; +} + +template +GLM_FUNC_QUALIFIER detail::tvec2 bitRevert +( + detail::tvec2 const & Value +) +{ + return detail::tvec2( + bitRevert(Value[0]), + bitRevert(Value[1])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec3 bitRevert +( + detail::tvec3 const & Value +) +{ + return detail::tvec3( + bitRevert(Value[0]), + bitRevert(Value[1]), + bitRevert(Value[2])); +} + +template +GLM_FUNC_QUALIFIER detail::tvec4 bitRevert +( + detail::tvec4 const & Value +) +{ + return detail::tvec4( + bitRevert(Value[0]), + bitRevert(Value[1]), + bitRevert(Value[2]), + bitRevert(Value[3])); +} + +template +GLM_FUNC_QUALIFIER genType bitRotateRight(genType const & In, std::size_t Shift) +{ + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitRotateRight' only accept integer values"); + + std::size_t BitSize = sizeof(genType) * 8; + return (In << Shift) | (In >> (BitSize - Shift)); +} + +template +GLM_FUNC_QUALIFIER detail::tvec2 bitRotateRight +( + detail::tvec2 const & Value, + std::size_t Shift +) +{ + return detail::tvec2( + bitRotateRight(Value[0], Shift), + bitRotateRight(Value[1], Shift)); +} + +template +GLM_FUNC_QUALIFIER detail::tvec3 bitRotateRight +( + detail::tvec3 const & Value, + std::size_t Shift +) +{ + return detail::tvec3( + bitRotateRight(Value[0], Shift), + bitRotateRight(Value[1], Shift), + bitRotateRight(Value[2], Shift)); +} + +template +GLM_FUNC_QUALIFIER detail::tvec4 bitRotateRight +( + detail::tvec4 const & Value, + std::size_t Shift +) +{ + return detail::tvec4( + bitRotateRight(Value[0], Shift), + bitRotateRight(Value[1], Shift), + bitRotateRight(Value[2], Shift), + bitRotateRight(Value[3], Shift)); +} + +template +GLM_FUNC_QUALIFIER genType bitRotateLeft(genType const & In, std::size_t Shift) +{ + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitRotateLeft' only accept integer values"); + + std::size_t BitSize = sizeof(genType) * 8; + return (In >> Shift) | (In << (BitSize - Shift)); +} + +template +GLM_FUNC_QUALIFIER detail::tvec2 bitRotateLeft +( + detail::tvec2 const & Value, + std::size_t Shift +) +{ + return detail::tvec2( + bitRotateLeft(Value[0], Shift), + bitRotateLeft(Value[1], Shift)); +} + +template +GLM_FUNC_QUALIFIER detail::tvec3 bitRotateLeft +( + detail::tvec3 const & Value, + std::size_t Shift +) +{ + return detail::tvec3( + bitRotateLeft(Value[0], Shift), + bitRotateLeft(Value[1], Shift), + bitRotateLeft(Value[2], Shift)); +} + +template +GLM_FUNC_QUALIFIER detail::tvec4 bitRotateLeft +( + detail::tvec4 const & Value, + std::size_t Shift +) +{ + return detail::tvec4( + bitRotateLeft(Value[0], Shift), + bitRotateLeft(Value[1], Shift), + bitRotateLeft(Value[2], Shift), + bitRotateLeft(Value[3], Shift)); +} + +template +GLM_FUNC_QUALIFIER genIUType fillBitfieldWithOne +( + genIUType const & Value, + int const & FromBit, + int const & ToBit +) +{ + assert(FromBit <= ToBit); + assert(ToBit <= sizeof(genIUType) * std::size_t(8)); + + genIUType Result = Value; + for(std::size_t i = 0; i <= ToBit; ++i) + Result |= (1 << i); + return Result; +} + +template +GLM_FUNC_QUALIFIER genIUType fillBitfieldWithZero +( + genIUType const & Value, + int const & FromBit, + int const & ToBit +) +{ + assert(FromBit <= ToBit); + assert(ToBit <= sizeof(genIUType) * std::size_t(8)); + + genIUType Result = Value; + for(std::size_t i = 0; i <= ToBit; ++i) + Result &= ~(1 << i); + return Result; +} + +}//namespace glm