Browse Source

Add physics namespace, move orbit-related functions into orbit namespace within physics namespace, add physics reference frame class, add functions to construct orbital reference frames

master
C. J. Howard 4 months ago
parent
commit
7477552eea
25 changed files with 865 additions and 1056 deletions
  1. +0
    -2
      src/astro/astro.hpp
  2. +0
    -78
      src/astro/orbit.cpp
  3. +0
    -75
      src/astro/orbit.hpp
  4. +0
    -214
      src/coordinates/ecliptic.hpp
  5. +0
    -208
      src/coordinates/equatorial.hpp
  6. +0
    -220
      src/coordinates/horizontal.hpp
  7. +0
    -175
      src/coordinates/rectangular.hpp
  8. +4
    -4
      src/ecs/components/celestial-body-component.hpp
  9. +4
    -4
      src/ecs/components/orbit-component.hpp
  10. +105
    -23
      src/ecs/systems/astronomy-system.cpp
  11. +5
    -8
      src/ecs/systems/solar-system.cpp
  12. +9
    -9
      src/game/states/play-state.cpp
  13. +58
    -0
      src/geom/cartesian.hpp
  14. +2
    -0
      src/geom/geom.hpp
  15. +11
    -11
      src/geom/spherical.hpp
  16. +69
    -0
      src/math/matrix-functions.hpp
  17. +53
    -1
      src/math/quaternion-type.hpp
  18. +134
    -0
      src/physics/frame.hpp
  19. +95
    -0
      src/physics/orbit/elements.hpp
  20. +131
    -0
      src/physics/orbit/frames.hpp
  21. +79
    -0
      src/physics/orbit/kepler.hpp
  22. +39
    -0
      src/physics/orbit/orbit.hpp
  23. +52
    -0
      src/physics/orbit/state.hpp
  24. +7
    -12
      src/physics/physics.hpp
  25. +8
    -12
      src/renderer/passes/sky-pass.cpp

+ 0
- 2
src/astro/astro.hpp View File

@ -26,8 +26,6 @@ namespace astro {}
#include "apparent-size.hpp"
#include "coordinates.hpp"
#include "constants.hpp"
#include "coordinates.hpp"
#include "illuminance.hpp"
#include "orbit.hpp"
#endif // ANTKEEPER_ASTRO_HPP

+ 0
- 78
src/astro/orbit.cpp View File

@ -1,78 +0,0 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "orbit.hpp"
#include "math/angles.hpp"
#include <cmath>
namespace astro
{
double solve_kepler(double ec, double ma, double tolerance, std::size_t iterations)
{
// Approximate eccentric anomaly, E
double e0 = ma + ec * std::sin(ma) * (1.0 + ec * std::cos(ma));
// Iteratively converge E0 and E1
for (std::size_t i = 0; i < iterations; ++i)
{
double e1 = e0 - (e0 - ec * std::sin(e0) - ma) / (1.0 - ec * std::cos(e0));
double error = std::abs(e1 - e0);
e0 = e1;
if (error < tolerance)
break;
}
return e0;
}
double3 orbital_elements_to_ecliptic(const orbital_elements& elements, double ke_tolerance, std::size_t ke_iterations)
{
// Calculate semi-minor axis, b
double b = elements.a * std::sqrt(1.0 - elements.ec * elements.ec);
// Solve Kepler's equation for eccentric anomaly, E
double ea = solve_kepler(elements.ec, elements.ma, ke_tolerance, ke_iterations);
// Calculate radial distance, r; and true anomaly, v
double xv = elements.a * (std::cos(ea) - elements.ec);
double yv = b * std::sin(ea);
double r = std::sqrt(xv * xv + yv * yv);
double v = std::atan2(yv, xv);
// Calculate true longitude, l
double l = elements.w + v;
// Transform vector (r, 0, 0) from local coordinates to ecliptic coordinates
// = Rz(-omega) * Rx(-i) * Rz(-l) * r
double cos_om = std::cos(elements.om);
double sin_om = std::sin(elements.om);
double cos_i = std::cos(elements.i);
double cos_l = std::cos(l);
double sin_l = std::sin(l);
return double3
{
r * (cos_om * cos_l - sin_om * sin_l * cos_i),
r * (sin_om * cos_l + cos_om * sin_l * cos_i),
r * sin_l * std::sin(elements.i)
};
}
} // namespace astro

+ 0
- 75
src/astro/orbit.hpp View File

@ -1,75 +0,0 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_ASTRO_ORBIT_HPP
#define ANTKEEPER_ASTRO_ORBIT_HPP
#include "utility/fundamental-types.hpp"
namespace astro
{
/**
* Contains six orbital elements which describe a Keplerian orbit.
*/
struct orbital_elements
{
double ec; ///< Eccentricity, e
double a; ///< Semi-major axis, a
double i; ///< Inclination, i (radians)
double om; ///< Longitude of the ascending node, OMEGA (radians)
double w; ///< Argument of periapsis, w (radians)
double ma; ///< Mean anomaly, M (radians)
};
/**
* Orbital state vectors.
*/
struct orbital_state
{
double3 r; ///< Cartesian position, r.
double3 v; ///< Cartesian velocity, v.
};
/**
* Iteratively solves Kepler's equation for eccentric anomaly, E.
*
* @param ec Eccentricity, e.
* @param ma Mean anomaly, M (radians).
* @param tolerance Tolerance of solution.
* @param iterations Maximum number of iterations.
* @return Eccentric anomaly.
*/
double solve_kepler(double ec, double ma, double tolerance, std::size_t iterations);
/**
* Calculates the ecliptic rectangular orbital position from Keplerian orbital elements.
*
* @note Only works for elliptical orbits.
*
* @param elements Orbital elements.
* @param ke_tolerance Kepler's equation tolerance.
* @param ke_iterations Kepler's equation iterations.
* @return Orbital state.
*/
double3 orbital_elements_to_ecliptic(const orbital_elements& elements, double ke_tolerance, std::size_t ke_iterations);
} // namespace astro
#endif // ANTKEEPER_ASTRO_ORBIT_HPP

