Found the cause: in ApplyInertialForcesJob, we calculate a solver-space wind intensity due to solver rotation/translation in world space if the solver's wind space is set to "world".
Rigidbodies in Unity have a maximum angular velocity, but rotating the solver transform in Obi does not. Typically, the solver is driven by the character's rigidbody so angular velocity stays within a safe range. But manually rotating the solver transform allows for very high angular velocity values, resulting in hurricane-like wind values for particles far enough from the center of rotation (eg. float4(-8505.487E12f, 0f, -43300.07E19f, 0f)). This eventually leads to "Inf" relative velocities between particles and wind, that when multiplied by 0 attack angle in aerodynamic constraints yields NaN.
The safest solution is simply to clamp the wind magnitude to a sane value that does not allow the relative velocity between wind and particles to get close to infinite:
Code:
float maxMagnitude = 100; // feel free to use your own value
float magnitude = math.length(wind[i]);
if (magnitude > maxMagnitude)
wind[i] = wind[i] / magnitude * maxMagnitude;
The Execute() method of ApplyInertialForcesJob.cs after this modification should look like this:
Code:
public void Execute(int index)
{
int i = activeParticles[index];
if (invMasses[i] > 0)
{
float4 euler = new float4(math.cross(eulerAccel.xyz, positions[i].xyz), 0);
float4 centrifugal = new float4(math.cross(angularVel.xyz, math.cross(angularVel.xyz, positions[i].xyz)), 0);
float4 coriolis = 2 * new float4(math.cross(angularVel.xyz, velocities[i].xyz), 0);
float4 angularAccel = euler + coriolis + centrifugal;
velocities[i] -= (inertialAccel * worldLinearInertiaScale + angularAccel * worldAngularInertiaScale) * deltaTime;
}
wind[i] = ambientWind;
if (inertialWind)
{
float4 wsPos = inertialFrame.frame.TransformPoint(positions[i]);
wind[i] -= inertialFrame.frame.InverseTransformVector(inertialFrame.VelocityAtPoint(wsPos));
float maxMagnitude = 100;
float magnitude = math.length(wind[i]);
if (magnitude > maxMagnitude)
wind[i] = wind[i] / magnitude * maxMagnitude;
}
}
Why not clamp the solver's angular velocity instead, like Unity does with rigidbodies? because linear velocity at a point due to rigid rotation depends on the cross product between the point position relative to the center of rotation and the angular velocity, so its magnitude
scales with the distance from the point to the center. Rigidbodies are typically small and points in the rigidbody not far from its center, but a particle may be arbitrarily far from the solver’s center. Clamping the angular velocity would still allow for extremely high wind values at points far away from the solver's center, so it's safer to clamp the wind magnitude directly.
let me know if I can be of further help,
kind regards