去掉obi,使用自写绳索
This commit is contained in:
@@ -1,62 +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 ApplyBatchedCollisionConstraintsBatchJob : IJobParallelFor
|
||||
{
|
||||
[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;
|
||||
[ReadOnly] public BatchData batchData;
|
||||
|
||||
public void Execute(int workItemIndex)
|
||||
{
|
||||
int start, end;
|
||||
batchData.GetConstraintRange(workItemIndex, out start, out end);
|
||||
|
||||
for (int i = start; i < end; ++i)
|
||||
{
|
||||
int simplexStartA = simplexCounts.GetSimplexStartAndSize(contacts[i].bodyA, out int simplexSizeA);
|
||||
int simplexStartB = simplexCounts.GetSimplexStartAndSize(contacts[i].bodyB, out int simplexSizeB);
|
||||
|
||||
for (int j = 0; j < simplexSizeA; ++j)
|
||||
{
|
||||
int particleIndex = simplices[simplexStartA + j];
|
||||
BurstConstraintsBatchImpl.ApplyPositionDelta(particleIndex, constraintParameters.SORFactor, ref positions, ref deltas, ref counts);
|
||||
BurstConstraintsBatchImpl.ApplyOrientationDelta(particleIndex, constraintParameters.SORFactor, ref orientations, ref orientationDeltas, ref orientationCounts);
|
||||
}
|
||||
|
||||
for (int j = 0; j < simplexSizeB; ++j)
|
||||
{
|
||||
int particleIndex = simplices[simplexStartB + j];
|
||||
BurstConstraintsBatchImpl.ApplyPositionDelta(particleIndex, constraintParameters.SORFactor, ref positions, ref deltas, ref counts);
|
||||
BurstConstraintsBatchImpl.ApplyOrientationDelta(particleIndex, constraintParameters.SORFactor, ref orientations, ref orientationDeltas, ref orientationCounts);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96623cff9b30e4504a4a6dbfe3d19ace
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,32 +0,0 @@
|
||||
#if (OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS)
|
||||
using System;
|
||||
using Unity.Jobs;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class BurstParticleCollisionConstraints : BurstConstraintsImpl<BurstParticleCollisionConstraintsBatch>
|
||||
{
|
||||
public BurstParticleCollisionConstraints(BurstSolverImpl solver) : base(solver, Oni.ConstraintType.ParticleCollision)
|
||||
{
|
||||
}
|
||||
|
||||
public override IConstraintsBatchImpl CreateConstraintsBatch()
|
||||
{
|
||||
var dataBatch = new BurstParticleCollisionConstraintsBatch(this);
|
||||
batches.Add(dataBatch);
|
||||
return dataBatch;
|
||||
}
|
||||
|
||||
public override void RemoveBatch(IConstraintsBatchImpl batch)
|
||||
{
|
||||
batches.Remove(batch as BurstParticleCollisionConstraintsBatch);
|
||||
batch.Destroy();
|
||||
}
|
||||
|
||||
public override int GetConstraintCount()
|
||||
{
|
||||
return ((BurstSolverImpl)solver).abstraction.particleContacts.count;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ef36a05943714c1db8f9ee0b28e9c51
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,364 +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 BurstParticleCollisionConstraintsBatch : BurstConstraintsBatchImpl, IParticleCollisionConstraintsBatchImpl
|
||||
{
|
||||
public BatchData batchData;
|
||||
|
||||
public BurstParticleCollisionConstraintsBatch(BurstParticleCollisionConstraints constraints)
|
||||
{
|
||||
m_Constraints = constraints;
|
||||
m_ConstraintType = Oni.ConstraintType.ParticleCollision;
|
||||
}
|
||||
|
||||
public BurstParticleCollisionConstraintsBatch(BatchData batchData) : base()
|
||||
{
|
||||
this.batchData = batchData;
|
||||
}
|
||||
|
||||
public override JobHandle Initialize(JobHandle inputDeps, float stepTime, float substepTime, int steps, float timeLeft)
|
||||
{
|
||||
var updateContacts = new UpdateParticleContactsJob()
|
||||
{
|
||||
prevPositions = solverImplementation.prevPositions,
|
||||
prevOrientations = solverImplementation.prevOrientations,
|
||||
velocities = solverImplementation.velocities,
|
||||
radii = solverImplementation.principalRadii,
|
||||
invMasses = solverImplementation.invMasses,
|
||||
invRotationalMasses = solverImplementation.invRotationalMasses,
|
||||
|
||||
simplices = solverImplementation.simplices,
|
||||
simplexCounts = solverImplementation.simplexCounts,
|
||||
|
||||
particleMaterialIndices = solverImplementation.collisionMaterials,
|
||||
collisionMaterials = ObiColliderWorld.GetInstance().collisionMaterials.AsNativeArray<BurstCollisionMaterial>(),
|
||||
|
||||
contacts = ((BurstSolverImpl)constraints.solver).abstraction.particleContacts.AsNativeArray<BurstContact>(),
|
||||
effectiveMasses = ((BurstSolverImpl)constraints.solver).abstraction.particleContactEffectiveMasses.AsNativeArray<ContactEffectiveMasses>(),
|
||||
batchData = batchData
|
||||
};
|
||||
|
||||
int batchCount = batchData.isLast ? batchData.workItemCount : 1;
|
||||
return updateContacts.Schedule(batchData.workItemCount, batchCount, inputDeps);
|
||||
}
|
||||
|
||||
public override JobHandle Evaluate(JobHandle inputDeps, float stepTime, float substepTime, int steps, float timeLeft)
|
||||
{
|
||||
var parameters = solverAbstraction.GetConstraintParameters(m_ConstraintType);
|
||||
|
||||
var projectConstraints = new ParticleCollisionConstraintsBatchJob()
|
||||
{
|
||||
positions = solverImplementation.positions,
|
||||
orientations = solverImplementation.orientations,
|
||||
invMasses = solverImplementation.invMasses,
|
||||
radii = solverImplementation.principalRadii,
|
||||
particleMaterialIndices = solverImplementation.collisionMaterials,
|
||||
fluidInterface = solverImplementation.fluidInterface,
|
||||
collisionMaterials = ObiColliderWorld.GetInstance().collisionMaterials.AsNativeArray<BurstCollisionMaterial>(),
|
||||
|
||||
simplices = solverImplementation.simplices,
|
||||
simplexCounts = solverImplementation.simplexCounts,
|
||||
|
||||
deltas = solverImplementation.positionDeltas,
|
||||
counts = solverImplementation.positionConstraintCounts,
|
||||
userData = solverImplementation.userData,
|
||||
contacts = solverAbstraction.particleContacts.AsNativeArray<BurstContact>(),
|
||||
effectiveMasses = ((BurstSolverImpl)constraints.solver).abstraction.particleContactEffectiveMasses.AsNativeArray<ContactEffectiveMasses>(),
|
||||
batchData = batchData,
|
||||
|
||||
constraintParameters = parameters,
|
||||
solverParameters = solverImplementation.abstraction.parameters,
|
||||
gravity = new float4(solverImplementation.abstraction.parameters.gravity, 0),
|
||||
substepTime = substepTime,
|
||||
};
|
||||
|
||||
int batchCount = batchData.isLast ? batchData.workItemCount : 1;
|
||||
return projectConstraints.Schedule(batchData.workItemCount, batchCount, inputDeps);
|
||||
}
|
||||
|
||||
public override JobHandle Apply(JobHandle inputDeps, float substepTime)
|
||||
{
|
||||
var parameters = solverAbstraction.GetConstraintParameters(m_ConstraintType);
|
||||
|
||||
var applyConstraints = new ApplyBatchedCollisionConstraintsBatchJob()
|
||||
{
|
||||
contacts = solverAbstraction.particleContacts.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,
|
||||
batchData = batchData,
|
||||
constraintParameters = parameters,
|
||||
};
|
||||
|
||||
int batchCount = batchData.isLast ? batchData.workItemCount : 1;
|
||||
return applyConstraints.Schedule(batchData.workItemCount, batchCount, inputDeps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates contact data (contact distance and frame) 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 UpdateParticleContactsJob : 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;
|
||||
|
||||
[NativeDisableContainerSafetyRestriction] [NativeDisableParallelForRestriction] public NativeArray<ContactEffectiveMasses> effectiveMasses;
|
||||
[NativeDisableContainerSafetyRestriction] [NativeDisableParallelForRestriction] public NativeArray<BurstContact> contacts;
|
||||
|
||||
[ReadOnly] public BatchData batchData;
|
||||
|
||||
public void Execute(int workItemIndex)
|
||||
{
|
||||
int start, end;
|
||||
batchData.GetConstraintRange(workItemIndex, out start, out end);
|
||||
|
||||
for (int i = start; i < end; ++i)
|
||||
{
|
||||
var contact = contacts[i];
|
||||
var efMasses = effectiveMasses[i];
|
||||
|
||||
int simplexStartA = simplexCounts.GetSimplexStartAndSize(contact.bodyA, out int simplexSizeA);
|
||||
int simplexStartB = simplexCounts.GetSimplexStartAndSize(contact.bodyB, out int simplexSizeB);
|
||||
|
||||
float4 simplexVelocityA = float4.zero;
|
||||
float4 simplexPrevPositionA = float4.zero;
|
||||
quaternion simplexPrevOrientationA = new quaternion(0, 0, 0, 0);
|
||||
float simplexRadiusA = 0;
|
||||
float simplexInvMassA = 0;
|
||||
float simplexInvRotationalMassA = 0;
|
||||
|
||||
float4 simplexVelocityB = float4.zero;
|
||||
float4 simplexPrevPositionB = float4.zero;
|
||||
quaternion simplexPrevOrientationB = new quaternion(0, 0, 0, 0);
|
||||
float simplexRadiusB = 0;
|
||||
float simplexInvMassB = 0;
|
||||
float simplexInvRotationalMassB = 0;
|
||||
|
||||
for (int j = 0; j < simplexSizeA; ++j)
|
||||
{
|
||||
int particleIndex = simplices[simplexStartA + j];
|
||||
simplexVelocityA += velocities[particleIndex] * contact.pointA[j];
|
||||
simplexPrevPositionA += prevPositions[particleIndex] * contact.pointA[j];
|
||||
simplexPrevOrientationA.value += prevOrientations[particleIndex].value * contact.pointA[j];
|
||||
simplexInvMassA += invMasses[particleIndex] * contact.pointA[j];
|
||||
simplexInvRotationalMassA += invRotationalMasses[particleIndex] * contact.pointA[j];
|
||||
simplexRadiusA += BurstMath.EllipsoidRadius(contact.normal, prevOrientations[particleIndex], radii[particleIndex].xyz) * contact.pointA[j];
|
||||
}
|
||||
|
||||
for (int j = 0; j < simplexSizeB; ++j)
|
||||
{
|
||||
int particleIndex = simplices[simplexStartB + j];
|
||||
simplexVelocityB += velocities[particleIndex] * contact.pointB[j];
|
||||
simplexPrevPositionB += prevPositions[particleIndex] * contact.pointB[j];
|
||||
simplexPrevOrientationB.value += prevOrientations[particleIndex].value * contact.pointB[j];
|
||||
simplexInvMassB += invMasses[particleIndex] * contact.pointB[j];
|
||||
simplexInvRotationalMassB += invRotationalMasses[particleIndex] * contact.pointB[j];
|
||||
simplexRadiusB += BurstMath.EllipsoidRadius(contact.normal, prevOrientations[particleIndex], radii[particleIndex].xyz) * contact.pointB[j];
|
||||
}
|
||||
|
||||
simplexPrevPositionA.w = 0;
|
||||
simplexPrevPositionB.w = 0;
|
||||
|
||||
// update contact distance
|
||||
float4 contactPointA = simplexPrevPositionA - contact.normal * simplexRadiusA;
|
||||
float4 contactPointB = simplexPrevPositionB + contact.normal * simplexRadiusB;
|
||||
|
||||
contact.distance = math.dot(contactPointA - contactPointB, contact.normal);
|
||||
|
||||
// update contact basis:
|
||||
contact.CalculateTangent(simplexVelocityA - simplexVelocityB);
|
||||
|
||||
// update contact masses:
|
||||
int aMaterialIndex = particleMaterialIndices[simplices[simplexStartA]];
|
||||
int bMaterialIndex = particleMaterialIndices[simplices[simplexStartB]];
|
||||
bool rollingContacts = (aMaterialIndex >= 0 ? collisionMaterials[aMaterialIndex].rollingContacts > 0 : false) |
|
||||
(bMaterialIndex >= 0 ? collisionMaterials[bMaterialIndex].rollingContacts > 0 : false);
|
||||
|
||||
float4 invInertiaTensorA = math.rcp(BurstMath.GetParticleInertiaTensor(simplexRadiusA, simplexInvRotationalMassA) + new float4(BurstMath.epsilon));
|
||||
float4 invInertiaTensorB = math.rcp(BurstMath.GetParticleInertiaTensor(simplexRadiusB, simplexInvRotationalMassB) + new float4(BurstMath.epsilon));
|
||||
|
||||
efMasses.CalculateContactMassesA(simplexInvMassA, invInertiaTensorA, simplexPrevPositionA, simplexPrevOrientationA, contactPointA, contact.normal, contact.tangent, contact.bitangent, rollingContacts);
|
||||
efMasses.CalculateContactMassesB(simplexInvMassB, invInertiaTensorB, simplexPrevPositionB, simplexPrevOrientationB, contactPointB, contact.normal, contact.tangent, contact.bitangent, rollingContacts);
|
||||
|
||||
contacts[i] = contact;
|
||||
effectiveMasses[i] = efMasses;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[BurstCompile]
|
||||
public struct ParticleCollisionConstraintsBatchJob : IJobParallelFor
|
||||
{
|
||||
[ReadOnly] public NativeArray<quaternion> orientations;
|
||||
[ReadOnly] public NativeArray<float> invMasses;
|
||||
[ReadOnly] public NativeArray<float4> radii;
|
||||
[ReadOnly] public NativeArray<int> particleMaterialIndices;
|
||||
[ReadOnly] public NativeArray<float4> fluidInterface;
|
||||
[ReadOnly] public NativeArray<BurstCollisionMaterial> collisionMaterials;
|
||||
|
||||
// simplex arrays:
|
||||
[ReadOnly] public NativeArray<int> simplices;
|
||||
[ReadOnly] public SimplexCounts simplexCounts;
|
||||
|
||||
[NativeDisableContainerSafetyRestriction] [NativeDisableParallelForRestriction] public NativeArray<float4> positions;
|
||||
[NativeDisableContainerSafetyRestriction] [NativeDisableParallelForRestriction] public NativeArray<float4> deltas;
|
||||
[NativeDisableContainerSafetyRestriction] [NativeDisableParallelForRestriction] public NativeArray<float4> userData;
|
||||
[NativeDisableContainerSafetyRestriction] [NativeDisableParallelForRestriction] public NativeArray<int> counts;
|
||||
[NativeDisableContainerSafetyRestriction] [NativeDisableParallelForRestriction] public NativeArray<BurstContact> contacts;
|
||||
[ReadOnly] public NativeArray<ContactEffectiveMasses> effectiveMasses;
|
||||
|
||||
[ReadOnly] public Oni.ConstraintParameters constraintParameters;
|
||||
[ReadOnly] public Oni.SolverParameters solverParameters;
|
||||
[ReadOnly] public float4 gravity;
|
||||
[ReadOnly] public float substepTime;
|
||||
|
||||
[ReadOnly] public BatchData batchData;
|
||||
|
||||
public void Execute(int workItemIndex)
|
||||
{
|
||||
int start, end;
|
||||
batchData.GetConstraintRange(workItemIndex, out start, out end);
|
||||
|
||||
for (int i = start; i < end; ++i)
|
||||
{
|
||||
var contact = contacts[i];
|
||||
|
||||
int simplexStartA = simplexCounts.GetSimplexStartAndSize(contact.bodyA, out int simplexSizeA);
|
||||
int simplexStartB = simplexCounts.GetSimplexStartAndSize(contact.bodyB, out int simplexSizeB);
|
||||
|
||||
// Combine collision materials:
|
||||
BurstCollisionMaterial material = CombineCollisionMaterials(simplices[simplexStartA], simplices[simplexStartB]);
|
||||
|
||||
float4 simplexPositionA = float4.zero, simplexPositionB = float4.zero;
|
||||
float simplexRadiusA = 0, simplexRadiusB = 0;
|
||||
float4 simplexUserDataA = float4.zero, simplexUserDataB = float4.zero;
|
||||
float miscibility = 0;
|
||||
|
||||
for (int j = 0; j < simplexSizeA; ++j)
|
||||
{
|
||||
int particleIndex = simplices[simplexStartA + j];
|
||||
simplexPositionA += positions[particleIndex] * contact.pointA[j];
|
||||
simplexRadiusA += BurstMath.EllipsoidRadius(contact.normal, orientations[particleIndex], radii[particleIndex].xyz) * contact.pointA[j];
|
||||
simplexUserDataA += userData[particleIndex] * contact.pointA[j];
|
||||
miscibility += fluidInterface[particleIndex].w * contact.pointA[j];
|
||||
}
|
||||
for (int j = 0; j < simplexSizeB; ++j)
|
||||
{
|
||||
int particleIndex = simplices[simplexStartB + j];
|
||||
simplexPositionB += positions[particleIndex] * contact.pointB[j];
|
||||
simplexRadiusB += BurstMath.EllipsoidRadius(contact.normal, orientations[particleIndex], radii[particleIndex].xyz) * contact.pointA[j];
|
||||
simplexUserDataB += userData[particleIndex] * contact.pointB[j];
|
||||
miscibility += fluidInterface[particleIndex].w * contact.pointB[j];
|
||||
}
|
||||
|
||||
simplexPositionA.w = 0;
|
||||
simplexPositionB.w = 0;
|
||||
|
||||
float4 posA = simplexPositionA - contact.normal * simplexRadiusA;
|
||||
float4 posB = simplexPositionB + contact.normal * simplexRadiusB;
|
||||
|
||||
// adhesion:
|
||||
float lambda = contact.SolveAdhesion(effectiveMasses[i].TotalNormalInvMass, posA, posB, material.stickDistance, material.stickiness, substepTime);
|
||||
|
||||
// depenetration:
|
||||
lambda += contact.SolvePenetration(effectiveMasses[i].TotalNormalInvMass, posA, posB, solverParameters.maxDepenetration * substepTime);
|
||||
|
||||
// Apply normal impulse to both particles (w/ shock propagation):
|
||||
if (math.abs(lambda) > BurstMath.epsilon)
|
||||
{
|
||||
float shock = solverParameters.shockPropagation * math.dot(contact.normal, math.normalizesafe(gravity));
|
||||
float4 delta = lambda * contact.normal;
|
||||
|
||||
float baryScale = BurstMath.BaryScale(contact.pointA);
|
||||
for (int j = 0; j < simplexSizeA; ++j)
|
||||
{
|
||||
int particleIndex = simplices[simplexStartA + j];
|
||||
deltas[particleIndex] += delta * invMasses[particleIndex] * contact.pointA[j] * baryScale * (1 - shock);
|
||||
counts[particleIndex]++;
|
||||
}
|
||||
|
||||
baryScale = BurstMath.BaryScale(contact.pointB);
|
||||
for (int j = 0; j < simplexSizeB; ++j)
|
||||
{
|
||||
int particleIndex = simplices[simplexStartB + j];
|
||||
deltas[particleIndex] -= delta * invMasses[particleIndex] * contact.pointB[j] * baryScale * (1 + shock);
|
||||
counts[particleIndex]++;
|
||||
}
|
||||
}
|
||||
|
||||
// property diffusion:
|
||||
if (contact.distance < solverParameters.collisionMargin)
|
||||
{
|
||||
float diffusionSpeed = miscibility * 0.5f * substepTime;
|
||||
float4 userDelta = (simplexUserDataB - simplexUserDataA) * solverParameters.diffusionMask * diffusionSpeed;
|
||||
|
||||
for (int j = 0; j < simplexSizeA; ++j)
|
||||
userData[simplices[simplexStartA + j]] += userDelta * contact.pointA[j];
|
||||
|
||||
for (int j = 0; j < simplexSizeB; ++j)
|
||||
userData[simplices[simplexStartB + j]] -= userDelta * contact.pointB[j];
|
||||
}
|
||||
|
||||
// Apply position deltas immediately, if using sequential evaluation:
|
||||
if (constraintParameters.evaluationOrder == Oni.ConstraintParameters.EvaluationOrder.Sequential)
|
||||
{
|
||||
for (int j = 0; j < simplexSizeA; ++j)
|
||||
ApplyPositionDelta(simplices[simplexStartA + j], constraintParameters.SORFactor, ref positions, ref deltas, ref counts);
|
||||
|
||||
for (int j = 0; j < simplexSizeB; ++j)
|
||||
ApplyPositionDelta(simplices[simplexStartB + j], constraintParameters.SORFactor, ref positions, ref deltas, ref counts);
|
||||
}
|
||||
|
||||
contacts[i] = contact;
|
||||
}
|
||||
}
|
||||
|
||||
private BurstCollisionMaterial CombineCollisionMaterials(int entityA, int entityB)
|
||||
{
|
||||
// Combine collision materials:
|
||||
int aMaterialIndex = particleMaterialIndices[entityA];
|
||||
int bMaterialIndex = particleMaterialIndices[entityB];
|
||||
|
||||
if (aMaterialIndex >= 0 && bMaterialIndex >= 0)
|
||||
return BurstCollisionMaterial.CombineWith(collisionMaterials[aMaterialIndex], collisionMaterials[bMaterialIndex]);
|
||||
else if (aMaterialIndex >= 0)
|
||||
return collisionMaterials[aMaterialIndex];
|
||||
else if (bMaterialIndex >= 0)
|
||||
return collisionMaterials[bMaterialIndex];
|
||||
|
||||
return new BurstCollisionMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61f5c3e93290646948b251d617f01c8d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,31 +0,0 @@
|
||||
#if (OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS)
|
||||
using System;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class BurstParticleFrictionConstraints : BurstConstraintsImpl<BurstParticleFrictionConstraintsBatch>
|
||||
{
|
||||
public BurstParticleFrictionConstraints(BurstSolverImpl solver) : base(solver, Oni.ConstraintType.ParticleFriction)
|
||||
{
|
||||
}
|
||||
|
||||
public override IConstraintsBatchImpl CreateConstraintsBatch()
|
||||
{
|
||||
var dataBatch = new BurstParticleFrictionConstraintsBatch(this);
|
||||
batches.Add(dataBatch);
|
||||
return dataBatch;
|
||||
}
|
||||
|
||||
public override void RemoveBatch(IConstraintsBatchImpl batch)
|
||||
{
|
||||
batches.Remove(batch as BurstParticleFrictionConstraintsBatch);
|
||||
batch.Destroy();
|
||||
}
|
||||
|
||||
public override int GetConstraintCount()
|
||||
{
|
||||
return ((BurstSolverImpl)solver).abstraction.particleContacts.count;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63dade0c384ee4c1398ddf4d60038764
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,289 +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 BurstParticleFrictionConstraintsBatch : BurstConstraintsBatchImpl, IParticleFrictionConstraintsBatchImpl
|
||||
{
|
||||
public BatchData batchData;
|
||||
|
||||
public BurstParticleFrictionConstraintsBatch(BurstParticleFrictionConstraints constraints)
|
||||
{
|
||||
m_Constraints = constraints;
|
||||
m_ConstraintType = Oni.ConstraintType.ParticleFriction;
|
||||
}
|
||||
|
||||
public BurstParticleFrictionConstraintsBatch(BatchData batchData) : base()
|
||||
{
|
||||
this.batchData = batchData;
|
||||
}
|
||||
|
||||
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 ParticleFrictionConstraintsBatchJob()
|
||||
{
|
||||
positions = solverImplementation.positions,
|
||||
prevPositions = solverImplementation.prevPositions,
|
||||
orientations = solverImplementation.orientations,
|
||||
prevOrientations = solverImplementation.prevOrientations,
|
||||
|
||||
invMasses = solverImplementation.invMasses,
|
||||
invRotationalMasses = solverImplementation.invRotationalMasses,
|
||||
radii = solverImplementation.principalRadii,
|
||||
particleMaterialIndices = solverImplementation.collisionMaterials,
|
||||
collisionMaterials = ObiColliderWorld.GetInstance().collisionMaterials.AsNativeArray<BurstCollisionMaterial>(),
|
||||
|
||||
simplices = solverImplementation.simplices,
|
||||
simplexCounts = solverImplementation.simplexCounts,
|
||||
|
||||
deltas = solverImplementation.positionDeltas,
|
||||
counts = solverImplementation.positionConstraintCounts,
|
||||
orientationDeltas = solverImplementation.orientationDeltas,
|
||||
orientationCounts = solverImplementation.orientationConstraintCounts,
|
||||
contacts = ((BurstSolverImpl)constraints.solver).abstraction.particleContacts.AsNativeArray<BurstContact>(),
|
||||
effectiveMasses = ((BurstSolverImpl)constraints.solver).abstraction.particleContactEffectiveMasses.AsNativeArray<ContactEffectiveMasses>(),
|
||||
|
||||
batchData = batchData,
|
||||
substepTime = substepTime,
|
||||
};
|
||||
|
||||
int batchCount = batchData.isLast ? batchData.workItemCount : 1;
|
||||
return projectConstraints.Schedule(batchData.workItemCount, batchCount, inputDeps);
|
||||
}
|
||||
|
||||
public override JobHandle Apply(JobHandle inputDeps, float substepTime)
|
||||
{
|
||||
|
||||
var parameters = solverAbstraction.GetConstraintParameters(m_ConstraintType);
|
||||
|
||||
var applyConstraints = new ApplyBatchedCollisionConstraintsBatchJob()
|
||||
{
|
||||
contacts = solverAbstraction.particleContacts.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,
|
||||
batchData = batchData
|
||||
};
|
||||
|
||||
int batchCount = batchData.isLast ? batchData.workItemCount : 1;
|
||||
return applyConstraints.Schedule(batchData.workItemCount, batchCount, inputDeps);
|
||||
}
|
||||
|
||||
[BurstCompile]
|
||||
public struct ParticleFrictionConstraintsBatchJob : IJobParallelFor
|
||||
{
|
||||
|
||||
[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;
|
||||
[ReadOnly] public NativeArray<BurstCollisionMaterial> collisionMaterials;
|
||||
|
||||
// simplex arrays:
|
||||
[ReadOnly] public NativeArray<int> simplices;
|
||||
[ReadOnly] public SimplexCounts simplexCounts;
|
||||
|
||||
[NativeDisableContainerSafetyRestriction] [NativeDisableParallelForRestriction] public NativeArray<float4> deltas;
|
||||
[NativeDisableContainerSafetyRestriction] [NativeDisableParallelForRestriction] public NativeArray<int> counts;
|
||||
|
||||
[NativeDisableContainerSafetyRestriction] [NativeDisableParallelForRestriction] public NativeArray<quaternion> orientationDeltas;
|
||||
[NativeDisableContainerSafetyRestriction] [NativeDisableParallelForRestriction] public NativeArray<int> orientationCounts;
|
||||
|
||||
[NativeDisableContainerSafetyRestriction] [NativeDisableParallelForRestriction] public NativeArray<BurstContact> contacts;
|
||||
[ReadOnly] public NativeArray<ContactEffectiveMasses> effectiveMasses;
|
||||
|
||||
[ReadOnly] public BatchData batchData;
|
||||
[ReadOnly] public float substepTime;
|
||||
|
||||
public void Execute(int workItemIndex)
|
||||
{
|
||||
int start, end;
|
||||
batchData.GetConstraintRange(workItemIndex, out start, out end);
|
||||
|
||||
for (int i = start; i < end; ++i)
|
||||
{
|
||||
var contact = contacts[i];
|
||||
|
||||
int simplexStartA = simplexCounts.GetSimplexStartAndSize(contact.bodyA, out int simplexSizeA);
|
||||
int simplexStartB = simplexCounts.GetSimplexStartAndSize(contact.bodyB, out int simplexSizeB);
|
||||
|
||||
// Combine collision materials:
|
||||
BurstCollisionMaterial material = CombineCollisionMaterials(simplices[simplexStartA], simplices[simplexStartB]);
|
||||
|
||||
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;
|
||||
|
||||
float4 prevPositionB = float4.zero;
|
||||
float4 linearVelocityB = float4.zero;
|
||||
float4 angularVelocityB = float4.zero;
|
||||
float invRotationalMassB = 0;
|
||||
quaternion orientationB = new quaternion(0, 0, 0, 0);
|
||||
float4 simplexRadiiB = float4.zero;
|
||||
|
||||
for (int j = 0; j < simplexSizeA; ++j)
|
||||
{
|
||||
int particleIndex = simplices[simplexStartA + 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];
|
||||
}
|
||||
for (int j = 0; j < simplexSizeB; ++j)
|
||||
{
|
||||
int particleIndex = simplices[simplexStartB + j];
|
||||
prevPositionB += prevPositions[particleIndex] * contact.pointB[j];
|
||||
linearVelocityB += BurstIntegration.DifferentiateLinear(positions[particleIndex], prevPositions[particleIndex], substepTime) * contact.pointB[j];
|
||||
angularVelocityB += BurstIntegration.DifferentiateAngular(orientations[particleIndex], prevOrientations[particleIndex], substepTime) * contact.pointB[j];
|
||||
invRotationalMassB += invRotationalMasses[particleIndex] * contact.pointB[j];
|
||||
orientationB.value += orientations[particleIndex].value * contact.pointB[j];
|
||||
simplexRadiiB += radii[particleIndex] * contact.pointB[j];
|
||||
}
|
||||
|
||||
float4 rA = float4.zero, rB = float4.zero;
|
||||
|
||||
// Consider angular velocities if rolling contacts are enabled:
|
||||
if (material.rollingContacts > 0)
|
||||
{
|
||||
rA = -contact.normal * BurstMath.EllipsoidRadius(contact.normal, orientationA, simplexRadiiA.xyz);
|
||||
rB = contact.normal * BurstMath.EllipsoidRadius(contact.normal, orientationB, simplexRadiiB.xyz);
|
||||
|
||||
linearVelocityA += new float4(math.cross(angularVelocityA.xyz, rA.xyz), 0);
|
||||
linearVelocityB += new float4(math.cross(angularVelocityB.xyz, rB.xyz), 0);
|
||||
}
|
||||
|
||||
// Calculate relative velocity:
|
||||
float4 relativeVelocity = linearVelocityA - linearVelocityB;
|
||||
|
||||
// Calculate friction impulses (in the tangent and bitangent directions):
|
||||
float2 impulses = contact.SolveFriction(effectiveMasses[i].TotalTangentInvMass, effectiveMasses[i].TotalBitangentInvMass, relativeVelocity, material.staticFriction, material.dynamicFriction, substepTime);
|
||||
|
||||
// Apply friction impulses to both particles:
|
||||
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 < simplexSizeA; ++j)
|
||||
{
|
||||
int particleIndex = simplices[simplexStartA + j];
|
||||
deltas[particleIndex] += (tangentImpulse * effectiveMasses[i].tangentInvMassA + bitangentImpulse * effectiveMasses[i].bitangentInvMassA) * substepTime * contact.pointA[j] * baryScale;
|
||||
counts[particleIndex]++;
|
||||
}
|
||||
|
||||
baryScale = BurstMath.BaryScale(contact.pointB);
|
||||
for (int j = 0; j < simplexSizeB; ++j)
|
||||
{
|
||||
int particleIndex = simplices[simplexStartB + j];
|
||||
deltas[particleIndex] -= (tangentImpulse * effectiveMasses[i].tangentInvMassB + bitangentImpulse * effectiveMasses[i].bitangentInvMassB) * substepTime * contact.pointB[j] * baryScale;
|
||||
counts[particleIndex]++;
|
||||
}
|
||||
|
||||
// Rolling contacts:
|
||||
if (material.rollingContacts > 0)
|
||||
{
|
||||
float4 invInertiaTensorA = math.rcp(BurstMath.GetParticleInertiaTensor(simplexRadiiA, invRotationalMassA) + new float4(BurstMath.epsilon));
|
||||
float4 invInertiaTensorB = math.rcp(BurstMath.GetParticleInertiaTensor(simplexRadiiB, invRotationalMassB) + new float4(BurstMath.epsilon));
|
||||
|
||||
// Calculate angular velocity deltas due to friction impulse:
|
||||
float4x4 solverInertiaA = BurstMath.TransformInertiaTensor(invInertiaTensorA, orientationA);
|
||||
float4x4 solverInertiaB = BurstMath.TransformInertiaTensor(invInertiaTensorB, orientationB);
|
||||
|
||||
float4 angVelDeltaA = math.mul(solverInertiaA, new float4(math.cross(rA.xyz, totalImpulse.xyz), 0));
|
||||
float4 angVelDeltaB = -math.mul(solverInertiaB, new float4(math.cross(rB.xyz, totalImpulse.xyz), 0));
|
||||
|
||||
// Final angular velocities, after adding the deltas:
|
||||
angularVelocityA += angVelDeltaA;
|
||||
angularVelocityB += angVelDeltaB;
|
||||
|
||||
// Calculate weights (inverse masses):
|
||||
float invMassA = math.length(math.mul(solverInertiaA, math.normalizesafe(angularVelocityA)));
|
||||
float invMassB = math.length(math.mul(solverInertiaB, 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 deltas to particles:
|
||||
quaternion orientationDeltaA = BurstIntegration.AngularVelocityToSpinQuaternion(orientationA, angVelDeltaA, substepTime);
|
||||
quaternion orientationDeltaB = BurstIntegration.AngularVelocityToSpinQuaternion(orientationB, angVelDeltaB, substepTime);
|
||||
|
||||
for (int j = 0; j < simplexSizeA; ++j)
|
||||
{
|
||||
int particleIndex = simplices[simplexStartA + j];
|
||||
quaternion qA = orientationDeltas[particleIndex];
|
||||
qA.value += orientationDeltaA.value;
|
||||
orientationDeltas[particleIndex] = qA;
|
||||
orientationCounts[particleIndex]++;
|
||||
}
|
||||
|
||||
for (int j = 0; j < simplexSizeB; ++j)
|
||||
{
|
||||
int particleIndex = simplices[simplexStartB + j];
|
||||
quaternion qB = orientationDeltas[particleIndex];
|
||||
qB.value += orientationDeltaB.value;
|
||||
orientationDeltas[particleIndex] = qB;
|
||||
orientationCounts[particleIndex]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contacts[i] = contact;
|
||||
}
|
||||
}
|
||||
|
||||
private BurstCollisionMaterial CombineCollisionMaterials(int entityA, int entityB)
|
||||
{
|
||||
// Combine collision materials:
|
||||
int aMaterialIndex = particleMaterialIndices[entityA];
|
||||
int bMaterialIndex = particleMaterialIndices[entityB];
|
||||
|
||||
if (aMaterialIndex >= 0 && bMaterialIndex >= 0)
|
||||
return BurstCollisionMaterial.CombineWith(collisionMaterials[aMaterialIndex], collisionMaterials[bMaterialIndex]);
|
||||
else if (aMaterialIndex >= 0)
|
||||
return collisionMaterials[aMaterialIndex];
|
||||
else if (bMaterialIndex >= 0)
|
||||
return collisionMaterials[bMaterialIndex];
|
||||
|
||||
return new BurstCollisionMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9a942dd261ea741b69997eba73462034
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user