2
0
Эх сурвалжийг харах

Implement g-truc#1370 (reflection matrix calculation)
- add reflect2D
- rewrite functions to accept an input matrix
- add tests

mariob92 6 өдөр өмнө
parent
commit
e282990dc0

+ 7 - 2
glm/gtx/transform2.hpp

@@ -57,10 +57,15 @@ namespace glm
 	// Identity + tan(angle) * cross(Normal, OnPlaneVector)     0
 	// - dot(PointOnPlane, normal) * OnPlaneVector              1
 
-	//! Build a reflection matrix.
+	//! Reflects a matrix on an arbitrary plane.
 	//! From GLM_GTX_transform2 extension.
 	template<typename T, qualifier Q>
-	GLM_FUNC_DECL mat<4, 4, T, Q> reflect3D(vec<3, T, Q> const& normal, T distance);
+	GLM_FUNC_DECL mat<3, 3, T, Q> reflect2D(mat<3, 3, T, Q> const& m, vec<2, T, Q> const& normal, T distance);
+
+	//! Reflects a matrix on an arbitrary plane.
+	//! From GLM_GTX_transform2 extension.
+	template<typename T, qualifier Q>
+	GLM_FUNC_DECL mat<4, 4, T, Q> reflect3D(mat<4, 4, T, Q> const& m, vec<3, T, Q> const& normal, T distance);
 
 	//! Build planar projection matrix along normal axis.
 	//! From GLM_GTX_transform2 extension.

+ 27 - 25
glm/gtx/transform2.inl

@@ -45,34 +45,36 @@ namespace glm
 		return m * r;
 	}
 
-	// template<typename T, qualifier Q>
-	// GLM_FUNC_QUALIFIER mat<3, 3, T, Q> reflect2D(mat<3, 3, T, Q> const& m, vec<3, T, Q> const& normal)
-	// {
-	// 	mat<3, 3, T, Q> r(static_cast<T>(1));
-	// 	r[0][0] = static_cast<T>(1) - static_cast<T>(2) * normal.x * normal.x;
-	// 	r[0][1] = -static_cast<T>(2) * normal.x * normal.y;
-	// 	r[1][0] = -static_cast<T>(2) * normal.x * normal.y;
-	// 	r[1][1] = static_cast<T>(1) - static_cast<T>(2) * normal.y * normal.y;
-	// 	return m * r;
-	// }
+	template<typename T, qualifier Q>
+	GLM_FUNC_QUALIFIER mat<3, 3, T, Q> reflect2D(mat<3, 3, T, Q> const& m, vec<2, T, Q> const& normal, T distance)
+	{
+		mat<3, 3, T, Q> r(static_cast<T>(1));
+		r[0][0] = static_cast<T>(1) - static_cast<T>(2) * normal.x * normal.x;
+		r[0][1] = -static_cast<T>(2) * normal.y * normal.x;
+		r[1][0] = -static_cast<T>(2) * normal.x * normal.y;
+		r[1][1] = static_cast<T>(1) - static_cast<T>(2) * normal.y * normal.y;
+		r[2][0] = -static_cast<T>(2) * normal.x * distance;
+		r[2][1] = -static_cast<T>(2) * normal.y * distance;
+		return m * r;
+	}
 
 	template<typename T, qualifier Q>
-	GLM_FUNC_DECL mat<4, 4, T, Q> reflect3D(vec<3, T, Q> const& normal, T distance)
+	GLM_FUNC_QUALIFIER mat<4, 4, T, Q> reflect3D(mat<4, 4, T, Q> const& m, vec<3, T, Q> const& normal, T distance)
 	{
-		mat<4, 4, T, Q> result(static_cast<T>(1));
-		result[0][0] = static_cast<T>(1) - static_cast<T>(2) * normal.x * normal.x;
-		result[0][1] = -static_cast<T>(2) * normal.y * normal.x;
-		result[0][2] = -static_cast<T>(2) * normal.z * normal.x;
-		result[1][0] = -static_cast<T>(2) * normal.x * normal.y;
-		result[1][1] = static_cast<T>(1) - static_cast<T>(2) * normal.y * normal.y;
-		result[1][2] = -static_cast<T>(2) * normal.z * normal.y;
-		result[2][0] = -static_cast<T>(2) * normal.x * normal.z;
-		result[2][1] = -static_cast<T>(2) * normal.y * normal.z;
-		result[2][2] = static_cast<T>(1) - static_cast<T>(2) * normal.z * normal.z;
-		result[3][0] = -static_cast<T>(2) * normal.x * distance;
-		result[3][1] = -static_cast<T>(2) * normal.y * distance;
-		result[3][2] = -static_cast<T>(2) * normal.z * distance;
-		return result;
+		mat<4, 4, T, Q> r(static_cast<T>(1));
+		r[0][0] = static_cast<T>(1) - static_cast<T>(2) * normal.x * normal.x;
+		r[0][1] = -static_cast<T>(2) * normal.y * normal.x;
+		r[0][2] = -static_cast<T>(2) * normal.z * normal.x;
+		r[1][0] = -static_cast<T>(2) * normal.x * normal.y;
+		r[1][1] = static_cast<T>(1) - static_cast<T>(2) * normal.y * normal.y;
+		r[1][2] = -static_cast<T>(2) * normal.z * normal.y;
+		r[2][0] = -static_cast<T>(2) * normal.x * normal.z;
+		r[2][1] = -static_cast<T>(2) * normal.y * normal.z;
+		r[2][2] = static_cast<T>(1) - static_cast<T>(2) * normal.z * normal.z;
+		r[3][0] = -static_cast<T>(2) * normal.x * distance;
+		r[3][1] = -static_cast<T>(2) * normal.y * distance;
+		r[3][2] = -static_cast<T>(2) * normal.z * distance;
+		return m * r;
 	}
 
 	template<typename T, qualifier Q>

