@series-inc/rundot-syncplay 6.0.0-rc.13 → 6.0.0-rc.14

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.
@@ -239,7 +239,7 @@ Collision observeGeometry(SolverOperation& operation,const Body& capsule,const B
239
239
  if(node.count<6)throw TriangleNativeFailure{tp::Failure::InvalidInput};const auto base=std::size_t(node.offset)*3;const auto countValue=payload[base+17];
240
240
  if(!finite(countValue)||countValue<1||countValue>node.count/6||std::floor(countValue)!=countValue)throw TriangleNativeFailure{tp::Failure::InvalidInput};
241
241
  const auto count=std::uint32_t(countValue);std::uint32_t previousEnd=count*6;
242
- for(std::uint32_t child=0;child<count;++child){work(operation);const auto at=base+std::size_t(child)*18;
242
+ for(std::uint32_t child=0;child<count;++child){const auto at=base+std::size_t(child)*18;
243
243
  auto code=[&](unsigned lane){const auto value=payload[at+lane];if(!finite(value)||value<0||value>std::numeric_limits<std::uint32_t>::max()||std::floor(value)!=value)throw TriangleNativeFailure{tp::Failure::InvalidInput};return std::uint32_t(value);};
244
244
  const auto kind=code(0),offset=code(13),size=code(14),format=code(15);
245
245
  if(kind>11||(payload[at+16]!=0.&&payload[at+16]!=1.)||code(17)!=count)throw TriangleNativeFailure{tp::Failure::InvalidInput};
@@ -247,6 +247,18 @@ Collision observeGeometry(SolverOperation& operation,const Body& capsule,const B
247
247
  if(complex){if(offset<previousEnd||offset>node.count||size>node.count-offset)throw TriangleNativeFailure{tp::Failure::InvalidInput};previousEnd=offset+size;}
248
248
  else if(offset||size||format)throw TriangleNativeFailure{tp::Failure::InvalidInput};
249
249
  const Vec3 translation{sum(operation,{node.translation.x,payload[at+1]}),sum(operation,{node.translation.y,payload[at+2]}),sum(operation,{node.translation.z,payload[at+3]})};
250
+ if(!complex){
251
+ const auto translated=rotateByOrientation(geometry,translation);
252
+ const double cX=geometry.x+geometry.shapeOffsetX+translated.x-(capsule.x+capsule.shapeOffsetX);
253
+ const double cY=geometry.y+geometry.shapeOffsetY+translated.y-(capsule.y+capsule.shapeOffsetY);
254
+ const double cZ=geometry.z+geometry.shapeOffsetZ+translated.z-(capsule.z+capsule.shapeOffsetZ);
255
+ const double p0=payload[at+4],p1=payload[at+5],p2=payload[at+6];
256
+ const double childRadius=kind==static_cast<std::uint32_t>(ShapeKind::Box)?std::sqrt(p0*p0+p1*p1+p2*p2):(kind==static_cast<std::uint32_t>(ShapeKind::Sphere)?p0:(p0+p1));
257
+ const double capsuleRadius=capsule.shape0+capsule.shape1;
258
+ const double maxDist=childRadius+capsuleRadius;
259
+ if(cX*cX+cY*cY+cZ*cZ>maxDist*maxDist)continue;
260
+ }
261
+ work(operation);
250
262
  if(child>std::uint32_t(std::numeric_limits<std::int32_t>::max()))throw TriangleNativeFailure{tp::Failure::FeatureCapacity};
251
263
  append(operation,pending,Node{ShapeKind(kind),complex?node.offset+offset:node.offset+child*6,size,format,translation,{payload[at+4],payload[at+5],payload[at+6]},node.outerChild<0?std::int32_t(child):node.outerChild});
252
264
  }continue;
@@ -257,6 +269,11 @@ Collision observeGeometry(SolverOperation& operation,const Body& capsule,const B
257
269
  const auto translated=rotateByOrientation(geometry,node.translation);
258
270
  child.x=sum(operation,{geometry.x,geometry.shapeOffsetX,translated.x,-capsule.x,-capsule.shapeOffsetX});child.y=sum(operation,{geometry.y,geometry.shapeOffsetY,translated.y,-capsule.y,-capsule.shapeOffsetY});child.z=sum(operation,{geometry.z,geometry.shapeOffsetZ,translated.z,-capsule.z,-capsule.shapeOffsetZ});
259
271
  child.shapeOffsetX=child.shapeOffsetY=child.shapeOffsetZ=0.;
272
+ const double p0=child.shape0,p1=child.shape1,p2=child.shape2;
273
+ const double childRadius=child.shape==ShapeKind::Box?std::sqrt(p0*p0+p1*p1+p2*p2):(child.shape==ShapeKind::Sphere?p0:(p0+p1));
274
+ const double capsuleRadius=capsule.shape0+capsule.shape1;
275
+ const double maxDist=childRadius+capsuleRadius;
276
+ if(child.x*child.x+child.y*child.y+child.z*child.z>maxDist*maxDist)continue;
260
277
  auto collision=node.kind==ShapeKind::Sphere?capsuleSphere(localCapsule,child):node.kind==ShapeKind::Box?capsuleBox(localCapsule,child):capsuleCapsule(localCapsule,child);
261
278
  if(collision.hit){if(!collision.pointCount){collision.pointCount=1;collision.points[0]={collision.pointX,collision.pointY,collision.pointZ};}
262
279
  auto& basis=collision.coordinates.emplace<TriangleManifoldBasis>();collision.geometryChildIndex=node.outerChild;basis.anchor={capsule.x,capsule.y,capsule.z};basis.shapeOffset={capsule.shapeOffsetX,capsule.shapeOffsetY,capsule.shapeOffsetZ};
@@ -2006,13 +2006,7 @@ Collision geometryBox(SolverOperation& operation, const Body& geometry, const Bo
2006
2006
  }
2007
2007
  if (geometry.shape == ShapeKind::Compound
2008
2008
  && (geometry.geometryFormat == 4 || geometry.geometryFormat == 5 || geometry.geometryFormat == 6)) {
2009
- Collision best;
2010
- for (std::uint32_t child = 0; child < compoundChildCount(operation, geometry); child += 1) {
2011
- const Body childBody = compoundChildBody(operation, geometry, child);
2012
- const Collision candidate = collide(operation, childBody, box);
2013
- if (candidate.hit && (!best.hit || candidate.penetration > best.penetration)) best = candidate;
2014
- }
2015
- return best;
2009
+ return collide(operation, geometry, box);
2016
2010
  }
2017
2011
  if (geometry.shape == ShapeKind::Compound && geometry.geometryFormat == 1) {
2018
2012
  Collision best;
@@ -3748,11 +3742,128 @@ Collision capsuleBox(const Body& capsule, const Body& box) {
3748
3742
  #include "capsule_triangle_native.inc"
3749
3743
 
3750
3744
  Collision collide(SolverOperation& operation, const Body& a, const Body& b) {
3745
+
3751
3746
  if (operation.materialMotionEpochs != nullptr) return collideMaterialCurrent(operation, a, b);
3752
3747
  const auto triangleGeometry=[](const Body& body){return body.shape==ShapeKind::Mesh||body.shape==ShapeKind::Heightfield
3753
3748
  ||(body.shape==ShapeKind::Compound&&body.geometryFormat==5);};
3754
3749
  if(a.shape==ShapeKind::Capsule&&triangleGeometry(b))return triangle_adapter_private::observeGeometry(operation,a,b);
3755
3750
  if(b.shape==ShapeKind::Capsule&&triangleGeometry(a))return flipCollision(triangle_adapter_private::observeGeometry(operation,b,a));
3751
+ if (a.shape == ShapeKind::Compound && (a.geometryFormat == 4 || a.geometryFormat == 5 || a.geometryFormat == 6)) {
3752
+ const BroadphaseBounds boundsA = queryProxyBounds(operation, a);
3753
+ const BroadphaseBounds boundsB = queryProxyBounds(operation, b);
3754
+ if (!boundsOverlap(boundsA, boundsB)) return {};
3755
+
3756
+ Collision best;
3757
+ std::int32_t bestChild = -1;
3758
+ struct CandidateContact {
3759
+ std::uint32_t childIndex = 0;
3760
+ Collision collision;
3761
+ };
3762
+ std::vector<CandidateContact> candidates;
3763
+ candidates.reserve(32);
3764
+
3765
+ for (std::uint32_t child = 0; child < compoundChildCount(operation, a); child += 1) {
3766
+ const Body childBody = compoundChildBody(operation, a, child);
3767
+ const BroadphaseBounds childBounds = queryProxyBounds(operation, childBody);
3768
+ if (!boundsOverlap(childBounds, boundsB)) continue;
3769
+ const Collision candidate = collide(operation, childBody, b);
3770
+ if (candidate.hit) {
3771
+ if (!best.hit || candidate.penetration > best.penetration) {
3772
+ best = candidate;
3773
+ bestChild = static_cast<std::int32_t>(child);
3774
+ }
3775
+ candidates.push_back({child, candidate});
3776
+ }
3777
+ }
3778
+ if (!best.hit) return {};
3779
+ if (bestChild >= 0) best.geometryChildIndex = bestChild;
3780
+ if (candidates.size() <= 1) return best;
3781
+
3782
+ const Vec3 primaryNormal{best.nx, best.ny, best.nz};
3783
+ struct MergedPoint {
3784
+ std::array<double, 3> pt;
3785
+ std::uint32_t featureId;
3786
+ double depth;
3787
+ std::uint32_t childIndex;
3788
+ };
3789
+ std::vector<MergedPoint> collected;
3790
+ collected.reserve(64);
3791
+
3792
+ for (std::size_t cIdx = 0; cIdx < candidates.size(); cIdx += 1) {
3793
+ const auto& entry = candidates[cIdx];
3794
+ const Collision& c = entry.collision;
3795
+ const Vec3 cNormal{c.nx, c.ny, c.nz};
3796
+ if (dotVec3(primaryNormal, cNormal) < 0.98) continue;
3797
+
3798
+ const std::uint32_t pCount = (c.pointCount == 0) ? 1u : std::min<std::uint32_t>(c.pointCount, 4u);
3799
+ for (std::uint32_t p = 0; p < pCount; p += 1) {
3800
+ std::array<double, 3> pos{};
3801
+ if (c.pointCount > 0) {
3802
+ pos = c.points[p];
3803
+ } else {
3804
+ pos = {c.pointX, c.pointY, c.pointZ};
3805
+ }
3806
+ const std::uint32_t rawFeature = (c.pointCount > 0) ? c.featureIds[p] : 0u;
3807
+ const std::uint32_t namespacedFeature = (rawFeature * 16777619u) ^ ((entry.childIndex + 1u) * 2166136261u) ^ (p * 374761393u);
3808
+ collected.push_back({pos, namespacedFeature, c.penetration, entry.childIndex});
3809
+ }
3810
+ }
3811
+
3812
+ if (collected.size() <= 1) return best;
3813
+
3814
+ std::array<std::uint32_t, 4> selectedIndices{};
3815
+ std::vector<std::uint8_t> used(collected.size(), 0);
3816
+ std::uint32_t selectedCount = 0;
3817
+
3818
+ while (selectedCount < std::min<std::uint32_t>(4, static_cast<std::uint32_t>(collected.size()))) {
3819
+ std::uint32_t bestIdx = 0;
3820
+ double bestScore = -1.0;
3821
+ bool found = false;
3822
+ for (std::uint32_t index = 0; index < collected.size(); index += 1) {
3823
+ if (used[index] != 0) continue;
3824
+ double score = collected[index].depth * collected[index].depth;
3825
+ if (selectedCount != 0) {
3826
+ score = std::numeric_limits<double>::infinity();
3827
+ const Vec3 ptA{collected[index].pt[0], collected[index].pt[1], collected[index].pt[2]};
3828
+ for (std::uint32_t chosen = 0; chosen < selectedCount; chosen += 1) {
3829
+ const auto& sel = collected[selectedIndices[chosen]];
3830
+ const Vec3 ptB{sel.pt[0], sel.pt[1], sel.pt[2]};
3831
+ const Vec3 delta = subtractVec3(ptA, ptB);
3832
+ score = std::min(score, dotVec3(delta, delta));
3833
+ }
3834
+ }
3835
+ if (!found || score > bestScore
3836
+ || (score == bestScore
3837
+ && collected[index].featureId < collected[bestIdx].featureId)) {
3838
+ bestIdx = index;
3839
+ bestScore = score;
3840
+ found = true;
3841
+ }
3842
+ }
3843
+ selectedIndices[selectedCount++] = bestIdx;
3844
+ used[bestIdx] = 1;
3845
+ }
3846
+
3847
+ best.pointCount = selectedCount;
3848
+ double avgX = 0.0, avgY = 0.0, avgZ = 0.0;
3849
+ for (std::uint32_t s = 0; s < selectedCount; s += 1) {
3850
+ best.points[s] = collected[selectedIndices[s]].pt;
3851
+ best.featureIds[s] = collected[selectedIndices[s]].featureId;
3852
+ avgX += collected[selectedIndices[s]].pt[0];
3853
+ avgY += collected[selectedIndices[s]].pt[1];
3854
+ avgZ += collected[selectedIndices[s]].pt[2];
3855
+ }
3856
+ const double invCount = 1.0 / static_cast<double>(selectedCount);
3857
+ best.pointX = avgX * invCount;
3858
+ best.pointY = avgY * invCount;
3859
+ best.pointZ = avgZ * invCount;
3860
+
3861
+ return best;
3862
+ }
3863
+ if (b.shape == ShapeKind::Compound && (b.geometryFormat == 4 || b.geometryFormat == 5 || b.geometryFormat == 6)) {
3864
+ const Collision result = collide(operation, b, a);
3865
+ return flipCollision(result);
3866
+ }
3756
3867
  if (a.shape == ShapeKind::Sphere && b.shape == ShapeKind::Sphere) {
3757
3868
  return sphereSphere(a, b);
3758
3869
  }
@@ -3812,25 +3923,7 @@ Collision collide(SolverOperation& operation, const Body& a, const Body& b) {
3812
3923
  if (a.shape == ShapeKind::Box && b.shape == ShapeKind::Box) {
3813
3924
  return boxBox(a, b);
3814
3925
  }
3815
- if (a.shape == ShapeKind::Compound && (a.geometryFormat == 4 || a.geometryFormat == 5 || a.geometryFormat == 6)) {
3816
- const BroadphaseBounds boundsA = queryProxyBounds(operation, a);
3817
- const BroadphaseBounds boundsB = queryProxyBounds(operation, b);
3818
- if (!boundsOverlap(boundsA, boundsB)) return {};
3819
3926
 
3820
- Collision best;
3821
- for (std::uint32_t child = 0; child < compoundChildCount(operation, a); child += 1) {
3822
- const Body childBody = compoundChildBody(operation, a, child);
3823
- const BroadphaseBounds childBounds = queryProxyBounds(operation, childBody);
3824
- if (!boundsOverlap(childBounds, boundsB)) continue;
3825
- const Collision candidate = collide(operation, childBody, b);
3826
- if (candidate.hit && (!best.hit || candidate.penetration > best.penetration)) best = candidate;
3827
- }
3828
- return best;
3829
- }
3830
- if (b.shape == ShapeKind::Compound && (b.geometryFormat == 4 || b.geometryFormat == 5 || b.geometryFormat == 6)) {
3831
- const Collision result = collide(operation, b, a);
3832
- return flipCollision(result);
3833
- }
3834
3927
  if (!robustConvexBodiesOverlap(operation, a, b)) return {};
3835
3928
  return convexSupportCollision(operation, a, b);
3836
3929
  }
@@ -7520,7 +7613,7 @@ ContactPassPolicy contactPassPolicy(ContactPass pass) {
7520
7613
  case ContactPass::StandaloneLaterSubstep:
7521
7614
  return {false, true, false, false, true, true};
7522
7615
  case ContactPass::LegacyJointContinueVelocity:
7523
- return {false, false, true, false, true, true};
7616
+ return {false, false, false, false, false, true};
7524
7617
  }
7525
7618
  std::terminate();
7526
7619
  }
@@ -7818,7 +7911,7 @@ void resolveSoAContacts(SolverOperation& operation, Body* bodies, std::uint32_t
7818
7911
  forEachCollectedSweepPair(operation, solveCollectedPair);
7819
7912
  }
7820
7913
  } else {
7821
- solvePreparedConstraints(iteration != 0);
7914
+ solvePreparedConstraints(iteration != 0 || pass == ContactPass::LegacyJointContinueVelocity);
7822
7915
  }
7823
7916
  if (solveVelocity && (beginSubstep || preparedSubstep) && iteration == 0) {
7824
7917
  std::sort(operation.storage.contactConstraints.begin(),
@@ -7852,7 +7945,7 @@ void resolveSoAContacts(SolverOperation& operation, Body* bodies, std::uint32_t
7852
7945
  operation.storage.broadphaseTree->forEachCollectedPair(solveCollectedPair);
7853
7946
  }
7854
7947
  } else {
7855
- solvePreparedConstraints(iteration != 0);
7948
+ solvePreparedConstraints(iteration != 0 || pass == ContactPass::LegacyJointContinueVelocity);
7856
7949
  }
7857
7950
  if (solveVelocity && (beginSubstep || preparedSubstep) && iteration == 0) {
7858
7951
  std::sort(operation.storage.contactConstraints.begin(),