vector: add {to,from}_euler
This commit is contained in:
parent
7396057508
commit
74d7f9c717
@ -61,12 +61,52 @@ test_polar (util::TAP::logger &tap)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
test_euler (util::TAP::logger &tap)
|
||||
{
|
||||
static const struct {
|
||||
util::vector3f dir;
|
||||
util::vector2f euler;
|
||||
const char *name;
|
||||
} TESTS[] = {
|
||||
// y-axis
|
||||
{ { 0, 0, -1 }, { 0.5f, 0.5f }, "forward" },
|
||||
{ { -1, 0, 0 }, { 0.5f, -1.0f }, "left" },
|
||||
{ { 0, 0, 1 }, { 0.5f, -0.5f }, "back" },
|
||||
{ { 1, 0, 0 }, { 0.5f, 0.0f }, "right" },
|
||||
|
||||
// x-axis
|
||||
{ { 0, 1, 0 }, { 0, 0 }, "up" },
|
||||
{ { 0, -1, 0 }, { 1, 0 }, "down" },
|
||||
};
|
||||
|
||||
// check that simple axis rotations look correct
|
||||
for (auto i: TESTS) {
|
||||
tap.expect_eq (util::to_euler (i.dir),
|
||||
i.euler * PI<float>,
|
||||
"to euler, %s", i.name);
|
||||
}
|
||||
|
||||
// check error in round trip through euler angles
|
||||
for (auto i: TESTS) {
|
||||
auto trip = util::from_euler (util::to_euler (i.dir));
|
||||
auto diff = i.dir - trip;
|
||||
auto norm = diff.magnitude ();
|
||||
|
||||
// trig functions reduce precision above almost_equal levels, so we
|
||||
// hard code a fairly low bound here instead.
|
||||
tap.expect_lt (norm, 1e-7, "euler round-trip error, %s", i.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
util::TAP::logger tap;
|
||||
|
||||
test_polar (tap);
|
||||
test_euler (tap);
|
||||
|
||||
tap.expect (!util::vector3f::ZERO.is_normalised (), "zero isn't normalised");
|
||||
tap.expect (!util::vector3f::UNIT.is_normalised (), "unit is normalised");
|
||||
|
33
vector.cpp
33
vector.cpp
@ -136,6 +136,39 @@ util::cartesian_to_polar (vector<2,T> v)
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
vector<3,T>
|
||||
util::from_euler (vector<2,T> euler)
|
||||
{
|
||||
return {
|
||||
std::sin (euler.x) * std::cos (euler.y),
|
||||
std::cos (euler.x),
|
||||
-std::sin (euler.x) * std::sin (euler.y),
|
||||
};
|
||||
}
|
||||
|
||||
template util::vector3f util::from_euler (util::vector2f);
|
||||
template util::vector3d util::from_euler (util::vector2d);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
vector<2,T>
|
||||
util::to_euler (vector<3,T> vec)
|
||||
{
|
||||
vec.normalise ();
|
||||
|
||||
return {
|
||||
std::acos (vec.y / vec.magnitude ()),
|
||||
-std::atan2 (vec.z, vec.x),
|
||||
};
|
||||
}
|
||||
|
||||
template util::vector2f util::to_euler (util::vector3f);
|
||||
template util::vector2d util::to_euler (util::vector3d);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
vector<3,T>
|
||||
|
@ -63,6 +63,9 @@ namespace util {
|
||||
template <typename T> vector<3,T> spherical_to_cartesian (vector<3,T>);
|
||||
template <typename T> vector<3,T> cartesian_to_spherical (vector<3,T>);
|
||||
|
||||
template <typename T> vector<2,T> to_euler (vector<3,T>);
|
||||
template <typename T> vector<3,T> from_euler (vector<2,T>);
|
||||
|
||||
// output and serialisation operators
|
||||
template <size_t S, typename T> std::ostream& operator<< (std::ostream&, vector<S,T>);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user