mirror of
https://github.com/BlackMATov/vmath.hpp.git
synced 2025-12-14 20:31:25 +07:00
basic qua ext rotation functions
This commit is contained in:
@@ -662,3 +662,57 @@ namespace vmath_hpp
|
|||||||
return dot(v, normal) / length2(normal) * normal;
|
return dot(v, normal) / length2(normal) * normal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Quaternion Transform
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace vmath_hpp
|
||||||
|
{
|
||||||
|
// qrotate
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
[[nodiscard]] qua<T> qrotate(T angle, const vec<T, 3>& axis) {
|
||||||
|
const auto [s, c] = sincos(angle * T(0.5));
|
||||||
|
const auto [x, y, z] = normalize(axis);
|
||||||
|
return {vec{x,y,z} * s, c};
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
[[nodiscard]] qua<T> qrotate(const qua<T>& q, T angle, const vec<T, 3>& axis) {
|
||||||
|
return q * qrotate(angle, axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
[[nodiscard]] qua<T> qrotate_x(T angle) {
|
||||||
|
const auto [s, c] = sincos(angle * T(0.5));
|
||||||
|
return {s, T(0), T(0), c};
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
[[nodiscard]] qua<T> qrotate_x(const qua<T>& q, T angle) {
|
||||||
|
return qrotate(q, angle, unit3_x<T>);
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
[[nodiscard]] qua<T> qrotate_y(T angle) {
|
||||||
|
const auto [s, c] = sincos(angle * T(0.5));
|
||||||
|
return {T(0), s, T(0), c};
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
[[nodiscard]] qua<T> qrotate_y(const qua<T>& q, T angle) {
|
||||||
|
return qrotate(q, angle, unit3_y<T>);
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
[[nodiscard]] qua<T> qrotate_z(T angle) {
|
||||||
|
const auto [s, c] = sincos(angle * T(0.5));
|
||||||
|
return {T(0), T(0), s, c};
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
[[nodiscard]] qua<T> qrotate_z(const qua<T>& q, T angle) {
|
||||||
|
return qrotate(q, angle, unit3_z<T>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -226,3 +226,24 @@ namespace vmath_hpp
|
|||||||
return not_equal_to(vec{xs}, vec{ys});
|
return not_equal_to(vec{xs}, vec{ys});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Quaternion Functions
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace vmath_hpp
|
||||||
|
{
|
||||||
|
// conjugate
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
[[nodiscard]] constexpr qua<T> conjugate(const qua<T>& q) {
|
||||||
|
return {-q.v, q.s};
|
||||||
|
}
|
||||||
|
|
||||||
|
// inverse
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
[[nodiscard]] constexpr qua<T> inverse(const qua<T>& q) {
|
||||||
|
return conjugate(q) * rcp(dot(q, q));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -293,4 +293,28 @@ TEST_CASE("vmath/ext") {
|
|||||||
REQUIRE(project(float2(2.f, 2.f), float2(0.f, 1.f)) == uapprox2(0.f, 2.f));
|
REQUIRE(project(float2(2.f, 2.f), float2(0.f, 1.f)) == uapprox2(0.f, 2.f));
|
||||||
REQUIRE(project(float3(2.f, 2.f, 2.f), float3(0.f, 0.f, 1.f)) == uapprox3(0.f, 0.f, 2.f));
|
REQUIRE(project(float3(2.f, 2.f, 2.f), float3(0.f, 0.f, 1.f)) == uapprox3(0.f, 0.f, 2.f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SUBCASE("quaternion qrotate") {
|
||||||
|
constexpr float pi = radians(180.f);
|
||||||
|
constexpr float pi_2 = radians(90.f);
|
||||||
|
constexpr float pi_4 = radians(45.f);
|
||||||
|
|
||||||
|
REQUIRE(float3(0.f,1.f,0.f) * qrotate_x(pi_2) == uapprox3(0.f,0.f,1.f));
|
||||||
|
REQUIRE(float3(0.f,0.f,1.f) * qrotate_y(pi_2) == uapprox3(1.f,0.f,0.f));
|
||||||
|
REQUIRE(float3(1.f,0.f,0.f) * qrotate_z(pi_2) == uapprox3(0.f,1.f,0.f));
|
||||||
|
|
||||||
|
REQUIRE(float3(0.f,1.f,0.f) * qrotate_x(qrotate_x(pi_4),pi_4) == uapprox3(0.f,0.f,1.f));
|
||||||
|
REQUIRE(float3(0.f,0.f,1.f) * qrotate_y(qrotate_y(pi_4),pi_4) == uapprox3(1.f,0.f,0.f));
|
||||||
|
REQUIRE(float3(1.f,0.f,0.f) * qrotate_z(qrotate_z(pi_4),pi_4) == uapprox3(0.f,1.f,0.f));
|
||||||
|
|
||||||
|
REQUIRE(float3(2.f,3.f,4.f) * qrotate(pi,{0.f,0.f,1.f}) == uapprox3(-2.f,-3.f,4.f));
|
||||||
|
REQUIRE(float3(2.f,3.f,4.f) * qrotate(pi,float3{0.f,0.f,1.f}) == uapprox3(-2.f,-3.f,4.f));
|
||||||
|
|
||||||
|
REQUIRE(float3(2.f,3.f,4.f) * qrotate(qrotate(pi_2,{0.f,0.f,1.f}),pi_2,{0.f,0.f,1.f}) == uapprox3(-2.f,-3.f,4.f));
|
||||||
|
REQUIRE(float3(2.f,3.f,4.f) * qrotate(qrotate(pi_2,float3{0.f,0.f,1.f}),pi_2,float3{0.f,0.f,1.f}) == uapprox3(-2.f,-3.f,4.f));
|
||||||
|
|
||||||
|
REQUIRE(qrotate_x(12.3f) == qrotate(12.3f, unit3_x<float> * 2.f));
|
||||||
|
REQUIRE(qrotate_y(12.3f) == qrotate(12.3f, unit3_y<float> * 2.f));
|
||||||
|
REQUIRE(qrotate_z(12.3f) == qrotate(12.3f, unit3_z<float> * 2.f));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,4 +91,13 @@ TEST_CASE("vmath/qua_fun") {
|
|||||||
STATIC_REQUIRE(equal_to(qua(1,1,1,1), qua(0,1,2,3)) == bool4(false, true, false, false));
|
STATIC_REQUIRE(equal_to(qua(1,1,1,1), qua(0,1,2,3)) == bool4(false, true, false, false));
|
||||||
STATIC_REQUIRE(not_equal_to(qua(1,1,1,1), qua(0,1,2,3)) == bool4(true, false, true, true));
|
STATIC_REQUIRE(not_equal_to(qua(1,1,1,1), qua(0,1,2,3)) == bool4(true, false, true, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SUBCASE("Quaternion Functions") {
|
||||||
|
STATIC_REQUIRE(conjugate(qua(1,2,3,4)) == qua(-1,-2,-3,4));
|
||||||
|
STATIC_REQUIRE(inverse(qua(0.f,0.f,0.7071067812f,0.7071067812f)).v == uapprox3(0.f,0.f,-0.7071067812f));
|
||||||
|
STATIC_REQUIRE(inverse(qua(0.f,0.f,0.7071067812f,0.7071067812f)).s == uapprox(0.7071067812f));
|
||||||
|
|
||||||
|
REQUIRE(inverse(qrotate_x(10.f)) == qrotate_x(-10.f));
|
||||||
|
REQUIRE(all(approx(inverse(qrotate_x(10.f) * qrotate_y(15.f)), qrotate_y(-15.f) * qrotate_x(-10.f))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user