15#include <Eigen/Geometry>
24 using Eigen::Quaterniond;
25 using Eigen::Vector3d;
26 using Eigen::Vector4d;
31 std::vector<Eigen::Vector3d, Eigen::aligned_allocator<Eigen::Vector3d>>;
32 using QuaterniondVec =
33 std::vector<Eigen::Quaterniond,
34 Eigen::aligned_allocator<Eigen::Quaterniond>>;
92 [[nodiscard]]
const Vector3d&
x() const noexcept {
101 [[nodiscard]]
const Vector3d&
v() const noexcept {
111 [[nodiscard]]
const Quaterniond&
q() const noexcept {
121 [[nodiscard]]
const Vector3d&
omega() const noexcept {
165 [[nodiscard]] Vector3d&
a();
173 [[nodiscard]] Vector3d&
alpha();
179 [[nodiscard]] Vector3d&
omega();
187 void addToX(
const Vector3d& correction);
196 Vector3d
applyImpulse(
const Vector3d& in_J,
const Vector3d& in_r_vec);
241 void dampenVelocity(
double linear_damping,
double angular_damping);
277 template <
typename T>
312 const Vector3d& in_v0,
const Vector3d& in_omega0) {
314 invM_.push_back(in_m > 0 ? 1.0 / in_m : 0.0);
316 if (
invM_.back() > 0 && in_r > 0) {
317 iInv_.push_back(1.0 / (0.4 * in_m * in_r * in_r));
319 iInv_.push_back(0.0);
323 a_.push_back(Vector3d::Zero());
324 q_.push_back(Quaterniond::Identity());
325 omega_.push_back(in_omega0);
326 alpha_.push_back(Vector3d::Zero());
327 torque_.push_back(Vector3d::Zero());
338#pragma omp parallel for schedule(static)
339 for (std::size_t i = 0; i <
size(); ++i) {
342 x_[i] +=
v_[i] * dt_pos + 0.5 *
a_[i] * dt_pos * dt_pos;
346 v_[i] += 0.5 *
a_[i] * dt;
358#pragma omp parallel for
359 for (std::size_t i = 0; i <
size(); ++i) {
362 v_[i] += 0.5 *
a_[i] * dt;
371 [[nodiscard]] std::size_t
size()
const {
return m_.size(); }
381 assert(index <
size() &&
"Index out of bounds");
393 assert(index <
size() &&
"Index out of bounds");
407 const Vector3d& omega,
const Vector4d& q_coeffs) {
408 const Vector3d q_vec = q_coeffs.head<3>();
409 const double q_w = q_coeffs.w();
411 const Vector3d derivative_vec = q_w * omega + omega.cross(q_vec);
412 const double derivative_w = -omega.dot(q_vec);
414 return {derivative_vec.x(), derivative_vec.y(), derivative_vec.z(),
428#pragma omp parallel for schedule(static)
429 for (std::size_t i = 0; i <
size(); ++i) {
431 if (
omega_[i].squaredNorm() < 1e-12) {
436 const Vector4d q_coeffs =
q_[i].coeffs();
444 const Vector4d q_mid = (q_coeffs + 0.25 * dt * k1).normalized();
452 q_[i].coeffs() += 0.5 * dt * k2;
458 std::vector<double>
m_;
464 std::vector<double>
r_;
470 std::vector<Vector3d>
x_;
473 std::vector<Vector3d>
v_;
476 std::vector<Vector3d>
a_;
479 std::vector<Quaterniond>
q_;
497 return {bodies_, index_};
515 const Vector3d& in_r_vec) {
517 return in_r_vec.cross(in_J);
533 const Vector3d& in_alpha) {
553 double angular_damping) {
561 std::size_t in_index)
An adapter to allow nanoflann to work directly with our Bodies SoA container.
Structure-of-Arrays (SoA) container for all bodies in the simulation.
std::vector< double > m_
Bodies’ masses.
std::vector< double > r_
Bodies radii.
std::vector< Vector3d > alpha_
Bodies' angular accelerations.
std::vector< Vector3d > omega_
Bodies' angular velocities.
std::vector< double > invM_
Bodies inverse masses.
void reserve(std::size_t n)
Reserve memory space for the data structure.
static Vector4d getQuaternionDerivative(const Vector3d &omega, const Vector4d &q_coeffs)
Calculates the time derivative of a quaternion.
std::vector< Quaterniond > q_
Bodies' orientations (quaternions).
std::size_t size() const
Get number of bodies in the simulation.
std::vector< Vector3d > torque_
Net torque applied to each body in a frame.
void updateRotationsRK2(double dt)
Vectorized update of orientations for all bodies using a 2nd-order Runge-Kutta method (RK2).
std::vector< Vector3d > v_
Bodies' velocities.
std::vector< Vector3d > a_
Bodies' accelerations.
std::vector< Vector3d > x_
Bodies' positions.
void integratePart2(double dt)
Vectorized Velocity Verlet: Part 2.
void emplaceBack(double in_m, double in_r, const Vector3d &in_x0, const Vector3d &in_v0, const Vector3d &in_omega0)
Add a new body at the back of the data structure.
ConstBodyProxy operator[](std::size_t index) const
Array like access to given body.
BodyProxy operator[](std::size_t index)
A proxy to access a given body.
std::vector< double > iInv_
Bodies inverse moments of inertia.
void integratePart1(double dt, double dt_pos)
Vectorized Velocity Verlet: Part 1.
A template base class for body proxies to reduce code duplication.
std::size_t index_
The index of the body this proxy refers to.
const Quaterniond & q() const noexcept
Access to body orientation.
const Vector3d & v() const noexcept
Access to body velocities.
BodyProxyBase(T &in_bodies, std::size_t in_index)
Construct a new Body Proxy Base object.
double getInverseInertia() const
Access to the inverse of the body's moment of inertia.
double m() const noexcept
Access to body masses.
T & bodies_
Reference to the main SoA container.
double getInverseMass() const
Access to the inverse of the body masses.
double r() const noexcept
Access to body radii.
const Vector3d & x() const noexcept
Access to body positions.
const Vector3d & omega() const noexcept
Access to body angular velocities.
A proxy object that provides an AoS-like interface to a body stored in the Bodies SoA container.
void setAcceleration(const Vector3d &new_a)
Set the acceleration of a body.
Vector3d & a()
Access to body accelerations.
void dampenVelocity(double linear_damping, double angular_damping)
Applies damping to linear and angular velocities.
void addToX(const Vector3d &correction)
Add a displacement to a position.
void accumulateAngularAcceleration(const Vector3d &in_alpha)
Accumulate an angular acceleration to a body.
void resetTorque()
Resets the accumulated torque to zero.
BodyProxy(Bodies &in_bodies, std::size_t in_index)
Construct a new Body Proxy object.
Vector3d & omega()
Access to body angular velocities.
void resetAccelerations()
Resets linear and angular accelerations to zero.
void updateAlphaFromTorque()
Updates angular acceleration based on the accumulated torque.
void setAngularAcceleration(const Vector3d &new_alpha)
Set the angular acceleration of a body.
Vector3d & alpha()
Access to body angular accelerations.
void accumulateTorque(const Vector3d &torque)
Accumulates a torque vector to the body's total torque.
Vector3d applyImpulse(const Vector3d &in_J, const Vector3d &in_r_vec)
Apply an impulse to a body.
void accumulateAcceleration(const Vector3d &accel)
Accumulate an acceleration to a body.
A const proxy object that provides a read-only AoS-like interface to a body stored in the Bodies SoA ...
ConstBodyProxy(const Bodies &in_bodies, std::size_t in_index)
Construct a new Const Body Proxy object.
Class describing a space in which move several bodies.