+ 0
- 214
src/coordinates/ecliptic.hpp View File

@ -1,214 +0,0 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_COORDINATES_ECLIPTIC_HPP
#define ANTKEEPER_COORDINATES_ECLIPTIC_HPP
#include "coordinates/rectangular.hpp"
#include "coordinates/spherical.hpp"
#include "utility/fundamental-types.hpp"
#include <cmath>
namespace coordinates {
namespace rectangular {
/// Rectangular coordinate system with the plane of the Earth's orbit as the fundamental plane. This is a right-handed coordinate system with the x-axis pointing to the vernal equinox, the y-axis pointing east, and the z-axis is the north orbital pole.
namespace ecliptic {
/**
* Produces a matrix which rotates rectangular coordinates from ecliptic space into equatorial space.
*
* @param ecl Obliquity of the ecliptic, in radians.
* @return Rotation matrix.
*
* @see coordinates::rectangular::equatorial
*/
template <class T>
math::matrix3<T> to_equatorial(T ecl);
/**
* Rotates rectangular coordinates from ecliptic space into equatorial space.
*
* @param v Rectangular coordinates in ecliptic space.
* @param ecl Obliquity of the ecliptic, in radians.
* @return Rectangular coordinates in equatorial space.
*
* @see coordinates::rectangular::equatorial
*/
template <class T>
math::vector3<T> to_equatorial(const math::vector3<T>& v, T ecl);
/**
* Produces a matrix which rotates rectangular coordinates from ecliptic space into local horizontal space.
*
* @param ecl Obliquity of the ecliptic, in radians.
* @param lat Observer's latitude, in radians.
* @param lst Local sidereal time, in radians.
* @return Rotation matrix.
*
* @see coordinates::rectangular::horizontal
*/
template <class T>
math::matrix3<T> to_horizontal(T ecl, T lat, T lst);
/**
* Rotates rectangular coordinates from ecliptic space into local horizontal space.
*
* @param v Rectangular coordinates in ecliptic space.
* @param ecl Obliquity of the ecliptic, in radians.
* @param lat Observer's latitude, in radians.
* @param lst Local sidereal time, in radians.
* @return Rectangular coordinates in local horizontal space.
*
* @see coordinates::rectangular::horizontal
*/
template <class T>
math::vector3<T> to_horizontal(const math::vector3<T>& v, T ecl, T lat, T lst);
} // namespace ecliptic
} // namespace rectangular
namespace spherical {
/// Spherical ecliptic coordinate system.
namespace ecliptic {
/**
* Rotates spherical coordinates from ecliptic space into equatorial space.
*
* @param v Spherical coordinates in ecliptic space, in the ISO order of radial distance, ecliptic latitude (radians), and ecliptic longitude (radians).
* @param ecl Obliquity of the ecliptic, in radians.
* @return Spherical coordinates in equatorial space, in the ISO order of radial distance, declination (radians), and right ascension (radians).
*
* @see coordinates::spherical::equatorial
*/
template <class T>
math::vector3<T> to_equatorial(const math::vector3<T>& v, T ecl);
/**
* Rotates spherical coordinates from ecliptic space into local horizontal space.
*
* @param v Spherical coordinates in ecliptic space, in the ISO order of radial distance, ecliptic latitude (radians), and ecliptic longitude (radians).
* @param ecl Obliquity of the ecliptic, in radians.
* @param lat Observer's latitude, in radians.
* @param lst Local sidereal time, in radians.
* @return Spherical coordinates in local horizontal space, in the ISO order of radial distance, altitude (radians), and azimuth (radians).
*
* @see coordinates::spherical::horizontal
*/
template <class T>
math::vector3<T> to_horizontal(const math::vector3<T>& v, T ecl, T lat, T lst);
} // namespace ecliptic
} // namespace spherical
namespace rectangular {
namespace ecliptic {
template <class T>
math::matrix3<T> to_equatorial(T ecl)
{
const T c_ecl = std::cos(ecl);
const T s_ecl = std::sin(ecl);
return math::matrix3<T>
{
T(1.0), T(0.0), T(0.0),
T(0.0), c_ecl, s_ecl,
T(0.0), -s_ecl, c_ecl
};
}
template <class T>
math::vector3<T> to_equatorial(const math::vector3<T>& v, T ecl)
{
return to_equatorial<T>(ecl) * v;
}
template <class T>
math::matrix3<T> to_horizontal(T ecl, T lat, T lst)
{
const T c_ecl = std::cos(ecl);
const T s_ecl = std::sin(ecl);
const T c_lat = std::cos(lat);
const T s_lat = std::sin(lat);
const T c_lst = std::cos(lst);
const T s_lst = std::sin(lst);
return math::matrix3<T>
{
s_lat * c_lst, s_lst, c_lat * c_lst,
s_lat * s_lst * c_ecl - c_lat * s_ecl, -c_lst * c_ecl, c_lat * s_lst * c_ecl + s_lat * s_ecl,
s_lat * s_lst * -s_ecl - c_lat * c_ecl, c_lst * s_ecl, c_lat * s_lst * -s_ecl + s_lat * c_ecl
};
}
template <class T>
math::vector3<T> to_horizontal(const math::vector3<T>& v, T ecl, T lat, T lst)
{
return to_horizontal<T>(ecl, lat, lst) * v;
}
} // namespace ecliptic
} // namespace rectangular
namespace spherical {
namespace ecliptic {
template <class T>
math::vector3<T> to_equatorial(const math::vector3<T>& v, T ecl)
{
return coordinates::rectangular::to_spherical<T>
(
coordinates::rectangular::ecliptic::to_equatorial<T>
(
coordinates::spherical::to_rectangular<T>(v),
ecl
)
);
}
template <class T>
math::vector3<T> to_horizontal(const math::vector3<T>& v, T ecl, T lat, T lst)
{
return coordinates::rectangular::to_spherical<T>
(
coordinates::rectangular::ecliptic::to_horizontal<T>
(
coordinates::spherical::to_rectangular<T>(v),
ecl,
lat,
lst
)
);
}
} // namespace ecliptic
} // namespace spherical
} // namespace coordinates
#endif // ANTKEEPER_COORDINATES_ECLIPTIC_HPP

