vector: add {to,from}_euler

This commit is contained in:
Danny Robson 2015-07-21 02:56:37 +10:00
parent 7396057508
commit 74d7f9c717
3 changed files with 76 additions and 0 deletions

View File

@ -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 int
main () main ()
{ {
util::TAP::logger tap; util::TAP::logger tap;
test_polar (tap); test_polar (tap);
test_euler (tap);
tap.expect (!util::vector3f::ZERO.is_normalised (), "zero isn't normalised"); tap.expect (!util::vector3f::ZERO.is_normalised (), "zero isn't normalised");
tap.expect (!util::vector3f::UNIT.is_normalised (), "unit is normalised"); tap.expect (!util::vector3f::UNIT.is_normalised (), "unit is normalised");

View File

@ -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> template <typename T>
vector<3,T> vector<3,T>

View File

@ -63,6 +63,9 @@ namespace util {
template <typename T> vector<3,T> spherical_to_cartesian (vector<3,T>); 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<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 // output and serialisation operators
template <size_t S, typename T> std::ostream& operator<< (std::ostream&, vector<S,T>); template <size_t S, typename T> std::ostream& operator<< (std::ostream&, vector<S,T>);