+ 1 - 0
test/gtx/CMakeLists.txt

@@ -53,6 +53,7 @@ glmCreateTestGTC(gtx_spline)
 glmCreateTestGTC(gtx_string_cast)
 glmCreateTestGTC(gtx_structured_bindings)
 glmCreateTestGTC(gtx_texture)
+glmCreateTestGTC(gtx_transform2)
 glmCreateTestGTC(gtx_type_aligned)
 glmCreateTestGTC(gtx_type_trait)
 glmCreateTestGTC(gtx_vec_swizzle)

+ 135 - 0
test/gtx/gtx_transform2.cpp

@@ -0,0 +1,135 @@
+#include <glm/glm.hpp>
+#include <glm/gtc/epsilon.hpp>
+
+#define GLM_ENABLE_EXPERIMENTAL
+#include <glm/gtx/transform2.hpp>
+
+static int test_reflect2D()
+{
+	int Error = 0;
+
+	{
+		const glm::mat3 m3(
+			1, 0, 0,
+			0, 1, 0,
+			1, 2, 1
+		);
+
+		const glm::mat3 eam3(
+			1, 0, 0,
+			0, -1, 0,
+			1, 2, 1
+		);
+
+		const glm::mat3 am3 = glm::reflect2D(
+			m3,
+			glm::vec2(0, 1),
+			static_cast<glm::mat3::row_type::value_type>(0)
+		);
+
+		Error += glm::all(glm::bvec3(
+			glm::all(glm::epsilonEqual(eam3[0], am3[0], glm::epsilon<float>())),
+			glm::all(glm::epsilonEqual(eam3[1], am3[1], glm::epsilon<float>())),
+			glm::all(glm::epsilonEqual(eam3[2], am3[2], glm::epsilon<float>())))) ? 0 : 1;
+	}
+
+	{
+		const glm::mat3 m3(
+			1, 0, 0,
+			0, 1, 0,
+			1, 2, 1
+		);
+
+		const glm::mat3 eam3(
+			0, 1, 0,
+			1, 0, 0,
+			1, 2, 1
+		);
+
+		const glm::mat3 am3 = glm::reflect2D(
+			m3,
+			glm::vec2(-0.70710678, 0.70710678),
+			static_cast<glm::mat3::row_type::value_type>(0)
+		);
+
+		Error += glm::all(glm::bvec3(
+			glm::all(glm::epsilonEqual(eam3[0], am3[0], glm::epsilon<float>())),
+			glm::all(glm::epsilonEqual(eam3[1], am3[1], glm::epsilon<float>())),
+			glm::all(glm::epsilonEqual(eam3[2], am3[2], glm::epsilon<float>())))) ? 0 : 1;
+	}
+		
+	return Error;
+}
+
+static int test_reflect3D()
+{
+	int Error = 0;
+
+	{
+		const glm::mat4 m4(
+			1, 0, 0, 0,
+			0, 1, 0, 0,
+			0, 0, 1, 0,
+			0, 0, 0, 1
+		);
+
+		const glm::mat4 eam4(
+			1, 0, 0, 0,
+			0, -1, 0, 0,
+			0, 0, 1, 0,
+			0, -2, 0, 1
+		);
+
+		const glm::mat4 am4 = glm::reflect3D(
+			m4,
+			glm::vec3(0, 1, 0),
+			static_cast<glm::mat4::row_type::value_type>(1)
+		);
+
+		Error += glm::all(glm::bvec4(
+			glm::all(glm::epsilonEqual(eam4[0], am4[0], glm::epsilon<float>())),
+			glm::all(glm::epsilonEqual(eam4[1], am4[1], glm::epsilon<float>())),
+			glm::all(glm::epsilonEqual(eam4[2], am4[2], glm::epsilon<float>())),
+			glm::all(glm::epsilonEqual(eam4[3], am4[3], glm::epsilon<float>())))) ? 0 : 1;
+	}
+
+	{
+		const glm::mat4 m4(
+			1, 0, 0, 0,
+			0, 1, 0, 0,
+			0, 0, 1, 0,
+			0, 0, 0, 1
+		);
+
+		const glm::mat4 eam4(
+			0, 1, 0, 0,
+			1, 0, 0, 0,
+			0, 0, 1, 0,
+			0, 0, 0, 1
+		);
+
+		const glm::mat4 am4 = glm::reflect3D(
+			m4,
+			glm::vec3(-0.70710678, 0.70710678, 0.0),
+			static_cast<glm::mat4::row_type::value_type>(0)
+		);
+
+		Error += glm::all(glm::bvec4(
+			glm::all(glm::epsilonEqual(eam4[0], am4[0], glm::epsilon<float>())),
+			glm::all(glm::epsilonEqual(eam4[1], am4[1], glm::epsilon<float>())),
+			glm::all(glm::epsilonEqual(eam4[2], am4[2], glm::epsilon<float>())),
+			glm::all(glm::epsilonEqual(eam4[3], am4[3], glm::epsilon<float>())))) ? 0 : 1;
+	}
+
+	return Error;
+}
+
+int main()
+{
+	int Error = 0;
+
+	Error += test_reflect2D();
+	Error += test_reflect3D();
+
+	return Error;
+}