_xiaofang/xiaofang/Assets/Obi/Resources/Compute/SkinConstraints.compute
杨号敬 bcc74f0465 add
2024-12-18 02:18:45 +08:00

71 lines
2.2 KiB
Plaintext

#pragma kernel Project
#pragma kernel Apply
#include "MathUtils.cginc"
#include "AtomicDeltas.cginc"
StructuredBuffer<int> particleIndices;
StructuredBuffer<float4> skinPoints;
StructuredBuffer<float4> skinNormals;
StructuredBuffer<float3> skinRadiiBackstop;
StructuredBuffer<float> skinCompliance;
RWStructuredBuffer<float> lambdas;
RWStructuredBuffer<float4> positions;
StructuredBuffer<float> invMasses;
// Variables set from the CPU
uint activeConstraintCount;
float deltaTime;
float sorFactor;
[numthreads(128, 1, 1)]
void Project (uint3 id : SV_DispatchThreadID)
{
unsigned int i = id.x;
if (i >= activeConstraintCount) return;
float radius = skinRadiiBackstop[i].x;
float collisionRadius = skinRadiiBackstop[i].y;
float backstopDistance = collisionRadius + skinRadiiBackstop[i].z;
float compliance = skinCompliance[i] / (deltaTime * deltaTime);
int p = particleIndices[i];
if (invMasses[p] > 0)
{
float4 toSkin = positions[p] - skinPoints[i];
float4 toBackstop = positions[p] - (skinPoints[i] - skinNormals[i] * backstopDistance);
// distance to skin and backstop sphere centers:
float d = length(toSkin);
float b = length(toBackstop);
// constrain particle within skin radius.
// ignore mass in the equations (use 1), as we don't want particle mass to interfere with skin compliance.
// We should be able to adjust skin properties and particle mass (for collisions) independently.
float constraint = max(0,d - radius);
float dlambda = (-constraint - compliance * lambdas[i]) / (1 + compliance);
lambdas[i] += dlambda;
float4 skinCorrection = dlambda * toSkin / (d + EPSILON);
// constrain particle outside the backstop sphere (0 compliance):
constraint = min(0, b - collisionRadius);
float4 backstopCorrection = - constraint * toBackstop / (b + EPSILON);
AddPositionDelta(p, skinCorrection + backstopCorrection);
}
}
[numthreads(128, 1, 1)]
void Apply (uint3 id : SV_DispatchThreadID)
{
unsigned int i = id.x;
if (i >= activeConstraintCount) return;
int p1 = particleIndices[i];
ApplyPositionDelta(positions, p1, sorFactor);
}