linmath: make raising quaternion to power more meaningful

Fixes #160
This commit is contained in:
rdb 2017-12-31 09:30:32 +01:00
parent 7ee9467f8d
commit a6f737d4eb
2 changed files with 25 additions and 0 deletions

View File

@ -26,6 +26,29 @@ pure_imaginary(const FLOATNAME(LVector3) &v) {
return FLOATNAME(LQuaternion)(0, v[0], v[1], v[2]);
}
/**
* Returns a new quaternion that represents this quaternion raised to the
* given power.
*/
FLOATNAME(LQuaternion) FLOATNAME(LQuaternion)::
__pow__(FLOATTYPE power) const {
if (IS_NEARLY_ZERO(power)) {
return FLOATNAME(LQuaternion)(1, 0, 0, 0);
}
FLOATTYPE l = length();
FLOATTYPE norm = _v(0) / l;
if (IS_NEARLY_EQUAL(cabs(norm), (FLOATTYPE)1)) {
return FLOATNAME(LQuaternion)(cpow(_v(0), power), 0, 0, 0);
}
FLOATTYPE angle = acos(norm);
FLOATTYPE angle2 = angle * power;
FLOATTYPE mag = cpow(l, power - 1);
FLOATTYPE mult = mag * (sin(angle2) / sin(angle));
return FLOATNAME(LQuaternion)(cos(angle2) * mag * l, _v(1) * mult, _v(2) * mult, _v(3) * mult);
}
/**
* Based on the quat lib from VRPN.
*/

View File

@ -57,6 +57,8 @@ PUBLISHED:
INLINE_LINMATH FLOATNAME(LMatrix3) operator *(const FLOATNAME(LMatrix3) &);
INLINE_LINMATH FLOATNAME(LMatrix4) operator *(const FLOATNAME(LMatrix4) &);
FLOATNAME(LQuaternion) __pow__(FLOATTYPE) const;
INLINE_LINMATH bool almost_equal(
const FLOATNAME(LQuaternion) &other) const;
INLINE_LINMATH bool almost_equal(