Browse Source

Fixed GTX_wrap #534, improved GTX_wrap for SIMD friendliness

Christophe Riccio 9 years ago
parent
commit
edc328c7c9
4 changed files with 82 additions and 123 deletions
  1. 9 8
      glm/gtx/wrap.hpp
  2. 24 115
      glm/gtx/wrap.inl
  3. 1 0
      readme.md
  4. 48 0
      test/gtx/gtx_wrap.cpp

+ 9 - 8
glm/gtx/wrap.hpp

@@ -14,6 +14,7 @@
 
 // Dependency:
 #include "../glm.hpp"
+#include "../gtc/vec1.hpp"
 
 #if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED))
 #	pragma message("GLM: GLM_GTX_wrap extension included")
@@ -26,23 +27,23 @@ namespace glm
 
 	/// Simulate GL_CLAMP OpenGL wrap mode
 	/// @see gtx_wrap extension.
-	template <typename genType> 
-	GLM_FUNC_DECL genType clamp(genType const & Texcoord);
+	template <typename genType>
+	GLM_FUNC_DECL genType clamp(genType const& Texcoord);
 
 	/// Simulate GL_REPEAT OpenGL wrap mode
 	/// @see gtx_wrap extension.
-	template <typename genType> 
-	GLM_FUNC_DECL genType repeat(genType const & Texcoord);
+	template <typename genType>
+	GLM_FUNC_DECL genType repeat(genType const& Texcoord);
 
 	/// Simulate GL_MIRRORED_REPEAT OpenGL wrap mode
 	/// @see gtx_wrap extension.
-	template <typename genType> 
-	GLM_FUNC_DECL genType mirrorClamp(genType const & Texcoord);
+	template <typename genType>
+	GLM_FUNC_DECL genType mirrorClamp(genType const& Texcoord);
 
 	/// Simulate GL_MIRROR_REPEAT OpenGL wrap mode
 	/// @see gtx_wrap extension.
-	template <typename genType> 
-	GLM_FUNC_DECL genType mirrorRepeat(genType const & Texcoord);
+	template <typename genType>
+	GLM_FUNC_DECL genType mirrorRepeat(genType const& Texcoord);
 
 	/// @}
 }// namespace glm

+ 24 - 115
glm/gtx/wrap.inl

