Kaynağa Gözat

math: add composition of SQT transforms and the corresponding unit tests.

undefined
Sam Hocevar 9 yıl önce
ebeveyn
işleme
d618053d00
2 değiştirilmiş dosya ile 118 ekleme ve 5 silme
  1. +24
    -5
      src/lol/math/transform.h
  2. +94
    -0
      src/t/math/sqt.cpp

+ 24
- 5
src/lol/math/transform.h Dosyayı Görüntüle

@@ -197,6 +197,7 @@ struct quat_t : public linear_ops::base<T>
return quat_t(w, -x, -y, -z);
}

/* Transform vectors or points */
inline vec_t<T,3> transform(vec_t<T,3> const &v) const
{
quat_t p = quat_t(0, v.x, v.y, v.z);
@@ -268,11 +269,21 @@ struct sqt_t
: q(other.q), t(other.t), s(other.s) {}

/* Various explicit constructors */
inline constexpr sqt_t(T const &s_,
quat_t<T> const &q_,
vec_t<T,3> const &t_)
: s(s_), q(q_), t(t_) {}
explicit inline constexpr sqt_t(T const &s_,
quat_t<T> const &q_,
vec_t<T,3> const &t_)
: q(q_), t(t_), s(s_) {}

explicit inline constexpr sqt_t(T const &s_)
: q(1.f), t(0.f), s(s_) {}

explicit inline constexpr sqt_t(quat_t<T> const &q_)
: q(q_), t(0.f), s(1.f) {}

explicit inline constexpr sqt_t(vec_t<T,3> const &t_)
: q(1.f), t(t_), s(1.f) {}

/* Transform vectors or points */
inline vec_t<T,3> transform(vec_t<T,3> const &v) const
{
return t + q.transform(s * v);
@@ -280,7 +291,7 @@ struct sqt_t

inline vec_t<T,4> transform(vec_t<T,4> const &v) const
{
// XXX: needs serious testing
// XXX: needs serious testing for w != 1
vec_t<T,4> tmp = q.transform(vec_t<T,4>(s * v.xyz, v.w));
return vec_t<T,4>(tmp.xyz, 0.f) + vec_t<T,4>(t, 1.f) * tmp.w;
}
@@ -295,6 +306,14 @@ struct sqt_t
return transform(v);
}

/* Compose two SQTs together */
inline sqt_t<T> operator *(sqt_t<T> const &other) const
{
return sqt_t<T>(s * other.s,
q * other.q,
transform(other.t));
}

quat_t<T> q;
vec_t<T,3> t;
T s;


+ 94
- 0
src/t/math/sqt.cpp Dosyayı Görüntüle

@@ -0,0 +1,94 @@
//
// Lol Engine — Unit tests for the SQT transform class
//
// Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
//

#include <lol/engine-internal.h>

#include <lolunit.h>

namespace lol
{

static sqt const test_sqt_1(1.5f,
quat::rotate(radians(20.f),
normalize(vec3(1.f, 2.f, 3.f))),
vec3(1.f, -1.f, 0.5f));

static vec4 test_vec4s[] =
{
vec4(1.f, 0.f, 0.f, 1.f),
vec4(0.f, 1.f, 0.f, 1.f),
vec4(0.f, 0.f, 1.f, 1.f),
vec4(1.f, 2.f, 3.f, 1.f),
vec4(-1.f, 50.f, 12.f, 1.f),
vec4(20.f, -10.f, 0.f, 1.f),
vec4(-20.f, 10.f, 8.f, 1.f),
};

lolunit_declare_fixture(sqt_test)
{
lolunit_declare_test(transform_vec3_vec4)
{
/* We check that transforming a vec3 and a vec4 with w==1
* yield the same results. */
for (vec4 v0 : test_vec4s)
{
vec4 v1 = test_sqt_1.transform(v0);
vec3 v2 = test_sqt_1.transform(v0.xyz);

lolunit_assert_doubles_equal(v1.x, v2.x, 1e-5f);
lolunit_assert_doubles_equal(v1.y, v2.y, 1e-5f);
lolunit_assert_doubles_equal(v1.z, v2.z, 1e-5f);
lolunit_assert_doubles_equal(v1.w, 1.0f, 1e-5f);
}
}

lolunit_declare_test(sqt_vs_matrix_vec4)
{
/* We check that transforming a vec4 with an SQT and a
* vec4 with a product of 4×4 matrices yield the same
* results. */
mat4 m = mat4::translate(test_sqt_1.t)
* mat4(test_sqt_1.q)
* mat4::scale(test_sqt_1.s);

for (vec4 v0 : test_vec4s)
{
vec4 v1 = test_sqt_1 * v0;
vec4 v2 = m * v0;

lolunit_assert_doubles_equal(v1.x, v2.x, 1e-5f);
lolunit_assert_doubles_equal(v1.y, v2.y, 1e-5f);
lolunit_assert_doubles_equal(v1.z, v2.z, 1e-5f);
lolunit_assert_doubles_equal(v1.w, v2.w, 1e-5f);
}
}

lolunit_declare_test(sqt_composition_vec4)
{
/* We check that transforming a vec4 with an SQT and a
* second SQT yields the same result as transforming a
* vec4 with the product of the two SQTs. */
for (vec4 v0 : test_vec4s)
{
vec4 v1 = (test_sqt_1 * test_sqt_1) * v0;
vec4 v2 = test_sqt_1 * (test_sqt_1 * v0);

lolunit_assert_doubles_equal(v1.x, v2.x, 1e-5f);
lolunit_assert_doubles_equal(v1.y, v2.y, 1e-5f);
lolunit_assert_doubles_equal(v1.z, v2.z, 1e-5f);
lolunit_assert_doubles_equal(v1.w, v2.w, 1e-5f);
}
}
};

} /* namespace lol */


Yükleniyor…
İptal
Kaydet