+ 0
- 208
src/coordinates/equatorial.hpp View File

@ -1,208 +0,0 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_COORDINATES_EQUATORIAL_HPP
#define ANTKEEPER_COORDINATES_EQUATORIAL_HPP
#include "coordinates/rectangular.hpp"
#include "coordinates/spherical.hpp"
#include "utility/fundamental-types.hpp"
#include <cmath>
namespace coordinates {
namespace rectangular {
/// Rectangular coordinate system with the Earth's equator as the fundamental plane. This is a right-handed coordinate system with the x-axis pointing to the vernal equinox, the y-axis pointing east, and the z-axis is the north celestial pole.
namespace equatorial {
/**
* Produces a matrix which rotates rectangular coordinates from equatorial space into ecliptic space.
*
* @param ecl Obliquity of the ecliptic, in radians.
* @return Rotation matrix.
*
* @see coordinates::rectangular::ecliptic
*/
template <class T>
math::matrix3<T> to_ecliptic(T ecl);
/**
* Rotates rectangular coordinates from equatorial space into ecliptic space.
*
* @param v Rectangular coordinates in equatorial space.
* @param ecl Obliquity of the ecliptic, in radians.
* @return Rectangular coordinates in ecliptic space.
*
* @see coordinates::rectangular::ecliptic
*/
template <class T>
math::vector3<T> to_ecliptic(const math::vector3<T>& v, T ecl);
/**
* Produces a matrix which rotates rectangular coordinates from equatorial space into local horizontal space.
*
* @param lat Observer's latitude, in radians.
* @param lst Local sidereal time, in radians.
* @return Rotation matrix.
*
* @see coordinates::rectangular::horizontal
*/
template <class T>
math::matrix3<T> to_horizontal(T lat, T lst);
/**
* Rotates rectangular coordinates from equatorial space into local horizontal space.
*
* @param v Rectangular coordinates in equatorial space.
* @param lat Observer's latitude, in radians.
* @param lst Local sidereal time, in radians.
* @return Rectangular coordinates in local horizontal space.
*
* @see coordinates::rectangular::horizontal
*/
template <class T>
math::vector3<T> to_horizontal(const math::vector3<T>& v, T lat, T lst);
} // namespace equatorial
} // namespace rectangular
namespace spherical {
/// Spherical equatorial coordinate system.
namespace equatorial {
/**
* Rotates spherical coordinates from equatorial space into ecliptic space.
*
* @param v Spherical coordinates in equatorial space, in the ISO order of radial distance, declination (radians), and right ascension (radians).
* @param ecl Obliquity of the ecliptic, in radians.
* @return Spherical coordinates in ecliptic space, in the ISO order of radial distance, ecliptic latitude (radians), and ecliptic longitude (radians).
*
* @see coordinates::spherical::ecliptic
*/
template <class T>
math::vector3<T> to_ecliptic(const math::vector3<T>& v, T ecl);
/**
* Rotates spherical coordinates from equatorial space into local horizontal space.
*
* @param v Spherical coordinates in equatorial space, in the ISO order of radial distance, declination (radians), and right ascension (radians).
* @param lat Observer's latitude, in radians.
* @param lst Local sidereal time, in radians.
* @return Spherical coordinates in local horizontal space, in the ISO order of radial distance, altitude (radians), and azimuth (radians).
*
* @see coordinates::spherical::horizontal
*/
template <class T>
math::vector3<T> to_horizontal(const math::vector3<T>& v, T lat, T lst);
} // namespace equatorial
} // namespace spherical
namespace rectangular {
namespace equatorial {
template <class T>
math::matrix3<T> to_ecliptic(T ecl)
{
const T c_ecl = std::cos(ecl);
const T s_ecl = std::sin(ecl);
return math::matrix3<T>
{
T(1.0), T(0.0), T(0.0),
T(0.0), c_ecl, -s_ecl,
T(0.0), s_ecl, c_ecl
};
}
template <class T>
math::vector3<T> to_ecliptic(const math::vector3<T>& v, T ecl)
{
return to_ecliptic(ecl) * v;
}
template <class T>
math::matrix3<T> to_horizontal(T lat, T lst)
{
const T c_lat = std::cos(lat);
const T s_lat = std::sin(lat);
const T c_lst = std::cos(lst);
const T s_lst = std::sin(lst);
return math::matrix3<T>
{
s_lat * c_lst, s_lst, c_lat * c_lst,
s_lat * s_lst, -c_lst, c_lat * s_lst,
-c_lat, T(0.0), s_lat
};
}
template <class T>
math::vector3<T> to_horizontal(const math::vector3<T>& v, T lat, T lst)
{
return to_horizontal(lat, lst) * v;
}
} // namespace equatorial
} // namespace rectangular
namespace spherical {
namespace equatorial {
template <class T>
math::vector3<T> to_ecliptic(const math::vector3<T>& v, T ecl)
{
return coordinates::rectangular::to_spherical<T>
(
coordinates::rectangular::equatorial::to_ecliptic<T>
(
coordinates::spherical::to_rectangular<T>(v),
ecl
)
);
}
template <class T>
math::vector3<T> to_horizontal(const math::vector3<T>& v, T lat, T lst)
{
return coordinates::rectangular::to_spherical<T>
(
coordinates::rectangular::equatorial::to_horizontal<T>
(
coordinates::spherical::to_rectangular<T>(v),
lat,
lst
)
);
}
} // namepace equatorial
} // namespace spherical
} // namespace coordinates
#endif // ANTKEEPER_COORDINATES_EQUATORIAL_HPP

+ 0
- 220
src/coordinates/horizontal.hpp View File

