Skip to content

Commit e68face

Browse files
Switches to using precomputed reciprocal math.
See issue #337 for more info.
1 parent 507a7c1 commit e68face

17 files changed

+129
-78
lines changed

PlayRho/Collision/AABB.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ AABB ComputeAABB(const DistanceProxy& proxy, const Transformation& xf) noexcept
4545
}
4646

4747
AABB ComputeAABB(const DistanceProxy& proxy,
48-
const Transformation& xfm0, const Transformation& xfm1) noexcept
48+
const Transformation& xfm0, const Transformation& xfm1) noexcept
4949
{
5050
assert(IsValid(xfm0));
5151
assert(IsValid(xfm1));

PlayRho/Collision/AABB.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,8 @@ PLAYRHO_CONSTEXPR inline Vector<Length, N> GetDimensions(const AABB<N>& aabb) no
236236
template <std::size_t N>
237237
PLAYRHO_CONSTEXPR inline Vector<Length, N> GetExtents(const AABB<N>& aabb) noexcept
238238
{
239-
return GetDimensions(aabb) / 2;
239+
PLAYRHO_CONSTEXPR const auto RealInverseOfTwo = Real{1} / Real{2};
240+
return GetDimensions(aabb) * RealInverseOfTwo;
240241
}
241242

242243
/// @brief Checks whether the first AABB fully contains the second AABB.

PlayRho/Collision/MassData.cpp

+6-3
Original file line numberDiff line numberDiff line change
@@ -145,16 +145,19 @@ MassData GetMassData(Length vertexRadius, NonNegative<AreaDensity> density,
145145

146146
const auto D = Cross(e1, e2);
147147

148-
const auto triangleArea = D / Real{2};
148+
PLAYRHO_CONSTEXPR const auto RealReciprocalOfTwo = Real{1} / Real{2}; // .5
149+
const auto triangleArea = D * RealReciprocalOfTwo;
149150
area += triangleArea;
150151

151152
// Area weighted centroid
152-
center += StripUnit(triangleArea) * (e1 + e2) / Real{3};
153+
PLAYRHO_CONSTEXPR const auto RealReciprocalOfThree = Real{1} / Real{3}; // .3333333...
154+
center += StripUnit(triangleArea) * (e1 + e2) * RealReciprocalOfThree;
153155

154156
const auto intx2 = Square(GetX(e1)) + GetX(e2) * GetX(e1) + Square(GetX(e2));
155157
const auto inty2 = Square(GetY(e1)) + GetY(e2) * GetY(e1) + Square(GetY(e2));
156158

157-
const auto triangleI = D * (intx2 + inty2) / Real{3 * 4};
159+
PLAYRHO_CONSTEXPR const auto RealReciprocalOfTwelve = Real{1} / Real{3 * 4}; // .083333..
160+
const auto triangleI = D * (intx2 + inty2) * RealReciprocalOfTwelve;
158161
I += triangleI;
159162
}
160163

PlayRho/Collision/RayCastOutput.cpp

+7-4
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,9 @@ RayCastOutput RayCast(const AABB& aabb, const RayCastInput& input) noexcept
9393
}
9494
else
9595
{
96-
auto t1 = Real{(range.GetMin() - p1i) / pdi};
97-
auto t2 = Real{(range.GetMax() - p1i) / pdi};
96+
const auto reciprocalOfPdi = Real{1} / pdi;
97+
auto t1 = Real{(range.GetMin() - p1i) * reciprocalOfPdi};
98+
auto t2 = Real{(range.GetMax() - p1i) * reciprocalOfPdi};
9899
auto s = -1; // Sign of the normal vector.
99100
if (t1 > t2)
100101
{
@@ -187,11 +188,13 @@ RayCastOutput RayCast(const DistanceProxy& proxy, const RayCastInput& input,
187188
const auto v0off = v0 + offset;
188189
const auto q_sub_p = v0off - ray0;
189190

191+
const auto reciprocalRayCrossEdge = Real{1} / ray_cross_edge;
192+
190193
// t = ((q - p) x s) / (r x s)
191-
const auto t = Cross(q_sub_p, edge) / ray_cross_edge;
194+
const auto t = Cross(q_sub_p, edge) * reciprocalRayCrossEdge;
192195

193196
// u = ((q - p) x r) / (r x s)
194-
const auto u = Cross(q_sub_p, ray) / ray_cross_edge;
197+
const auto u = Cross(q_sub_p, ray) * reciprocalRayCrossEdge;
195198

196199
if ((t >= 0) && (t <= 1) && (u >= 0) && (u <= 1))
197200
{

PlayRho/Collision/Simplex.cpp

+10-10
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ Simplex Simplex::Get(const SimplexEdge& s0, const SimplexEdge& s1) noexcept
111111
}
112112

113113
// Must be in e12 region.
114-
const auto d12_sum = d12_1 + d12_2;
115-
return Simplex{{s0, s1}, {d12_1 / d12_sum, d12_2 / d12_sum}};
114+
const auto inv_sum = Real{1} / (d12_1 + d12_2);
115+
return Simplex{{s0, s1}, {d12_1 * inv_sum, d12_2 * inv_sum}};
116116
}
117117

118118
Simplex Simplex::Get(const SimplexEdge& s0, const SimplexEdge& s1, const SimplexEdge& s2) noexcept
@@ -179,31 +179,31 @@ Simplex Simplex::Get(const SimplexEdge& s0, const SimplexEdge& s1, const Simplex
179179
const auto d123_3 = n123 * cp_w1_w2;
180180
if ((d12_1 > 0_m2) && (d12_2 > 0_m2) && (d123_3 <= 0 * SquareMeter * SquareMeter))
181181
{
182-
const auto d12_sum = d12_1 + d12_2;
183-
return Simplex{{s0, s1}, {d12_1 / d12_sum, d12_2 / d12_sum}};
182+
const auto inv_sum = Real{1} / (d12_1 + d12_2);
183+
return Simplex{{s0, s1}, {d12_1 * inv_sum, d12_2 * inv_sum}};
184184
}
185185

186186
// e13
187187
const auto cp_w3_w1 = Cross(w3, w1);
188188
const auto d123_2 = n123 * cp_w3_w1;
189189
if ((d13_1 > 0_m2) && (d13_2 > 0_m2) && (d123_2 <= 0 * SquareMeter * SquareMeter))
190190
{
191-
const auto d13_sum = d13_1 + d13_2;
192-
return Simplex{{s0, s2}, {d13_1 / d13_sum, d13_2 / d13_sum}};
191+
const auto inv_sum = Real{1} / (d13_1 + d13_2);
192+
return Simplex{{s0, s2}, {d13_1 * inv_sum, d13_2 * inv_sum}};
193193
}
194194

195195
// e23
196196
const auto cp_w2_w3 = Cross(w2, w3);
197197
const auto d123_1 = n123 * cp_w2_w3;
198198
if ((d23_1 > 0_m2) && (d23_2 > 0_m2) && (d123_1 <= 0 * SquareMeter * SquareMeter))
199199
{
200-
const auto d23_sum = d23_1 + d23_2;
201-
return Simplex{{s2, s1}, {d23_2 / d23_sum, d23_1 / d23_sum}};
200+
const auto inv_sum = Real{1} / (d23_1 + d23_2);
201+
return Simplex{{s2, s1}, {d23_2 * inv_sum, d23_1 * inv_sum}};
202202
}
203203

204204
// Must be in triangle123
205-
const auto d123_sum = d123_1 + d123_2 + d123_3;
206-
return Simplex{{s0, s1, s2}, {d123_1 / d123_sum, d123_2 / d123_sum, d123_3 / d123_sum}};
205+
const auto inv_sum = Real{1} / (d123_1 + d123_2 + d123_3);
206+
return Simplex{{s0, s1, s2}, {d123_1 * inv_sum, d123_2 * inv_sum, d123_3 * inv_sum}};
207207
}
208208

209209
Simplex Simplex::Get(const SimplexEdges& edges) noexcept

PlayRho/Common/Acceleration.hpp

+2-11
Original file line numberDiff line numberDiff line change
@@ -132,17 +132,8 @@ namespace d2 {
132132
/// @relatedalso Acceleration
133133
PLAYRHO_CONSTEXPR inline Acceleration operator/ (const Acceleration& lhs, const Real rhs)
134134
{
135-
/*
136-
* While it can be argued that division operations shouldn't be supported due to
137-
* hardware support for division typically being significantly slower than hardware
138-
* support for multiplication, it can also be argued that it shouldn't be the
139-
* software developer's role to attempt to optimize what the compiler should be
140-
* much better at knowing how to optimize. So here the code chooses the latter
141-
* strategy which allows the intention to be clearer, and just passes the division
142-
* on down to the Vec2 and Angle types (rather than manually rewriting the divisions
143-
* as multiplications).
144-
*/
145-
return Acceleration{lhs.linear / rhs, lhs.angular / rhs};
135+
const auto inverseRhs = Real{1} / rhs;
136+
return Acceleration{lhs.linear * inverseRhs, lhs.angular * inverseRhs};
146137
}
147138

148139
} // namespace d2

PlayRho/Common/Math.cpp

+8-4
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,13 @@ Length2 ComputeCentroid(const Span<const Length2>& vertices)
6262
const auto e1 = p2 - p1;
6363
const auto e2 = p3 - p1;
6464

65-
const auto triangleArea = Area{Cross(e1, e2) / Real(2)};
65+
PLAYRHO_CONSTEXPR const auto RealInverseOfTwo = Real{1} / Real{2};
66+
const auto triangleArea = Area{Cross(e1, e2) * RealInverseOfTwo};
6667
area += triangleArea;
6768

6869
// Area weighted centroid
69-
const auto aveP = (p1 + p2 + p3) / Real{3};
70+
PLAYRHO_CONSTEXPR const auto RealInverseOfThree = Real{1} / Real{3};
71+
const auto aveP = (p1 + p2 + p3) * RealInverseOfThree;
7072
c += triangleArea * aveP;
7173
}
7274

@@ -129,7 +131,8 @@ NonNegative<Area> GetAreaOfPolygon(Span<const Length2> vertices)
129131

130132
// Note that using the absolute value isn't necessary for vertices in counter-clockwise
131133
// ordering; only needed for clockwise ordering.
132-
return abs(sum) / Real{2};
134+
PLAYRHO_CONSTEXPR const auto RealInverseOfTwo = Real{1} / Real{2};
135+
return abs(sum) * RealInverseOfTwo;
133136
}
134137

