mirror of
https://github.com/g-truc/glm.git
synced 2026-06-08 02:23:48 +00:00
Implement g-truc#1370 (reflection matrix calculation)
- add reflect2D - rewrite functions to accept an input matrix - add tests
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
test/gtx/gtx_transform2.cpp
Normal file
135
test/gtx/gtx_transform2.cpp
Normal file
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user