Skip to content

Instantly share code, notes, and snippets.

@hiroakioishi
Last active June 14, 2020 20:30
Show Gist options
  • Save hiroakioishi/fbcf4af43a4f034f70f0f6b6764f7ef0 to your computer and use it in GitHub Desktop.
Save hiroakioishi/fbcf4af43a4f034f70f0f6b6764f7ef0 to your computer and use it in GitHub Desktop.
Quaternionの球面線形補間(HLSL)
// Quaternion slerp
// https://en.wikipedia.org/wiki/Slerp
float4 slerp(float4 q0, float4 q1, float t)
{
q0 = normalize(q0);
q1 = normalize(q1);
float dot_q0q1 = dot(q0, q1);
bool dotIsNegative = dot_q0q1 < 0.0;
q1 = dotIsNegative ? -q1 : q1;
dot_q0q1 = dotIsNegative ? -dot_q0q1 : dot_q0q1;
const float DOT_THREDHOLD = 0.9995;
bool valuesAreTooClose = dot_q0q1 > 0.9995;
if (valuesAreTooClose)
{
float4 result = q0 + t * (q1 - q0);
result = normalize(result);
return result;
}
// sin dot is in range [0, DOT_THRESHOLD], acos is safe
float theta_0 = acos(dot_q0q1); // theta_0 = angle between input vectors
float theta = theta_0 * t; // theta = angle between q0 and result
float sin_theta = sin(theta); // compute this value only once
float sin_theta_0 = sin(theta_0); // compute this value only once
float s0 = cos(theta) - dot_q0q1 * sin_theta / sin_theta_0; // == sin(theta_0 - theta) / sin(theta_0)
float s1 = sin_theta / sin_theta_0;
return (s0 * q0) + (s1 * q1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment