Created
April 6, 2025 19:00
-
-
Save Bloodwyn/44d4c5180303280a5a9d8d75421fef03 to your computer and use it in GitHub Desktop.
HLSL Quaternion Functions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
float4 qMul(in const float4 a, in const float4 b){ | |
return float4( | |
a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y, | |
a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x, | |
a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w, | |
a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z | |
); | |
} | |
float4 qId(){ | |
return float4(0.,0.,0.,1.); | |
} | |
float4 qConj(in const float4 q){ | |
return float4(-q.xyz, q.w); | |
} | |
float3 qTransform(in const float4 q, in const float3 p){ | |
return qMul(qMul(q, float4(p, 0.)), qConj(q)).xyz; | |
} | |
float3 qGetX(in const float4 q){ | |
return float3(q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z, | |
2*q.w*q.z + 2*q.x*q.y, | |
-2*q.w*q.y + 2*q.x*q.z); | |
} | |
float3 qGetY(in const float4 q){ | |
return float3(-2*q.w*q.z + 2*q.x*q.y, | |
q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z, | |
2*q.w*q.x + 2*q.y*q.z); | |
} | |
float3 qGetZ(in const float4 q){ | |
return float3( 2*q.w*q.y + 2*q.x*q.z, | |
-2*q.w*q.x + 2*q.y*q.z, | |
q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z); | |
} | |
float4 qRotateAxisAngle(in const float3 axis, in const float angle){ | |
float halfAngle = angle * 0.5; | |
return float4(normalize(axis) * sin(halfAngle), cos(halfAngle)); | |
} | |
float4 qRotateX(in const float radians){ return qRotateAxisAngle(float3(1,0,0), radians);} | |
float4 qRotateY(in const float radians){ return qRotateAxisAngle(float3(0,1,0), radians);} | |
float4 qRotateZ(in const float radians){ return qRotateAxisAngle(float3(0,0,1), radians);} | |
float4 qSlerp(in const float4 a, in const float4 b, in const float t) { | |
float theta = acos(clamp(dot(a, b), -1.0, 1.0)); | |
if (abs(theta) < 1e-5) return lerp(a, b, t); | |
float wa = sin((1.0 - t) * theta); | |
float wb = sin(t * theta); | |
return (a * wa + b * wb) / sin(theta); | |
} | |
float4 qSlerpShortest(in const float4 a, in const float4 b, in const float t) { | |
if (dot(a, b) < 0.0) return qSlerp(a, -b, t); | |
return qSlerp(a, b, t); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment