Added linear interpolation (Lerp) to math module
Former-commit-id: 5920e21f25d42701a1895734eca492fdf5351669
This commit is contained in:
parent
737f2a70bd
commit
cfd54b859d
|
|
@ -31,6 +31,7 @@ inline unsigned int NzGetNumberLength(unsigned long long number);
|
|||
inline unsigned int NzGetNumberLength(float number, nzUInt8 precision = NAZARA_CORE_REAL_PRECISION);
|
||||
inline unsigned int NzGetNumberLength(double number, nzUInt8 precision = NAZARA_CORE_REAL_PRECISION);
|
||||
inline unsigned int NzGetNumberLength(long double number, nzUInt8 precision = NAZARA_CORE_REAL_PRECISION);
|
||||
template<typename T, typename F> T NzLerp(T from, T to, F interpolation);
|
||||
template<typename T> T NzNormalizeAngle(T angle);
|
||||
template<typename T> bool NzNumberEquals(T a, T b);
|
||||
inline NzString NzNumberToString(long long number, nzUInt8 radix = 10);
|
||||
|
|
|
|||
|
|
@ -132,6 +132,20 @@ unsigned int NzGetNumberLength(long double number, nzUInt8 precision)
|
|||
return NzGetNumberLength(static_cast<long long>(number)) + precision + 1; // Plus un pour le point
|
||||
}
|
||||
|
||||
template<typename T, typename F>
|
||||
T NzLerp(T from, T to, F interpolation)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (interpolation < F(0.0) || interpolation > F(1.0))
|
||||
{
|
||||
NazaraError("Interpolation must be in range [0..1] (Got " + NzString::Number(interpolation) + ')');
|
||||
return Zero();
|
||||
}
|
||||
#endif
|
||||
|
||||
return from + interpolation*(to-from);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzNormalizeAngle(T angle)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,28 +20,28 @@ class NzCube
|
|||
NzCube(const T cube[6]);
|
||||
NzCube(const NzRect<T>& rect);
|
||||
NzCube(const NzVector3<T>& vec1, const NzVector3<T>& vec2);
|
||||
template<typename U> explicit NzCube(const NzCube<U>& rect);
|
||||
NzCube(const NzCube& rect) = default;
|
||||
template<typename U> explicit NzCube(const NzCube<U>& cube);
|
||||
NzCube(const NzCube& cube) = default;
|
||||
~NzCube() = default;
|
||||
|
||||
bool Contains(T X, T Y, T Z) const;
|
||||
bool Contains(const NzVector3<T>& point) const;
|
||||
bool Contains(const NzCube& rect) const;
|
||||
bool Contains(const NzCube& cube) const;
|
||||
|
||||
void ExtendTo(const NzVector3<T>& point);
|
||||
void ExtendTo(const NzCube& rect);
|
||||
void ExtendTo(const NzCube& cube);
|
||||
|
||||
NzVector3<T> GetCenter() const;
|
||||
|
||||
bool Intersect(const NzCube& rect, NzCube* intersection = nullptr) const;
|
||||
bool Intersect(const NzCube& cube, NzCube* intersection = nullptr) const;
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
void Set(T X, T Y, T Z, T Width, T Height, T Depth);
|
||||
void Set(const T rect[6]);
|
||||
void Set(const T cube[6]);
|
||||
void Set(const NzRect<T>& rect);
|
||||
void Set(const NzVector3<T>& vec1, const NzVector3<T>& vec2);
|
||||
template<typename U> void Set(const NzCube<U>& rect);
|
||||
template<typename U> void Set(const NzCube<U>& cube);
|
||||
|
||||
NzString ToString() const;
|
||||
|
||||
|
|
@ -50,6 +50,8 @@ class NzCube
|
|||
T& operator[](unsigned int i);
|
||||
T operator[](unsigned int i) const;
|
||||
|
||||
static NzCube Lerp(const NzCube& from, const NzCube& to, T interpolation);
|
||||
|
||||
T x, y, z, width, height, depth;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -39,9 +39,9 @@ NzCube<T>::NzCube(const NzVector3<T>& vec1, const NzVector3<T>& vec2)
|
|||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzCube<T>::NzCube(const NzCube<U>& rect)
|
||||
NzCube<T>::NzCube(const NzCube<U>& cube)
|
||||
{
|
||||
Set(rect);
|
||||
Set(cube);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -59,10 +59,10 @@ bool NzCube<T>::Contains(const NzVector3<T>& point) const
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzCube<T>::Contains(const NzCube<T>& rect) const
|
||||
bool NzCube<T>::Contains(const NzCube<T>& cube) const
|
||||
{
|
||||
return Contains(rect.x, rect.y, rect.z) &&
|
||||
Contains(rect.x + rect.width, rect.y + rect.height, rect.z + rect.depth);
|
||||
return Contains(cube.x, cube.y, cube.z) &&
|
||||
Contains(cube.x + cube.width, cube.y + cube.height, cube.z + cube.depth);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -77,14 +77,14 @@ void NzCube<T>::ExtendTo(const NzVector3<T>& point)
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
void NzCube<T>::ExtendTo(const NzCube& rect)
|
||||
void NzCube<T>::ExtendTo(const NzCube& cube)
|
||||
{
|
||||
x = std::min(x, rect.x);
|
||||
y = std::min(y, rect.y);
|
||||
z = std::min(y, rect.z);
|
||||
width = std::max(x+width, rect.x+rect.width)-x;
|
||||
height = std::max(x+height, rect.y+rect.height)-y;
|
||||
depth = std::max(x+depth, rect.z+rect.depth)-z;
|
||||
x = std::min(x, cube.x);
|
||||
y = std::min(y, cube.y);
|
||||
z = std::min(y, cube.z);
|
||||
width = std::max(x+width, cube.x+cube.width)-x;
|
||||
height = std::max(x+height, cube.y+cube.height)-y;
|
||||
depth = std::max(x+depth, cube.z+cube.depth)-z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -94,14 +94,14 @@ NzVector3<T> NzCube<T>::GetCenter() const
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzCube<T>::Intersect(const NzCube& rect, NzCube* intersection) const
|
||||
bool NzCube<T>::Intersect(const NzCube& cube, NzCube* intersection) const
|
||||
{
|
||||
T left = std::max(x, rect.x);
|
||||
T right = std::min(x+width, rect.x+rect.width);
|
||||
T top = std::max(y, rect.y);
|
||||
T bottom = std::min(y+height, rect.y+rect.height);
|
||||
T up = std::max(z, rect.z);
|
||||
T down = std::min(z+depth, rect.z+rect.depth);
|
||||
T left = std::max(x, cube.x);
|
||||
T right = std::min(x+width, cube.x+cube.width);
|
||||
T top = std::max(y, cube.y);
|
||||
T bottom = std::min(y+height, cube.y+cube.height);
|
||||
T up = std::max(z, cube.z);
|
||||
T down = std::min(z+depth, cube.z+cube.depth);
|
||||
|
||||
if (left < right && top < bottom && up < down)
|
||||
{
|
||||
|
|
@ -139,14 +139,14 @@ void NzCube<T>::Set(T X, T Y, T Z, T Width, T Height, T Depth)
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
void NzCube<T>::Set(const T rect[6])
|
||||
void NzCube<T>::Set(const T cube[6])
|
||||
{
|
||||
x = rect[0];
|
||||
y = rect[1];
|
||||
z = rect[2];
|
||||
width = rect[3];
|
||||
height = rect[4];
|
||||
depth = rect[5];
|
||||
x = cube[0];
|
||||
y = cube[1];
|
||||
z = cube[2];
|
||||
width = cube[3];
|
||||
height = cube[4];
|
||||
depth = cube[5];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -230,9 +230,31 @@ T NzCube<T>::operator[](unsigned int i) const
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzCube<T>& rect)
|
||||
NzCube<T> NzCube<T>::Lerp(const NzCube& from, const NzCube& to, T interpolation)
|
||||
{
|
||||
return out << rect.ToString();
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (interpolation < F(0.0) || interpolation > F(1.0))
|
||||
{
|
||||
NazaraError("Interpolation must be in range [0..1] (Got " + NzString::Number(interpolation) + ')');
|
||||
return Zero();
|
||||
}
|
||||
#endif
|
||||
|
||||
NzCube cube;
|
||||
cube.x = NzLerp(from.x, to.x, interpolation);
|
||||
cube.y = NzLerp(from.y, to.y, interpolation);
|
||||
cube.z = NzLerp(from.z, to.z, interpolation);
|
||||
cube.width = NzLerp(from.width, to.width, interpolation);
|
||||
cube.height = NzLerp(from.height, to.height, interpolation);
|
||||
cube.depth = NzLerp(from.depth, to.depth, interpolation);
|
||||
|
||||
return cube;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzCube<T>& cube)
|
||||
{
|
||||
return out << cube.ToString();
|
||||
}
|
||||
|
||||
#undef F
|
||||
|
|
|
|||
|
|
@ -77,7 +77,8 @@ template<typename T> class NzQuaternion
|
|||
bool operator>=(const NzQuaternion& quat) const;
|
||||
|
||||
static NzQuaternion Identity();
|
||||
static NzQuaternion Slerp(const NzQuaternion& quatA, const NzQuaternion& quatB, T interp);
|
||||
static NzQuaternion Lerp(const NzQuaternion& from, const NzQuaternion& to, T interpolation);
|
||||
static NzQuaternion Slerp(const NzQuaternion& from, const NzQuaternion& to, T interpolation);
|
||||
static NzQuaternion Zero();
|
||||
|
||||
T w, x, y, z;
|
||||
|
|
|
|||
|
|
@ -365,32 +365,48 @@ NzQuaternion<T> NzQuaternion<T>::Identity()
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T> NzQuaternion<T>::Slerp(const NzQuaternion& quatA, const NzQuaternion& quatB, T interp)
|
||||
NzQuaternion<T> NzQuaternion<T>::Lerp(const NzQuaternion& from, const NzQuaternion& to, T interpolation)
|
||||
{
|
||||
if (interp <= F(0.0))
|
||||
return quatA;
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (interpolation < F(0.0) || interpolation > F(1.0))
|
||||
{
|
||||
NazaraError("Interpolation must be in range [0..1] (Got " + NzString::Number(interpolation) + ')');
|
||||
return Zero();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (interp >= F(1.0))
|
||||
return quatB;
|
||||
return from + interpolation*(to-from);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T> NzQuaternion<T>::Slerp(const NzQuaternion& from, const NzQuaternion& to, T interpolation)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (interpolation < F(0.0) || interpolation > F(1.0))
|
||||
{
|
||||
NazaraError("Interpolation must be in range [0..1] (Got " + NzString::Number(interpolation) + ')');
|
||||
return Zero();
|
||||
}
|
||||
#endif
|
||||
|
||||
NzQuaternion q;
|
||||
|
||||
T cosOmega = quatA.DotProduct(quatB);
|
||||
T cosOmega = from.DotProduct(to);
|
||||
if (cosOmega < F(0.0))
|
||||
{
|
||||
// On inverse tout
|
||||
q.Set(-quatB.w, -quatB.x, -quatB.y, -quatB.z);
|
||||
q.Set(-to.w, -to.x, -to.y, -to.z);
|
||||
cosOmega = -cosOmega;
|
||||
}
|
||||
else
|
||||
q.Set(quatB);
|
||||
q.Set(to);
|
||||
|
||||
T k0, k1;
|
||||
if (cosOmega > F(0.9999))
|
||||
{
|
||||
// Interpolation linéaire pour éviter une division par zéro
|
||||
k0 = F(1.0) - interp;
|
||||
k1 = interp;
|
||||
k0 = F(1.0) - interpolation;
|
||||
k1 = interpolation;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -400,11 +416,11 @@ NzQuaternion<T> NzQuaternion<T>::Slerp(const NzQuaternion& quatA, const NzQuater
|
|||
// Pour éviter deux divisions
|
||||
sinOmega = F(1.0)/sinOmega;
|
||||
|
||||
k0 = std::sin((F(1.0) - interp) * omega) * sinOmega;
|
||||
k1 = std::sin(interp*omega) * sinOmega;
|
||||
k0 = std::sin((F(1.0) - interpolation) * omega) * sinOmega;
|
||||
k1 = std::sin(interpolation*omega) * sinOmega;
|
||||
}
|
||||
|
||||
NzQuaternion result(k0 * quatA.w, k0 * quatA.x, k0 * quatA.y, k0 * quatA.z);
|
||||
NzQuaternion result(k0 * from.w, k0 * from.x, k0 * from.y, k0 * from.z);
|
||||
return result += q*k1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ class NzRect
|
|||
T& operator[](unsigned int i);
|
||||
T operator[](unsigned int i) const;
|
||||
|
||||
static NzRect Lerp(const NzRect& from, const NzRect& to, T interpolation);
|
||||
|
||||
T x, y, width, height;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -195,6 +195,26 @@ T NzRect<T>::operator[](unsigned int i) const
|
|||
return *(&x+i);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T> NzRect<T>::Lerp(const NzRect& from, const NzRect& to, T interpolation)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (interpolation < F(0.0) || interpolation > F(1.0))
|
||||
{
|
||||
NazaraError("Interpolation must be in range [0..1] (Got " + NzString::Number(interpolation) + ')');
|
||||
return Zero();
|
||||
}
|
||||
#endif
|
||||
|
||||
NzRect rect;
|
||||
rect.x = NzLerp(from.x, to.x, interpolation);
|
||||
rect.y = NzLerp(from.y, to.y, interpolation);
|
||||
rect.width = NzLerp(from.width, to.width, interpolation);
|
||||
rect.height = NzLerp(from.height, to.height, interpolation);
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzRect<T>& rect)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ template<typename T> class NzVector2
|
|||
bool operator>(const NzVector2& vec) const;
|
||||
bool operator>=(const NzVector2& vec) const;
|
||||
|
||||
static NzVector2 Lerp(const NzVector2& from, const NzVector2& to, T interpolation);
|
||||
static NzVector2 UnitX();
|
||||
static NzVector2 UnitY();
|
||||
static NzVector2 Zero();
|
||||
|
|
|
|||
|
|
@ -428,6 +428,12 @@ bool NzVector2<T>::operator>=(const NzVector2& vec) const
|
|||
return !operator<(vec);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzVector2<T>::Lerp(const NzVector2& from, const NzVector2& to, T interpolation)
|
||||
{
|
||||
return NzLerp(from, to, interpolation);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzVector2<T>::UnitX()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ template<typename T> class NzVector3
|
|||
static T DotProduct(const NzVector3& vec1, const NzVector3& vec2);
|
||||
static NzVector3 Forward();
|
||||
static NzVector3 Left();
|
||||
static NzVector3 Lerp(const NzVector3& from, const NzVector3& to, T interpolation);
|
||||
static NzVector3 Normalize(const NzVector3& vec);
|
||||
static NzVector3 UnitX();
|
||||
static NzVector3 UnitY();
|
||||
|
|
|
|||
|
|
@ -515,6 +515,12 @@ NzVector3<T> NzVector3<T>::Left()
|
|||
return vector;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector3<T> NzVector3<T>::Lerp(const NzVector3& from, const NzVector3& to, T interpolation)
|
||||
{
|
||||
return NzLerp(from, to, interpolation);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector3<T> NzVector3<T>::Normalize(const NzVector3& vec)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue