去掉obi,使用自写绳索

This commit is contained in:
2026-02-23 20:51:03 +08:00
parent cb636f862d
commit 91e2309eeb
2011 changed files with 2593 additions and 190578 deletions

View File

@@ -1,49 +0,0 @@
#if (OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS)
using UnityEngine;
using Unity.Jobs;
using Unity.Collections;
using Unity.Mathematics;
using Unity.Burst;
using System;
using System.Collections;
namespace Obi
{
[BurstCompile]
public struct ApplyCollisionConstraintsBatchJob : IJob
{
[ReadOnly] public NativeArray<BurstContact> contacts;
[ReadOnly] public NativeArray<int> simplices;
[ReadOnly] public SimplexCounts simplexCounts;
[NativeDisableParallelForRestriction] public NativeArray<float4> positions;
[NativeDisableParallelForRestriction] public NativeArray<float4> deltas;
[NativeDisableParallelForRestriction] public NativeArray<int> counts;
[NativeDisableParallelForRestriction] public NativeArray<quaternion> orientations;
[NativeDisableParallelForRestriction] public NativeArray<quaternion> orientationDeltas;
[NativeDisableParallelForRestriction] public NativeArray<int> orientationCounts;
[ReadOnly] public Oni.ConstraintParameters constraintParameters;
public void Execute()
{
for (int i = 0; i < contacts.Length; ++i)
{
int simplexStart = simplexCounts.GetSimplexStartAndSize(contacts[i].bodyA, out int simplexSize);
for (int j = 0; j < simplexSize; ++j)
{
int particleIndex = simplices[simplexStart + j];
BurstConstraintsBatchImpl.ApplyPositionDelta(particleIndex, constraintParameters.SORFactor, ref positions, ref deltas, ref counts);
BurstConstraintsBatchImpl.ApplyOrientationDelta(particleIndex, constraintParameters.SORFactor, ref orientations, ref orientationDeltas, ref orientationCounts);
}
}
}
}
}
#endif

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: f97613844b24a40899f10722bcfc4cf8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,31 +0,0 @@
#if (OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS)
using System;
namespace Obi
{
public class BurstColliderCollisionConstraints : BurstConstraintsImpl<BurstColliderCollisionConstraintsBatch>
{
public BurstColliderCollisionConstraints(BurstSolverImpl solver) : base(solver, Oni.ConstraintType.Collision)
{
}
public override IConstraintsBatchImpl CreateConstraintsBatch()
{
var dataBatch = new BurstColliderCollisionConstraintsBatch(this);
batches.Add(dataBatch);
return dataBatch;
}
public override void RemoveBatch(IConstraintsBatchImpl batch)
{
batches.Remove(batch as BurstColliderCollisionConstraintsBatch);
batch.Destroy();
}
public override int GetConstraintCount()
{
return ((BurstSolverImpl)solver).abstraction.colliderContacts.count;
}
}
}
#endif

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: e31847a0e619545c0bc70258b413a42e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,344 +0,0 @@
#if (OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS)
using UnityEngine;
using Unity.Jobs;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Mathematics;
using Unity.Burst;
using System.Collections;
namespace Obi
{
public class BurstColliderCollisionConstraintsBatch : BurstConstraintsBatchImpl, IColliderCollisionConstraintsBatchImpl
{
public BurstColliderCollisionConstraintsBatch(BurstColliderCollisionConstraints constraints)
{
m_Constraints = constraints;
m_ConstraintType = Oni.ConstraintType.Collision;
}
public override JobHandle Initialize(JobHandle inputDeps, float stepTime, float substepTime, int steps, float timeLeft)
{
var updateContacts = new UpdateContactsJob()
{
prevPositions = solverImplementation.prevPositions,
prevOrientations = solverImplementation.prevOrientations,
velocities = solverImplementation.velocities,
radii = solverImplementation.principalRadii,
invMasses = solverImplementation.invMasses,
invRotationalMasses = solverImplementation.invRotationalMasses,
particleMaterialIndices = solverImplementation.collisionMaterials,
collisionMaterials = ObiColliderWorld.GetInstance().collisionMaterials.AsNativeArray<BurstCollisionMaterial>(),
simplices = solverImplementation.simplices,
simplexCounts = solverImplementation.simplexCounts,
shapes = ObiColliderWorld.GetInstance().colliderShapes.AsNativeArray<BurstColliderShape>(),
transforms = ObiColliderWorld.GetInstance().colliderTransforms.AsNativeArray<BurstAffineTransform>(),
rigidbodies = ObiColliderWorld.GetInstance().rigidbodies.AsNativeArray<BurstRigidbody>(),
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>(),
inertialFrame = ((BurstSolverImpl)constraints.solver).inertialFrame
};
return updateContacts.Schedule(((BurstSolverImpl)constraints.solver).abstraction.colliderContacts.count, 128, inputDeps);
}
public override JobHandle Evaluate(JobHandle inputDeps, float stepTime, float substepTime, int steps, float timeLeft)
{
var parameters = solverAbstraction.GetConstraintParameters(m_ConstraintType);
var projectConstraints = new CollisionConstraintsBatchJob()
{
positions = solverImplementation.positions,
prevPositions = solverImplementation.prevPositions,
orientations = solverImplementation.orientations,
prevOrientations = solverImplementation.prevOrientations,
invMasses = solverImplementation.invMasses,
radii = solverImplementation.principalRadii,
particleMaterialIndices = solverImplementation.collisionMaterials,
simplices = solverImplementation.simplices,
simplexCounts = solverImplementation.simplexCounts,
shapes = ObiColliderWorld.GetInstance().colliderShapes.AsNativeArray<BurstColliderShape>(),
transforms = ObiColliderWorld.GetInstance().colliderTransforms.AsNativeArray<BurstAffineTransform>(),
collisionMaterials = ObiColliderWorld.GetInstance().collisionMaterials.AsNativeArray<BurstCollisionMaterial>(),
rigidbodies = ObiColliderWorld.GetInstance().rigidbodies.AsNativeArray<BurstRigidbody>(),
rigidbodyLinearDeltas = solverImplementation.abstraction.rigidbodyLinearDeltas.AsNativeArray<float4>(),
rigidbodyAngularDeltas = solverImplementation.abstraction.rigidbodyAngularDeltas.AsNativeArray<float4>(),
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>(),
inertialFrame = ((BurstSolverImpl)constraints.solver).inertialFrame,
constraintParameters = parameters,
solverParameters = solverAbstraction.parameters,
steps = steps,
timeLeft = timeLeft,
stepTime = stepTime,
substepTime = substepTime
};
return projectConstraints.Schedule(inputDeps);
}
public override JobHandle Apply(JobHandle inputDeps, float substepTime)
{
var parameters = solverAbstraction.GetConstraintParameters(m_ConstraintType);
var applyConstraints = new ApplyCollisionConstraintsBatchJob()
{
contacts = ((BurstSolverImpl)constraints.solver).abstraction.colliderContacts.AsNativeArray<BurstContact>(),
simplices = solverImplementation.simplices,
simplexCounts = solverImplementation.simplexCounts,
positions = solverImplementation.positions,
deltas = solverImplementation.positionDeltas,
counts = solverImplementation.positionConstraintCounts,
orientations = solverImplementation.orientations,
orientationDeltas = solverImplementation.orientationDeltas,
orientationCounts = solverImplementation.orientationConstraintCounts,
constraintParameters = parameters
};
return applyConstraints.Schedule(inputDeps);
}
/**
* 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.
*/
[BurstCompile]
public struct UpdateContactsJob : IJobParallelFor
{
[ReadOnly] public NativeArray<float4> prevPositions;
[ReadOnly] public NativeArray<quaternion> prevOrientations;
[ReadOnly] public NativeArray<float4> velocities;
[ReadOnly] public NativeArray<float4> radii;
[ReadOnly] public NativeArray<float> invMasses;
[ReadOnly] public NativeArray<float> invRotationalMasses;
[ReadOnly] public NativeArray<int> particleMaterialIndices;
[ReadOnly] public NativeArray<BurstCollisionMaterial> collisionMaterials;
// simplex arrays:
[ReadOnly] public NativeArray<int> simplices;
[ReadOnly] public SimplexCounts simplexCounts;
[ReadOnly] public NativeArray<BurstColliderShape> shapes;
[ReadOnly] public NativeArray<BurstAffineTransform> transforms;
[ReadOnly] public NativeArray<BurstRigidbody> rigidbodies;
[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);
// get the material from the first particle in the simplex:
int aMaterialIndex = particleMaterialIndices[simplices[simplexStart]];
bool rollingContacts = aMaterialIndex >= 0 ? collisionMaterials[aMaterialIndex].rollingContacts > 0 : false;
float4 relativeVelocity = float4.zero;
float4 simplexPrevPosition = float4.zero;
quaternion simplexPrevOrientation = new quaternion(0, 0, 0, 0);
float simplexInvMass = 0;
float simplexInvRotationalMass = 0;
float simplexRadius = 0;
for (int j = 0; j < simplexSize; ++j)
{
int particleIndex = simplices[simplexStart + j];
relativeVelocity += velocities[particleIndex] * contact.pointA[j];
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];
simplexRadius += BurstMath.EllipsoidRadius(contact.normal, prevOrientations[particleIndex], radii[particleIndex].xyz) * contact.pointA[j];
}
// if there's a rigidbody present, subtract its velocity from the relative velocity:
int rigidbodyIndex = shapes[contact.bodyB].rigidbodyIndex;
if (rigidbodyIndex >= 0)
{
relativeVelocity -= BurstMath.GetRigidbodyVelocityAtPoint(rigidbodyIndex, contact.pointB, rigidbodies, rigidbodyLinearDeltas, rigidbodyAngularDeltas, inertialFrame);
int bMaterialIndex = shapes[contact.bodyB].materialIndex;
rollingContacts |= bMaterialIndex >= 0 ? collisionMaterials[bMaterialIndex].rollingContacts > 0 : false;
}
// update contact distance
contact.distance = math.dot(simplexPrevPosition - contact.pointB, contact.normal) - simplexRadius;
// 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);
// 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);
// 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();
contacts[i] = contact;
effectiveMasses[i] = efMasses;
}
}
[BurstCompile]
public struct CollisionConstraintsBatchJob : IJob
{
[ReadOnly] public NativeArray<float4> prevPositions;
[ReadOnly] public NativeArray<quaternion> orientations;
[ReadOnly] public NativeArray<quaternion> prevOrientations;
[ReadOnly] public NativeArray<float> invMasses;
[ReadOnly] public NativeArray<float4> radii;
[ReadOnly] public NativeArray<int> particleMaterialIndices;
// simplex arrays:
[ReadOnly] public NativeArray<int> simplices;
[ReadOnly] public SimplexCounts simplexCounts;
[ReadOnly] public NativeArray<BurstColliderShape> shapes;
[ReadOnly] public NativeArray<BurstAffineTransform> transforms;
[ReadOnly] public NativeArray<BurstCollisionMaterial> collisionMaterials;
[ReadOnly] public NativeArray<BurstRigidbody> rigidbodies;
public NativeArray<float4> rigidbodyLinearDeltas;
public NativeArray<float4> rigidbodyAngularDeltas;
[NativeDisableContainerSafetyRestriction] [NativeDisableParallelForRestriction] public NativeArray<float4> positions;
[NativeDisableContainerSafetyRestriction] [NativeDisableParallelForRestriction] public NativeArray<float4> deltas;
[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;
public void Execute()
{
for (int i = 0; i < contacts.Length; ++i)
{
var contact = contacts[i];
int simplexStart = simplexCounts.GetSimplexStartAndSize(contact.bodyA, out int simplexSize);
int colliderIndex = contact.bodyB;
// Skip contacts involving triggers:
if (shapes[colliderIndex].isTrigger)
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);
// Get relative velocity at contact point.
// As we do not consider true ellipses for collision detection, particle contact points are never off-axis.
// So particle angular velocity does not contribute to normal impulses, and we can skip it.
float4 simplexPosition = float4.zero;
float4 simplexPrevPosition = float4.zero;
float simplexRadius = 0;
for (int j = 0; j < simplexSize; ++j)
{
int particleIndex = simplices[simplexStart + j];
simplexPosition += positions[particleIndex] * contact.pointA[j];
simplexPrevPosition += prevPositions[particleIndex] * contact.pointA[j];
simplexRadius += BurstMath.EllipsoidRadius(contact.normal, orientations[particleIndex], radii[particleIndex].xyz) * contact.pointA[j];
}
// project position to the end of the full step:
float4 posA = math.lerp(simplexPrevPosition, simplexPosition, substepsToEnd);
posA += -contact.normal * simplexRadius;
float4 posB = contact.pointB;
if (rigidbodyIndex >= 0)
posB += BurstMath.GetRigidbodyVelocityAtPoint(rigidbodyIndex, contact.pointB, rigidbodies, rigidbodyLinearDeltas, rigidbodyAngularDeltas, inertialFrame) * frameEnd;
// adhesion:
float lambda = contact.SolveAdhesion(effectiveMasses[i].TotalNormalInvMass, posA, posB, material.stickDistance, material.stickiness, stepTime);
// depenetration:
lambda += contact.SolvePenetration(effectiveMasses[i].TotalNormalInvMass, 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;
for (int j = 0; j < simplexSize; ++j)
{
int particleIndex = simplices[simplexStart + j];
deltas[particleIndex] += delta * invMasses[particleIndex] * contact.pointA[j];
counts[particleIndex]++;
}
// Apply position deltas immediately, if using sequential evaluation:
if (constraintParameters.evaluationOrder == Oni.ConstraintParameters.EvaluationOrder.Sequential)
{
for (int j = 0; j < simplexSize; ++j)
{
int particleIndex = simplices[simplexStart + j];
BurstConstraintsBatchImpl.ApplyPositionDelta(particleIndex, constraintParameters.SORFactor, ref positions, ref deltas, ref counts);
}
}
if (rigidbodyIndex >= 0)
{
BurstMath.ApplyImpulse(rigidbodyIndex, -lambda / frameEnd * contact.normal, contact.pointB, rigidbodies, rigidbodyLinearDeltas, rigidbodyAngularDeltas, inertialFrame.frame);
}
}
contacts[i] = contact;
}
}
private BurstCollisionMaterial CombineCollisionMaterials(int entityA, int entityB)
{
// Combine collision materials:
int particleMaterialIndex = particleMaterialIndices[entityA];
int colliderMaterialIndex = shapes[entityB].materialIndex;
if (colliderMaterialIndex >= 0 && particleMaterialIndex >= 0)
return BurstCollisionMaterial.CombineWith(collisionMaterials[particleMaterialIndex], collisionMaterials[colliderMaterialIndex]);
else if (particleMaterialIndex >= 0)
return collisionMaterials[particleMaterialIndex];
else if (colliderMaterialIndex >= 0)
return collisionMaterials[colliderMaterialIndex];
return new BurstCollisionMaterial();
}
}
}
}
#endif

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 273c5561da8534560bb9b9e8d32ae092
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,33 +0,0 @@
#if (OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS)
using System;
namespace Obi
{
public class BurstColliderFrictionConstraints : BurstConstraintsImpl<BurstColliderFrictionConstraintsBatch>
{
public BurstColliderFrictionConstraints(BurstSolverImpl solver) : base(solver, Oni.ConstraintType.Friction)
{
}
public override IConstraintsBatchImpl CreateConstraintsBatch()
{
var dataBatch = new BurstColliderFrictionConstraintsBatch(this);
batches.Add(dataBatch);
return dataBatch;
}
public override void RemoveBatch(IConstraintsBatchImpl batch)
{
batches.Remove(batch as BurstColliderFrictionConstraintsBatch);
batch.Destroy();
}
public override int GetConstraintCount()
{
return ((BurstSolverImpl)solver).abstraction.colliderContacts.count;
}
}
}
#endif

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 00f91403e75564dc6ace566943caa172
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,280 +0,0 @@
#if (OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS)
using Unity.Jobs;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Mathematics;
using Unity.Burst;
namespace Obi
{
public class BurstColliderFrictionConstraintsBatch : BurstConstraintsBatchImpl, IColliderFrictionConstraintsBatchImpl
{
public BurstColliderFrictionConstraintsBatch(BurstColliderFrictionConstraints constraints)
{
m_Constraints = constraints;
m_ConstraintType = Oni.ConstraintType.Friction;
}
public override JobHandle Initialize(JobHandle inputDeps, float stepTime, float substepTime, int steps, float timeLeft)
{
return inputDeps;
}
public override JobHandle Evaluate(JobHandle inputDeps, float stepTime, float substepTime, int steps, float timeLeft)
{
var projectConstraints = new FrictionConstraintsBatchJob()
{
positions = solverImplementation.positions,
prevPositions = solverImplementation.prevPositions,
orientations = solverImplementation.orientations,
prevOrientations = solverImplementation.prevOrientations,
invMasses = solverImplementation.invMasses,
invRotationalMasses = solverImplementation.invRotationalMasses,
radii = solverImplementation.principalRadii,
particleMaterialIndices = solverImplementation.collisionMaterials,
simplices = solverImplementation.simplices,
simplexCounts = solverImplementation.simplexCounts,
shapes = ObiColliderWorld.GetInstance().colliderShapes.AsNativeArray<BurstColliderShape>(),
transforms = ObiColliderWorld.GetInstance().colliderTransforms.AsNativeArray<BurstAffineTransform>(),
collisionMaterials = ObiColliderWorld.GetInstance().collisionMaterials.AsNativeArray<BurstCollisionMaterial>(),
rigidbodies = ObiColliderWorld.GetInstance().rigidbodies.AsNativeArray<BurstRigidbody>(),
rigidbodyLinearDeltas = solverImplementation.abstraction.rigidbodyLinearDeltas.AsNativeArray<float4>(),
rigidbodyAngularDeltas = solverImplementation.abstraction.rigidbodyAngularDeltas.AsNativeArray<float4>(),
deltas = solverImplementation.positionDeltas,
counts = solverImplementation.positionConstraintCounts,
orientationDeltas = solverImplementation.orientationDeltas,
orientationCounts = solverImplementation.orientationConstraintCounts,
contacts = ((BurstSolverImpl)constraints.solver).abstraction.colliderContacts.AsNativeArray<BurstContact>(),
effectiveMasses = ((BurstSolverImpl)constraints.solver).abstraction.contactEffectiveMasses.AsNativeArray<ContactEffectiveMasses>(),
inertialFrame = ((BurstSolverImpl)constraints.solver).inertialFrame,
steps = steps,
stepTime = stepTime,
substepTime = substepTime
};
return projectConstraints.Schedule(inputDeps);
}
public override JobHandle Apply(JobHandle inputDeps, float substepTime)
{
var parameters = solverAbstraction.GetConstraintParameters(m_ConstraintType);
var applyConstraints = new ApplyCollisionConstraintsBatchJob()
{
contacts = ((BurstSolverImpl)constraints.solver).abstraction.colliderContacts.AsNativeArray<BurstContact>(),
simplices = solverImplementation.simplices,
simplexCounts = solverImplementation.simplexCounts,
positions = solverImplementation.positions,
deltas = solverImplementation.positionDeltas,
counts = solverImplementation.positionConstraintCounts,
orientations = solverImplementation.orientations,
orientationDeltas = solverImplementation.orientationDeltas,
orientationCounts = solverImplementation.orientationConstraintCounts,
constraintParameters = parameters
};
return applyConstraints.Schedule(inputDeps);
}
[BurstCompile]
public struct FrictionConstraintsBatchJob : IJob
{
[ReadOnly] public NativeArray<float4> positions;
[ReadOnly] public NativeArray<float4> prevPositions;
[ReadOnly] public NativeArray<quaternion> orientations;
[ReadOnly] public NativeArray<quaternion> prevOrientations;
[ReadOnly] public NativeArray<float> invMasses;
[ReadOnly] public NativeArray<float> invRotationalMasses;
[ReadOnly] public NativeArray<float4> radii;
[ReadOnly] public NativeArray<int> particleMaterialIndices;
// simplex arrays:
[ReadOnly] public NativeArray<int> simplices;
[ReadOnly] public SimplexCounts simplexCounts;
[ReadOnly] public NativeArray<BurstColliderShape> shapes;
[ReadOnly] public NativeArray<BurstAffineTransform> transforms;
[ReadOnly] public NativeArray<BurstCollisionMaterial> collisionMaterials;
[ReadOnly] public NativeArray<BurstRigidbody> rigidbodies;
public NativeArray<float4> rigidbodyLinearDeltas;
public NativeArray<float4> rigidbodyAngularDeltas;
[NativeDisableContainerSafetyRestriction] [NativeDisableParallelForRestriction] public NativeArray<float4> deltas;
[NativeDisableContainerSafetyRestriction] [NativeDisableParallelForRestriction] public NativeArray<int> counts;
[NativeDisableContainerSafetyRestriction] [NativeDisableParallelForRestriction] public NativeArray<quaternion> orientationDeltas;
[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;
public void Execute()
{
for (int i = 0; i < contacts.Length; ++i)
{
var contact = contacts[i];
// Get the indices of the particle and collider involved in this contact:
int simplexStart = simplexCounts.GetSimplexStartAndSize(contact.bodyA, out int simplexSize);
int colliderIndex = contact.bodyB;
// Skip contacts involving triggers:
if (shapes[colliderIndex].isTrigger)
continue;
// Get the rigidbody index (might be < 0, in that case there's no rigidbody present)
int rigidbodyIndex = shapes[colliderIndex].rigidbodyIndex;
// Combine collision materials (use material from first particle in simplex)
BurstCollisionMaterial material = CombineCollisionMaterials(simplices[simplexStart], colliderIndex);
// Calculate relative velocity:
float4 rA = float4.zero, rB = float4.zero;
float4 prevPositionA = float4.zero;
float4 linearVelocityA = float4.zero;
float4 angularVelocityA = float4.zero;
float invRotationalMassA = 0;
quaternion orientationA = new quaternion(0, 0, 0, 0);
float4 simplexRadiiA = float4.zero;
for (int j = 0; j < simplexSize; ++j)
{
int particleIndex = simplices[simplexStart + j];
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];
orientationA.value += orientations[particleIndex].value * contact.pointA[j];
simplexRadiiA += radii[particleIndex] * 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);
relativeVelocity += new float4(math.cross(angularVelocityA.xyz, rA.xyz), 0);
}
// Subtract rigidbody velocity:
if (rigidbodyIndex >= 0)
{
// 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);
}
// Determine impulse magnitude:
float2 impulses = contact.SolveFriction(effectiveMasses[i].TotalTangentInvMass, effectiveMasses[i].TotalBitangentInvMass, relativeVelocity, material.staticFriction, material.dynamicFriction, stepTime);
if (math.abs(impulses.x) > BurstMath.epsilon || math.abs(impulses.y) > BurstMath.epsilon)
{
float4 tangentImpulse = impulses.x * contact.tangent;
float4 bitangentImpulse = impulses.y * contact.bitangent;
float4 totalImpulse = tangentImpulse + bitangentImpulse;
float baryScale = BurstMath.BaryScale(contact.pointA);
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;
counts[particleIndex]++;
}
if (rigidbodyIndex >= 0)
{
BurstMath.ApplyImpulse(rigidbodyIndex, -totalImpulse, contact.pointB, rigidbodies, rigidbodyLinearDeltas, rigidbodyAngularDeltas, inertialFrame.frame);
}
// Rolling contacts:
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);
float4 angVelDeltaA = math.mul(solverInertiaA, new float4(math.cross(rA.xyz, totalImpulse.xyz), 0));
float4 angVelDeltaB = float4.zero;
// Final angular velocities, after adding the deltas:
angularVelocityA += angVelDeltaA;
float4 angularVelocityB = float4.zero;
// Calculate weights (inverse masses):
float invMassA = math.length(math.mul(solverInertiaA, math.normalizesafe(angularVelocityA)));
float invMassB = 0;
if (rigidbodyIndex >= 0)
{
angVelDeltaB = math.mul(-rigidbodies[rigidbodyIndex].inverseInertiaTensor, new float4(math.cross(rB.xyz, totalImpulse.xyz), 0));
angularVelocityB = rigidbodies[rigidbodyIndex].angularVelocity + angVelDeltaB;
invMassB = math.length(math.mul(rigidbodies[rigidbodyIndex].inverseInertiaTensor, math.normalizesafe(angularVelocityB)));
}
// Calculate rolling axis and angular velocity deltas:
float4 rollAxis = float4.zero;
float rollingImpulse = contact.SolveRollingFriction(angularVelocityA, angularVelocityB, material.rollingFriction, invMassA, invMassB, ref rollAxis);
angVelDeltaA += rollAxis * rollingImpulse * invMassA;
angVelDeltaB -= rollAxis * rollingImpulse * invMassB;
// Apply orientation delta to particles:
quaternion orientationDelta = BurstIntegration.AngularVelocityToSpinQuaternion(orientationA, angVelDeltaA, substepTime);
for (int j = 0; j < simplexSize; ++j)
{
int particleIndex = simplices[simplexStart + j];
quaternion qA = orientationDeltas[particleIndex];
qA.value += orientationDelta.value;
orientationDeltas[particleIndex] = qA;
orientationCounts[particleIndex]++;
}
// Apply angular velocity delta to rigidbody:
if (rigidbodyIndex >= 0)
{
float4 angularDelta = rigidbodyAngularDeltas[rigidbodyIndex];
angularDelta += angVelDeltaB;
rigidbodyAngularDeltas[rigidbodyIndex] = angularDelta;
}
}
}
contacts[i] = contact;
}
}
private BurstCollisionMaterial CombineCollisionMaterials(int entityA, int entityB)
{
// Combine collision materials:
int particleMaterialIndex = particleMaterialIndices[entityA];
int colliderMaterialIndex = shapes[entityB].materialIndex;
if (colliderMaterialIndex >= 0 && particleMaterialIndex >= 0)
return BurstCollisionMaterial.CombineWith(collisionMaterials[particleMaterialIndex], collisionMaterials[colliderMaterialIndex]);
else if (particleMaterialIndex >= 0)
return collisionMaterials[particleMaterialIndex];
else if (colliderMaterialIndex >= 0)
return collisionMaterials[colliderMaterialIndex];
return new BurstCollisionMaterial();
}
}
}
}
#endif

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 9abf9b1d2ee1a4d09b965103ae78fe53
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: