fuckingtech/public/assets/glsl/lygia/math/quat/lerp.msl
Elias Rhouzlane bf76c6b086 fix: code
2025-04-06 17:23:52 +02:00

47 lines
No EOL
1.8 KiB
Text

/*
contributors: Patricio Gonzalez Vivo
description: |
Linear interpolation between two quaternions.
This function is based on the implementation of slerp() found inthe GLM library.
use: <QUAT> quatLerp(<QUAT> a, <QUAT> b, <float> t)
license:
- Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0
- Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license
*/
#ifndef FNC_QUATLERP
#define FNC_QUATLERP
QUAT quatLerp(QUAT qa, QUAT qb, float t) {
// qa = normalize(qa);
// qb = normalize(qb);
// Calculate angle between them.
float cosHalfTheta = qa.w * qb.w + dot(qa.xyz, qb.xyz);
// avoid taking the longer way: choose one representation
qb = (cosHalfTheta < 0.0)? -qb : qb;
// qb = (cosHalfTheta < 0.0)? quatNeg(qb) : qb;
cosHalfTheta = (cosHalfTheta < 0.0)? -cosHalfTheta : cosHalfTheta;
// if qa = qb or qa = -qb then theta = 0 and we can return qa
if (abs(cosHalfTheta) >= 1.0) // greater-sign necessary for numerical stability
return qa;
// Calculate temporary values.
float halfTheta = acos(cosHalfTheta);
float sinHalfTheta = sqrt(1.0 - cosHalfTheta * cosHalfTheta); // NOTE: we checked above that |cosHalfTheta| < 1
// if theta = pi then result is not fully defined
// we could rotate around any axis normal to qa or qb
if (abs(sinHalfTheta) < 0.001/*some epsilon*/)
// return quatAdd( quatMul(qa, 0.5), quatMul(qb, 0.5));
return normalize( qa * 0.5 + qb * 0.5 );
float ratioA = sin((1.0 - t) * halfTheta) / sinHalfTheta;
float ratioB = sin(t * halfTheta) / sinHalfTheta;
// return quatNorm( quatAdd( quatMul(qa, ratioA), quatMul(qb, ratioB)) );
return normalize( qa * ratioA + qb * ratioB );
}
#endif