修改水

This commit is contained in:
2026-01-01 22:00:33 +08:00
parent 040a222bd6
commit 9ceffccd39
1800 changed files with 103929 additions and 139495 deletions

View File

@@ -24,7 +24,9 @@ namespace Obi
public override int GetConstraintCount()
{
return ((BurstSolverImpl)solver).abstraction.colliderContacts.count;
if (!((BurstSolverImpl)solver).colliderContacts.IsCreated)
return 0;
return ((BurstSolverImpl)solver).colliderContacts.Length;
}
}
}

View File

@@ -17,7 +17,7 @@ namespace Obi
m_ConstraintType = Oni.ConstraintType.Collision;
}
public override JobHandle Initialize(JobHandle inputDeps, float stepTime, float substepTime, int steps, float timeLeft)
public override JobHandle Initialize(JobHandle inputDeps, float substepTime)
{
var updateContacts = new UpdateContactsJob()
{
@@ -26,7 +26,7 @@ namespace Obi
velocities = solverImplementation.velocities,
radii = solverImplementation.principalRadii,
invMasses = solverImplementation.invMasses,
invRotationalMasses = solverImplementation.invRotationalMasses,
invInertiaTensors = solverImplementation.invInertiaTensors,
particleMaterialIndices = solverImplementation.collisionMaterials,
collisionMaterials = ObiColliderWorld.GetInstance().collisionMaterials.AsNativeArray<BurstCollisionMaterial>(),
@@ -39,14 +39,13 @@ namespace Obi
rigidbodyLinearDeltas = solverImplementation.abstraction.rigidbodyLinearDeltas.AsNativeArray<float4>(),
rigidbodyAngularDeltas = solverImplementation.abstraction.rigidbodyAngularDeltas.AsNativeArray<float4>(),
contacts = ((BurstSolverImpl)constraints.solver).abstraction.colliderContacts.AsNativeArray<BurstContact>(),
effectiveMasses = ((BurstSolverImpl)constraints.solver).abstraction.contactEffectiveMasses.AsNativeArray<ContactEffectiveMasses>(),
contacts = ((BurstSolverImpl)constraints.solver).colliderContacts,
inertialFrame = ((BurstSolverImpl)constraints.solver).inertialFrame
};
return updateContacts.Schedule(((BurstSolverImpl)constraints.solver).abstraction.colliderContacts.count, 128, inputDeps);
return updateContacts.Schedule(((BurstSolverImpl)constraints.solver).colliderContacts.Length, 128, inputDeps);
}
public override JobHandle Evaluate(JobHandle inputDeps, float stepTime, float substepTime, int steps, float timeLeft)
public override JobHandle Evaluate(JobHandle inputDeps, float stepTime, float substepTime, int substeps)
{
var parameters = solverAbstraction.GetConstraintParameters(m_ConstraintType);
@@ -73,13 +72,11 @@ namespace Obi
deltas = solverAbstraction.positionDeltas.AsNativeArray<float4>(),
counts = solverAbstraction.positionConstraintCounts.AsNativeArray<int>(),
contacts = ((BurstSolverImpl)constraints.solver).abstraction.colliderContacts.AsNativeArray<BurstContact>(),
effectiveMasses = ((BurstSolverImpl)constraints.solver).abstraction.contactEffectiveMasses.AsNativeArray<ContactEffectiveMasses>(),
contacts = ((BurstSolverImpl)constraints.solver).colliderContacts,
inertialFrame = ((BurstSolverImpl)constraints.solver).inertialFrame,
constraintParameters = parameters,
solverParameters = solverAbstraction.parameters,
steps = steps,
timeLeft = timeLeft,
substeps = substeps,
stepTime = stepTime,
substepTime = substepTime
};
@@ -92,7 +89,7 @@ namespace Obi
var applyConstraints = new ApplyCollisionConstraintsBatchJob()
{
contacts = ((BurstSolverImpl)constraints.solver).abstraction.colliderContacts.AsNativeArray<BurstContact>(),
contacts = ((BurstSolverImpl)constraints.solver).colliderContacts,
simplices = solverImplementation.simplices,
simplexCounts = solverImplementation.simplexCounts,
@@ -111,7 +108,7 @@ namespace Obi
/**
* Updates contact data (such as contact distance) at the beginning of each substep. This is
* necessary because contacts are generated only once at the beginning of each step, not every substep.
* necessary because contacts are generalted only once at the beginning of each step, not every substep.
*/
[BurstCompile]
public struct UpdateContactsJob : IJobParallelFor
@@ -121,7 +118,7 @@ namespace Obi
[ReadOnly] public NativeArray<float4> velocities;
[ReadOnly] public NativeArray<float4> radii;
[ReadOnly] public NativeArray<float> invMasses;
[ReadOnly] public NativeArray<float> invRotationalMasses;
[ReadOnly] public NativeArray<float4> invInertiaTensors;
[ReadOnly] public NativeArray<int> particleMaterialIndices;
[ReadOnly] public NativeArray<BurstCollisionMaterial> collisionMaterials;
@@ -136,14 +133,12 @@ namespace Obi
[ReadOnly] public NativeArray<float4> rigidbodyLinearDeltas;
[ReadOnly] public NativeArray<float4> rigidbodyAngularDeltas;
public NativeArray<ContactEffectiveMasses> effectiveMasses;
public NativeArray<BurstContact> contacts;
[ReadOnly] public BurstInertialFrame inertialFrame;
public void Execute(int i)
{
var contact = contacts[i];
var efMasses = effectiveMasses[i];
int simplexStart = simplexCounts.GetSimplexStartAndSize(contact.bodyA, out int simplexSize);
@@ -155,7 +150,7 @@ namespace Obi
float4 simplexPrevPosition = float4.zero;
quaternion simplexPrevOrientation = new quaternion(0, 0, 0, 0);
float simplexInvMass = 0;
float simplexInvRotationalMass = 0;
float4 simplexInvInertia = float4.zero;
float simplexRadius = 0;
for (int j = 0; j < simplexSize; ++j)
@@ -165,7 +160,7 @@ namespace Obi
simplexPrevPosition += prevPositions[particleIndex] * contact.pointA[j];
simplexPrevOrientation.value += prevOrientations[particleIndex].value * contact.pointA[j];
simplexInvMass += invMasses[particleIndex] * contact.pointA[j];
simplexInvRotationalMass = invRotationalMasses[particleIndex] * contact.pointA[j];
simplexInvInertia += invInertiaTensors[particleIndex] * contact.pointA[j];
simplexRadius += BurstMath.EllipsoidRadius(contact.normal, prevOrientations[particleIndex], radii[particleIndex].xyz) * contact.pointA[j];
}
@@ -173,7 +168,7 @@ namespace Obi
int rigidbodyIndex = shapes[contact.bodyB].rigidbodyIndex;
if (rigidbodyIndex >= 0)
{
relativeVelocity -= BurstMath.GetRigidbodyVelocityAtPoint(rigidbodyIndex, contact.pointB, rigidbodies, rigidbodyLinearDeltas, rigidbodyAngularDeltas, inertialFrame);
relativeVelocity -= BurstMath.GetRigidbodyVelocityAtPoint(rigidbodyIndex, contact.pointB, rigidbodies, rigidbodyLinearDeltas, rigidbodyAngularDeltas, inertialFrame.frame);
int bMaterialIndex = shapes[contact.bodyB].materialIndex;
rollingContacts |= bMaterialIndex >= 0 ? collisionMaterials[bMaterialIndex].rollingContacts > 0 : false;
@@ -185,21 +180,17 @@ namespace Obi
// calculate contact point in A's surface:
float4 contactPoint = contact.pointB + contact.normal * contact.distance;
// calculate contact tangent (first friction direction) using relative velocity:
contact.CalculateTangent(relativeVelocity);
// update contact orthonormal basis:
contact.CalculateBasis(relativeVelocity);
// calculate A's contact mass.
float4 invInertiaTensor = math.rcp(BurstMath.GetParticleInertiaTensor(simplexRadius, simplexInvRotationalMass) + new float4(BurstMath.epsilon));
efMasses.CalculateContactMassesA(simplexInvMass, invInertiaTensor, simplexPrevPosition, simplexPrevOrientation, contactPoint, contact.normal, contact.tangent, contact.bitangent, rollingContacts);
contact.CalculateContactMassesA(simplexInvMass, simplexInvInertia, simplexPrevPosition, simplexPrevOrientation, contactPoint, rollingContacts);
// calculate B's contact mass.
if (rigidbodyIndex >= 0)
efMasses.CalculateContactMassesB(rigidbodies[rigidbodyIndex], inertialFrame.frame, contact.pointB, contact.normal, contact.tangent, contact.bitangent);
else
efMasses.ClearContactMassesB();
contact.CalculateContactMassesB(rigidbodies[rigidbodyIndex], inertialFrame.frame);
contacts[i] = contact;
effectiveMasses[i] = efMasses;
}
}
@@ -229,14 +220,12 @@ namespace Obi
[NativeDisableContainerSafetyRestriction] [NativeDisableParallelForRestriction] public NativeArray<int> counts;
public NativeArray<BurstContact> contacts;
[ReadOnly] public NativeArray<ContactEffectiveMasses> effectiveMasses;
[ReadOnly] public BurstInertialFrame inertialFrame;
[ReadOnly] public Oni.ConstraintParameters constraintParameters;
[ReadOnly] public Oni.SolverParameters solverParameters;
[ReadOnly] public float stepTime;
[ReadOnly] public float substepTime;
[ReadOnly] public float timeLeft;
[ReadOnly] public int steps;
[ReadOnly] public int substeps;
public void Execute()
{
@@ -248,15 +237,12 @@ namespace Obi
int colliderIndex = contact.bodyB;
// Skip contacts involving triggers:
if (shapes[colliderIndex].isTrigger)
if (shapes[colliderIndex].flags > 0)
continue;
// Get the rigidbody index (might be < 0, in that case there's no rigidbody present)
int rigidbodyIndex = shapes[colliderIndex].rigidbodyIndex;
float frameEnd = stepTime * steps;
float substepsToEnd = timeLeft / substepTime;
// Combine collision materials (use material from first particle in simplex)
BurstCollisionMaterial material = CombineCollisionMaterials(simplices[simplexStart], colliderIndex);
@@ -276,24 +262,24 @@ namespace Obi
}
// project position to the end of the full step:
float4 posA = math.lerp(simplexPrevPosition, simplexPosition, substepsToEnd);
float4 posA = math.lerp(simplexPrevPosition, simplexPosition, substeps);
posA += -contact.normal * simplexRadius;
float4 posB = contact.pointB;
if (rigidbodyIndex >= 0)
posB += BurstMath.GetRigidbodyVelocityAtPoint(rigidbodyIndex, contact.pointB, rigidbodies, rigidbodyLinearDeltas, rigidbodyAngularDeltas, inertialFrame) * frameEnd;
posB += BurstMath.GetRigidbodyVelocityAtPoint(rigidbodyIndex, contact.pointB, rigidbodies, rigidbodyLinearDeltas, rigidbodyAngularDeltas, inertialFrame.frame) * stepTime;
// adhesion:
float lambda = contact.SolveAdhesion(effectiveMasses[i].TotalNormalInvMass, posA, posB, material.stickDistance, material.stickiness, stepTime);
float lambda = contact.SolveAdhesion(posA, posB, material.stickDistance, material.stickiness, stepTime);
// depenetration:
lambda += contact.SolvePenetration(effectiveMasses[i].TotalNormalInvMass, posA, posB, solverParameters.maxDepenetration * stepTime);
lambda += contact.SolvePenetration(posA, posB, solverParameters.maxDepenetration * stepTime);
// Apply normal impulse to both simplex and rigidbody:
if (math.abs(lambda) > BurstMath.epsilon)
{
float4 delta = lambda * contact.normal * BurstMath.BaryScale(contact.pointA) / substepsToEnd;
float4 delta = lambda * contact.normal * BurstMath.BaryScale(contact.pointA) / substeps;
for (int j = 0; j < simplexSize; ++j)
{
int particleIndex = simplices[simplexStart + j];
@@ -312,8 +298,8 @@ namespace Obi
}
if (rigidbodyIndex >= 0)
{
BurstMath.ApplyImpulse(rigidbodyIndex, -lambda / frameEnd * contact.normal, contact.pointB, rigidbodies, rigidbodyLinearDeltas, rigidbodyAngularDeltas, inertialFrame.frame);
{
BurstMath.ApplyImpulse(rigidbodyIndex, -lambda / stepTime * contact.normal, contact.pointB, rigidbodies, rigidbodyLinearDeltas, rigidbodyAngularDeltas, inertialFrame.frame);
}
}

View File

@@ -25,7 +25,9 @@ namespace Obi
public override int GetConstraintCount()
{
return ((BurstSolverImpl)solver).abstraction.colliderContacts.count;
if (!((BurstSolverImpl)solver).colliderContacts.IsCreated)
return 0;
return ((BurstSolverImpl)solver).colliderContacts.Length;
}
}
}