135138
SecondMomentOfArea GetPolarMoment(Span<const Length2> vertices)
@@ -161,7 +164,8 @@ SecondMomentOfArea GetPolarMoment(Span<const Length2> vertices)
161164
}
162165
const auto secondMomentOfAreaX = SecondMomentOfArea{sum_x};
163166
const auto secondMomentOfAreaY = SecondMomentOfArea{sum_y};
164-
return (secondMomentOfAreaX + secondMomentOfAreaY) / Real{12};
167+
PLAYRHO_CONSTEXPR const auto RealInverseOfTwelve = Real{1} / Real{12};
168+
return (secondMomentOfAreaX + secondMomentOfAreaY) * RealInverseOfTwelve;
165169
}
166170

167171
namespace d2 {

PlayRho/Common/Math.hpp

+11-8
Original file line numberDiff line numberDiff line change
@@ -451,11 +451,12 @@ template <typename T, typename U>
451451
PLAYRHO_CONSTEXPR inline auto Solve(const Matrix22<U> mat, const Vector2<T> b) noexcept
452452
{
453453
const auto cp = Cross(get<0>(mat), get<1>(mat));
454+
const auto inverseCp = Real{1} / cp;
454455
using OutType = decltype((U{} * T{}) / cp);
455456
return (!AlmostZero(StripUnit(cp)))?
456457
Vector2<OutType>{
457-
(get<1>(mat)[1] * b[0] - get<1>(mat)[0] * b[1]) / cp,
458-
(get<0>(mat)[0] * b[1] - get<0>(mat)[1] * b[0]) / cp
458+
(get<1>(mat)[1] * b[0] - get<1>(mat)[0] * b[1]) * inverseCp,
459+
(get<0>(mat)[0] * b[1] - get<0>(mat)[1] * b[0]) * inverseCp
459460
}: Vector2<OutType>{};
460461
}
461462

@@ -465,10 +466,11 @@ PLAYRHO_CONSTEXPR inline auto Invert(const Matrix22<IN_TYPE> value) noexcept
465466
{
466467
const auto cp = Cross(get<0>(value), get<1>(value));
467468
using OutType = decltype(get<0>(value)[0] / cp);
469+
const auto inverseCp = Real{1} / cp;
468470
return (!AlmostZero(StripUnit(cp)))?
469471
Matrix22<OutType>{
470-
Vector2<OutType>{ get<1>(get<1>(value)) / cp, -get<1>(get<0>(value)) / cp},
471-
Vector2<OutType>{-get<0>(get<1>(value)) / cp, get<0>(get<0>(value)) / cp}
472+
Vector2<OutType>{ get<1>(get<1>(value)) * inverseCp, -get<1>(get<0>(value)) * inverseCp},
473+
Vector2<OutType>{-get<0>(get<1>(value)) * inverseCp, get<0>(get<0>(value)) * inverseCp}
472474
}:
473475
Matrix22<OutType>{};
474476
}
@@ -478,7 +480,7 @@ PLAYRHO_CONSTEXPR inline auto Invert(const Matrix22<IN_TYPE> value) noexcept
478480
PLAYRHO_CONSTEXPR inline Vec3 Solve33(const Mat33& mat, const Vec3 b) noexcept
479481
{
480482
const auto dp = Dot(GetX(mat), Cross(GetY(mat), GetZ(mat)));
481-
const auto det = (dp != 0)? 1 / dp: dp;
483+
const auto det = (dp != 0)? Real{1} / dp: dp;
482484
const auto x = det * Dot(b, Cross(GetY(mat), GetZ(mat)));
483485
const auto y = det * Dot(GetX(mat), Cross(b, GetZ(mat)));
484486
const auto z = det * Dot(GetX(mat), Cross(GetY(mat), b));
@@ -492,7 +494,7 @@ template <typename T>
492494
PLAYRHO_CONSTEXPR inline T Solve22(const Mat33& mat, const T b) noexcept
493495
{
494496
const auto cp = GetX(GetX(mat)) * GetY(GetY(mat)) - GetX(GetY(mat)) * GetY(GetX(mat));
495-
const auto det = (cp != 0)? 1 / cp: cp;
497+
const auto det = (cp != 0)? Real{1} / cp: cp;
496498
const auto x = det * (GetY(GetY(mat)) * GetX(b) - GetX(GetY(mat)) * GetY(b));
497499
const auto y = det * (GetX(GetX(mat)) * GetY(b) - GetY(GetX(mat)) * GetX(b));
498500
return T{x, y};
@@ -623,7 +625,7 @@ inline Real Normalize(Vec2& vector)
623625
const auto length = GetMagnitude(vector);
624626
if (!AlmostZero(length))
625627
{
626-
const auto invLength = 1 / length;
628+
const auto invLength = Real{1} / length;
627629
vector[0] *= invLength;
628630
vector[1] *= invLength;
629631
return length;
@@ -734,7 +736,8 @@ PLAYRHO_CONSTEXPR inline Vector2<T> operator* (const UnitVec u, const T s) noexc
734736
/// @brief Division operator.
735737
PLAYRHO_CONSTEXPR inline Vec2 operator/ (const UnitVec u, const UnitVec::value_type s) noexcept
736738
{
737-
return Vec2{GetX(u) / s, GetY(u) / s};
739+
const auto inverseS = Real{1} / s;
740+
return Vec2{GetX(u) * inverseS, GetY(u) * inverseS};
738741
}
739742

740743
/// @brief Rotates a vector by a given angle.

PlayRho/Common/UnitVec.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ class UnitVec
132132
{
133133
const auto magnitude = sqrt(magnitudeSquared);
134134
assert(isnormal(magnitude));
135-
return {UnitVec{value_type{x / magnitude}, value_type{y / magnitude}}, magnitude};
135+
const auto invMagnitude = Real{1} / magnitude;
136+
return {UnitVec{value_type{x * invMagnitude}, value_type{y * invMagnitude}}, magnitude};
136137
}
137138

138139
// Failed the faster way, try the more accurate and robust way...

PlayRho/Common/Vector.hpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -355,9 +355,10 @@ PLAYRHO_CONSTEXPR inline
355355
std::enable_if_t<std::is_same<T1, decltype(T1{} / T2{})>::value, Vector<T1, N>&>
356356
operator/= (Vector<T1, N>& lhs, const T2 rhs) noexcept
357357
{
358+
const auto inverseRhs = Real{1} / rhs;
358359
for (auto i = decltype(N){0}; i < N; ++i)
359360
{
360-
lhs[i] /= rhs;
361+
lhs[i] *= inverseRhs;
361362
}
362363
return lhs;
363364
}
@@ -506,9 +507,10 @@ operator/ (Vector<T1, N> a, const T2 s) noexcept
506507
{
507508
// Can't base this off of /= since result type in this case can be different
508509
auto result = Vector<OT, N>{};
510+
const auto inverseS = Real{1} / s;
509511
for (auto i = decltype(N){0}; i < N; ++i)
510512
{
511-
result[i] = a[i] / s;
513+
result[i] = a[i] * inverseS;
512514
}
513515
return result;
514516
}

PlayRho/Common/Velocity.hpp

+2-11
Original file line numberDiff line numberDiff line change
@@ -134,17 +134,8 @@ PLAYRHO_CONSTEXPR inline Velocity operator* (const Real lhs, const Velocity& rhs
134134
/// @relatedalso Velocity
135135
PLAYRHO_CONSTEXPR inline Velocity operator/ (const Velocity& lhs, const Real rhs)
136136
{
137-
/*
138-
* While it can be argued that division operations shouldn't be supported due to
139-
* hardware support for division typically being significantly slower than hardware
140-
* support for multiplication, it can also be argued that it shouldn't be the
141-
* software developer's role to attempt to optimize what the compiler should be
142-
* much better at knowing how to optimize. So here the code chooses the latter
143-
* strategy which allows the intention to be clearer, and just passes the division
144-
* on down to the Vec2 and Angle types (rather than manually rewriting the divisions
145-
* as multiplications).
146-
*/
147-
return Velocity{lhs.linear / rhs, lhs.angular / rhs};
137+
const auto inverseRhs = Real{1} / rhs;
138+
return Velocity{lhs.linear * inverseRhs, lhs.angular * inverseRhs};
148139
}
149140

150141
/// @brief Velocity pair.

PlayRho/Dynamics/Body.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -536,9 +536,9 @@ Force2 GetCentripetalForce(const Body& body, Length2 axis)
536536
const auto location = body.GetLocation();
537537
const auto mass = GetMass(body);
538538
const auto delta = axis - location;
539-
const auto radius = GetMagnitude(delta);
540-
const auto dir = delta / radius;
541-
return Force2{dir * mass * Square(magnitudeOfVelocity) / radius};
539+
const auto invRadius = Real{1} / GetMagnitude(delta);
540+
const auto dir = delta * invRadius;
541+
return Force2{dir * mass * Square(magnitudeOfVelocity) * invRadius};
542542
}
543543

544544
Acceleration CalcGravitationalAcceleration(const Body& body) noexcept

UnitTests/DiskShape.cpp

+6-5
Original file line numberDiff line numberDiff line change
@@ -174,15 +174,16 @@ TEST(DiskShapeConf, ComputeAABB)
174174
{
175175
const auto radius = 2.4_m;
176176
const auto position = Length2{2_m, 1_m};
177-
auto conf = DiskShapeConf{};
178-
conf.vertexRadius = radius;
179-
conf.location = position;
180-
Shape foo{conf};
181-
const auto aabb = ComputeAABB(foo, Transform_identity);
177+
const auto conf = DiskShapeConf{}.UseRadius(radius).UseLocation(position);
178+
const auto shape = Shape{conf};
179+
ASSERT_EQ(GetChildCount(shape), static_cast<decltype(GetChildCount(shape))>(1));
180+
const auto aabb = ComputeAABB(shape, Transform_identity);
182181
EXPECT_EQ(GetX(GetLowerBound(aabb)), GetX(position) - radius);
183182
EXPECT_EQ(GetY(GetLowerBound(aabb)), GetY(position) - radius);
184183
EXPECT_EQ(GetX(GetUpperBound(aabb)), GetX(position) + radius);
185184
EXPECT_EQ(GetY(GetUpperBound(aabb)), GetY(position) + radius);
185+
EXPECT_NEAR(static_cast<double>(Real{GetX(GetExtents(aabb))/1_m}), static_cast<double>(Real{radius/1_m}), 1.0/1000000);
186+
EXPECT_NEAR(static_cast<double>(Real{GetY(GetExtents(aabb))/1_m}), static_cast<double>(Real{radius/1_m}), 1.0/1000000);
186187
EXPECT_TRUE(AlmostEqual(StripUnit(GetX(GetExtents(aabb))), StripUnit(radius)));
187188
EXPECT_TRUE(AlmostEqual(StripUnit(GetY(GetExtents(aabb))), StripUnit(radius)));
188189
EXPECT_EQ(GetX(GetCenter(aabb)), GetX(position));

UnitTests/MultiShape.cpp

+36-7
Original file line numberDiff line numberDiff line change
@@ -224,10 +224,22 @@ TEST(MultiShapeConf, AddConvexHullWithOnePointSameAsDisk)
224224

225225
const auto massData = GetMassData(foo);
226226
EXPECT_NE(massData, defaultMassData);
227-
EXPECT_EQ(massData.center, center);
227+
EXPECT_NEAR(static_cast<double>(Real{GetX(massData.center)/1_m}),
228+
static_cast<double>(Real{GetX(center)/1_m}),
229+
1.0/1000000);
230+
EXPECT_NEAR(static_cast<double>(Real{GetY(massData.center)/1_m}),
231+
static_cast<double>(Real{GetY(center)/1_m}),
232+
1.0/1000000);
228233

229234
const auto diskMassData = playrho::d2::GetMassData(0.7_m, conf.density, center);
230-
EXPECT_EQ(massData, diskMassData);
235+
EXPECT_NEAR(static_cast<double>(Real{GetX(massData.center)/1_m}),
236+
static_cast<double>(Real{GetX(diskMassData.center)/1_m}),
237+
1.0/1000000);
238+
EXPECT_NEAR(static_cast<double>(Real{GetY(massData.center)/1_m}),
239+
static_cast<double>(Real{GetY(diskMassData.center)/1_m}),
240+
1.0/1000000);
241+
EXPECT_EQ(massData.mass, diskMassData.mass);
242+
EXPECT_EQ(massData.I, diskMassData.I);
231243
}
232244

233245
TEST(MultiShapeConf, AddConvexHullWithTwoPointsSameAsEdge)
@@ -260,12 +272,23 @@ TEST(MultiShapeConf, AddConvexHullWithTwoPointsSameAsEdge)
260272

261273
const auto massData = GetMassData(foo);
262274
EXPECT_NE(massData, defaultMassData);
263-
EXPECT_EQ(massData.center, (p0 + p1) / Real(2));
264-
275+
const auto expectedCenter = (p0 + p1) / Real(2);
276+
EXPECT_NEAR(static_cast<double>(Real{GetX(massData.center)/1_m}),
277+
static_cast<double>(Real{GetX(expectedCenter)/1_m}),
278+
1.0/1000000);
279+
EXPECT_NEAR(static_cast<double>(Real{GetY(massData.center)/1_m}),
280+
static_cast<double>(Real{GetY(expectedCenter)/1_m}),
281+
1.0/1000000);
282+
265283
const auto edgeMassData = playrho::d2::GetMassData(0.7_m, conf.density, p0, p1);
266-
EXPECT_EQ(massData.center, edgeMassData.center);
267-
/// @note Units of L^-2 M^-1 QP^2.
284+
EXPECT_NEAR(static_cast<double>(Real{GetX(massData.center)/1_m}),
285+
static_cast<double>(Real{GetX(edgeMassData.center)/1_m}),
286+
1.0/1000000);
287+
EXPECT_NEAR(static_cast<double>(Real{GetY(massData.center)/1_m}),
288+
static_cast<double>(Real{GetY(edgeMassData.center)/1_m}),
289+
1.0/1000000);
268290

291+
/// @note Units of L^-2 M^-1 QP^2.
269292
EXPECT_NEAR(static_cast<double>(Real{massData.I / (SquareMeter*1_kg/SquareRadian)}),
270293
static_cast<double>(Real{edgeMassData.I / (SquareMeter*1_kg/SquareRadian)}),
271294
228.4113/1000000.0);
@@ -319,7 +342,13 @@ TEST(MultiShapeConf, AddTwoConvexHullWithOnePoint)
319342

320343
const auto massData = GetMassData(foo);
321344
EXPECT_NE(massData, defaultMassData);
322-
EXPECT_EQ(massData.center, (p0 + p1) / Real(2));
345+
const auto expectedCenter = (p0 + p1) / Real(2);
346+
EXPECT_NEAR(static_cast<double>(Real{GetX(massData.center)/1_m}),
347+
static_cast<double>(Real{GetX(expectedCenter)/1_m}),
348+
1.0/1000000);
349+
EXPECT_NEAR(static_cast<double>(Real{GetY(massData.center)/1_m}),
350+
static_cast<double>(Real{GetY(expectedCenter)/1_m}),
351+
1.0/1000000);
323352

324353
const auto massDataP0 = playrho::d2::GetMassData(0.7_m, conf.density, p0);
325354
const auto massDataP1 = playrho::d2::GetMassData(0.7_m, conf.density, p1);

0 commit comments

Comments
 (0)