@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){
|
|
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
|
-
|
|
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,
|
|
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(),
|