@@ -3,147 +3,56 @@
 
 namespace glm
 {
-	template <typename genType> 
-	GLM_FUNC_QUALIFIER genType clamp(genType const & Texcoord)
-	{
-		return glm::clamp(Texcoord, genType(0), genType(1));
-	}
-
-	template <typename T, precision P> 
-	GLM_FUNC_QUALIFIER tvec2<T, P> clamp(tvec2<T, P> const & Texcoord)
+	template <typename T, precision P, template <typename, precision> class vecType>
+	GLM_FUNC_QUALIFIER vecType<T, P> clamp(vecType<T, P> const& Texcoord)
 	{
-		tvec2<T, P> Result;
-		for(typename tvec2<T, P>::size_type i = 0; i < tvec2<T, P>::value_size(); ++i)
-			Result[i] = clamp_to_edge(Texcoord[i]);
-		return Result;
+		return glm::clamp(Texcoord, vecType<T, P>(0), vecType<T, P>(1));
 	}
 
-	template <typename T, precision P> 
-	GLM_FUNC_QUALIFIER tvec3<T, P> clamp(tvec3<T, P> const & Texcoord)
+	template <typename genType>
+	GLM_FUNC_QUALIFIER genType clamp(genType const & Texcoord)
 	{
-		tvec3<T, P> Result;
-		for(typename tvec3<T, P>::size_type i = 0; i < tvec3<T, P>::value_size(); ++i)
-			Result[i] = clamp_to_edge(Texcoord[i]);
-		return Result;
+		return clamp(tvec1<genType, defaultp>(Texcoord)).x;
 	}
 
-	template <typename T, precision P> 
-	GLM_FUNC_QUALIFIER tvec4<T, P> clamp(tvec4<T, P> const & Texcoord)
+	template <typename T, precision P, template <typename, precision> class vecType>
+	GLM_FUNC_QUALIFIER vecType<T, P> repeat(vecType<T, P> const& Texcoord)
 	{
-		tvec4<T, P> Result;
-		for(typename tvec4<T, P>::size_type i = 0; i < tvec4<T, P>::value_size(); ++i)
-			Result[i] = clamp_to_edge(Texcoord[i]);
-		return Result;
+		return glm::fract(Texcoord);
 	}
 
 	template <typename genType>
 	GLM_FUNC_QUALIFIER genType repeat(genType const & Texcoord)
 	{
-		return glm::fract(Texcoord);
-	}
-
-	template <typename T, precision P>
-	GLM_FUNC_QUALIFIER tvec2<T, P> repeat(tvec2<T, P> const & Texcoord)
-	{
-		tvec2<T, P> Result;
-		for(typename tvec2<T, P>::size_type i = 0; i < tvec2<T, P>::value_size(); ++i)
-			Result[i] = repeat(Texcoord[i]);
-		return Result;
-	}
-
-	template <typename T, precision P>
-	GLM_FUNC_QUALIFIER tvec3<T, P> repeat(tvec3<T, P> const & Texcoord)
-	{
-		tvec3<T, P> Result;
-		for(typename tvec3<T, P>::size_type i = 0; i < tvec3<T, P>::value_size(); ++i)
-			Result[i] = repeat(Texcoord[i]);
-		return Result;
+		return repeat(tvec1<genType, defaultp>(Texcoord)).x;
 	}
 
-	template <typename T, precision P>
-	GLM_FUNC_QUALIFIER tvec4<T, P> repeat(tvec4<T, P> const & Texcoord)
+	template <typename T, precision P, template <typename, precision> class vecType>
+	GLM_FUNC_QUALIFIER vecType<T, P> mirrorClamp(vecType<T, P> const& Texcoord)
 	{
-		tvec4<T, P> Result;
-		for(typename tvec4<T, P>::size_type i = 0; i < tvec4<T, P>::value_size(); ++i)
-			Result[i] = repeat(Texcoord[i]);
-		return Result;
+		return glm::fract(glm::abs(Texcoord));
 	}
 
 	template <typename genType>
 	GLM_FUNC_QUALIFIER genType mirrorClamp(genType const & Texcoord)
 	{
-		return glm::fract(glm::abs(Texcoord));
-		//return glm::mod(glm::abs(Texcoord), 1.0f);
-	}
-
-	template <typename T, precision P>
-	GLM_FUNC_QUALIFIER tvec2<T, P> mirrorClamp(tvec2<T, P> const & Texcoord)
-	{
-		tvec2<T, P> Result;
-		for(typename tvec2<T, P>::size_type i = 0; i < tvec2<T, P>::value_size(); ++i)
-			Result[i] = mirrorClamp(Texcoord[i]);
-		return Result;
-	}
-
-	template <typename T, precision P>
-	GLM_FUNC_QUALIFIER tvec3<T, P> mirrorClamp(tvec3<T, P> const & Texcoord)
-	{
-		tvec3<T, P> Result;
-		for(typename tvec3<T, P>::size_type i = 0; i < tvec3<T, P>::value_size(); ++i)
-			Result[i] = mirrorClamp(Texcoord[i]);
-		return Result;
+		return mirrorClamp(tvec1<genType, defaultp>(Texcoord)).x;
 	}
 
-	template <typename T, precision P>
-	GLM_FUNC_QUALIFIER tvec4<T, P> mirrorClamp(tvec4<T, P> const & Texcoord)
+	template <typename T, precision P, template <typename, precision> class vecType>
+	GLM_FUNC_QUALIFIER vecType<T, P> mirrorRepeat(vecType<T, P> const& Texcoord)
 	{
-		tvec4<T, P> Result;
-		for(typename tvec4<T, P>::size_type i = 0; i < tvec4<T, P>::value_size(); ++i)
-			Result[i] = mirrorClamp(Texcoord[i]);
-		return Result;
+		vecType<T, P> const Abs = glm::abs(Texcoord);
+		vecType<T, P> const Clamp = glm::mod(glm::floor(Abs), vecType<T, P>(2));
+		vecType<T, P> const Floor = glm::floor(Abs);
+		vecType<T, P> const Rest = Abs - Floor;
+		vecType<T, P> const Mirror = Clamp + Rest;
+		return mix(Rest, vecType<T, P>(1) - Rest, glm::greaterThanEqual(Mirror, vecType<T, P>(1)));
 	}
 
 	template <typename genType>
-	GLM_FUNC_QUALIFIER genType mirrorRepeat(genType const & Texcoord)
-	{
-		genType const Abs = glm::abs(Texcoord);
-		genType const Clamp = genType(int(glm::floor(Abs)) % 2);
-		genType const Floor = glm::floor(Abs);
-		genType const Rest = Abs - Floor;
-		genType const Mirror = Clamp + Rest;
-
-		genType Out;
-		if(Mirror >= genType(1))
-			Out = genType(1) - Rest;
-		else
-			Out = Rest;
-		return Out;
-	}
-
-	template <typename T, precision P>
-	GLM_FUNC_QUALIFIER tvec2<T, P> mirrorRepeat(tvec2<T, P> const & Texcoord)
-	{
-		tvec2<T, P> Result;
-		for(typename tvec2<T, P>::size_type i = 0; i < tvec2<T, P>::value_size(); ++i)
-			Result[i] = mirrorRepeat(Texcoord[i]);
-		return Result;
-	}
-
-	template <typename T, precision P>
-	GLM_FUNC_QUALIFIER tvec3<T, P> mirrorRepeat(tvec3<T, P> const & Texcoord)
-	{
-		tvec3<T, P> Result;
-		for(typename tvec3<T, P>::size_type i = 0; i < tvec3<T, P>::value_size(); ++i)
-			Result[i] = mirrorRepeat(Texcoord[i]);
-		return Result;
-	}
-
-	template <typename T, precision P>
-	GLM_FUNC_QUALIFIER tvec4<T, P> mirrorRepeat(tvec4<T, P> const & Texcoord)
+	GLM_FUNC_QUALIFIER genType mirrorRepeat(genType const& Texcoord)
 	{
-		tvec4<T, P> Result;
-		for(typename tvec4<T, P>::size_type i = 0; i < tvec4<T, P>::value_size(); ++i)
-			Result[i] = mirrorRepeat(Texcoord[i]);
-		return Result;
+		return mirrorRepeat(tvec1<genType, defaultp>(Texcoord)).x;
 	}
 }//namespace glm

