#pragma kernel Project #pragma kernel Apply #include "MathUtils.cginc" #include "AtomicDeltas.cginc" StructuredBuffer particleIndices; StructuredBuffer orientationIndices; StructuredBuffer restLengths; StructuredBuffer restOrientations; StructuredBuffer stiffnesses; RWStructuredBuffer lambdas; RWStructuredBuffer positions; RWStructuredBuffer orientations; StructuredBuffer invMasses; StructuredBuffer invRotationalMasses; // 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; int p1 = particleIndices[i * 2]; int p2 = particleIndices[i * 2 + 1]; int q = orientationIndices[i]; float w1 = invMasses[p1]; float w2 = invMasses[p2]; // calculate time adjusted compliance float3 compliances = stiffnesses[i] / (deltaTime * deltaTime); float3 e = rotate_vector(restOrientations[i], float3(0, 0, 1)); quaternion basis = qmul(orientations[q],restOrientations[i]); // calculate rod vector in local element space: float3 gamma = rotate_vector(q_conj(basis), (positions[p2] - positions[p1]).xyz) / (restLengths[i] + EPSILON); // subtract third director vector (0,0,1): gamma[2] -= 1; float W = (w1 + w2) / (restLengths[i] + EPSILON) + invRotationalMasses[q] * 4.0f * restLengths[i]; float3 dlambda = (gamma - compliances * lambdas[i]) / (W + compliances + EPSILON); lambdas[i] += dlambda; // convert lambda delta lambda back to world space: dlambda = rotate_vector(basis, dlambda); float4 delta1 = float4(dlambda, 0) * w1; float4 delta2 = -float4(dlambda, 0) * w2; quaternion e_3 = quaternion(e.x,e.y,e.z,0); quaternion q_e_3_bar = qmul(orientations[q],q_conj(e_3)); // calculate rotation delta: quaternion rotDelta = qmul(quaternion(dlambda[0], dlambda[1], dlambda[2], 0.0f),q_e_3_bar); rotDelta *= 2.0f * invRotationalMasses[q] * restLengths[i]; AddPositionDelta(p1, delta1); AddPositionDelta(p2, delta2); AddOrientationDelta(q, rotDelta); } [numthreads(128, 1, 1)] void Apply (uint3 id : SV_DispatchThreadID) { unsigned int i = id.x; if (i >= activeConstraintCount) return; int p1 = particleIndices[i * 2]; int p2 = particleIndices[i * 2 + 1]; int q = orientationIndices[i]; ApplyPositionDelta(positions, p1, sorFactor); ApplyPositionDelta(positions, p2, sorFactor); ApplyOrientationDelta(orientations, q, sorFactor); }