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

108 lines
3.9 KiB
HLSL

#ifndef RIGIDBODY_INCLUDE
#define RIGIDBODY_INCLUDE
#include "InertialFrame.cginc"
#include "InterlockedUtils.cginc"
#include "Integration.cginc"
RWStructuredBuffer<uint4> linearDeltasAsInt;
RWStructuredBuffer<uint4> angularDeltasAsInt;
struct rigidbody
{
float4x4 inverseInertiaTensor;
float4 velocity;
float4 angularVelocity;
float4 com;
float inverseMass;
int constraintCount;
int pad1;
int pad2;
};
StructuredBuffer<rigidbody> rigidbodies;
void CalculateContactMassesB(in rigidbody rb,
in transform t,
float4 pointB,
float4 normal,
float4 bitangent,
float4 tangent,
out float normalInvMassB,
out float tangentInvMassB,
out float bitangentInvMassB)
{
float4 rB = t.TransformPoint(pointB) - rb.com;
// initialize inverse linear masses:
normalInvMassB = tangentInvMassB = bitangentInvMassB = rb.inverseMass;
normalInvMassB += RotationalInvMass(rb.inverseInertiaTensor, rB, normal);
tangentInvMassB += RotationalInvMass(rb.inverseInertiaTensor, rB, tangent);
bitangentInvMassB += RotationalInvMass(rb.inverseInertiaTensor, rB, bitangent);
}
float4 GetRigidbodyVelocityAtPoint(in rigidbody rb,
float4 pnt,
float4 linearDelta,
float4 angularDelta,
in inertialFrame frame)
{
float4 linearVel = rb.velocity + linearDelta;
float4 angularVel = rb.angularVelocity + angularDelta;
float4 r = frame.frame.TransformPoint(pnt) - rb.com;
// calculate rigidbody velocity. (point is assumed to be expressed in solver space, convert it to world space):
float4 wsRigidbodyVel = linearVel + float4(cross(angularVel.xyz, r.xyz), 0);
// calculate solver velocity:
float4 wsSolverVelocity = frame.velocity + float4(cross(frame.angularVelocity.xyz, pnt.xyz), 0);
// convert the resulting velocity back to solver space:
return frame.frame.InverseTransformVector(wsRigidbodyVel - wsSolverVelocity);
};
void AtomicAddLinearDelta(in int rigidbodyIndex, in float4 delta)
{
InterlockedAddFloat(linearDeltasAsInt, rigidbodyIndex, 0, delta.x);
InterlockedAddFloat(linearDeltasAsInt, rigidbodyIndex, 1, delta.y);
InterlockedAddFloat(linearDeltasAsInt, rigidbodyIndex, 2, delta.z);
}
void AtomicAddAngularDelta(in int rigidbodyIndex, in float4 delta)
{
InterlockedAddFloat(angularDeltasAsInt, rigidbodyIndex, 0, delta.x);
InterlockedAddFloat(angularDeltasAsInt, rigidbodyIndex, 1, delta.y);
InterlockedAddFloat(angularDeltasAsInt, rigidbodyIndex, 2, delta.z);
}
void ApplyImpulse(int rigidbodyIndex,
float4 impulse,
float4 pnt,
in transform frame)
{
float4 impulseWS = frame.TransformVector(impulse);
float4 r = frame.TransformPoint(pnt) - rigidbodies[rigidbodyIndex].com;
float4 linearDelta = rigidbodies[rigidbodyIndex].inverseMass * impulseWS;
float4 angularDelta = mul(rigidbodies[rigidbodyIndex].inverseInertiaTensor, float4(cross(r.xyz, impulseWS.xyz), 0));
AtomicAddLinearDelta (rigidbodyIndex, linearDelta);
AtomicAddAngularDelta(rigidbodyIndex, angularDelta);
}
void ApplyDeltaQuaternion(int rigidbodyIndex,
quaternion rotation,
quaternion delta,
in transform frame,
float dt)
{
quaternion rotationWS = qmul(frame.rotation, rotation);
quaternion deltaWS = qmul(frame.rotation, delta);
// convert quaternion delta to angular acceleration:
quaternion newRotation = normalize(rotationWS + deltaWS);
AtomicAddAngularDelta(rigidbodyIndex, DifferentiateAngular(newRotation, rotationWS, dt));
}
#endif