+ 1 - 0
readme.md

@@ -74,6 +74,7 @@ glm::mat4 camera(float Translate, glm::vec2 const & Rotate)
 - Improved GTC_reciprocal documentation
 - Improved GLM_FORCE_EXPLICIT_CTOR coverage #481
 - Improved OpenMP support detection for Clang, GCC, ICC and VC
+- Improved GTX_wrap for SIMD friendliness
 - Added constexpr for *vec*, *mat*, *quat* and *dual_quat* types #493
 - Added NEON instruction set detection
 - Added MIPS CPUs detection

+ 48 - 0
test/gtx/gtx_wrap.cpp

@@ -22,6 +22,18 @@ namespace clamp
 		float E = glm::clamp(1.5f);
 		Error += glm::epsilonEqual(E, 1.0f, 0.00001f) ? 0 : 1;
 
+		glm::vec2 K = glm::clamp(glm::vec2(0.5f));
+		Error += glm::all(glm::epsilonEqual(K, glm::vec2(0.5f), glm::vec2(0.00001f))) ? 0 : 1;
+
+		glm::vec3 L = glm::clamp(glm::vec3(0.5f));
+		Error += glm::all(glm::epsilonEqual(L, glm::vec3(0.5f), glm::vec3(0.00001f))) ? 0 : 1;
+
+		glm::vec4 M = glm::clamp(glm::vec4(0.5f));
+		Error += glm::all(glm::epsilonEqual(M, glm::vec4(0.5f), glm::vec4(0.00001f))) ? 0 : 1;
+
+		glm::vec1 N = glm::clamp(glm::vec1(0.5f));
+		Error += glm::all(glm::epsilonEqual(N, glm::vec1(0.5f), glm::vec1(0.00001f))) ? 0 : 1;
+
 		return Error;
 	}
 }//namespace clamp
