2015-04-02 14:57:30 +11:00
|
|
|
#include "vector.hpp"
|
|
|
|
|
|
|
|
#include "maths.hpp"
|
2015-04-13 16:45:56 +10:00
|
|
|
#include "tap.hpp"
|
2015-04-02 14:57:30 +11:00
|
|
|
|
|
|
|
using util::vector;
|
|
|
|
using util::vector2f;
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2015-07-21 02:55:11 +10:00
|
|
|
test_polar (util::TAP::logger &tap)
|
2015-04-02 14:57:30 +11:00
|
|
|
{
|
|
|
|
static const struct {
|
|
|
|
util::vector2f polar;
|
|
|
|
util::vector2f cartesian;
|
|
|
|
const char *desc;
|
|
|
|
} TESTS[] {
|
|
|
|
{
|
|
|
|
{ 0.f, 0.f },
|
|
|
|
{ 0.f, 0.f },
|
|
|
|
"all zeroes"
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
{ 1.f, 0.f },
|
|
|
|
{ 1.f, 0.f },
|
|
|
|
"unit length, unrotated"
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
2015-11-16 11:42:20 +11:00
|
|
|
{ 1.f, util::PI<float> / 2.f },
|
2015-04-02 14:57:30 +11:00
|
|
|
{ 0.f, 1.f },
|
|
|
|
"unit length, rotated"
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
2015-11-16 11:42:20 +11:00
|
|
|
{ 1.f, 2 * util::PI<float> },
|
2015-04-02 14:57:30 +11:00
|
|
|
{ 1.f, 0.f },
|
|
|
|
"full rotation, unit length"
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
for (const auto &t: TESTS) {
|
|
|
|
// Compare the difference of cartesian representations. Don't use
|
|
|
|
// direct equality comparisons here as the numeric stability can be
|
|
|
|
// poor and we have nice whole numbers to start with.
|
|
|
|
auto in_cart = t.cartesian;
|
|
|
|
auto to_cart = util::polar_to_cartesian (t.polar);
|
|
|
|
|
2015-07-21 02:55:11 +10:00
|
|
|
tap.expect_lt ((in_cart - to_cart).magnitude (), 0.00001f, t.desc);
|
2015-04-02 14:57:30 +11:00
|
|
|
|
|
|
|
// Compare polar representations. Make sure to normalise them first.
|
|
|
|
auto in_polar = t.polar;
|
|
|
|
auto to_polar = util::cartesian_to_polar (t.cartesian);
|
|
|
|
|
2015-11-16 11:42:20 +11:00
|
|
|
in_polar[1] = std::fmod (in_polar[1], 2 * util::PI<float>);
|
|
|
|
to_polar[1] = std::fmod (to_polar[1], 2 * util::PI<float>);
|
2015-04-02 14:57:30 +11:00
|
|
|
|
2015-07-21 02:55:11 +10:00
|
|
|
tap.expect_eq (in_polar, to_polar, t.desc);
|
2015-04-02 14:57:30 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-21 02:56:37 +10:00
|
|
|
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),
|
2015-11-16 11:42:20 +11:00
|
|
|
i.euler * util::PI<float>,
|
2015-07-21 02:56:37 +10:00
|
|
|
"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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-02 14:57:30 +11:00
|
|
|
int
|
|
|
|
main ()
|
|
|
|
{
|
2015-07-21 02:55:11 +10:00
|
|
|
util::TAP::logger tap;
|
2015-04-15 13:48:51 +10:00
|
|
|
|
2015-07-21 02:55:11 +10:00
|
|
|
test_polar (tap);
|
2015-07-21 02:56:37 +10:00
|
|
|
test_euler (tap);
|
2015-04-15 13:48:51 +10:00
|
|
|
|
2015-07-21 02:55:11 +10:00
|
|
|
tap.expect (!util::vector3f::ZERO.is_normalised (), "zero isn't normalised");
|
|
|
|
tap.expect (!util::vector3f::UNIT.is_normalised (), "unit is normalised");
|
2015-04-15 13:48:51 +10:00
|
|
|
|
2015-07-21 02:55:11 +10:00
|
|
|
return tap.status ();
|
2015-04-02 14:57:30 +11:00
|
|
|
}
|