@series-inc/rundot-syncplay 6.0.0-rc.7 → 6.0.0-rc.9

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.
@@ -2686,6 +2686,8 @@ BroadphaseBounds bodyBounds(SolverOperation& operation, const Body& body) {
2686
2686
  (geometry.maxZ - geometry.minZ) / 2.0});
2687
2687
  }
2688
2688
 
2689
+ BroadphaseBounds queryProxyBounds(SolverOperation& operation, const Body& body);
2690
+
2689
2691
  bool boundsOverlap(const BroadphaseBounds& left, const BroadphaseBounds& right) {
2690
2692
  return left.minX <= right.maxX && right.minX <= left.maxX
2691
2693
  && left.minY <= right.maxY && right.minY <= left.maxY
@@ -2861,9 +2863,10 @@ public:
2861
2863
  }
2862
2864
 
2863
2865
  template <typename Callback>
2864
- void forEachPair(const Body*, Callback&& callback) {
2866
+ void forEachPair(const Body* bodies, Callback&& callback) {
2865
2867
  if (root == -1) return;
2866
2868
  for (std::uint32_t bodyIndex = 0; bodyIndex < bodyCount; bodyIndex += 1) {
2869
+ const bool bodyStatic = bodies && !bodies[bodyIndex].dynamic && !bodies[bodyIndex].kinematic;
2867
2870
  const BroadphaseBounds actualLeafBounds = actualBounds[bodyIndex];
2868
2871
  std::uint32_t matchCount = 0;
2869
2872
  queryStackCount = 1;
@@ -2874,6 +2877,7 @@ public:
2874
2877
  if (!boundsOverlap(actualLeafBounds, node.bounds)) continue;
2875
2878
  if (node.leaf) {
2876
2879
  if (node.bodyIndex > bodyIndex
2880
+ && !(bodyStatic && bodies && !bodies[node.bodyIndex].dynamic && !bodies[node.bodyIndex].kinematic)
2877
2881
  && boundsOverlap(actualLeafBounds, actualBounds[node.bodyIndex])) {
2878
2882
  queryMatches[matchCount++] = node.bodyIndex;
2879
2883
  }
@@ -2887,12 +2891,13 @@ public:
2887
2891
  }
2888
2892
  }
2889
2893
 
2890
- void collectPairs() {
2894
+ void collectPairs(const Body* bodies = nullptr) {
2891
2895
  pairCount = 0;
2892
2896
  pairOverflow = false;
2893
2897
  pairsReady = true;
2894
2898
  if (root == -1) return;
2895
2899
  for (std::uint32_t bodyIndex = 0; bodyIndex < bodyCount; bodyIndex += 1) {
2900
+ const bool bodyStatic = bodies && !bodies[bodyIndex].dynamic && !bodies[bodyIndex].kinematic;
2896
2901
  const BroadphaseBounds actualLeafBounds = nodes[leafNodes[bodyIndex]].bounds;
2897
2902
  const std::uint32_t pairStart = pairCount;
2898
2903
  queryStackCount = 1;
@@ -2903,6 +2908,7 @@ public:
2903
2908
  if (!boundsOverlap(actualLeafBounds, node.bounds)) continue;
2904
2909
  if (node.leaf) {
2905
2910
  if (node.bodyIndex > bodyIndex
2911
+ && !(bodyStatic && bodies && !bodies[node.bodyIndex].dynamic && !bodies[node.bodyIndex].kinematic)
2906
2912
  && boundsOverlap(actualLeafBounds, nodes[leafNodes[node.bodyIndex]].bounds)) {
2907
2913
  if (pairCount >= pairCapacity) {
2908
2914
  pairOverflow = true;
@@ -3342,9 +3348,11 @@ void forEachSweepPair(SolverOperation& operation, const Body* bodies, std::uint3
3342
3348
  prepareBroadphase(operation, bodies, bodyCount);
3343
3349
  for (std::uint32_t leftOrder = 0; leftOrder < bodyCount; leftOrder += 1) {
3344
3350
  const std::uint32_t left = operation.storage.broadphaseOrder[leftOrder];
3351
+ const bool leftStatic = !bodies[left].dynamic && !bodies[left].kinematic;
3345
3352
  for (std::uint32_t rightOrder = leftOrder + 1; rightOrder < bodyCount; rightOrder += 1) {
3346
3353
  const std::uint32_t right = operation.storage.broadphaseOrder[rightOrder];
3347
3354
  if (operation.storage.broadphaseBounds[right].minX > operation.storage.broadphaseBounds[left].maxX) break;
3355
+ if (leftStatic && !bodies[right].dynamic && !bodies[right].kinematic) continue;
3348
3356
  if (boundsOverlap(operation.storage.broadphaseBounds[left], operation.storage.broadphaseBounds[right])) {
3349
3357
  callback(std::min(left, right), std::max(left, right));
3350
3358
  }
@@ -3358,9 +3366,11 @@ void collectSweepPairs(SolverOperation& operation, const Body* bodies, std::uint
3358
3366
  operation.storage.broadphasePairOverflow = false;
3359
3367
  for (std::uint32_t leftOrder = 0; leftOrder < bodyCount; leftOrder += 1) {
3360
3368
  const std::uint32_t left = operation.storage.broadphaseOrder[leftOrder];
3369
+ const bool leftStatic = !bodies[left].dynamic && !bodies[left].kinematic;
3361
3370
  for (std::uint32_t rightOrder = leftOrder + 1; rightOrder < bodyCount; rightOrder += 1) {
3362
3371
  const std::uint32_t right = operation.storage.broadphaseOrder[rightOrder];
3363
3372
  if (operation.storage.broadphaseBounds[right].minX > operation.storage.broadphaseBounds[left].maxX) break;
3373
+ if (leftStatic && !bodies[right].dynamic && !bodies[right].kinematic) continue;
3364
3374
  if (!boundsOverlap(operation.storage.broadphaseBounds[left], operation.storage.broadphaseBounds[right])) continue;
3365
3375
  if (operation.storage.broadphasePairCount >= operation.storage.broadphasePairFirst.size()) {
3366
3376
  operation.storage.broadphasePairOverflow = true;
@@ -3684,9 +3694,15 @@ Collision collide(SolverOperation& operation, const Body& a, const Body& b) {
3684
3694
  return boxBox(a, b);
3685
3695
  }
3686
3696
  if (a.shape == ShapeKind::Compound && (a.geometryFormat == 4 || a.geometryFormat == 5)) {
3697
+ const BroadphaseBounds boundsA = queryProxyBounds(operation, a);
3698
+ const BroadphaseBounds boundsB = queryProxyBounds(operation, b);
3699
+ if (!boundsOverlap(boundsA, boundsB)) return {};
3700
+
3687
3701
  Collision best;
3688
3702
  for (std::uint32_t child = 0; child < compoundChildCount(operation, a); child += 1) {
3689
3703
  const Body childBody = compoundChildBody(operation, a, child);
3704
+ const BroadphaseBounds childBounds = queryProxyBounds(operation, childBody);
3705
+ if (!boundsOverlap(childBounds, boundsB)) continue;
3690
3706
  const Collision candidate = collide(operation, childBody, b);
3691
3707
  if (candidate.hit && (!best.hit || candidate.penetration > best.penetration)) best = candidate;
3692
3708
  }
@@ -6891,10 +6907,25 @@ std::int32_t runOverlapQuery(SolverOperation& operation,
6891
6907
  const double length = solverSqrt(dotVec3(rawDirection, rawDirection));
6892
6908
  const Vec3 direction = scaleVec3(rawDirection, 1.0 / length);
6893
6909
  const double maxDistance = queryData[17];
6910
+ const BroadphaseBounds baseQueryBounds = queryProxyBounds(operation, queryBody);
6911
+ BroadphaseBounds queryBounds = baseQueryBounds;
6912
+ if (cast && maxDistance > 0.0) {
6913
+ const Vec3 sweepDelta = scaleVec3(direction, maxDistance);
6914
+ if (sweepDelta.x < 0.0) queryBounds.minX += sweepDelta.x; else queryBounds.maxX += sweepDelta.x;
6915
+ if (sweepDelta.y < 0.0) queryBounds.minY += sweepDelta.y; else queryBounds.maxY += sweepDelta.y;
6916
+ if (sweepDelta.z < 0.0) queryBounds.minZ += sweepDelta.z; else queryBounds.maxZ += sweepDelta.z;
6917
+ }
6894
6918
  for (std::uint32_t index = 0; index < bodyCount; index += 1) {
6895
6919
  if (static_cast<std::int32_t>(queryData[20]) == static_cast<std::int32_t>(index)
6896
6920
  || !queryBodyAllowed(operation.storage.soaBodies[index], queryData)) continue;
6897
6921
  Body& target = operation.storage.soaBodies[index];
6922
+ // Mesh, hull, and heightfield queries charge geometry work before a miss.
6923
+ // A body cull would hide that cost. Compounds and primitive shapes still cull.
6924
+ if (target.shape != ShapeKind::Mesh && target.shape != ShapeKind::Hull
6925
+ && target.shape != ShapeKind::Heightfield) {
6926
+ const BroadphaseBounds targetBounds = queryProxyBounds(operation, target);
6927
+ if (!boundsOverlap(queryBounds, targetBounds)) continue;
6928
+ }
6898
6929
  RayHit result;
6899
6930
  const bool useGeometryProxy = (isGeometryShape(queryBody.shape) && isGeometryShape(target.shape))
6900
6931
  || (cast && (target.shape == ShapeKind::Mesh && target.geometryCount % 3 != 0))
@@ -7435,6 +7466,7 @@ void resolveSoAContacts(SolverOperation& operation, Body* bodies, std::uint32_t
7435
7466
  std::uint32_t preparedBegin,
7436
7467
  std::uint32_t preparedEnd) {
7437
7468
  if (initialize && collisionDisabled(operation, first, second)) return;
7469
+ if (initialize && !bodies[first].dynamic && !bodies[first].kinematic && !bodies[second].dynamic && !bodies[second].kinematic) return;
7438
7470
  if (!solveVelocity) {
7439
7471
  if (resolveContactPair(operation, bodies[first], bodies[second], options,
7440
7472
  nullptr, nullptr, nullptr, nullptr, nullptr, true,
@@ -7683,7 +7715,7 @@ void resolveSoAContacts(SolverOperation& operation, Body* bodies, std::uint32_t
7683
7715
  if (beginSubstep) {
7684
7716
  operation.storage.broadphaseTree->ensure(operation, bodies, bodyCount);
7685
7717
  if (!operation.storage.broadphaseTree->pairsAreReady()) {
7686
- operation.storage.broadphaseTree->collectPairs();
7718
+ operation.storage.broadphaseTree->collectPairs(bodies);
7687
7719
  }
7688
7720
  }
7689
7721
  for (std::uint32_t iteration = 0; iteration < velocityIterations; iteration += 1) {
@@ -7839,12 +7871,15 @@ void updateSleepingStates(SolverOperation& operation,
7839
7871
  continue;
7840
7872
  }
7841
7873
  const double threshold = body.sleepThreshold;
7842
- const double speedSquared = body.vx * body.vx + body.vy * body.vy + body.vz * body.vz
7843
- + body.angularVelX * body.angularVelX
7874
+ const double linearSpeedSquared = body.vx * body.vx + body.vy * body.vy + body.vz * body.vz;
7875
+ const double angularSpeedSquared = body.angularVelX * body.angularVelX
7844
7876
  + body.angularVelY * body.angularVelY
7845
7877
  + body.angularVelZ * body.angularVelZ;
7878
+ const double angularThreshold = threshold * 2.0;
7846
7879
  if (!body.sleepEnabled || threshold <= 0.0
7847
- || speedSquared > threshold * threshold || !finite(speedSquared)) {
7880
+ || linearSpeedSquared > threshold * threshold
7881
+ || angularSpeedSquared > angularThreshold * angularThreshold
7882
+ || !finite(linearSpeedSquared) || !finite(angularSpeedSquared)) {
7848
7883
  body.sleepTime = 0.0;
7849
7884
  operation.storage.sleepCanSleep[root] = false;
7850
7885
  continue;