@ -1,220 +0,0 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_COORDINATES_HORIZONTAL_HPP
#define ANTKEEPER_COORDINATES_HORIZONTAL_HPP
#include "coordinates/rectangular.hpp"
#include "coordinates/spherical.hpp"
#include "utility/fundamental-types.hpp"
#include <cmath>
namespace coordinates {
namespace rectangular {
/// Rectangular local horizontal coordinate system in which the x-axis points north, the y-axis points east, and the z-axis points to the vertical.
namespace horizontal {
/**
* Produces a matrix which rotates rectangular coordinates from local horizontal space into equatorial space.
*
* @param lat Observer's latitude, in radians.
* @param lst Local sidereal time, in radians.
* @return Rotation matrix.
*
* @see coordinates::rectangular::equatorial
*/
template <class T>
math::matrix3<T> to_equatorial(T lat, T lst);
/**
* Rotates rectangular coordinates from local horizontal space into equatorial space.
*
* @param v Rectangular coordinates in local horizontal space.
* @param lat Observer's latitude, in radians.
* @param lst Local sidereal time, in radians.
* @return Rectangular coordinates in equatorial space.
*
* @see coordinates::rectangular::equatorial
*/
template <class T>
math::vector3<T> to_equatorial(const math::vector3<T>& v, T lat, T lst);
/**
* Produces a matrix which rotates rectangular coordinates from local horizontal space into ecliptic space.
*
* @param ecl Obliquity of the ecliptic, in radians.
* @param lat Observer's latitude, in radians.
* @param lst Local sidereal time, in radians.
* @return Rotation matrix.
*
* @see coordinates::rectangular::ecliptic
*/
template <class T>
math::matrix3<T> to_ecliptic(T ecl, T lat, T lst);
/**
* Rotates rectangular coordinates from local horizontal space into ecliptic space.
*
* @param v Rectangular coordinates in local horizontal space.
* @param ecl Obliquity of the ecliptic, in radians.
* @param lat Observer's latitude, in radians.
* @param lst Local sidereal time, in radians.
* @return Rectangular coordinates in ecliptic space.
*
* @see coordinates::rectangular::ecliptic
*/
template <class T>
math::vector3<T> to_ecliptic(const math::vector3<T>& v, T ecl, T lat, T lst);
} // namespace horizontal
} // namespace rectangular
namespace spherical {
/// Spherical local horizontal coordinate system.
namespace horizontal {
/**
* Rotates spherical coordinates from local horizontal space into equatorial space.
*
* @param v Spherical coordinates in local horizontal space, in the ISO order of radial distance, altitude (radians), and azimuth (radians).
* @param lat Observer's latitude, in radians.
* @param lst Local sidereal time, in radians.
* @return Spherical coordinates in equatorial space, in the ISO order of radial distance, declination (radians), and right ascension (radians).
*
* @see coordinates::spherical::equatorial
*/
template <class T>
math::vector3<T> to_equatorial(const math::vector3<T>& v, T lat, T lst);
/**
* Rotates spherical coordinates from local horizontal space into ecliptic space.
*
* @param v Spherical coordinates in local horizontal space, in the ISO order of radial distance, altitude (radians), and azimuth (radians).
* @param ecl Obliquity of the ecliptic, in radians.
* @param lat Observer's latitude, in radians.
* @param lst Local sidereal time, in radians.
* @return Spherical coordinates in ecliptic space, in the ISO order of radial distance, ecliptic latitude (radians), and ecliptic longitude (radians).
*
* @see coordinates::spherical::ecliptic
*/
template <class T>
math::vector3<T> to_ecliptic(const math::vector3<T>& v, T ecl, T lat, T lst);
} // namespace horizontal
} // namespace spherical
namespace rectangular {
namespace horizontal {
template <class T>
math::matrix3<T> to_equatorial(T lat, T lst)
{
const T c_lat = std::cos(lat);
const T s_lat = std::sin(lat);
const T c_lst = std::cos(lst);
const T s_lst = std::sin(lst);
return math::matrix3<T>
{
c_lst * s_lat, s_lst * s_lat, -c_lat,
s_lst, c_lst, T(0.0),
c_lst * c_lat, s_lst * c_lat, s_lat
};
}
template <class T>
math::vector3<T> to_equatorial(const math::vector3<T>& v, T lat, T lst)
{
return to_equatorial<T>(lat, lst) * v;
}
template <class T>
math::matrix3<T> to_ecliptic(T ecl, T lat, T lst)
{
const T c_ecl = std::cos(ecl);
const T s_ecl = std::sin(ecl);
const T c_lat = std::cos(lat);
const T s_lat = std::sin(lat);
const T c_lst = std::cos(lst);
const T s_lst = std::sin(lst);
return math::matrix3<T>
{
s_lat * c_lst, s_lat * s_lst * c_ecl - c_lat * s_ecl, s_lat * s_lst * -s_ecl - c_lat * c_ecl,
s_lst, -c_lst * c_ecl, c_lst * s_ecl,
c_lat * c_lst, c_lat * s_lst * c_ecl + s_lat * s_ecl, c_lat * s_lst * -s_ecl + s_lat * c_ecl
};
}
template <class T>
math::vector3<T> to_ecliptic(const math::vector3<T>& v, T ecl, T lat, T lst)
{
return to_ecliptic<T>(ecl, lat, lst) * v;
}
} // namespace horizontal
} // namespace rectangular
namespace spherical {
namespace horizontal {
template <class T>
math::vector3<T> to_equatorial(const math::vector3<T>& v, T lat, T lst)
{
return coordinates::rectangular::to_spherical<T>
(
coordinates::rectangular::horizontal::to_equatorial<T>
(
coordinates::spherical::to_rectangular<T>(v),
lat,
lst
)
);
}
template <class T>
math::vector3<T> to_ecliptic(const math::vector3<T>& v, T ecl, T lat, T lst)
{
return coordinates::rectangular::to_spherical<T>
(
coordinates::rectangular::horizontal::to_ecliptic<T>
(
coordinates::spherical::to_rectangular<T>(v),
ecl,
lat,
lst
)
);
}
} // namespace horizontal
} // namespace spherical
} // namespace coordinates
#endif // ANTKEEPER_COORDINATES_HORIZONTAL_HPP

+ 0
- 175
src/coordinates/rectangular.hpp View File

