16inline constexpr int64_t k_moment_safe_limit = int64_t {1} << 62;
38 constexpr auto operator==(
const MassMoments&)
const noexcept ->
bool =
default;
41 constexpr auto isEmpty() const noexcept ->
bool {
45 constexpr void add(int32_t x, int32_t y, int32_t z, uint32_t density)
noexcept {
46 accumulate(x, y, z,
static_cast<int64_t
>(density));
49 constexpr void remove(int32_t x, int32_t y, int32_t z, uint32_t density)
noexcept {
50 accumulate(x, y, z, -
static_cast<int64_t
>(density));
54 constexpr auto operator-=(
const MassMoments& other)
noexcept -> MassMoments& {
70 constexpr auto scaled(int64_t factor)
const noexcept -> MassMoments {
72 out.mass =
mass * factor;
73 out.m_x =
m_x * factor;
74 out.m_y = m_y * factor;
75 out.m_z = m_z * factor;
76 out.m_xx =
m_xx * factor;
77 out.m_yy = m_yy * factor;
78 out.m_zz = m_zz * factor;
79 out.m_xy =
m_xy * factor;
80 out.m_xz = m_xz * factor;
81 out.m_yz = m_yz * factor;
86 constexpr auto operator+=(
const MassMoments& other)
noexcept -> MassMoments& {
102 constexpr auto operator+(
const MassMoments& other)
const noexcept -> MassMoments {
103 MassMoments out = *
this;
109 constexpr auto shifted(int32_t ox, int32_t oy, int32_t oz)
const noexcept -> MassMoments {
110 const int64_t dx = ox;
111 const int64_t dy = oy;
112 const int64_t dz = oz;
117 out.m_y = m_y + (dy *
mass);
118 out.m_z = m_z + (dz *
mass);
119 out.m_xx =
m_xx + (2 * dx *
m_x) + (dx * dx *
mass);
120 out.m_yy = m_yy + (2 * dy * m_y) + (dy * dy *
mass);
121 out.m_zz = m_zz + (2 * dz * m_z) + (dz * dz *
mass);
122 out.m_xy =
m_xy + (dx * m_y) + (dy *
m_x) + (dx * dy *
mass);
123 out.m_xz = m_xz + (dx * m_z) + (dz *
m_x) + (dx * dz *
mass);
124 out.m_yz = m_yz + (dy * m_z) + (dz * m_y) + (dy * dz *
mass);
130 constexpr void accumulate(int32_t x, int32_t y, int32_t z, int64_t signed_density)
noexcept {
131 const int64_t lx = x;
132 const int64_t ly = y;
133 const int64_t lz = z;
135 mass += signed_density;
136 m_x += signed_density * lx;
137 m_y += signed_density * ly;
138 m_z += signed_density * lz;
139 m_xx += signed_density * lx * lx;
140 m_yy += signed_density * ly * ly;
141 m_zz += signed_density * lz * lz;
142 m_xy += signed_density * lx * ly;
143 m_xz += signed_density * lx * lz;
144 m_yz += signed_density * ly * lz;
148 constexpr void checkHeadroom() const noexcept {
149 assert(
m_xx < k_moment_safe_limit && m_yy < k_moment_safe_limit && m_zz < k_moment_safe_limit);
165inline auto resolveMass(
const MassMoments& moments,
float voxel_size = k_voxel_size) ->
float {
166 const double s =
static_cast<double>(voxel_size);
167 return static_cast<float>(
static_cast<double>(moments.mass) * s * s * s);
173 if (moments.mass <= 0) {
177 const double s = voxel_size;
178 const double s3 = s * s * s;
179 const double s5 = s3 * s * s;
181 const double density_sum =
static_cast<double>(moments.mass);
182 const double total_mass = density_sum * s3;
185 const auto product = [&](int64_t m_ab, int64_t m_a, int64_t m_b) {
186 return static_cast<double>(m_ab) + (0.5 * (
static_cast<double>(m_a) +
static_cast<double>(m_b))) + (0.25 * density_sum);
189 const double p_xx = product(moments.m_xx, moments.m_x, moments.m_x);
190 const double p_yy = product(moments.m_yy, moments.m_y, moments.m_y);
191 const double p_zz = product(moments.m_zz, moments.m_z, moments.m_z);
192 const double p_xy = product(moments.m_xy, moments.m_x, moments.m_y);
193 const double p_xz = product(moments.m_xz, moments.m_x, moments.m_z);
194 const double p_yz = product(moments.m_yz, moments.m_y, moments.m_z);
196 const double com_x = ((
static_cast<double>(moments.m_x) / density_sum) + 0.5) * s;
197 const double com_y = ((
static_cast<double>(moments.m_y) / density_sum) + 0.5) * s;
198 const double com_z = ((
static_cast<double>(moments.m_z) / density_sum) + 0.5) * s;
201 const double self_term = total_mass * s * s / 6.0;
203 double i_xx = (s5 * (p_yy + p_zz)) + self_term;
204 double i_yy = (s5 * (p_xx + p_zz)) + self_term;
205 double i_zz = (s5 * (p_xx + p_yy)) + self_term;
206 double i_xy = -s5 * p_xy;
207 double i_xz = -s5 * p_xz;
208 double i_yz = -s5 * p_yz;
210 i_xx -= total_mass * ((com_y * com_y) + (com_z * com_z));
211 i_yy -= total_mass * ((com_x * com_x) + (com_z * com_z));
212 i_zz -= total_mass * ((com_x * com_x) + (com_y * com_y));
213 i_xy += total_mass * com_x * com_y;
214 i_xz += total_mass * com_x * com_z;
215 i_yz += total_mass * com_y * com_z;
217 out.mass =
static_cast<float>(total_mass);
218 out.center_of_mass = glm::vec3(
static_cast<float>(com_x),
static_cast<float>(com_y),
static_cast<float>(com_z));
219 out.inertia = glm::mat3(
220 static_cast<float>(i_xx),
221 static_cast<float>(i_xy),
222 static_cast<float>(i_xz),
223 static_cast<float>(i_xy),
224 static_cast<float>(i_yy),
225 static_cast<float>(i_yz),
226 static_cast<float>(i_xz),
227 static_cast<float>(i_yz),
228 static_cast<float>(i_zz)
Definition mass_accumulator.hpp:18
int64_t mass
Sum of densities.
Definition mass_accumulator.hpp:20
int64_t m_xx
Sum of density * coordinate*coordinate.
Definition mass_accumulator.hpp:28
int64_t m_x
Sum of density * coordinate.
Definition mass_accumulator.hpp:23
int64_t m_xy
Sum of density * coordinate_a * coordinate_b.
Definition mass_accumulator.hpp:33
Definition mass_accumulator.hpp:153
float mass
kg
Definition mass_accumulator.hpp:155
glm::mat3 inertia
kg·m² about the centre of mass
Definition mass_accumulator.hpp:161
glm::vec3 center_of_mass
Volume local metres.
Definition mass_accumulator.hpp:158