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
|
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");
|
||||||
|
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>
|
template <typename T>
|
||||||
vector<3,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> 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>);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user