View File

@@ -15,13 +15,16 @@ namespace Obi
m_ConstraintType = Oni.ConstraintType.Friction;
}
public override JobHandle Initialize(JobHandle inputDeps, float stepTime, float substepTime, int steps, float timeLeft)
public override JobHandle Initialize(JobHandle inputDeps, float substepTime)
{
return inputDeps;
}
public override JobHandle Evaluate(JobHandle inputDeps, float stepTime, float substepTime, int steps, float timeLeft)
public override JobHandle Evaluate(JobHandle inputDeps, float stepTime, float substepTime, int substeps)
{
if (!((BurstSolverImpl)constraints.solver).colliderContacts.IsCreated)
return inputDeps;
var projectConstraints = new FrictionConstraintsBatchJob()
{
positions = solverImplementation.positions,
@@ -30,7 +33,7 @@ namespace Obi
prevOrientations = solverImplementation.prevOrientations,
invMasses = solverImplementation.invMasses,
invRotationalMasses = solverImplementation.invRotationalMasses,
invInertiaTensors = solverImplementation.invInertiaTensors,
radii = solverImplementation.principalRadii,
particleMaterialIndices = solverImplementation.collisionMaterials,
@@ -49,10 +52,9 @@ namespace Obi
orientationDeltas = solverImplementation.orientationDeltas,
orientationCounts = solverImplementation.orientationConstraintCounts,
contacts = ((BurstSolverImpl)constraints.solver).abstraction.colliderContacts.AsNativeArray<BurstContact>(),
effectiveMasses = ((BurstSolverImpl)constraints.solver).abstraction.contactEffectiveMasses.AsNativeArray<ContactEffectiveMasses>(),
contacts = ((BurstSolverImpl)constraints.solver).colliderContacts,
inertialFrame = ((BurstSolverImpl)constraints.solver).inertialFrame,
steps = steps,
substeps = substeps,
stepTime = stepTime,
substepTime = substepTime
};
@@ -61,11 +63,14 @@ namespace Obi
public override JobHandle Apply(JobHandle inputDeps, float substepTime)
{
if (!((BurstSolverImpl)constraints.solver).colliderContacts.IsCreated)
return inputDeps;
var parameters = solverAbstraction.GetConstraintParameters(m_ConstraintType);
var applyConstraints = new ApplyCollisionConstraintsBatchJob()
{
contacts = ((BurstSolverImpl)constraints.solver).abstraction.colliderContacts.AsNativeArray<BurstContact>(),
contacts = ((BurstSolverImpl)constraints.solver).colliderContacts,
simplices = solverImplementation.simplices,
simplexCounts = solverImplementation.simplexCounts,
@@ -91,7 +96,7 @@ namespace Obi
[ReadOnly] public NativeArray<quaternion> prevOrientations;
[ReadOnly] public NativeArray<float> invMasses;
[ReadOnly] public NativeArray<float> invRotationalMasses;
[ReadOnly] public NativeArray<float4> invInertiaTensors;
[ReadOnly] public NativeArray<float4> radii;
[ReadOnly] public NativeArray<int> particleMaterialIndices;
@@ -113,11 +118,10 @@ namespace Obi
[NativeDisableContainerSafetyRestriction] [NativeDisableParallelForRestriction] public NativeArray<int> orientationCounts;
public NativeArray<BurstContact> contacts;
[ReadOnly] public NativeArray<ContactEffectiveMasses> effectiveMasses;
[ReadOnly] public BurstInertialFrame inertialFrame;
[ReadOnly] public float stepTime;
[ReadOnly] public float substepTime;
[ReadOnly] public int steps;
[ReadOnly] public int substeps;
public void Execute()
{
@@ -130,7 +134,7 @@ namespace Obi
int colliderIndex = contact.bodyB;
// Skip contacts involving triggers:
if (shapes[colliderIndex].isTrigger)
if (shapes[colliderIndex].flags > 0)
continue;
// Get the rigidbody index (might be < 0, in that case there's no rigidbody present)
@@ -145,9 +149,9 @@ namespace Obi
float4 prevPositionA = float4.zero;
float4 linearVelocityA = float4.zero;
float4 angularVelocityA = float4.zero;
float invRotationalMassA = 0;
float4 invInertiaTensorA = float4.zero;
quaternion orientationA = new quaternion(0, 0, 0, 0);
float4 simplexRadiiA = float4.zero;
float simplexRadiusA = 0;
for (int j = 0; j < simplexSize; ++j)
{
@@ -155,17 +159,17 @@ namespace Obi
prevPositionA += prevPositions[particleIndex] * contact.pointA[j];
linearVelocityA += BurstIntegration.DifferentiateLinear(positions[particleIndex],prevPositions[particleIndex], substepTime) * contact.pointA[j];
angularVelocityA += BurstIntegration.DifferentiateAngular(orientations[particleIndex], prevOrientations[particleIndex], substepTime) * contact.pointA[j];
invRotationalMassA += invRotationalMasses[particleIndex] * contact.pointA[j];
invInertiaTensorA += invInertiaTensors[particleIndex] * contact.pointA[j];
orientationA.value += orientations[particleIndex].value * contact.pointA[j];
simplexRadiiA += radii[particleIndex] * contact.pointA[j];
simplexRadiusA += BurstMath.EllipsoidRadius(contact.normal, prevOrientations[particleIndex], radii[particleIndex].xyz) * contact.pointA[j];
}
float4 relativeVelocity = linearVelocityA;
// Add particle angular velocity if rolling contacts are enabled:
if (material.rollingContacts > 0)
{
rA = -contact.normal * BurstMath.EllipsoidRadius(contact.normal, orientationA, simplexRadiiA.xyz);
rA = -contact.normal * simplexRadiusA;
relativeVelocity += new float4(math.cross(angularVelocityA.xyz, rA.xyz), 0);
}
@@ -174,11 +178,11 @@ namespace Obi
{
// Note: unlike rA, that is expressed in solver space, rB is expressed in world space.
rB = inertialFrame.frame.TransformPoint(contact.pointB) - rigidbodies[rigidbodyIndex].com;
relativeVelocity -= BurstMath.GetRigidbodyVelocityAtPoint(rigidbodyIndex, contact.pointB, rigidbodies, rigidbodyLinearDeltas, rigidbodyAngularDeltas, inertialFrame);
relativeVelocity -= BurstMath.GetRigidbodyVelocityAtPoint(rigidbodyIndex, contact.pointB, rigidbodies, rigidbodyLinearDeltas, rigidbodyAngularDeltas, inertialFrame.frame);
}
// Determine impulse magnitude:
float2 impulses = contact.SolveFriction(effectiveMasses[i].TotalTangentInvMass, effectiveMasses[i].TotalBitangentInvMass, relativeVelocity, material.staticFriction, material.dynamicFriction, stepTime);
float2 impulses = contact.SolveFriction(relativeVelocity, material.staticFriction, material.dynamicFriction, stepTime);
if (math.abs(impulses.x) > BurstMath.epsilon || math.abs(impulses.y) > BurstMath.epsilon)
{
@@ -190,7 +194,8 @@ namespace Obi
for (int j = 0; j < simplexSize; ++j)
{
int particleIndex = simplices[simplexStart + j];
deltas[particleIndex] += (tangentImpulse * effectiveMasses[i].tangentInvMassA + bitangentImpulse * effectiveMasses[i].bitangentInvMassA) * substepTime * contact.pointA[j] * baryScale;
//(tangentImpulse * contact.tangentInvMassA + bitangentImpulse * contact.bitangentInvMassA) * dt;
deltas[particleIndex] += (tangentImpulse * contact.tangentInvMassA + bitangentImpulse * contact.bitangentInvMassA) * substepTime * contact.pointA[j] * baryScale;
counts[particleIndex]++;
}
@@ -203,8 +208,7 @@ namespace Obi
if (material.rollingContacts > 0)
{
// Calculate angular velocity deltas due to friction impulse:
float4 invInertiaTensor = math.rcp(BurstMath.GetParticleInertiaTensor(simplexRadiiA, invRotationalMassA) + new float4(BurstMath.epsilon));
float4x4 solverInertiaA = BurstMath.TransformInertiaTensor(invInertiaTensor, orientationA);
float4x4 solverInertiaA = BurstMath.TransformInertiaTensor(invInertiaTensorA, orientationA);
float4 angVelDeltaA = math.mul(solverInertiaA, new float4(math.cross(rA.xyz, totalImpulse.xyz), 0));
float4 angVelDeltaB = float4.zero;