218 lines
10 KiB
C++
218 lines
10 KiB
C++
#include "tap.hpp"
|
|
|
|
#include "vector.hpp"
|
|
#include "matrix.hpp"
|
|
#include "quaternion.hpp"
|
|
|
|
#include "coord/iostream.hpp"
|
|
#include "matrix.hpp"
|
|
|
|
#include <array>
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
test_matrix_identities (util::TAP::logger &tap)
|
|
{
|
|
static constexpr util::vector3f UP {0,1,0};
|
|
|
|
{
|
|
util::point3f p { 1, 2, 3 };
|
|
|
|
auto m = util::translation (0-p);
|
|
auto x = m * p.homog<4> ();
|
|
tap.expect_eq (x, util::point4f {0,0,0,1}, "trivial translation to origin");
|
|
}
|
|
|
|
{
|
|
util::point3f p {0};
|
|
auto m = util::rotation<float> (1, { 1, 0, 0 }) *
|
|
util::rotation<float> (1, { 0, 1, 0 }) *
|
|
util::rotation<float> (1, { 0, 0, 1 });
|
|
auto x = m * p.homog<4> ();
|
|
|
|
tap.expect_eq (x, util::point4f {0,0,0,1}, "trivial rotation at origin");
|
|
}
|
|
|
|
{
|
|
util::point3f eye { 1, 2, 3 };
|
|
util::point3f tgt { 0, 0, 0 };
|
|
|
|
auto m = util::look_at (eye, tgt, UP);
|
|
auto x = m * eye.homog<4> ();
|
|
tap.expect_eq (x, util::point4f {0,0,0,1}, "look_at eye translation");
|
|
}
|
|
|
|
{
|
|
util::point3f eye { 1, 2, 3 };
|
|
util::point3f tgt { 4, 5, 6 };
|
|
|
|
auto m = util::look_at (eye, tgt, UP);
|
|
auto x = m * eye.homog<4> ();
|
|
tap.expect_eq (x, util::point4f {0,0,0,1}, "look_at eye translation with target");
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
test_perspective (util::TAP::logger &tap)
|
|
{
|
|
static const struct {
|
|
float w, h;
|
|
float near, far;
|
|
float fov;
|
|
float a, b, c, d;
|
|
} TESTS[] = {
|
|
{ 1.f, 1.f, 1.f, 100.f, 45.f, 2.414213419f, 2.414213419f, -1.020202041f, -2.020201921f },
|
|
{ 1.f, 1.f, 1.f, 100.f, 60.f, 1.732050776f, 1.732050776f, -1.020202041f, -2.020201921f },
|
|
{ 1.f, 1.f, 1.f, 100.f, 90.f, 1.000000000f, 1.000000000f, -1.020202041f, -2.020201921f },
|
|
{ 1.f, 1.f, 1.f, 100.f, 120.f, 0.577350199f, 0.577350199f, -1.020202041f, -2.020201921f },
|
|
{ 1.f, 1.f, 1e-08f, 1e+08f, 45.f, 2.414213419f, 2.414213419f, -1.000000000f, -0.000000020f },
|
|
{ 1.f, 1.f, 1e-08f, 1e+08f, 60.f, 1.732050776f, 1.732050776f, -1.000000000f, -0.000000020f },
|
|
{ 1.f, 1.f, 1e-08f, 1e+08f, 90.f, 1.000000000f, 1.000000000f, -1.000000000f, -0.000000020f },
|
|
{ 1.f, 1.f, 1e-08f, 1e+08f, 120.f, 0.577350199f, 0.577350199f, -1.000000000f, -0.000000020f },
|
|
{ 1.f, 1.f, 0.01f, 1000.f, 45.f, 2.414213419f, 2.414213419f, -1.000020027f, -0.020000201f },
|
|
{ 1.f, 1.f, 0.01f, 1000.f, 60.f, 1.732050776f, 1.732050776f, -1.000020027f, -0.020000201f },
|
|
{ 1.f, 1.f, 0.01f, 1000.f, 90.f, 1.000000000f, 1.000000000f, -1.000020027f, -0.020000201f },
|
|
{ 1.f, 1.f, 0.01f, 1000.f, 120.f, 0.577350199f, 0.577350199f, -1.000020027f, -0.020000201f },
|
|
{ 4.f, 3.f, 1.f, 100.f, 45.f, 1.810660124f, 2.414213419f, -1.020202041f, -2.020201921f },
|
|
{ 4.f, 3.f, 1.f, 100.f, 60.f, 1.299038053f, 1.732050776f, -1.020202041f, -2.020201921f },
|
|
{ 4.f, 3.f, 1.f, 100.f, 90.f, 0.750000000f, 1.000000000f, -1.020202041f, -2.020201921f },
|
|
{ 4.f, 3.f, 1.f, 100.f, 120.f, 0.433012664f, 0.577350199f, -1.020202041f, -2.020201921f },
|
|
{ 4.f, 3.f, 1e-08f, 1e+08f, 45.f, 1.810660124f, 2.414213419f, -1.000000000f, -0.000000020f },
|
|
{ 4.f, 3.f, 1e-08f, 1e+08f, 60.f, 1.299038053f, 1.732050776f, -1.000000000f, -0.000000020f },
|
|
{ 4.f, 3.f, 1e-08f, 1e+08f, 90.f, 0.750000000f, 1.000000000f, -1.000000000f, -0.000000020f },
|
|
{ 4.f, 3.f, 1e-08f, 1e+08f, 120.f, 0.433012664f, 0.577350199f, -1.000000000f, -0.000000020f },
|
|
{ 4.f, 3.f, 0.01f, 1000.f, 45.f, 1.810660124f, 2.414213419f, -1.000020027f, -0.020000201f },
|
|
{ 4.f, 3.f, 0.01f, 1000.f, 60.f, 1.299038053f, 1.732050776f, -1.000020027f, -0.020000201f },
|
|
{ 4.f, 3.f, 0.01f, 1000.f, 90.f, 0.750000000f, 1.000000000f, -1.000020027f, -0.020000201f },
|
|
{ 4.f, 3.f, 0.01f, 1000.f, 120.f, 0.433012664f, 0.577350199f, -1.000020027f, -0.020000201f },
|
|
{ 16.f, 9.f, 1.f, 100.f, 45.f, 1.357995033f, 2.414213419f, -1.020202041f, -2.020201921f },
|
|
{ 16.f, 9.f, 1.f, 100.f, 60.f, 0.974278569f, 1.732050776f, -1.020202041f, -2.020201921f },
|
|
{ 16.f, 9.f, 1.f, 100.f, 90.f, 0.562500000f, 1.000000000f, -1.020202041f, -2.020201921f },
|
|
{ 16.f, 9.f, 1.f, 100.f, 120.f, 0.324759483f, 0.577350199f, -1.020202041f, -2.020201921f },
|
|
{ 16.f, 9.f, 1e-08f, 1e+08f, 45.f, 1.357995033f, 2.414213419f, -1.000000000f, -0.000000020f },
|
|
{ 16.f, 9.f, 1e-08f, 1e+08f, 60.f, 0.974278569f, 1.732050776f, -1.000000000f, -0.000000020f },
|
|
{ 16.f, 9.f, 1e-08f, 1e+08f, 90.f, 0.562500000f, 1.000000000f, -1.000000000f, -0.000000020f },
|
|
{ 16.f, 9.f, 1e-08f, 1e+08f, 120.f, 0.324759483f, 0.577350199f, -1.000000000f, -0.000000020f },
|
|
{ 16.f, 9.f, 0.01f, 1000.f, 45.f, 1.357995033f, 2.414213419f, -1.000020027f, -0.020000201f },
|
|
{ 16.f, 9.f, 0.01f, 1000.f, 60.f, 0.974278569f, 1.732050776f, -1.000020027f, -0.020000201f },
|
|
{ 16.f, 9.f, 0.01f, 1000.f, 90.f, 0.562500000f, 1.000000000f, -1.000020027f, -0.020000201f },
|
|
{ 16.f, 9.f, 0.01f, 1000.f, 120.f, 0.324759483f, 0.577350199f, -1.000020027f, -0.020000201f },
|
|
{ 16.f, 10.f, 1.f, 100.f, 45.f, 1.508883357f, 2.414213419f, -1.020202041f, -2.020201921f },
|
|
{ 16.f, 10.f, 1.f, 100.f, 60.f, 1.082531691f, 1.732050776f, -1.020202041f, -2.020201921f },
|
|
{ 16.f, 10.f, 1.f, 100.f, 90.f, 0.625000000f, 1.000000000f, -1.020202041f, -2.020201921f },
|
|
{ 16.f, 10.f, 1.f, 100.f, 120.f, 0.360843867f, 0.577350199f, -1.020202041f, -2.020201921f },
|
|
{ 16.f, 10.f, 1e-08f, 1e+08f, 45.f, 1.508883357f, 2.414213419f, -1.000000000f, -0.000000020f },
|
|
{ 16.f, 10.f, 1e-08f, 1e+08f, 60.f, 1.082531691f, 1.732050776f, -1.000000000f, -0.000000020f },
|
|
{ 16.f, 10.f, 1e-08f, 1e+08f, 90.f, 0.625000000f, 1.000000000f, -1.000000000f, -0.000000020f },
|
|
{ 16.f, 10.f, 1e-08f, 1e+08f, 120.f, 0.360843867f, 0.577350199f, -1.000000000f, -0.000000020f },
|
|
{ 16.f, 10.f, 0.01f, 1000.f, 45.f, 1.508883357f, 2.414213419f, -1.000020027f, -0.020000201f },
|
|
{ 16.f, 10.f, 0.01f, 1000.f, 60.f, 1.082531691f, 1.732050776f, -1.000020027f, -0.020000201f },
|
|
{ 16.f, 10.f, 0.01f, 1000.f, 90.f, 0.625000000f, 1.000000000f, -1.000020027f, -0.020000201f },
|
|
{ 16.f, 10.f, 0.01f, 1000.f, 120.f, 0.360843867f, 0.577350199f, -1.000020027f, -0.020000201f },
|
|
{ 21.f, 9.f, 1.f, 100.f, 45.f, 1.034662843f, 2.414213419f, -1.020202041f, -2.020201921f },
|
|
{ 21.f, 9.f, 1.f, 100.f, 60.f, 0.742307484f, 1.732050776f, -1.020202041f, -2.020201921f },
|
|
{ 21.f, 9.f, 1.f, 100.f, 90.f, 0.428571433f, 1.000000000f, -1.020202041f, -2.020201921f },
|
|
{ 21.f, 9.f, 1.f, 100.f, 120.f, 0.247435793f, 0.577350199f, -1.020202041f, -2.020201921f },
|
|
{ 21.f, 9.f, 1e-08f, 1e+08f, 45.f, 1.034662843f, 2.414213419f, -1.000000000f, -0.000000020f },
|
|
{ 21.f, 9.f, 1e-08f, 1e+08f, 60.f, 0.742307484f, 1.732050776f, -1.000000000f, -0.000000020f },
|
|
{ 21.f, 9.f, 1e-08f, 1e+08f, 90.f, 0.428571433f, 1.000000000f, -1.000000000f, -0.000000020f },
|
|
{ 21.f, 9.f, 1e-08f, 1e+08f, 120.f, 0.247435793f, 0.577350199f, -1.000000000f, -0.000000020f },
|
|
{ 21.f, 9.f, 0.01f, 1000.f, 45.f, 1.034662843f, 2.414213419f, -1.000020027f, -0.020000201f },
|
|
{ 21.f, 9.f, 0.01f, 1000.f, 60.f, 0.742307484f, 1.732050776f, -1.000020027f, -0.020000201f },
|
|
{ 21.f, 9.f, 0.01f, 1000.f, 90.f, 0.428571433f, 1.000000000f, -1.000020027f, -0.020000201f },
|
|
{ 21.f, 9.f, 0.01f, 1000.f, 120.f, 0.247435793f, 0.577350199f, -1.000020027f, -0.020000201f },
|
|
};
|
|
|
|
for (const auto &t: TESTS) {
|
|
util::matrix4f m {0};
|
|
m[0][0] = t.a;
|
|
m[1][1] = t.b;
|
|
m[2][2] = t.c;
|
|
m[2][3] = t.d;
|
|
m[3][2] = -1.f;
|
|
|
|
const auto p = util::perspective (util::to_radians (t.fov), t.w / t.h, {t.near, t.far});
|
|
|
|
tap.expect (
|
|
util::relatively_equal (m, p, 1e-7f),
|
|
"perspective %!:%!@%!",
|
|
t.w, t.h, t.fov
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
test_mq_axis (util::TAP::logger &tap)
|
|
{
|
|
static const struct {
|
|
util::vector3f euler;
|
|
const char *msg;
|
|
} TESTS[] = {
|
|
{ { 1, 0, 0 }, "x-axis" },
|
|
{ { 0, 1, 0 }, "y-axis" },
|
|
{ { 0, 0, 1 }, "z-axis" },
|
|
};
|
|
|
|
for (auto t: TESTS) {
|
|
auto m = util::rotation<float> (1, t.euler);
|
|
auto q = util::quaternionf::angle_axis (1, t.euler);
|
|
|
|
auto diff = sum (abs (m - q.as_matrix ()));
|
|
tap.expect_le (diff, 1e-6f, "matrix/quaternion rotation identities, %s", t.msg);
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
test_mq_euler (util::TAP::logger &tap)
|
|
{
|
|
static const struct {
|
|
float x, y, z;
|
|
const char *msg;
|
|
} TESTS[] = {
|
|
{ 0, 0, 0, "zeroes" },
|
|
{ 1, 0, 0, "x-axis" },
|
|
{ 0, 1, 0, "y-axis" },
|
|
{ 0, 0, 1, "z-axis" },
|
|
{ 1, 1, 1, "ones" },
|
|
{ 9, 9, 9, "nines" }
|
|
};
|
|
|
|
for (auto t: TESTS) {
|
|
const auto mx = util::rotation<float> (t.x, {1,0,0});
|
|
const auto my = util::rotation<float> (t.y, {0,1,0});
|
|
const auto mz = util::rotation<float> (t.z, {0,0,1});
|
|
const auto m = mx * my * mz;
|
|
|
|
auto q = (
|
|
util::quaternionf::angle_axis (t.x, { 1, 0, 0 }) *
|
|
util::quaternionf::angle_axis (t.y, { 0, 1, 0 }) *
|
|
util::quaternionf::angle_axis (t.z, { 0, 0, 1 })
|
|
).as_matrix ();
|
|
|
|
auto diff = util::sum (abs (m - q));
|
|
tap.expect_le (diff, 1e-6f, "matrix-quaternion xyz euler rotations, %s", t.msg);
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
int
|
|
main (int, char**)
|
|
{
|
|
util::TAP::logger tap;
|
|
|
|
test_matrix_identities (tap);
|
|
test_mq_axis (tap);
|
|
test_mq_euler (tap);
|
|
test_perspective (tap);
|
|
|
|
return tap.status ();
|
|
}
|