@series-inc/rundot-syncplay 6.0.0-rc.45 → 6.0.0-rc.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,7 +11,14 @@
11
11
  #include <array>
12
12
  #include <bit>
13
13
  #include <cmath>
14
+ #include <cstdlib>
14
15
  #include <cstring>
16
+
17
+ #if defined(RUNDOT_PHYSICS_DEBUG_INVARIANTS)
18
+ #define RUNDOT_PHYSICS_DEBUG_ASSERT(expr) do { if (!(expr)) { std::abort(); } } while (0)
19
+ #else
20
+ #define RUNDOT_PHYSICS_DEBUG_ASSERT(expr) ((void)0)
21
+ #endif
15
22
  #include <exception>
16
23
  #include <functional>
17
24
  #include <limits>
@@ -3813,6 +3820,7 @@ BroadphaseBounds orientedBounds(const Body& body, const Vec3& localCenter, const
3813
3820
  }
3814
3821
 
3815
3822
  constexpr std::uint32_t kBroadphasePairCapacity = 1u << 20;
3823
+ enum class BroadphasePairOwner : std::uint8_t { None, Sweep, Tree };
3816
3824
  constexpr std::uint32_t kJointCapacity = 10000;
3817
3825
  static_assert(kJointCapacity <= std::numeric_limits<std::uint16_t>::max());
3818
3826
  constexpr std::uint32_t kContactTelemetryTableCapacity = 1u << 18;
