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

107 lines
3.5 KiB
Plaintext

#include "ColliderDefinitions.cginc"
#include "QueryDefinitions.cginc"
#include "ContactHandling.cginc"
#include "Transform.cginc"
#include "Simplex.cginc"
#include "Bounds.cginc"
#include "SolverParameters.cginc"
#include "Optimization.cginc"
#pragma kernel GenerateResults
StructuredBuffer<float4> positions;
StructuredBuffer<quaternion> orientations;
StructuredBuffer<float4> principalRadii;
StructuredBuffer<int> simplices;
StructuredBuffer<transform> transforms;
StructuredBuffer<queryShape> shapes;
StructuredBuffer<uint2> contactPairs;
StructuredBuffer<int> contactOffsetsPerType;
RWStructuredBuffer<queryResult> results;
RWStructuredBuffer<uint> dispatchBuffer;
StructuredBuffer<transform> worldToSolver;
uint maxContacts;
struct Sphere : IDistanceFunction
{
queryShape s;
transform colliderToSolver;
void Evaluate(in float4 pos, in float4 radii, in quaternion orientation, inout SurfacePoint projectedPoint)
{
float4 center = s.center * colliderToSolver.scale;
float4 pnt = colliderToSolver.InverseTransformPointUnscaled(pos) - center;
float radius = s.size.x * cmax(colliderToSolver.scale.xyz);
float distanceToCenter = length(pnt);
float4 normal = pnt / (distanceToCenter + EPSILON);
projectedPoint.pos = colliderToSolver.TransformPointUnscaled(center + normal * (radius + s.contactOffset));
projectedPoint.normal = colliderToSolver.TransformDirection(normal);
projectedPoint.bary = float4(1,0,0,0);
}
};
[numthreads(128, 1, 1)]
void GenerateResults (uint3 id : SV_DispatchThreadID)
{
uint i = id.x;
// entry #11 in the dispatch buffer is the amount of pairs for the first shape type.
if (i >= dispatchBuffer[11 + 4*SPHERE_QUERY]) return;
int firstPair = contactOffsetsPerType[SPHERE_QUERY];
int simplexIndex = contactPairs[firstPair + i].x;
int queryIndex = contactPairs[firstPair + i].y;
queryResult c = (queryResult)0;
Sphere sphereShape;
sphereShape.colliderToSolver = worldToSolver[0].Multiply(transforms[queryIndex]);
sphereShape.s = shapes[queryIndex];
int simplexSize;
int simplexStart = GetSimplexStartAndSize(simplexIndex, simplexSize);
float4 simplexBary = BarycenterForSimplexOfSize(simplexSize);
float4 simplexPoint;
SurfacePoint surfacePoint = Optimize(sphereShape, positions, orientations, principalRadii,
simplices, simplexStart, simplexSize, simplexBary, simplexPoint, surfaceCollisionIterations, surfaceCollisionTolerance);
float4 simplexPrevPosition = FLOAT4_ZERO;
float simplexRadius = 0;
for (int j = 0; j < simplexSize; ++j)
{
int particleIndex = simplices[simplexStart + j];
simplexPrevPosition += positions[particleIndex] * simplexBary[j];
simplexRadius += EllipsoidRadius(surfacePoint.normal, orientations[particleIndex], principalRadii[particleIndex].xyz) * simplexBary[j];
}
c.queryPoint = surfacePoint.pos;
c.normal = surfacePoint.normal;
c.simplexBary = simplexBary;
c.simplexIndex = simplexIndex;
c.queryIndex = queryIndex;
c.dist = dot(simplexPrevPosition - surfacePoint.pos,surfacePoint.normal) - simplexRadius;
if (c.dist <= sphereShape.s.maxDistance)
{
uint count = results.IncrementCounter();
if (count < maxContacts)
{
results[count] = c;
InterlockedMax(dispatchBuffer[0],(count + 1) / 128 + 1);
InterlockedMax(dispatchBuffer[3], count + 1);
}
}
}