diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2024-10-20 16:24:14 +0100 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2024-10-20 16:24:14 +0100 |
commit | 5b6a6f3b241fea6d19521ddbb705e27d5e4c0268 (patch) | |
tree | 2c7fd705a6cff4be087f62b9ce940b413f8942b4 | |
parent | Misc readability fixes (diff) | |
download | ilt-5b6a6f3b241fea6d19521ddbb705e27d5e4c0268.tar.bz2 ilt-5b6a6f3b241fea6d19521ddbb705e27d5e4c0268.tar.xz ilt-5b6a6f3b241fea6d19521ddbb705e27d5e4c0268.zip |
Move lots of maths helpers to inline, constexpr, templates
Always for working with different dimensions/types
-rw-r--r-- | assetFactory/mutation.cpp | 5 | ||||
-rw-r--r-- | game/network/link.cpp | 2 | ||||
-rw-r--r-- | game/network/network.cpp | 2 | ||||
-rw-r--r-- | game/network/rail.cpp | 4 | ||||
-rw-r--r-- | gfx/gl/shadowStenciller.cpp | 4 | ||||
-rw-r--r-- | lib/maths.cpp | 97 | ||||
-rw-r--r-- | lib/maths.h | 287 | ||||
-rw-r--r-- | test/test-geoData.cpp | 2 | ||||
-rw-r--r-- | test/test-maths.cpp | 10 |
9 files changed, 218 insertions, 195 deletions
diff --git a/assetFactory/mutation.cpp b/assetFactory/mutation.cpp index 6695dff..2ab2a76 100644 --- a/assetFactory/mutation.cpp +++ b/assetFactory/mutation.cpp @@ -1,12 +1,11 @@ #include "mutation.h" -#include <algorithm> #include <glm/gtx/transform.hpp> #include <maths.h> Mutation::Matrix Mutation::getMatrix() const { - return glm::translate(glm::identity<Matrix>(), position) * rotate_ypr(rotation) + return glm::translate(glm::identity<Matrix>(), position) * rotate_ypr<4>(rotation) * glm::scale(glm::identity<Matrix>(), scale); } @@ -19,7 +18,7 @@ Mutation::getDeformationMatrix() const Mutation::Matrix Mutation::getLocationMatrix() const { - return glm::translate(glm::identity<Matrix>(), position) * rotate_ypr(rotation); + return glm::translate(glm::identity<Matrix>(), position) * rotate_ypr<4>(rotation); } bool diff --git a/game/network/link.cpp b/game/network/link.cpp index 248fe7d..745896c 100644 --- a/game/network/link.cpp +++ b/game/network/link.cpp @@ -51,7 +51,7 @@ LinkCurve::positionAt(float dist, unsigned char start) const + RelativePosition3D {0, 0, static_cast<RelativeDistance>(es.first->pos.z - centreBase.z) + (static_cast<RelativeDistance>(es.second->pos.z - es.first->pos.z) * frac)}}; - const auto pitch {vector_pitch({0, 0, static_cast<RelativeDistance>(es.second->pos.z - es.first->pos.z) / length})}; + const auto pitch {vector_pitch(difference(es.second->pos, es.first->pos) / length)}; return Location {GlobalPosition3D(relPos + relClimb) + centreBase, {pitch, normalize(ang + dirOffset[start]), 0}}; } diff --git a/game/network/network.cpp b/game/network/network.cpp index 65b2a62..fa86cb5 100644 --- a/game/network/network.cpp +++ b/game/network/network.cpp @@ -95,7 +95,7 @@ Network::routeFromTo(const Link::End & end, const Node::Ptr & dest) const GenCurveDef Network::genCurveDef(const GlobalPosition3D & start, const GlobalPosition3D & end, float startDir) { - const auto diff {end - start}; + const auto diff = difference(end, start); const auto vy {vector_yaw(diff)}; const auto dir = pi + startDir; const auto flatStart {start.xy()}, flatEnd {end.xy()}; diff --git a/game/network/rail.cpp b/game/network/rail.cpp index fd07ace..c29217a 100644 --- a/game/network/rail.cpp +++ b/game/network/rail.cpp @@ -32,7 +32,7 @@ RailLinks::addLinksBetween(GlobalPosition3D start, GlobalPosition3D end) } // Find start link/end - opposite entry dir to existing link; so pi +... const Angle dir = pi + findNodeDirection(node1ins.first); - if (dir == vector_yaw(end - start)) { + if (dir == vector_yaw(difference(end, start))) { return addLink<RailLinkStraight>(start, end); } const auto flatStart {start.xy()}, flatEnd {end.xy()}; @@ -62,7 +62,7 @@ RailLinks::addLinksBetween(GlobalPosition3D start, GlobalPosition3D end) return addLink<RailLinkCurve>(midh, end, c2); } } - const auto diff {end - start}; + const auto diff = difference(end, start); const auto vy {vector_yaw(diff)}; const auto n2ed {(vy * 2) - dir - pi}; const auto centre {find_arc_centre(flatStart, dir, flatEnd, n2ed)}; diff --git a/gfx/gl/shadowStenciller.cpp b/gfx/gl/shadowStenciller.cpp index eab4797..86b77e4 100644 --- a/gfx/gl/shadowStenciller.cpp +++ b/gfx/gl/shadowStenciller.cpp @@ -24,8 +24,8 @@ ShadowStenciller::setLightDirection(const LightDirection & lightDir) { viewProjections = [&lightDir]<GLint... Ep>(std::integer_sequence<GLint, Ep...>) { constexpr float STEP = two_pi / STENCIL_ANGLES<decltype(two_pi)>; - return std::array { - rotate_pitch(half_pi - lightDir.position().y) * rotate_yaw((Ep * STEP) - lightDir.position().x)...}; + return std::array {rotate_pitch<4>(half_pi - lightDir.position().y) + * rotate_yaw<4>((Ep * STEP) - lightDir.position().x)...}; }(std::make_integer_sequence<GLint, STENCIL_ANGLES<GLint>>()); } diff --git a/lib/maths.cpp b/lib/maths.cpp index f527881..3a9bf9b 100644 --- a/lib/maths.cpp +++ b/lib/maths.cpp @@ -19,103 +19,6 @@ flat_orientation(const Direction3D & diff) return (std::isnan(e[0][0])) ? oneeighty : e; } -// Helper to lookup into a matrix given an xy vector coordinate -template<typename M, typename I> -inline auto & -operator^(M & m, glm::vec<2, I> xy) -{ - return m[xy.x][xy.y]; -} - -// Create a matrix for the angle, given the targets into the matrix -template<typename M, typename I> -inline auto -rotation(typename M::value_type a, glm::vec<2, I> c1, glm::vec<2, I> s1, glm::vec<2, I> c2, glm::vec<2, I> ms2) -{ - M m(1); - sincosf(a, m ^ s1, m ^ c1); - m ^ c2 = m ^ c1; - m ^ ms2 = -(m ^ s1); - return m; -} - -// Create a flat (2D) transformation matrix -glm::mat2 -rotate_flat(float a) -{ - return rotation<glm::mat2, glm::length_t>(a, {0, 0}, {0, 1}, {1, 1}, {1, 0}); -} - -// Create a yaw transformation matrix -glm::mat4 -rotate_yaw(float a) -{ - return rotation<glm::mat4, glm::length_t>(a, {0, 0}, {1, 0}, {1, 1}, {0, 1}); -} - -// Create a roll transformation matrix -glm::mat4 -rotate_roll(float a) -{ - return rotation<glm::mat4, glm::length_t>(a, {0, 0}, {2, 0}, {2, 2}, {0, 2}); -} - -// Create a pitch transformation matrix -glm::mat4 -rotate_pitch(float a) -{ - return rotation<glm::mat4, glm::length_t>(a, {1, 1}, {1, 2}, {2, 2}, {2, 1}); -} - -// Create a combined yaw, pitch, roll transformation matrix -glm::mat4 -rotate_ypr(Rotation3D a) -{ - return rotate_yaw(a.y) * rotate_pitch(a.x) * rotate_roll(a.z); -} - -glm::mat4 -rotate_yp(Rotation2D a) -{ - return rotate_yp(a.y, a.x); -} - -glm::mat4 -rotate_yp(Angle yaw, Angle pitch) -{ - return rotate_yaw(yaw) * rotate_pitch(pitch); -} - -float -vector_yaw(const Direction2D & diff) -{ - return std::atan2(diff.x, diff.y); -} - -float -vector_pitch(const Direction3D & diff) -{ - return std::atan(diff.z); -} - -float -round_frac(const float & v, const float & frac) -{ - return std::round(v / frac) * frac; -} - -float -normalize(float ang) -{ - while (ang > pi) { - ang -= two_pi; - } - while (ang <= -pi) { - ang += two_pi; - } - return ang; -} - static_assert(pow(1, 0) == 1); static_assert(pow(1, 1) == 1); static_assert(pow(1, 2) == 1); diff --git a/lib/maths.h b/lib/maths.h index 97b7ef5..94e357b 100644 --- a/lib/maths.h +++ b/lib/maths.h @@ -17,22 +17,22 @@ struct Arc : public std::pair<Angle, Angle> { } Arc(const RelativePosition2D & dir0, const RelativePosition2D & dir1); - Arc(const Angle angb, const Angle anga); + Arc(Angle anga, Angle angb); auto - operator[](bool i) const + operator[](bool getSecond) const { - return i ? second : first; + return getSecond ? second : first; } - [[nodiscard]] constexpr inline float + [[nodiscard]] constexpr float length() const { return second - first; } }; -constexpr const RelativePosition3D up {0, 0, 1}; +constexpr const RelativePosition3D up {0, 0, 1}; // NOLINT(readability-identifier-length) constexpr const RelativePosition3D down {0, 0, -1}; constexpr const RelativePosition3D north {0, 1, 0}; constexpr const RelativePosition3D south {0, -1, 0}; @@ -40,7 +40,7 @@ constexpr const RelativePosition3D east {1, 0, 0}; constexpr const RelativePosition3D west {-1, 0, 0}; constexpr auto half_pi {glm::half_pi<float>()}; constexpr auto quarter_pi {half_pi / 2}; -constexpr auto pi {glm::pi<float>()}; +constexpr auto pi {glm::pi<float>()}; // NOLINT(readability-identifier-length) constexpr auto two_pi {glm::two_pi<float>()}; constexpr auto degreesToRads = pi / 180.F; @@ -48,153 +48,274 @@ constexpr auto earthMeanRadius = 6371.01F; // In km constexpr auto astronomicalUnit = 149597890.F; // In km template<glm::length_t D> -constexpr inline GlobalPosition<D> -operator+(const GlobalPosition<D> & g, const RelativePosition<D> & r) +constexpr GlobalPosition<D> +operator+(const GlobalPosition<D> & global, const RelativePosition<D> & relative) { - return g + GlobalPosition<D>(glm::round(r)); + return global + GlobalPosition<D>(glm::round(relative)); } template<glm::length_t D> -constexpr inline GlobalPosition<D> -operator+(const GlobalPosition<D> & g, const CalcPosition<D> & r) +constexpr GlobalPosition<D> +operator+(const GlobalPosition<D> & global, const CalcPosition<D> & relative) { - return g + GlobalPosition<D>(r); + return global + GlobalPosition<D>(relative); } template<glm::length_t D> -constexpr inline GlobalPosition<D> -operator-(const GlobalPosition<D> & g, const RelativePosition<D> & r) +constexpr GlobalPosition<D> +operator-(const GlobalPosition<D> & global, const RelativePosition<D> & relative) { - return g - GlobalPosition<D>(glm::round(r)); + return global - GlobalPosition<D>(glm::round(relative)); } template<glm::length_t D> -constexpr inline GlobalPosition<D> -operator-(const GlobalPosition<D> & g, const CalcPosition<D> & r) +constexpr GlobalPosition<D> +operator-(const GlobalPosition<D> & global, const CalcPosition<D> & relative) { - return g - GlobalPosition<D>(r); + return global - GlobalPosition<D>(relative); +} + +template<glm::length_t D, std::integral T, glm::qualifier Q> +constexpr RelativePosition<D> +difference(const glm::vec<D, T, Q> & globalA, const glm::vec<D, T, Q> & globalB) +{ + return globalA - globalB; } glm::mat4 flat_orientation(const Rotation3D & diff); -// C++ wrapper for C's sincosf, but with references, not pointers -inline auto -sincosf(float a, float & s, float & c) +namespace { + // Helpers + // C++ wrapper for C's sincosf, but with references, not pointers + constexpr auto + sincosf(float angle, float & sinOut, float & cosOut) + { + if consteval { + sinOut = ::sinf(angle); + cosOut = ::cosf(angle); + } + else { + ::sincosf(angle, &sinOut, &cosOut); + } + } + + template<std::floating_point T> + constexpr auto + sincosf(const T angle) + { + Rotation2D sincosOut; + sincosf(angle, sincosOut.x, sincosOut.y); + return sincosOut; + } + + // Helper to lookup into a matrix given an xy vector coordinate + template<typename M, typename I> + constexpr auto & + operator^(M & matrix, glm::vec<2, I> rowCol) + { + return matrix[rowCol.x][rowCol.y]; + } + + // Create a matrix for the angle, given the targets into the matrix + template<typename M, typename I> + constexpr auto + rotation(typename M::value_type angle, glm::vec<2, I> cos1, glm::vec<2, I> sin1, glm::vec<2, I> cos2, + glm::vec<2, I> negSin1) + { + M out(1); + sincosf(angle, out ^ sin1, out ^ cos1); + out ^ cos2 = out ^ cos1; + out ^ negSin1 = -(out ^ sin1); + return out; + } +} + +// Create a flat transformation matrix +template<glm::length_t D = 2, glm::qualifier Q = glm::qualifier::defaultp, std::floating_point T> + requires(D >= 2) +constexpr auto +rotate_flat(const T angle) { - return sincosf(a, &s, &c); + return rotation<glm::mat<D, D, T, Q>, glm::length_t>(angle, {0, 0}, {0, 1}, {1, 1}, {1, 0}); } -inline Rotation2D -sincosf(float a) +// Create a yaw transformation matrix +template<glm::length_t D = 3, glm::qualifier Q = glm::qualifier::defaultp, std::floating_point T> + requires(D >= 2) +constexpr auto +rotate_yaw(const T angle) { - Rotation2D sc; - sincosf(a, sc.x, sc.y); - return sc; + return rotation<glm::mat<D, D, T, Q>, glm::length_t>(angle, {0, 0}, {1, 0}, {1, 1}, {0, 1}); } -glm::mat2 rotate_flat(float); -glm::mat4 rotate_roll(float); -glm::mat4 rotate_yaw(float); -glm::mat4 rotate_pitch(float); -glm::mat4 rotate_yp(Rotation2D); -glm::mat4 rotate_yp(Angle yaw, Angle pitch); -glm::mat4 rotate_ypr(Rotation3D); +// Create a roll transformation matrix +template<glm::length_t D = 3, glm::qualifier Q = glm::qualifier::defaultp, std::floating_point T> + requires(D >= 3) +constexpr auto +rotate_roll(const T angle) +{ + return rotation<glm::mat<D, D, T, Q>, glm::length_t>(angle, {0, 0}, {2, 0}, {2, 2}, {0, 2}); +} -float vector_yaw(const Direction2D & diff); -float vector_pitch(const Direction3D & diff); +// Create a pitch transformation matrix +template<glm::length_t D = 3, glm::qualifier Q = glm::qualifier::defaultp, std::floating_point T> + requires(D >= 3) +constexpr auto +rotate_pitch(const T angle) +{ + return rotation<glm::mat<D, D, T, Q>, glm::length_t>(angle, {1, 1}, {1, 2}, {2, 2}, {2, 1}); +} + +// Create a combined yaw, pitch, roll transformation matrix +template<glm::length_t D = 3, glm::qualifier Q = glm::qualifier::defaultp, std::floating_point T> + requires(D >= 3) +constexpr auto +rotate_ypr(const glm::vec<3, T, Q> & angles) +{ + return rotate_yaw<D>(angles.y) * rotate_pitch<D>(angles.x) * rotate_roll<D>(angles.z); +} + +template<glm::length_t D = 3, glm::qualifier Q = glm::qualifier::defaultp, std::floating_point T> + requires(D >= 3) +constexpr auto +rotate_yp(const T yaw, const T pitch) +{ + return rotate_yaw<D>(yaw) * rotate_pitch<D>(pitch); +} + +template<glm::length_t D = 3, glm::qualifier Q = glm::qualifier::defaultp, std::floating_point T> + requires(D >= 3) +constexpr auto +rotate_yp(const glm::vec<2, T, Q> & angles) +{ + return rotate_yp<D>(angles.y, angles.x); +} + +template<glm::length_t D, glm::qualifier Q = glm::qualifier::defaultp, typename T> + requires(D >= 2) +constexpr auto +vector_yaw(const glm::vec<D, T, Q> & diff) +{ + return std::atan2(diff.x, diff.y); +} + +template<glm::length_t D, glm::qualifier Q = glm::qualifier::defaultp, typename T> + requires(D >= 3) +constexpr auto +vector_pitch(const glm::vec<D, T, Q> & diff) +{ + return std::atan(diff.z); +} template<typename T, glm::qualifier Q> -glm::vec<2, T, Q> -vector_normal(const glm::vec<2, T, Q> & v) +constexpr glm::vec<2, T, Q> +vector_normal(const glm::vec<2, T, Q> & vector) { - return {-v.y, v.x}; + return {-vector.y, vector.x}; }; -float round_frac(const float & v, const float & frac); +template<std::floating_point T> +constexpr auto +round_frac(const T value, const T frac) +{ + return std::round(value / frac) * frac; +} template<typename T> -inline constexpr auto -sq(T v) + requires requires(T value) { value * value; } +constexpr auto +sq(T value) { - return v * v; + return value * value; } template<glm::qualifier Q> -inline constexpr glm::vec<3, int64_t, Q> -crossProduct(const glm::vec<3, int64_t, Q> a, const glm::vec<3, int64_t, Q> b) +constexpr glm::vec<3, int64_t, Q> +crossProduct(const glm::vec<3, int64_t, Q> & valueA, const glm::vec<3, int64_t, Q> & valueB) { return { - (a.y * b.z) - (a.z * b.y), - (a.z * b.x) - (a.x * b.z), - (a.x * b.y) - (a.y * b.x), + (valueA.y * valueB.z) - (valueA.z * valueB.y), + (valueA.z * valueB.x) - (valueA.x * valueB.z), + (valueA.x * valueB.y) - (valueA.y * valueB.x), }; } template<std::integral T, glm::qualifier Q> -inline constexpr glm::vec<3, T, Q> -crossProduct(const glm::vec<3, T, Q> a, const glm::vec<3, T, Q> b) +constexpr glm::vec<3, T, Q> +crossProduct(const glm::vec<3, T, Q> & valueA, const glm::vec<3, T, Q> & valueB) { - return crossProduct<Q>(a, b); + return crossProduct<Q>(valueA, valueB); } template<std::floating_point T, glm::qualifier Q> -inline constexpr glm::vec<3, T, Q> -crossProduct(const glm::vec<3, T, Q> a, const glm::vec<3, T, Q> b) +constexpr glm::vec<3, T, Q> +crossProduct(const glm::vec<3, T, Q> & valueA, const glm::vec<3, T, Q> & valueB) { - return glm::cross(a, b); + return glm::cross(valueA, valueB); } template<typename R = float, typename Ta, typename Tb> -inline constexpr auto -ratio(Ta a, Tb b) +constexpr auto +ratio(const Ta valueA, const Tb valueB) { - return (static_cast<R>(a) / static_cast<R>(b)); + return (static_cast<R>(valueA) / static_cast<R>(valueB)); } template<typename R = float, typename T, glm::qualifier Q> -inline constexpr auto -ratio(glm::vec<2, T, Q> v) +constexpr auto +ratio(const glm::vec<2, T, Q> & value) { - return ratio<R>(v.x, v.y); + return ratio<R>(value.x, value.y); } -template<glm::length_t L = 3, typename T, glm::qualifier Q> -inline constexpr glm::vec<L, T, Q> -perspective_divide(glm::vec<4, T, Q> v) +template<glm::length_t L = 3, std::floating_point T, glm::qualifier Q> +constexpr auto +perspective_divide(const glm::vec<4, T, Q> & value) { - return v / v.w; + return value / value.w; } template<glm::length_t L1, glm::length_t L2, typename T, glm::qualifier Q> -inline constexpr glm::vec<L1 + L2, T, Q> -operator||(const glm::vec<L1, T, Q> v1, const glm::vec<L2, T, Q> v2) +constexpr glm::vec<L1 + L2, T, Q> +operator||(const glm::vec<L1, T, Q> valueA, const glm::vec<L2, T, Q> valueB) { - return {v1, v2}; + return {valueA, valueB}; } template<glm::length_t L, typename T, glm::qualifier Q> -inline constexpr glm::vec<L + 1, T, Q> -operator||(const glm::vec<L, T, Q> v1, const T v2) +constexpr glm::vec<L + 1, T, Q> +operator||(const glm::vec<L, T, Q> valueA, const T valueB) { - return {v1, v2}; + return {valueA, valueB}; } -template<glm::length_t L, typename T, glm::qualifier Q> -inline constexpr glm::vec<L, T, Q> -perspectiveMultiply(const glm::vec<L, T, Q> & p, const glm::mat<L + 1, L + 1, T, Q> & mutation) +template<glm::length_t L, std::floating_point T, glm::qualifier Q> +constexpr glm::vec<L, T, Q> +perspectiveMultiply(const glm::vec<L, T, Q> & base, const glm::mat<L + 1, L + 1, T, Q> & mutation) { - const auto p2 = mutation * (p || T(1)); - return p2 / p2.w; + const auto mutated = mutation * (base || T(1)); + return mutated / mutated.w; } -template<glm::length_t L, typename T, glm::qualifier Q> -inline constexpr glm::vec<L, T, Q> -perspectiveApply(glm::vec<L, T, Q> & p, const glm::mat<L + 1, L + 1, T, Q> & mutation) +template<glm::length_t L, std::floating_point T, glm::qualifier Q> +constexpr glm::vec<L, T, Q> +perspectiveApply(glm::vec<L, T, Q> & base, const glm::mat<L + 1, L + 1, T, Q> & mutation) { - return p = perspectiveMultiply(p, mutation); + return base = perspectiveMultiply(base, mutation); } -float normalize(float ang); +template<std::floating_point T> +constexpr T +normalize(T ang) +{ + while (ang > glm::pi<T>()) { + ang -= glm::two_pi<T>(); + } + while (ang <= -glm::pi<T>()) { + ang += glm::two_pi<T>(); + } + return ang; +} template<typename T, glm::qualifier Q> std::pair<glm::vec<2, T, Q>, bool> @@ -264,7 +385,7 @@ midpoint(const std::pair<T, T> & v) // std::pow is not constexpr template<typename T> requires requires(T n) { n *= n; } -constexpr inline T +constexpr T pow(const T base, std::integral auto exp) { T res {1}; @@ -276,14 +397,14 @@ pow(const T base, std::integral auto exp) // Conversions template<typename T> -inline constexpr auto +constexpr auto mph_to_ms(T v) { return v / 2.237L; } template<typename T> -inline constexpr auto +constexpr auto kph_to_ms(T v) { return v / 3.6L; diff --git a/test/test-geoData.cpp b/test/test-geoData.cpp index 4a7b98d..35d6bae 100644 --- a/test/test-geoData.cpp +++ b/test/test-geoData.cpp @@ -168,7 +168,7 @@ BOOST_DATA_TEST_CASE(walkTerrainSetsFromFace, from, to, visits) { GeoData::PointFace pf {from}; - BOOST_CHECK_NO_THROW(fixedTerrtain.walk(pf, to, [](auto) {})); + BOOST_CHECK_NO_THROW(fixedTerrtain.walk(pf, to, [](auto) { })); BOOST_CHECK_EQUAL(pf.face(&fixedTerrtain).idx(), visits.front()); } diff --git a/test/test-maths.cpp b/test/test-maths.cpp index ccfb113..f7f34b3 100644 --- a/test/test-maths.cpp +++ b/test/test-maths.cpp @@ -107,9 +107,9 @@ const auto angs = boost::unit_test::data::make({pi, half_pi, two_pi, quarter_pi, * boost::unit_test::data::make(0); const auto random_angs = boost::unit_test::data::random(-two_pi, two_pi) ^ boost::unit_test::data::xrange(1000); const auto rots = boost::unit_test::data::make<std::tuple<glm::vec3, glm::mat4 (*)(float), std::string_view>>({ - {down, rotate_yaw, "yaw"}, - {east, rotate_pitch, "pitch"}, - {north, rotate_roll, "roll"}, + {down, rotate_yaw<4>, "yaw"}, + {east, rotate_pitch<4>, "pitch"}, + {north, rotate_roll<4>, "roll"}, }); BOOST_DATA_TEST_CASE(test_rotations, (angs + random_angs) * rots, angle, ai, axis, ilt_func, name) @@ -247,13 +247,13 @@ BOOST_DATA_TEST_CASE(curve1, BOOST_CHECK_EQUAL(l.radius, 1.F); { const auto p = l.positionAt(0, 0); - const auto angForReversed = normalize(vector_yaw(-e1) * 2 - angFor); + const auto angForReversed = normalize(vector_yaw(difference({}, e1)) * 2 - angFor); BOOST_CHECK_CLOSE_VECI(p.pos, e1); BOOST_CHECK_CLOSE_VEC(p.rot, glm::vec3(0, angForReversed, 0)); } { const auto p = l.positionAt(0, 1); - const auto angBackReversed = normalize(vector_yaw(e1) * 2 - angBack); + const auto angBackReversed = normalize(vector_yaw(difference(e1, {})) * 2 - angBack); BOOST_CHECK_CLOSE_VECI(p.pos, GlobalPosition3D {}); BOOST_CHECK_CLOSE_VEC(p.rot, glm::vec3(0, angBackReversed, 0)); } |