@ -1,175 +0,0 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_COORDINATES_RECTANGULAR_HPP
#define ANTKEEPER_COORDINATES_RECTANGULAR_HPP
#include "utility/fundamental-types.hpp"
#include <cmath>
namespace coordinates {
/// Rectangular (Cartesian) coordinate systems.
namespace rectangular {
/**
* Produces a matrix which rotates rectangular coordinates about the x-axis by a given angle.
*
* @param angle Angle of rotation, in radians.
* @return Rotation matrix.
*/
template <class T>
math::matrix3<T> rotate_x(T angle);
/**
* Rotates rectangular coordinates about the x-axis.
*
* @param v Rectangular coordinates to rotate.
* @param angle Angle of rotation, in radians.
* @return Rotated rectangular coordinates.
*/
template <class T>
math::vector3<T> rotate_x(const math::vector3<T>& v, T angle);
/**
* Produces a matrix which rotates rectangular coordinates about the y-axis by a given angle.
*
* @param angle Angle of rotation, in radians.
* @return Rotation matrix.
*/
template <class T>
math::matrix3<T> rotate_y(T angle);
/**
* Rotates rectangular coordinates about the y-axis.
*
* @param v Rectangular coordinates to rotate.
* @param angle Angle of rotation, in radians.
* @return Rotated rectangular coordinates.
*/
template <class T>
math::vector3<T> rotate_y(const math::vector3<T>& v, T angle);
/**
* Produces a matrix which rotates rectangular coordinates about the z-axis by a given angle.
*
* @param angle Angle of rotation, in radians.
* @return Rotation matrix.
*/
template <class T>
math::matrix3<T> rotate_z(T angle);
/**
* Rotates rectangular coordinates about the z-axis.
*
* @param v Rectangular coordinates to rotate.
* @param angle Angle of rotation, in radians.
* @return Rotated rectangular coordinates.
*/
template <class T>
math::vector3<T> rotate_z(const math::vector3<T>& v, T angle);
/**
* Converts rectangular coordinates to spherical coordinates.
*
* @param v Rectangular coordinates.
* @return Spherical coordinates, in the ISO order of radial distance, polar angle (radians), and azimuthal angle (radians).
*
* @see coordinates::spherical
*/
template <class T>
math::vector3<T> to_spherical(const math::vector3<T>& v);
template <class T>
math::vector3<T> to_spherical(const math::vector3<T>& v)
{
const T xx_yy = v.x * v.x + v.y * v.y;
return math::vector3<T>
{
std::sqrt(xx_yy + v.z * v.z),
std::atan2(v.z, std::sqrt(xx_yy)),
std::atan2(v.y, v.x)
};
}
template <class T>
math::matrix3<T> rotate_x(T angle)
{
const T c = std::cos(angle);
const T s = std::sin(angle);
return math::matrix3<T>
{
T(1), T(0), T(0),
T(0), c, -s,
T(0), s, c
};
}
template <class T>
math::vector3<T> rotate_x(const math::vector3<T>& v, T angle)
{
return rotate_x(angle) * v;
}
template <class T>
math::matrix3<T> rotate_y(T angle)
{
const T c = std::cos(angle);
const T s = std::sin(angle);
return math::matrix3<T>
{
c, T(0), s,
T(0), T(1), T(0),
-s, T(0), c
};
}
template <class T>
math::vector3<T> rotate_y(const math::vector3<T>& v, T angle)
{
return rotate_y(angle) * v;
}
template <class T>
math::matrix3<T> rotate_z(T angle)
{
const T c = std::cos(angle);
const T s = std::sin(angle);
return math::matrix3<T>
{
c, -s, T(0),
s, c, T(0),
T(0), T(0), T(1)
};
}
template <class T>
math::vector3<T> rotate_z(const math::vector3<T>& v, T angle)
{
return rotate_z(angle) * v;
}
} // namespace rectangular
} // namespace coordinates
#endif // ANTKEEPER_COORDINATES_RECTANGULAR_HPP

+ 4
- 4
src/ecs/components/celestial-body-component.hpp View File