@@ -50,6 +62,18 @@ namespace repeat
 		float F = glm::repeat(0.9f);
 		Error += glm::epsilonEqual(F, 0.9f, 0.00001f) ? 0 : 1;
 
+		glm::vec2 K = glm::repeat(glm::vec2(0.5f));
+		Error += glm::all(glm::epsilonEqual(K, glm::vec2(0.5f), glm::vec2(0.00001f))) ? 0 : 1;
+
+		glm::vec3 L = glm::repeat(glm::vec3(0.5f));
+		Error += glm::all(glm::epsilonEqual(L, glm::vec3(0.5f), glm::vec3(0.00001f))) ? 0 : 1;
+
+		glm::vec4 M = glm::repeat(glm::vec4(0.5f));
+		Error += glm::all(glm::epsilonEqual(M, glm::vec4(0.5f), glm::vec4(0.00001f))) ? 0 : 1;
+
+		glm::vec1 N = glm::repeat(glm::vec1(0.5f));
+		Error += glm::all(glm::epsilonEqual(N, glm::vec1(0.5f), glm::vec1(0.00001f))) ? 0 : 1;
+
 		return Error;
 	}
 }//namespace repeat
@@ -87,6 +111,18 @@ namespace mirrorClamp
 		float I = glm::mirrorClamp(-0.9f);
 		Error += glm::epsilonEqual(I, 0.9f, 0.00001f) ? 0 : 1;
 
+		glm::vec2 K = glm::mirrorClamp(glm::vec2(0.5f));
+		Error += glm::all(glm::epsilonEqual(K, glm::vec2(0.5f), glm::vec2(0.00001f))) ? 0 : 1;
+
+		glm::vec3 L = glm::mirrorClamp(glm::vec3(0.5f));
+		Error += glm::all(glm::epsilonEqual(L, glm::vec3(0.5f), glm::vec3(0.00001f))) ? 0 : 1;
+
+		glm::vec4 M = glm::mirrorClamp(glm::vec4(0.5f));
+		Error += glm::all(glm::epsilonEqual(M, glm::vec4(0.5f), glm::vec4(0.00001f))) ? 0 : 1;
+
+		glm::vec1 N = glm::mirrorClamp(glm::vec1(0.5f));
+		Error += glm::all(glm::epsilonEqual(N, glm::vec1(0.5f), glm::vec1(0.00001f))) ? 0 : 1;
+
 		return Error;
 	}
 }//namespace mirrorClamp
@@ -124,6 +160,18 @@ namespace mirrorRepeat
 		float I = glm::mirrorRepeat(-1.0f);
 		Error += glm::epsilonEqual(I, 1.0f, 0.00001f) ? 0 : 1;
 
+		glm::vec2 K = glm::mirrorRepeat(glm::vec2(0.5f));
+		Error += glm::all(glm::epsilonEqual(K, glm::vec2(0.5f), glm::vec2(0.00001f))) ? 0 : 1;
+
+		glm::vec3 L = glm::mirrorRepeat(glm::vec3(0.5f));
+		Error += glm::all(glm::epsilonEqual(L, glm::vec3(0.5f), glm::vec3(0.00001f))) ? 0 : 1;
+
+		glm::vec4 M = glm::mirrorRepeat(glm::vec4(0.5f));
+		Error += glm::all(glm::epsilonEqual(M, glm::vec4(0.5f), glm::vec4(0.00001f))) ? 0 : 1;
+
+		glm::vec1 N = glm::mirrorRepeat(glm::vec1(0.5f));
+		Error += glm::all(glm::epsilonEqual(N, glm::vec1(0.5f), glm::vec1(0.00001f))) ? 0 : 1;
+
 		return Error;
 	}
 }//namespace mirrorRepeat