@@ -3835,6 +3843,7 @@ struct SolverStorage {
3835
3843
  std::uint32_t broadphaseOrderCount = 0;
3836
3844
  std::uint32_t broadphasePairCount = 0;
3837
3845
  bool broadphasePairOverflow = false;
3846
+ BroadphasePairOwner broadphasePairOwner = BroadphasePairOwner::None;
3838
3847
  std::vector<Body> soaBodies;
3839
3848
  std::vector<BodyMotionEpoch> motionEpochs;
3840
3849
  std::vector<BodyPose> stagedMotionPoses;
@@ -4024,15 +4033,14 @@ struct DynamicAabbTreeNode {
4024
4033
 
4025
4034
  class FixedDynamicAabbTree {
4026
4035
  public:
4027
- void prepare(std::uint32_t count, std::uint32_t maximumPairs) {
4028
- actualBounds.resize(count);
4029
- queryMatches.resize(count);
4030
- nodes.resize(static_cast<std::size_t>(count) * 2);
4031
- leafNodes.resize(count);
4032
- queryStack.resize(static_cast<std::size_t>(count) * 2);
4033
- pairFirst.resize(maximumPairs);
4034
- pairSecond.resize(maximumPairs);
4035
- pairCapacity = maximumPairs;
4036
+ void prepare(std::uint32_t count, std::span<std::uint32_t> first, std::span<std::uint32_t> second) {
4037
+ if (actualBounds.size() < count) actualBounds.resize(count);
4038
+ if (queryMatches.size() < count) queryMatches.resize(count);
4039
+ if (nodes.size() < static_cast<std::size_t>(count) * 2) nodes.resize(static_cast<std::size_t>(count) * 2);
4040
+ if (leafNodes.size() < count) leafNodes.resize(count);
4041
+ if (queryStack.size() < static_cast<std::size_t>(count) * 2) queryStack.resize(static_cast<std::size_t>(count) * 2);
4042
+ pairFirst = first;
4043
+ pairSecond = second;
4036
4044
  }
4037
4045
 
4038
4046
  void reset(std::uint32_t count) {
@@ -4045,7 +4053,7 @@ public:
4045
4053
  }
4046
4054
 
4047
4055
  void rebuild(std::span<const BroadphaseBounds> bounds) {
4048
- prepare(static_cast<std::uint32_t>(bounds.size()), 0);
4056
+ prepare(static_cast<std::uint32_t>(bounds.size()), {}, {});
4049
4057
  reset(static_cast<std::uint32_t>(bounds.size()));
4050
4058
  std::copy(bounds.begin(), bounds.end(), actualBounds.begin());
4051
4059
  for (std::uint32_t index = 0; index < bounds.size(); index += 1) {
@@ -4179,6 +4187,7 @@ public:
4179
4187
  pairOverflow = false;
4180
4188
  pairsReady = true;
4181
4189
  if (root == -1) return;
4190
+ const std::uint32_t pairCapacity = static_cast<std::uint32_t>(std::min(pairFirst.size(), pairSecond.size()));
4182
4191
  for (std::uint32_t bodyIndex = 0; bodyIndex < bodyCount; bodyIndex += 1) {
4183
4192
  const bool bodyStatic = bodies && !bodies[bodyIndex].dynamic && !bodies[bodyIndex].kinematic;
4184
4193
  const BroadphaseBounds actualLeafBounds = nodes[leafNodes[bodyIndex]].bounds;
@@ -4190,9 +4199,9 @@ public:
4190
4199
  const DynamicAabbTreeNode& node = nodes[index];
4191
4200
  if (!boundsOverlap(actualLeafBounds, node.bounds)) continue;
4192
4201
  if (node.leaf) {
4202
+ RUNDOT_PHYSICS_DEBUG_ASSERT(leafNodes[node.bodyIndex] == index);
4193
4203
  if (node.bodyIndex > bodyIndex
4194
- && !(bodyStatic && bodies && !bodies[node.bodyIndex].dynamic && !bodies[node.bodyIndex].kinematic)
4195
- && boundsOverlap(actualLeafBounds, nodes[leafNodes[node.bodyIndex]].bounds)) {
4204
+ && !(bodyStatic && bodies && !bodies[node.bodyIndex].dynamic && !bodies[node.bodyIndex].kinematic)) {
4196
4205
  if (pairCount >= pairCapacity) {
4197
4206
  pairOverflow = true;
4198
4207
  return;
@@ -4249,9 +4258,7 @@ public:
4249
4258
  + static_cast<std::uint64_t>(queryMatches.capacity()) * sizeof(std::uint32_t)
4250
4259
  + static_cast<std::uint64_t>(nodes.capacity()) * sizeof(DynamicAabbTreeNode)
4251
4260
  + static_cast<std::uint64_t>(leafNodes.capacity()) * sizeof(std::int32_t)
4252
- + static_cast<std::uint64_t>(queryStack.capacity()) * sizeof(std::int32_t)
4253
- + static_cast<std::uint64_t>(pairFirst.capacity()) * sizeof(std::uint32_t)
4254
- + static_cast<std::uint64_t>(pairSecond.capacity()) * sizeof(std::uint32_t);
4261
+ + static_cast<std::uint64_t>(queryStack.capacity()) * sizeof(std::int32_t);
4255
4262
  }
4256
4263
 
4257
4264
  private:
@@ -4392,9 +4399,8 @@ private:
4392
4399
  std::vector<DynamicAabbTreeNode> nodes;
4393
4400
  std::vector<std::int32_t> leafNodes;
4394
4401
  std::vector<std::int32_t> queryStack;
4395
- std::vector<std::uint32_t> pairFirst;
4396
- std::vector<std::uint32_t> pairSecond;
4397
- std::uint32_t pairCapacity = 0;
4402
+ std::span<std::uint32_t> pairFirst;
4403
+ std::span<std::uint32_t> pairSecond;
4398
4404
  std::uint32_t bodyCount = 0;
4399
4405
  std::uint32_t nodeCount = 0;
4400
4406
  std::uint32_t queryStackCount = 0;
@@ -4419,6 +4425,7 @@ void SolverStorage::invalidate() noexcept {
4419
4425
  broadphaseOrderCount = 0;
4420
4426
  broadphasePairCount = 0;
4421
4427
  broadphasePairOverflow = false;
4428
+ broadphasePairOwner = BroadphasePairOwner::None;
4422
4429
  contactTelemetryCount = 0;
4423
4430
  worldContactOutputCount = 0;
4424
4431
  contactConstraintCount = 0;
@@ -4582,7 +4589,10 @@ void prepareStepStorage(SolverStorage& storage, std::uint32_t bodyCount, std::ui
4582
4589
  storage.sleepHasKinematic.resize(bodyCount);
4583
4590
  storage.sleepHasStaticAnchor.resize(bodyCount);
4584
4591
  storage.bodyJointAffected.assign(bodyCount, 0);
4585
- storage.broadphaseTree->prepare(bodyCount, pairCapacity);
4592
+ storage.broadphaseTree->prepare(
4593
+ bodyCount,
4594
+ std::span<std::uint32_t>(storage.broadphasePairFirst),
4595
+ std::span<std::uint32_t>(storage.broadphasePairSecond));
4586
4596
  }
4587
4597
 
4588
4598
  void prepareQueryStorage(SolverStorage& storage, std::uint32_t bodyCount) {
@@ -4676,6 +4686,7 @@ void collectSweepPairs(SolverOperation& operation, const Body* bodies, std::uint
4676
4686
  prepareBroadphase(operation, bodies, bodyCount);
4677
4687
  operation.storage.broadphasePairCount = 0;
4678
4688
  operation.storage.broadphasePairOverflow = false;
4689
+ operation.storage.broadphasePairOwner = BroadphasePairOwner::Sweep;
4679
4690
  for (std::uint32_t leftOrder = 0; leftOrder < bodyCount; leftOrder += 1) {
4680
4691
  const std::uint32_t left = operation.storage.broadphaseOrder[leftOrder];
4681
4692
  const bool leftStatic = !bodies[left].dynamic && !bodies[left].kinematic;
@@ -4697,6 +4708,7 @@ void collectSweepPairs(SolverOperation& operation, const Body* bodies, std::uint
4697
4708
 
4698
4709
  template <typename Callback>
4699
4710
  void forEachCollectedSweepPair(SolverOperation& operation, Callback&& callback) {
4711
+ RUNDOT_PHYSICS_DEBUG_ASSERT(operation.storage.broadphasePairOwner == BroadphasePairOwner::Sweep);
4700
4712
  for (std::uint32_t index = 0; index < operation.storage.broadphasePairCount; index += 1) {
4701
4713
  callback(operation.storage.broadphasePairFirst[index], operation.storage.broadphasePairSecond[index]);
4702
4714
  }
@@ -9808,6 +9820,16 @@ void finalizeContactCache(SolverOperation& operation) {
9808
9820
  }
9809
9821
 
9810
9822
 
9823
+ bool treePairsReady(const SolverOperation& operation) {
9824
+ return operation.storage.broadphasePairOwner == BroadphasePairOwner::Tree
9825
+ && operation.storage.broadphaseTree->pairsAreReady();
9826
+ }
9827
+
9828
+ void collectTreePairs(SolverOperation& operation, const Body* bodies) {
9829
+ operation.storage.broadphaseTree->collectPairs(bodies);
9830
+ operation.storage.broadphasePairOwner = BroadphasePairOwner::Tree;
9831
+ }
9832
+
9811
9833
  void discoverContactWakes(
9812
9834
  SolverOperation& operation, Body* bodies, std::uint32_t bodyCount) {
9813
9835
  const auto visit = [&](std::uint32_t first, std::uint32_t second) {
@@ -9841,6 +9863,7 @@ void discoverContactWakes(
9841
9863
  if (operation.storage.broadphaseTree->pairsOverflowed()) {
9842
9864
  operation.storage.broadphaseTree->forEachPair(bodies, visit);
9843
9865
  } else {
9866
+ RUNDOT_PHYSICS_DEBUG_ASSERT(operation.storage.broadphasePairOwner == BroadphasePairOwner::Tree);
9844
9867
  operation.storage.broadphaseTree->forEachCollectedPair(visit);
9845
9868
  }
9846
9869
  }
@@ -10241,8 +10264,8 @@ void resolveSoAContacts(SolverOperation& operation, Body* bodies, std::uint32_t
10241
10264
  }
10242
10265
  if (beginSubstep) {
10243
10266
  operation.storage.broadphaseTree->ensure(operation, bodies, bodyCount);
10244
- if (!operation.storage.broadphaseTree->pairsAreReady()) {
10245
- operation.storage.broadphaseTree->collectPairs(bodies);
10267
+ if (!treePairsReady(operation)) {
10268
+ collectTreePairs(operation, bodies);
10246
10269
  }
10247
10270
  }
10248
10271
  for (std::uint32_t iteration = 0; iteration < velocityIterations; iteration += 1) {
@@ -10255,6 +10278,7 @@ void resolveSoAContacts(SolverOperation& operation, Body* bodies, std::uint32_t
10255
10278
  if (operation.storage.broadphaseTree->pairsOverflowed()) {
10256
10279
  operation.storage.broadphaseTree->forEachPair(bodies, solveCollectedPair);
10257
10280
  } else {
10281
+ RUNDOT_PHYSICS_DEBUG_ASSERT(operation.storage.broadphasePairOwner == BroadphasePairOwner::Tree);
10258
10282
  operation.storage.broadphaseTree->forEachCollectedPair(solveCollectedPair);
10259
10283
  }
10260
10284
  } else {
@@ -10569,8 +10593,8 @@ void updateJointIslandMembership(SolverOperation& operation,
10569
10593
  collectSweepPairs(operation, bodies, bodyCount);
10570
10594
  } else {
10571
10595
  operation.storage.broadphaseTree->ensure(operation, bodies, bodyCount);
10572
- if (!operation.storage.broadphaseTree->pairsAreReady()) {
10573
- operation.storage.broadphaseTree->collectPairs(bodies);
10596
+ if (!treePairsReady(operation)) {
10597
+ collectTreePairs(operation, bodies);
10574
10598
  }
10575
10599
  }
10576
10600
 
@@ -10619,6 +10643,7 @@ void updateJointIslandMembership(SolverOperation& operation,
10619
10643
  if (operation.storage.broadphaseTree->pairsOverflowed()) {
10620
10644
  operation.storage.broadphaseTree->forEachPair(bodies, unionDynamicPair);
10621
10645
  } else {
10646
+ RUNDOT_PHYSICS_DEBUG_ASSERT(operation.storage.broadphasePairOwner == BroadphasePairOwner::Tree);
10622
10647
  operation.storage.broadphaseTree->forEachCollectedPair(unionDynamicPair);
10623
10648
  }
10624
10649
  }
@@ -10653,6 +10678,7 @@ void updateJointIslandMembership(SolverOperation& operation,
10653
10678
  if (operation.storage.broadphaseTree->pairsOverflowed()) {
10654
10679
  operation.storage.broadphaseTree->forEachPair(bodies, markMovingNeighbor);
10655
10680
  } else {
10681
+ RUNDOT_PHYSICS_DEBUG_ASSERT(operation.storage.broadphasePairOwner == BroadphasePairOwner::Tree);
10656
10682
  operation.storage.broadphaseTree->forEachCollectedPair(markMovingNeighbor);
10657
10683
  }
10658
10684
  }