@ -20,7 +20,7 @@
#ifndef ANTKEEPER_ECS_CELESTIAL_BODY_COMPONENT_HPP
#define ANTKEEPER_ECS_CELESTIAL_BODY_COMPONENT_HPP
#include "astro/orbit.hpp"
#include "physics/orbit/elements.hpp"
#include "utility/fundamental-types.hpp"
#include "math/quaternion-type.hpp"
@ -28,9 +28,9 @@ namespace ecs {
struct celestial_body_component
{
astro::orbital_elements orbital_elements;
astro::orbital_elements orbital_rate;
astro::orbital_state orbital_state;
physics::orbit::elements<double> orbital_elements;
physics::orbit::elements<double> orbital_rate;
physics::orbit::state<double> orbital_state;
double3 position;
double3 velocity;

+ 4
- 4
src/ecs/components/orbit-component.hpp View File

@ -20,15 +20,15 @@
#ifndef ANTKEEPER_ECS_ORBIT_COMPONENT_HPP
#define ANTKEEPER_ECS_ORBIT_COMPONENT_HPP
#include "astro/orbit.hpp"
#include "physics/orbit/elements.hpp"
namespace ecs {
struct orbit_component
{
astro::orbital_elements elements;
astro::orbital_elements rate;
astro::orbital_state state;
physics::orbit::elements<double> elements;
physics::orbit::elements<double> rate;
physics::orbit::elements<double> state;
};
} // namespace ecs

+ 105
- 23
src/ecs/systems/astronomy-system.cpp View File

@ -18,12 +18,13 @@
*/
#include "ecs/systems/astronomy-system.hpp"
#include "coordinates/coordinates.hpp"
#include "astro/apparent-size.hpp"
#include "ecs/components/celestial-body-component.hpp"
#include "ecs/components/transform-component.hpp"
#include "renderer/passes/sky-pass.hpp"
#include "color/color.hpp"
#include "physics/orbit/orbit.hpp"
#include "geom/cartesian.hpp"
#include <iostream>
namespace ecs {
@ -49,48 +50,127 @@ void astronomy_system::update(double t, double dt)
// Add scaled timestep to current time
set_universal_time(universal_time + dt * days_per_timestep);
set_universal_time(0.0);
// Update horizontal (topocentric) positions of intrasolar celestial bodies
registry.view<celestial_body_component, transform_component>().each(
[&](ecs::entity entity, auto& body, auto& transform)
{
double time_correction = observer_location[2] / (math::two_pi<double> / 24.0);
double local_jd = universal_time + time_correction / 24.0 - 0.5;
double local_time = (local_jd - std::floor(local_jd)) * 24.0;
double local_lst = local_time / 24.0f * math::two_pi<float>;
// Transform orbital position from ecliptic space to horizontal space
double3 horizontal = ecliptic_to_horizontal * body.orbital_state.r;
//double3 horizontal = ecliptic_to_horizontal * body.orbital_state.r;
double3 horizontal = ecliptic_to_horizontal * double3{1, 0, 0};
// Subtract observer's radial distance (planet radius + observer's altitude)
horizontal.z -= observer_location[0];
//horizontal.z -= observer_location[0];
// Convert rectangular horizontal coordinates to spherical
double3 spherical = coordinates::rectangular::to_spherical(horizontal);
// Convert Cartesian horizontal coordinates to spherical
double3 spherical = geom::cartesian::to_spherical(horizontal);
// Find angular radius
double angular_radius = astro::find_angular_radius(body.radius, spherical[0]);
// Transform into local coordinates
const double3x3 horizontal_to_local =
{
0.0, 0.0, -1.0,
1.0, 0.0, 0.0,
0.0, 1.0, 0.0
};
const double3x3 horizontal_to_local = math::rotate_x(-math::half_pi<double>) * math::rotate_z(-math::half_pi<double>);
double3 translation = horizontal_to_local * horizontal;
double3x3 rotation = horizontal_to_local * ecliptic_to_horizontal;
// Set local transform of transform component
transform.local.translation = math::type_cast<float>(translation);
transform.local.rotation = math::type_cast<float>(math::quaternion_cast(rotation));
transform.local.rotation = math::normalize(math::type_cast<float>(math::quaternion_cast(rotation)));
transform.local.scale = math::type_cast<float>(double3{body.radius, body.radius, body.radius});
if (sun_light != nullptr)
{
math::quaternion<float> sun_azimuth_rotation = math::angle_axis(static_cast<float>(spherical.z), float3{0, 1, 0});
math::quaternion<float> sun_elevation_rotation = math::angle_axis(static_cast<float>(spherical.y), float3{-1, 0, 0});
math::quaternion<float> sun_az_el_rotation = math::normalize(sun_azimuth_rotation * sun_elevation_rotation);
const double universal_time_cy = universal_time * 2.7397e-5;
const double3 solar_system_barycenter = {0, 0, 0};
physics::orbit::elements<double> earth_elements;
earth_elements.a = 1.00000261 + 0.00000562 * universal_time_cy;
earth_elements.e = 0.01671123 + -0.00004392 * universal_time_cy;
earth_elements.i = math::radians(-0.00001531) + math::radians(-0.01294668) * universal_time_cy;
earth_elements.raan = 0.0;
const double earth_elements_mean_longitude = math::radians(100.46457166) + math::radians(35999.37244981) * universal_time_cy;
const double earth_elements_longitude_perihelion = math::radians(102.93768193) + math::radians(0.32327364) * universal_time_cy;
earth_elements.w = earth_elements_longitude_perihelion - earth_elements.raan;
earth_elements.ta = earth_elements_mean_longitude - earth_elements_longitude_perihelion;
// Calculate semi-minor axis, b
double b = physics::orbit::derive_semiminor_axis(earth_elements.a, earth_elements.e);
// Solve Kepler's equation for eccentric anomaly (E)
double ea = physics::orbit::kepler_ea(earth_elements.e, earth_elements.ta, 10, 1e-6);
// Calculate radial distance, r; and true anomaly, v
double xv = earth_elements.a * (std::cos(ea) - earth_elements.e);
double yv = b * std::sin(ea);
double r = std::sqrt(xv * xv + yv * yv);
double ta = std::atan2(yv, xv);
// Position of the body in perifocal space
const math::vector3<double> earth_position_pqw = math::quaternion<double>::rotate_z(ta) * math::vector3<double>{r, 0, 0};
//sun_az_el_rotation = math::angle_axis((float)universal_time * math::two_pi<float>, float3{1, 0, 0});
//
//sun_light->look_at({0, 0, 0}, {0, -1, 0}, {0, 0, 1});
const double earth_axial_tilt = math::radians(23.45);
const double earth_axial_rotation = math::two_pi<double> * (0.7790572732640 + 1.00273781191135448 * universal_time);
const double earth_radius_au = 4.2635e-5;
const double observer_altitude = earth_radius_au;
const double observer_latitude = math::radians(0.0);
const double observer_longitude = math::radians(0.0);
const physics::frame<double> earth_inertial_to_pqw = physics::orbit::inertial::to_perifocal(solar_system_barycenter, earth_elements.raan, earth_elements.i, earth_elements.w);
const math::vector3<double> earth_position_inertial = earth_inertial_to_pqw.inverse() * earth_position_pqw;
const math::vector3<double> sun_position_intertial = math::vector3<double>{0, 0, 0};
const physics::frame<double> earth_inertial_to_bci = physics::orbit::inertial::to_bci(earth_position_inertial, earth_elements.i, earth_axial_tilt);
const physics::frame<double> earth_inertial_to_bcbf = physics::orbit::inertial::to_bcbf(earth_position_inertial, earth_elements.i, earth_axial_tilt, earth_axial_rotation);
const physics::frame<double> earth_bcbf_to_topo = physics::orbit::bcbf::to_topocentric(observer_altitude, observer_latitude, observer_longitude);
const math::vector3<double> sun_position_earth_bci = earth_inertial_to_bci * sun_position_intertial;
const math::vector3<double> sun_position_earth_bcbf = earth_inertial_to_bcbf * sun_position_intertial;
const math::vector3<double> sun_position_earth_topo = earth_bcbf_to_topo * sun_position_earth_bcbf;
const math::vector3<double> sun_radec = geom::cartesian::to_spherical(sun_position_earth_bci);
const math::vector3<double> sun_azel = geom::cartesian::to_spherical(sun_position_earth_topo);
const double sun_az = sun_azel.z;
const double sun_el = sun_azel.y;
double sun_ra = sun_radec.z;
const double sun_dec = sun_radec.y;
if (sun_ra < 0.0)
sun_ra += math::two_pi<double>;
std::cout << "ra: " << (sun_ra / math::two_pi<double> * 24.0) << "; dec: " << math::degrees(sun_dec) << std::endl;
std::cout << "az: " << math::degrees(math::pi<double> - sun_az) << "; el: " << math::degrees(sun_el) << std::endl;
float az = spherical.z;
float el = spherical.y;
if (az < 0.0f)
az += math::two_pi<float>;
//std::cout << "local: " << translation << std::endl;
//std::cout << "az: " << math::degrees(az) << "; ";
//std::cout << "el: " << math::degrees(el) << std::endl;
math::quaternion<float> sun_azimuth_rotation = math::angle_axis(static_cast<float>(spherical.z), float3{0, 1, 0});
math::quaternion<float> sun_elevation_rotation = math::angle_axis(static_cast<float>(spherical.y), float3{1, 0, 0});
math::quaternion<float> sun_az_el_rotation = math::normalize(sun_azimuth_rotation * sun_elevation_rotation);
// Set sun color
float cct = 3000.0f + std::sin(spherical.y) * 5000.0f;
@ -104,14 +184,16 @@ void astronomy_system::update(double t, double dt)
sun_light->set_intensity(intensity);
sun_light->set_translation({0, 500, 0});
//sun_light->set_rotation(math::look_rotation(math::normalize(transform.local.translation), {0, 1, 0}));
sun_light->set_rotation(sun_az_el_rotation);
//sun_light->set_translation({0, 500, 0});
sun_light->set_translation(transform.local.translation);
//sun_light->set_rotation(transform.local.rotation);
//sun_light->set_rotation(sun_az_el_rotation);
//sun_light->set_rotation(sun_elevation_rotation);
sun_light->set_rotation(math::look_rotation(math::normalize(-transform.local.translation), {0, 0, -1}));
if (this->sky_pass)
{
this->sky_pass->set_sun_coordinates(sun_az_el_rotation * float3{0, 0, -1}, {static_cast<float>(spherical.z), static_cast<float>(spherical.y)});
this->sky_pass->set_sun_coordinates(transform.local.rotation * float3{0, 0, -1}, {static_cast<float>(spherical.z), static_cast<float>(spherical.y)});
}
}
});
@ -186,7 +268,7 @@ void astronomy_system::update_sidereal_time()
void astronomy_system::update_ecliptic_to_horizontal()
{
ecliptic_to_horizontal = coordinates::rectangular::ecliptic::to_horizontal(obliquity, observer_location[1], lst);
//ecliptic_to_horizontal = coordinates::rectangular::ecliptic::to_horizontal(obliquity, observer_location[1], lst);
}
} // namespace ecs

+ 5
- 8
src/ecs/systems/solar-system.cpp View File

@ -18,9 +18,6 @@
*/
#include "ecs/systems/solar-system.hpp"
#include "coordinates/coordinates.hpp"
#include "astro/orbit.hpp"
#include "astro/constants.hpp"
#include "ecs/components/celestial-body-component.hpp"
#include "ecs/entity.hpp"
@ -45,16 +42,16 @@ void solar_system::update(double t, double dt)
registry.view<celestial_body_component>().each(
[&](ecs::entity entity, auto& body)
{
astro::orbital_elements elements = body.orbital_elements;
auto elements = body.orbital_elements;
elements.a += body.orbital_rate.a * universal_time;
elements.ec += body.orbital_rate.ec * universal_time;
elements.e += body.orbital_rate.e * universal_time;
elements.w += body.orbital_rate.w * universal_time;
elements.ma += body.orbital_rate.ma * universal_time;
elements.ta += body.orbital_rate.ta * universal_time;
elements.i += body.orbital_rate.i * universal_time;
elements.om += body.orbital_rate.om * universal_time;
elements.raan += body.orbital_rate.raan * universal_time;
// Calculate ecliptic orbital position
body.orbital_state.r = astro::orbital_elements_to_ecliptic(elements, ke_tolerance, ke_iterations);
//body.orbital_state.r = astro::orbital_elements_to_ecliptic(elements, ke_tolerance, ke_iterations);
});
}

+ 9
- 9
src/game/states/play-state.cpp View File

@ -119,18 +119,18 @@ void play_state_enter(game_context* ctx)
{
ecs::celestial_body_component sun_body;
sun_body.orbital_elements.a = 1.0;
sun_body.orbital_elements.ec = 0.016709;
sun_body.orbital_elements.e = 0.016709;
sun_body.orbital_elements.w = math::radians(282.9404);
sun_body.orbital_elements.ma = math::radians(356.0470);
sun_body.orbital_elements.ta = math::radians(356.0470);
sun_body.orbital_elements.i = 0.0;
sun_body.orbital_elements.om = 0.0;
sun_body.orbital_elements.raan = 0.0;
sun_body.orbital_rate.a = 0.0;
sun_body.orbital_rate.ec = -1.151e-9;
sun_body.orbital_rate.e = -1.151e-9;
sun_body.orbital_rate.w = math::radians(4.70935e-5);
sun_body.orbital_rate.ma = math::radians(0.9856002585);
sun_body.orbital_rate.ta = math::radians(0.9856002585);
sun_body.orbital_rate.i = 0.0;
sun_body.orbital_rate.om = 0.0;
sun_body.orbital_rate.raan = 0.0;
ecs::transform_component sun_transform;
sun_transform.local = math::identity_transform<float>;
@ -161,7 +161,7 @@ void play_state_enter(game_context* ctx)
ctx->solar_system->set_universal_time(0.0);
ctx->astronomy_system->set_observer_location(double3{4.26352e-5, ctx->biome->location[0], ctx->biome->location[1]});
ctx->astronomy_system->set_observer_location(double3{4.26352e-5, math::radians(10.0f), 0.0f});
ctx->astronomy_system->set_universal_time(0.0);
ctx->astronomy_system->set_obliquity(math::radians(23.4393));
ctx->astronomy_system->set_axial_rotation_at_epoch(math::radians(280.4606));
@ -228,7 +228,7 @@ void play_state_enter(game_context* ctx)
// Create ant-hill
auto ant_hill_entity = ant_hill_archetype->create(ecs_registry);
ecs::command::place(ecs_registry, ant_hill_entity, {0, 0});
ecs::command::place(ecs_registry, ant_hill_entity, {0, -40});
// Creat nest
auto nest_entity = nest_archetype->create(ecs_registry);
@ -346,7 +346,7 @@ void play_state_enter(game_context* ctx)
{
auto larva = larva_archetype->create(ecs_registry);
ecs::command::assign_render_layers(ecs_registry, larva, 1);
ecs::command::warp_to(ecs_registry, larva, {50, 0.1935f, 10});
ecs::command::warp_to(ecs_registry, larva, {50, 0.1935f, 0});
//auto& transform = ecs_registry.get<ecs::transform_component>(larva_entity);
//transform.transform = math::identity_transform<float>;
//transform.transform.translation = nest->get_shaft_position(*central_shaft, central_shaft->depth[1]);

+ 58
- 0
src/geom/cartesian.hpp View File

@ -0,0 +1,58 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_GEOM_CARTESIAN_HPP
#define ANTKEEPER_GEOM_CARTESIAN_HPP
#include "utility/fundamental-types.hpp"
#include <cmath>
namespace geom {
/// Functions which operate on Cartesian (rectangular) coordinates.
namespace cartesian {
/**
* Converts Cartesian (rectangular) coordinates to spherical coordinates.
*
* @param v Cartesian coordinates.
* @return Spherical coordinates, in the ISO order of radial distance, polar angle (radians), and azimuthal angle (radians).
*
* @see geom::coordinates::spherical
*/
template <class T>
math::vector3<T> to_spherical(const math::vector3<T>& v);
template <class T>
math::vector3<T> to_spherical(const math::vector3<T>& v)
{
const T xx_yy = v.x * v.x + v.y * v.y;
return math::vector3<T>
{
std::sqrt(xx_yy + v.z * v.z),
std::atan2(v.z, std::sqrt(xx_yy)),
std::atan2(v.y, v.x)
};
}
} // namespace cartesian
} // namespace geom
#endif // ANTKEEPER_GEOM_CARTESIAN_HPP

+ 2
- 0
src/geom/geom.hpp View File

@ -26,6 +26,7 @@ namespace geom {}
#include "aabb.hpp"
#include "bounding-volume.hpp"
#include "convex-hull.hpp"
#include "cartesian.hpp"
#include "csg.hpp"
#include "intersection.hpp"
#include "marching-cubes.hpp"
@ -39,6 +40,7 @@ namespace geom {}
#include "ray.hpp"
#include "sdf.hpp"
#include "sphere.hpp"
#include "spherical.hpp"
#include "view-frustum.hpp"
#endif // ANTKEEPER_GEOM_HPP

src/coordinates/spherical.hpp → src/geom/spherical.hpp View File

@ -17,30 +17,30 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_COORDINATES_SPHERICAL_HPP
#define ANTKEEPER_COORDINATES_SPHERICAL_HPP
#ifndef ANTKEEPER_GEOM_SPHERICAL_HPP
#define ANTKEEPER_GEOM_SPHERICAL_HPP
#include "utility/fundamental-types.hpp"
#include <cmath>
namespace coordinates {
namespace geom {
/// Spherical coordinate systems.
/// Functions which operate on spherical coordinates.
namespace spherical {
/**
* Converts spherical coordinates to rectangular coordinates.
* Converts spherical coordinates to Cartesian (rectangular) coordinates.
*
* @param v Spherical coordinates, in the ISO order of radial distance, polar angle (radians), and azimuthal angle (radians).
* @return Rectangular coordinates.
* @return Cartesian coordinates.
*
* @see coordinates::rectangular
* @see geom::coordinates::cartesian
*/
template <class T>
math::vector3<T> to_rectangular(const math::vector3<T>& v);
math::vector3<T> to_cartesian(const math::vector3<T>& v);
template <class T>
math::vector3<T> to_rectangular(const math::vector3<T>& v)
math::vector3<T> to_cartesian(const math::vector3<T>& v)
{
const T x = v[0] * std::cos(v[1]);
@ -53,6 +53,6 @@ math::vector3 to_rectangular(const math::vector3& v)
}
} // namespace spherical
} // namespace coordinates
} // namespace geom
#endif // ANTKEEPER_COORDINATES_SPHERICAL_HPP
#endif // ANTKEEPER_GEOM_SPHERICAL_HPP

+ 69
- 0
src/math/matrix-functions.hpp View File

@ -251,6 +251,33 @@ matrix resize(const matrix& m);
template <class T>
matrix<T, 4, 4> rotate(const matrix<T, 4, 4>& m, T angle, const vector<T, 3>& axis);
/**
* Produces a matrix which rotates Cartesian coordinates about the x-axis by a given angle.
*
* @param angle Angle of rotation, in radians.
* @return Rotation matrix.
*/
template <class T>
matrix3<T> rotate_x(T angle);
/**
* Produces a matrix which rotates Cartesian coordinates about the y-axis by a given angle.
*
* @param angle Angle of rotation, in radians.
* @return Rotation matrix.
*/
template <class T>
matrix3<T> rotate_y(T angle);
/**
* Produces a matrix which rotates Cartesian coordinates about the z-axis by a given angle.
*
* @param angle Angle of rotation, in radians.
* @return Rotation matrix.
*/
template <class T>
matrix3<T> rotate_z(T angle);
/**
* Scales a matrix.
*
@ -734,6 +761,48 @@ matrix rotate(const matrix& m, T angle, const vector& ax
return mul(m, rotation);
}
template <class T>
matrix3<T> rotate_x(T angle)
{
const T c = std::cos(angle);
const T s = std::sin(angle);
return matrix3<T>
{
T(1), T(0), T(