Merge branch 'master' into NDK-ShadowMapping
Former-commit-id: 83435ab51753299b30a102871fbcd5558d2ac4f1
This commit is contained in:
@@ -28,35 +28,38 @@
|
||||
#define M_SQRT3 1.7320508075688772935274463
|
||||
#endif
|
||||
|
||||
template<typename T> T NzApproach(T value, T objective, T increment);
|
||||
template<typename T> constexpr T NzClamp(T value, T min, T max);
|
||||
template<typename T> T NzCountBits(T value);
|
||||
template<typename T> constexpr T NzFromDegrees(T degrees);
|
||||
template<typename T> constexpr T NzFromRadians(T radians);
|
||||
template<typename T> constexpr T NzDegreeToRadian(T degrees);
|
||||
unsigned int NzGetNearestPowerOfTwo(unsigned int number);
|
||||
unsigned int NzGetNumberLength(signed char number);
|
||||
unsigned int NzGetNumberLength(unsigned char number);
|
||||
unsigned int NzGetNumberLength(int number);
|
||||
unsigned int NzGetNumberLength(unsigned int number);
|
||||
unsigned int NzGetNumberLength(long long number);
|
||||
unsigned int NzGetNumberLength(unsigned long long number);
|
||||
unsigned int NzGetNumberLength(float number, nzUInt8 precision = NAZARA_CORE_DECIMAL_DIGITS);
|
||||
unsigned int NzGetNumberLength(double number, nzUInt8 precision = NAZARA_CORE_DECIMAL_DIGITS);
|
||||
unsigned int NzGetNumberLength(long double number, nzUInt8 precision = NAZARA_CORE_DECIMAL_DIGITS);
|
||||
template<typename T> unsigned int NzIntegralLog2(T number);
|
||||
template<typename T> unsigned int NzIntegralLog2Pot(T pot);
|
||||
unsigned int NzIntegralPow(unsigned int base, unsigned int exponent);
|
||||
template<typename T, typename T2> T NzLerp(T from, T to, T2 interpolation);
|
||||
template<typename T> T NzMultiplyAdd(T x, T y, T z);
|
||||
template<typename T> T NzNormalizeAngle(T angle);
|
||||
template<typename T> bool NzNumberEquals(T a, T b);
|
||||
template<typename T> bool NzNumberEquals(T a, T b, T maxDifference);
|
||||
NzString NzNumberToString(long long number, nzUInt8 radix = 10);
|
||||
template<typename T> T NzRadianToDegree(T radians);
|
||||
long long NzStringToNumber(NzString str, nzUInt8 radix = 10, bool* ok = nullptr);
|
||||
template<typename T> constexpr T NzToDegrees(T angle);
|
||||
template<typename T> constexpr T NzToRadians(T angle);
|
||||
namespace Nz
|
||||
{
|
||||
template<typename T> T Approach(T value, T objective, T increment);
|
||||
template<typename T> constexpr T Clamp(T value, T min, T max);
|
||||
template<typename T> T CountBits(T value);
|
||||
template<typename T> constexpr T FromDegrees(T degrees);
|
||||
template<typename T> constexpr T FromRadians(T radians);
|
||||
template<typename T> constexpr T DegreeToRadian(T degrees);
|
||||
template<typename T> T GetNearestPowerOfTwo(T number);
|
||||
unsigned int GetNumberLength(signed char number);
|
||||
unsigned int GetNumberLength(unsigned char number);
|
||||
unsigned int GetNumberLength(int number);
|
||||
unsigned int GetNumberLength(unsigned int number);
|
||||
unsigned int GetNumberLength(long long number);
|
||||
unsigned int GetNumberLength(unsigned long long number);
|
||||
unsigned int GetNumberLength(float number, UInt8 precision = NAZARA_CORE_DECIMAL_DIGITS);
|
||||
unsigned int GetNumberLength(double number, UInt8 precision = NAZARA_CORE_DECIMAL_DIGITS);
|
||||
unsigned int GetNumberLength(long double number, UInt8 precision = NAZARA_CORE_DECIMAL_DIGITS);
|
||||
template<typename T> unsigned int IntegralLog2(T number);
|
||||
template<typename T> unsigned int IntegralLog2Pot(T pot);
|
||||
unsigned int IntegralPow(unsigned int base, unsigned int exponent);
|
||||
template<typename T, typename T2> T Lerp(T from, T to, T2 interpolation);
|
||||
template<typename T> T MultiplyAdd(T x, T y, T z);
|
||||
template<typename T> T NormalizeAngle(T angle);
|
||||
template<typename T> bool NumberEquals(T a, T b);
|
||||
template<typename T> bool NumberEquals(T a, T b, T maxDifference);
|
||||
String NumberToString(long long number, UInt8 radix = 10);
|
||||
template<typename T> T RadianToDegree(T radians);
|
||||
long long StringToNumber(String str, UInt8 radix = 10, bool* ok = nullptr);
|
||||
template<typename T> constexpr T ToDegrees(T angle);
|
||||
template<typename T> constexpr T ToRadians(T angle);
|
||||
}
|
||||
|
||||
#include <Nazara/Math/Algorithm.inl>
|
||||
|
||||
|
||||
@@ -11,451 +11,457 @@
|
||||
#include <type_traits>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace
|
||||
namespace Nz
|
||||
{
|
||||
// https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
|
||||
static const unsigned int MultiplyDeBruijnBitPosition[32] =
|
||||
namespace Detail
|
||||
{
|
||||
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
|
||||
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
|
||||
};
|
||||
|
||||
static const unsigned int MultiplyDeBruijnBitPosition2[32] =
|
||||
{
|
||||
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
|
||||
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
typename std::enable_if<sizeof(T) <= sizeof(nzUInt32), unsigned int>::type NzImplIntegralLog2(T number)
|
||||
{
|
||||
// https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
|
||||
number |= number >> 1; // first round down to one less than a power of 2
|
||||
number |= number >> 2;
|
||||
number |= number >> 4;
|
||||
number |= number >> 8;
|
||||
number |= number >> 16;
|
||||
|
||||
return MultiplyDeBruijnBitPosition[static_cast<nzUInt32>(number * 0x07C4ACDDU) >> 27];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
// Les parenthèses autour de la condition sont nécesaires pour que GCC compile ça
|
||||
typename std::enable_if<(sizeof(T) > sizeof(nzUInt32)), unsigned int>::type NzImplIntegralLog2(T number)
|
||||
{
|
||||
static_assert(sizeof(T) % sizeof(nzUInt32) == 0, "Assertion failed");
|
||||
|
||||
// L'algorithme pour le logarithme base 2 (au dessus) ne fonctionne qu'avec des nombres au plus 32bits
|
||||
// ce code décompose les nombres plus grands en nombres 32 bits par masquage et bit shifting
|
||||
for (int i = sizeof(T)-sizeof(nzUInt32); i >= 0; i -= sizeof(nzUInt32))
|
||||
namespace
|
||||
{
|
||||
// Le masque 32 bits sur la partie du nombre qu'on traite actuellement
|
||||
T mask = T(std::numeric_limits<nzUInt32>::max()) << i*8;
|
||||
T val = (number & mask) >> i*8; // Masquage et shifting des bits vers la droite (pour le ramener sur 32bits)
|
||||
// https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
|
||||
static const unsigned int MultiplyDeBruijnBitPosition[32] =
|
||||
{
|
||||
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
|
||||
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
|
||||
};
|
||||
|
||||
// Appel de la fonction avec le nombre 32bits, si le résultat est non-nul nous avons la réponse
|
||||
unsigned int log2 = NzImplIntegralLog2<nzUInt32>(val);
|
||||
if (log2)
|
||||
return log2 + i*8;
|
||||
static const unsigned int MultiplyDeBruijnBitPosition2[32] =
|
||||
{
|
||||
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
|
||||
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
|
||||
};
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
typename std::enable_if<sizeof(T) <= sizeof(nzUInt32), unsigned int>::type NzImplIntegralLog2Pot(T number)
|
||||
{
|
||||
// https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
|
||||
return MultiplyDeBruijnBitPosition2[static_cast<nzUInt32>(number * 0x077CB531U) >> 27];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
// Les parenthèses autour de la condition sont nécesaires pour que GCC compile ça
|
||||
typename std::enable_if<(sizeof(T) > sizeof(nzUInt32)), unsigned int>::type NzImplIntegralLog2Pot(T number)
|
||||
{
|
||||
static_assert(sizeof(T) % sizeof(nzUInt32) == 0, "Assertion failed");
|
||||
|
||||
// L'algorithme pour le logarithme base 2 (au dessus) ne fonctionne qu'avec des nombres au plus 32bits
|
||||
// ce code décompose les nombres plus grands en nombres 32 bits par masquage et bit shifting
|
||||
for (int i = sizeof(T)-sizeof(nzUInt32); i >= 0; i -= sizeof(nzUInt32))
|
||||
template<typename T>
|
||||
typename std::enable_if<sizeof(T) <= sizeof(UInt32), unsigned int>::type IntegralLog2(T number)
|
||||
{
|
||||
// Le masque 32 bits sur la partie du nombre qu'on traite actuellement
|
||||
T mask = T(std::numeric_limits<nzUInt32>::max()) << i*8;
|
||||
nzUInt32 val = nzUInt32((number & mask) >> i*8); // Masquage et shifting des bits vers la droite (pour le ramener sur 32bits)
|
||||
// https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
|
||||
number |= number >> 1; // first round down to one less than a power of 2
|
||||
number |= number >> 2;
|
||||
number |= number >> 4;
|
||||
number |= number >> 8;
|
||||
number |= number >> 16;
|
||||
|
||||
// Appel de la fonction avec le nombre 32bits, si le résultat est non-nul nous avons la réponse
|
||||
unsigned int log2 = NzImplIntegralLog2Pot<nzUInt32>(val);
|
||||
if (log2)
|
||||
return log2 + i*8;
|
||||
return MultiplyDeBruijnBitPosition[static_cast<UInt32>(number * 0x07C4ACDDU) >> 27];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
template<typename T>
|
||||
// Les parenthèses autour de la condition sont nécesaires pour que GCC compile ça
|
||||
typename std::enable_if<(sizeof(T) > sizeof(UInt32)), unsigned int>::type IntegralLog2(T number)
|
||||
{
|
||||
static_assert(sizeof(T) % sizeof(UInt32) == 0, "Assertion failed");
|
||||
|
||||
template<typename T>
|
||||
T NzApproach(T value, T objective, T increment)
|
||||
{
|
||||
///TODO: Marquer comme constexpr en C++14
|
||||
if (value < objective)
|
||||
return std::min(value + increment, objective);
|
||||
else if (value > objective)
|
||||
return std::max(value - increment, objective);
|
||||
else
|
||||
return value;
|
||||
}
|
||||
// L'algorithme pour le logarithme base 2 (au dessus) ne fonctionne qu'avec des nombres au plus 32bits
|
||||
// ce code décompose les nombres plus grands en nombres 32 bits par masquage et bit shifting
|
||||
for (int i = sizeof(T)-sizeof(UInt32); i >= 0; i -= sizeof(UInt32))
|
||||
{
|
||||
// Le masque 32 bits sur la partie du nombre qu'on traite actuellement
|
||||
T mask = T(std::numeric_limits<UInt32>::max()) << i*8;
|
||||
T val = (number & mask) >> i*8; // Masquage et shifting des bits vers la droite (pour le ramener sur 32bits)
|
||||
|
||||
template<typename T>
|
||||
constexpr T NzClamp(T value, T min, T max)
|
||||
{
|
||||
return std::max(std::min(value, max), min);
|
||||
}
|
||||
// Appel de la fonction avec le nombre 32bits, si le résultat est non-nul nous avons la réponse
|
||||
unsigned int log2 = IntegralLog2<UInt32>(val);
|
||||
if (log2)
|
||||
return log2 + i*8;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzCountBits(T value)
|
||||
{
|
||||
// https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
|
||||
unsigned int count = 0;
|
||||
while (value)
|
||||
{
|
||||
value &= value - 1;
|
||||
count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
typename std::enable_if<sizeof(T) <= sizeof(UInt32), unsigned int>::type IntegralLog2Pot(T number)
|
||||
{
|
||||
// https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
|
||||
return MultiplyDeBruijnBitPosition2[static_cast<UInt32>(number * 0x077CB531U) >> 27];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
// Les parenthèses autour de la condition sont nécesaires pour que GCC compile ça
|
||||
typename std::enable_if<(sizeof(T) > sizeof(UInt32)), unsigned int>::type IntegralLog2Pot(T number)
|
||||
{
|
||||
static_assert(sizeof(T) % sizeof(UInt32) == 0, "Assertion failed");
|
||||
|
||||
// L'algorithme pour le logarithme base 2 (au dessus) ne fonctionne qu'avec des nombres au plus 32bits
|
||||
// ce code décompose les nombres plus grands en nombres 32 bits par masquage et bit shifting
|
||||
for (int i = sizeof(T)-sizeof(UInt32); i >= 0; i -= sizeof(UInt32))
|
||||
{
|
||||
// Le masque 32 bits sur la partie du nombre qu'on traite actuellement
|
||||
T mask = T(std::numeric_limits<UInt32>::max()) << i*8;
|
||||
UInt32 val = UInt32((number & mask) >> i*8); // Masquage et shifting des bits vers la droite (pour le ramener sur 32bits)
|
||||
|
||||
// Appel de la fonction avec le nombre 32bits, si le résultat est non-nul nous avons la réponse
|
||||
unsigned int log2 = IntegralLog2Pot<UInt32>(val);
|
||||
if (log2)
|
||||
return log2 + i*8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T NzDegreeToRadian(T degrees)
|
||||
{
|
||||
return degrees * T(M_PI/180.0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T NzFromDegrees(T degrees)
|
||||
{
|
||||
#if NAZARA_MATH_ANGLE_RADIAN
|
||||
return NzDegreeToRadian(degrees);
|
||||
#else
|
||||
return degrees;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T NzFromRadians(T radians)
|
||||
{
|
||||
#if NAZARA_MATH_ANGLE_RADIAN
|
||||
return radians;
|
||||
#else
|
||||
return NzRadianToDegree(radians);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline unsigned int NzGetNearestPowerOfTwo(unsigned int number)
|
||||
{
|
||||
///TODO: Marquer comme constexpr en C++14
|
||||
unsigned int x = 1;
|
||||
// Tant que x est plus petit que n, on décale ses bits vers la gauche, ce qui revient à multiplier par deux
|
||||
while (x < number)
|
||||
x <<= 1;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
inline unsigned int NzGetNumberLength(signed char number)
|
||||
{
|
||||
///TODO: Marquer comme constexpr en C++14
|
||||
// Le standard définit le char comme étant codé sur un octet
|
||||
static_assert(sizeof(number) == 1, "Signed char must be one byte-sized");
|
||||
|
||||
if (number >= 100)
|
||||
return 3;
|
||||
else if (number >= 10)
|
||||
return 2;
|
||||
else if (number >= 0)
|
||||
return 1;
|
||||
else if (number > -10)
|
||||
return 2;
|
||||
else if (number > -100)
|
||||
return 3;
|
||||
else
|
||||
return 4;
|
||||
}
|
||||
|
||||
inline unsigned int NzGetNumberLength(unsigned char number)
|
||||
{
|
||||
///TODO: Marquer comme constexpr en C++14
|
||||
// Le standard définit le char comme étant codé sur un octet
|
||||
static_assert(sizeof(number) == 1, "Unsigned char must be one byte-sized");
|
||||
|
||||
if (number >= 100)
|
||||
return 3;
|
||||
else if (number >= 10)
|
||||
return 2;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline unsigned int NzGetNumberLength(int number)
|
||||
{
|
||||
if (number == 0)
|
||||
return 1;
|
||||
|
||||
return static_cast<unsigned int>(std::log10(std::abs(number))) + (number < 0 ? 2 : 1);
|
||||
}
|
||||
|
||||
inline unsigned int NzGetNumberLength(unsigned int number)
|
||||
{
|
||||
if (number == 0)
|
||||
return 1;
|
||||
|
||||
return static_cast<unsigned int>(std::log10(number))+1;
|
||||
}
|
||||
|
||||
inline unsigned int NzGetNumberLength(long long number)
|
||||
{
|
||||
if (number == 0)
|
||||
return 1;
|
||||
|
||||
return static_cast<unsigned int>(std::log10(std::abs(number))) + (number < 0 ? 2 : 1);
|
||||
}
|
||||
|
||||
inline unsigned int NzGetNumberLength(unsigned long long number)
|
||||
{
|
||||
if (number == 0)
|
||||
return 1;
|
||||
|
||||
return static_cast<unsigned int>(std::log10(number)) + 1;
|
||||
}
|
||||
|
||||
inline unsigned int NzGetNumberLength(float number, nzUInt8 precision)
|
||||
{
|
||||
// L'imprécision des flottants nécessite un cast (log10(9.99999) = 0.99999)
|
||||
return NzGetNumberLength(static_cast<long long>(number)) + precision + 1; // Plus un pour le point
|
||||
}
|
||||
|
||||
inline unsigned int NzGetNumberLength(double number, nzUInt8 precision)
|
||||
{
|
||||
// L'imprécision des flottants nécessite un cast (log10(9.99999) = 0.99999)
|
||||
return NzGetNumberLength(static_cast<long long>(number)) + precision + 1; // Plus un pour le point
|
||||
}
|
||||
|
||||
inline unsigned int NzGetNumberLength(long double number, nzUInt8 precision)
|
||||
{
|
||||
// L'imprécision des flottants nécessite un cast (log10(9.99999) = 0.99999)
|
||||
return NzGetNumberLength(static_cast<long long>(number)) + precision + 1; // Plus un pour le point
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
unsigned int NzIntegralLog2(T number)
|
||||
{
|
||||
// Proxy nécessaire pour éviter un problème de surcharge
|
||||
return NzImplIntegralLog2<T>(number);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
unsigned int NzIntegralLog2Pot(T pot)
|
||||
{
|
||||
return NzImplIntegralLog2Pot<T>(pot);
|
||||
}
|
||||
|
||||
inline unsigned int NzIntegralPow(unsigned int base, unsigned int exponent)
|
||||
{
|
||||
///TODO: Marquer comme constexpr en C++14
|
||||
unsigned int r = 1;
|
||||
for (unsigned int i = 0; i < exponent; ++i)
|
||||
r *= base;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename T, typename T2>
|
||||
T NzLerp(T from, T to, T2 interpolation)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (interpolation < T2(0.0) || interpolation > T2(1.0))
|
||||
NazaraWarning("Interpolation should be in range [0..1] (Got " + NzString::Number(interpolation) + ')');
|
||||
#endif
|
||||
|
||||
return from + interpolation * (to - from);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzMultiplyAdd(T x, T y, T z)
|
||||
{
|
||||
return x*y + z;
|
||||
}
|
||||
|
||||
#ifdef FP_FAST_FMAF
|
||||
template<>
|
||||
inline float NzMultiplyAdd(float x, float y, float z)
|
||||
{
|
||||
return std::fmaf(x, y, z);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FP_FAST_FMA
|
||||
template<>
|
||||
inline double NzMultiplyAdd(double x, double y, double z)
|
||||
{
|
||||
return std::fma(x, y, z);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FP_FAST_FMAL
|
||||
template<>
|
||||
inline long double NzMultiplyAdd(long double x, long double y, long double z)
|
||||
{
|
||||
return std::fmal(x, y, z);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
T NzNormalizeAngle(T angle)
|
||||
{
|
||||
#if NAZARA_MATH_ANGLE_RADIAN
|
||||
const T limit = T(M_PI);
|
||||
#else
|
||||
const T limit = T(180.0);
|
||||
#endif
|
||||
const T twoLimit = limit * T(2);
|
||||
|
||||
angle = std::fmod(angle + limit, twoLimit);
|
||||
if (angle < T(0))
|
||||
angle += twoLimit;
|
||||
|
||||
return angle - limit;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzNumberEquals(T a, T b)
|
||||
{
|
||||
return NzNumberEquals(a, b, std::numeric_limits<T>::epsilon());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzNumberEquals(T a, T b, T maxDifference)
|
||||
{
|
||||
if (b > a)
|
||||
std::swap(a, b);
|
||||
|
||||
T diff = a - b;
|
||||
return diff <= maxDifference;
|
||||
}
|
||||
|
||||
inline NzString NzNumberToString(long long number, nzUInt8 radix)
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (radix < 2 || radix > 36)
|
||||
template<typename T>
|
||||
T Approach(T value, T objective, T increment)
|
||||
{
|
||||
NazaraError("Base must be between 2 and 36");
|
||||
return NzString();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (number == 0)
|
||||
return NzString('0');
|
||||
|
||||
static const char* symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
bool negative;
|
||||
if (number < 0)
|
||||
{
|
||||
negative = true;
|
||||
number = -number;
|
||||
}
|
||||
else
|
||||
negative = false;
|
||||
|
||||
NzString str;
|
||||
str.Reserve(NzGetNumberLength(number)); // Prends en compte le signe négatif
|
||||
|
||||
do
|
||||
{
|
||||
str.Append(symbols[number % radix]);
|
||||
number /= radix;
|
||||
}
|
||||
while (number > 0);
|
||||
|
||||
if (negative)
|
||||
str.Append('-');
|
||||
|
||||
return str.Reverse();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzRadianToDegree(T radians)
|
||||
{
|
||||
return radians * T(180.0/M_PI);
|
||||
}
|
||||
|
||||
inline long long NzStringToNumber(NzString str, nzUInt8 radix, bool* ok)
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (radix < 2 || radix > 36)
|
||||
{
|
||||
NazaraError("Radix must be between 2 and 36");
|
||||
|
||||
if (ok)
|
||||
*ok = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char* symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
str.Simplify();
|
||||
if (radix > 10)
|
||||
str = str.ToUpper();
|
||||
|
||||
bool negative = str.StartsWith('-');
|
||||
|
||||
char* digit = &str[(negative) ? 1 : 0];
|
||||
unsigned long long total = 0;
|
||||
do
|
||||
{
|
||||
if (*digit == ' ')
|
||||
continue;
|
||||
|
||||
total *= radix;
|
||||
const char* c = std::strchr(symbols, *digit);
|
||||
if (c && c-symbols < radix)
|
||||
total += c-symbols;
|
||||
///TODO: Marquer comme constexpr en C++14
|
||||
if (value < objective)
|
||||
return std::min(value + increment, objective);
|
||||
else if (value > objective)
|
||||
return std::max(value - increment, objective);
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T Clamp(T value, T min, T max)
|
||||
{
|
||||
return std::max(std::min(value, max), min);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T CountBits(T value)
|
||||
{
|
||||
// https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
|
||||
unsigned int count = 0;
|
||||
while (value)
|
||||
{
|
||||
value &= value - 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T DegreeToRadian(T degrees)
|
||||
{
|
||||
return degrees * T(M_PI/180.0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T FromDegrees(T degrees)
|
||||
{
|
||||
#if NAZARA_MATH_ANGLE_RADIAN
|
||||
return DegreeToRadian(degrees);
|
||||
#else
|
||||
return degrees;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T FromRadians(T radians)
|
||||
{
|
||||
#if NAZARA_MATH_ANGLE_RADIAN
|
||||
return radians;
|
||||
#else
|
||||
return RadianToDegree(radians);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T GetNearestPowerOfTwo(T number)
|
||||
{
|
||||
///TODO: Marquer comme constexpr en C++14
|
||||
T x = 1;
|
||||
// Tant que x est plus petit que n, on décale ses bits vers la gauche, ce qui revient à multiplier par deux
|
||||
while (x < number)
|
||||
x <<= 1;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
inline unsigned int GetNumberLength(signed char number)
|
||||
{
|
||||
///TODO: Marquer comme constexpr en C++14
|
||||
// Le standard définit le char comme étant codé sur un octet
|
||||
static_assert(sizeof(number) == 1, "Signed char must be one byte-sized");
|
||||
|
||||
if (number >= 100)
|
||||
return 3;
|
||||
else if (number >= 10)
|
||||
return 2;
|
||||
else if (number >= 0)
|
||||
return 1;
|
||||
else if (number > -10)
|
||||
return 2;
|
||||
else if (number > -100)
|
||||
return 3;
|
||||
else
|
||||
return 4;
|
||||
}
|
||||
|
||||
inline unsigned int GetNumberLength(unsigned char number)
|
||||
{
|
||||
///TODO: Marquer comme constexpr en C++14
|
||||
// Le standard définit le char comme étant codé sur un octet
|
||||
static_assert(sizeof(number) == 1, "Unsigned char must be one byte-sized");
|
||||
|
||||
if (number >= 100)
|
||||
return 3;
|
||||
else if (number >= 10)
|
||||
return 2;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline unsigned int GetNumberLength(int number)
|
||||
{
|
||||
if (number == 0)
|
||||
return 1;
|
||||
|
||||
return static_cast<unsigned int>(std::log10(std::abs(number))) + (number < 0 ? 2 : 1);
|
||||
}
|
||||
|
||||
inline unsigned int GetNumberLength(unsigned int number)
|
||||
{
|
||||
if (number == 0)
|
||||
return 1;
|
||||
|
||||
return static_cast<unsigned int>(std::log10(number))+1;
|
||||
}
|
||||
|
||||
inline unsigned int GetNumberLength(long long number)
|
||||
{
|
||||
if (number == 0)
|
||||
return 1;
|
||||
|
||||
return static_cast<unsigned int>(std::log10(std::abs(number))) + (number < 0 ? 2 : 1);
|
||||
}
|
||||
|
||||
inline unsigned int GetNumberLength(unsigned long long number)
|
||||
{
|
||||
if (number == 0)
|
||||
return 1;
|
||||
|
||||
return static_cast<unsigned int>(std::log10(number)) + 1;
|
||||
}
|
||||
|
||||
inline unsigned int GetNumberLength(float number, UInt8 precision)
|
||||
{
|
||||
// L'imprécision des flottants nécessite un cast (log10(9.99999) = 0.99999)
|
||||
return GetNumberLength(static_cast<long long>(number)) + precision + 1; // Plus un pour le point
|
||||
}
|
||||
|
||||
inline unsigned int GetNumberLength(double number, UInt8 precision)
|
||||
{
|
||||
// L'imprécision des flottants nécessite un cast (log10(9.99999) = 0.99999)
|
||||
return GetNumberLength(static_cast<long long>(number)) + precision + 1; // Plus un pour le point
|
||||
}
|
||||
|
||||
inline unsigned int GetNumberLength(long double number, UInt8 precision)
|
||||
{
|
||||
// L'imprécision des flottants nécessite un cast (log10(9.99999) = 0.99999)
|
||||
return GetNumberLength(static_cast<long long>(number)) + precision + 1; // Plus un pour le point
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
unsigned int IntegralLog2(T number)
|
||||
{
|
||||
// Proxy nécessaire pour éviter un problème de surcharge
|
||||
return Detail::IntegralLog2<T>(number);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
unsigned int IntegralLog2Pot(T pot)
|
||||
{
|
||||
return Detail::IntegralLog2Pot<T>(pot);
|
||||
}
|
||||
|
||||
inline unsigned int IntegralPow(unsigned int base, unsigned int exponent)
|
||||
{
|
||||
///TODO: Marquer comme constexpr en C++14
|
||||
unsigned int r = 1;
|
||||
for (unsigned int i = 0; i < exponent; ++i)
|
||||
r *= base;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename T, typename T2>
|
||||
T Lerp(T from, T to, T2 interpolation)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (interpolation < T2(0.0) || interpolation > T2(1.0))
|
||||
NazaraWarning("Interpolation should be in range [0..1] (Got " + String::Number(interpolation) + ')');
|
||||
#endif
|
||||
|
||||
return from + interpolation * (to - from);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T MultiplyAdd(T x, T y, T z)
|
||||
{
|
||||
return x*y + z;
|
||||
}
|
||||
|
||||
#ifdef FP_FAST_FMAF
|
||||
template<>
|
||||
inline float MultiplyAdd(float x, float y, float z)
|
||||
{
|
||||
return std::fmaf(x, y, z);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FP_FAST_FMA
|
||||
template<>
|
||||
inline double MultiplyAdd(double x, double y, double z)
|
||||
{
|
||||
return std::fma(x, y, z);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FP_FAST_FMAL
|
||||
template<>
|
||||
inline long double MultiplyAdd(long double x, long double y, long double z)
|
||||
{
|
||||
return std::fmal(x, y, z);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
T NormalizeAngle(T angle)
|
||||
{
|
||||
#if NAZARA_MATH_ANGLE_RADIAN
|
||||
const T limit = T(M_PI);
|
||||
#else
|
||||
const T limit = T(180.0);
|
||||
#endif
|
||||
const T twoLimit = limit * T(2);
|
||||
|
||||
angle = std::fmod(angle + limit, twoLimit);
|
||||
if (angle < T(0))
|
||||
angle += twoLimit;
|
||||
|
||||
return angle - limit;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NumberEquals(T a, T b)
|
||||
{
|
||||
return NumberEquals(a, b, std::numeric_limits<T>::epsilon());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NumberEquals(T a, T b, T maxDifference)
|
||||
{
|
||||
if (b > a)
|
||||
std::swap(a, b);
|
||||
|
||||
T diff = a - b;
|
||||
return diff <= maxDifference;
|
||||
}
|
||||
|
||||
inline String NumberToString(long long number, UInt8 radix)
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (radix < 2 || radix > 36)
|
||||
{
|
||||
NazaraError("Base must be between 2 and 36");
|
||||
return String();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (number == 0)
|
||||
return String('0');
|
||||
|
||||
static const char* symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
bool negative;
|
||||
if (number < 0)
|
||||
{
|
||||
negative = true;
|
||||
number = -number;
|
||||
}
|
||||
else
|
||||
negative = false;
|
||||
|
||||
String str;
|
||||
str.Reserve(GetNumberLength(number)); // Prends en compte le signe négatif
|
||||
|
||||
do
|
||||
{
|
||||
str.Append(symbols[number % radix]);
|
||||
number /= radix;
|
||||
}
|
||||
while (number > 0);
|
||||
|
||||
if (negative)
|
||||
str.Append('-');
|
||||
|
||||
return str.Reverse();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T RadianToDegree(T radians)
|
||||
{
|
||||
return radians * T(180.0/M_PI);
|
||||
}
|
||||
|
||||
inline long long StringToNumber(String str, UInt8 radix, bool* ok)
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (radix < 2 || radix > 36)
|
||||
{
|
||||
NazaraError("Radix must be between 2 and 36");
|
||||
|
||||
if (ok)
|
||||
*ok = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char* symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
str.Simplify();
|
||||
if (radix > 10)
|
||||
str = str.ToUpper();
|
||||
|
||||
bool negative = str.StartsWith('-');
|
||||
|
||||
char* digit = &str[(negative) ? 1 : 0];
|
||||
unsigned long long total = 0;
|
||||
do
|
||||
{
|
||||
if (*digit == ' ')
|
||||
continue;
|
||||
|
||||
total *= radix;
|
||||
const char* c = std::strchr(symbols, *digit);
|
||||
if (c && c-symbols < radix)
|
||||
total += c-symbols;
|
||||
else
|
||||
{
|
||||
if (ok)
|
||||
*ok = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
while (*++digit);
|
||||
|
||||
if (ok)
|
||||
*ok = true;
|
||||
|
||||
return (negative) ? -static_cast<long long>(total) : total;
|
||||
}
|
||||
while (*++digit);
|
||||
|
||||
if (ok)
|
||||
*ok = true;
|
||||
template<typename T>
|
||||
constexpr T ToDegrees(T angle)
|
||||
{
|
||||
#if NAZARA_MATH_ANGLE_RADIAN
|
||||
return RadianToDegree(angle);
|
||||
#else
|
||||
return angle;
|
||||
#endif
|
||||
}
|
||||
|
||||
return (negative) ? -static_cast<long long>(total) : total;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T NzToDegrees(T angle)
|
||||
{
|
||||
#if NAZARA_MATH_ANGLE_RADIAN
|
||||
return NzRadianToDegree(angle);
|
||||
#else
|
||||
return angle;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T NzToRadians(T angle)
|
||||
{
|
||||
#if NAZARA_MATH_ANGLE_RADIAN
|
||||
return angle;
|
||||
#else
|
||||
return NzDegreeToRadian(angle);
|
||||
template<typename T>
|
||||
constexpr T ToRadians(T angle)
|
||||
{
|
||||
#if NAZARA_MATH_ANGLE_RADIAN
|
||||
return angle;
|
||||
#else
|
||||
return DegreeToRadian(angle);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -12,61 +12,64 @@
|
||||
#include <Nazara/Math/OrientedBox.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
|
||||
template<typename T>
|
||||
class NzBoundingVolume
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzBoundingVolume();
|
||||
NzBoundingVolume(nzExtend Extend);
|
||||
NzBoundingVolume(T X, T Y, T Z, T Width, T Height, T Depth);
|
||||
NzBoundingVolume(const NzBox<T>& box);
|
||||
NzBoundingVolume(const NzOrientedBox<T>& orientedBox);
|
||||
NzBoundingVolume(const NzVector3<T>& vec1, const NzVector3<T>& vec2);
|
||||
template<typename U> explicit NzBoundingVolume(const NzBoundingVolume<U>& volume);
|
||||
NzBoundingVolume(const NzBoundingVolume& volume) = default;
|
||||
~NzBoundingVolume() = default;
|
||||
template<typename T>
|
||||
class BoundingVolume
|
||||
{
|
||||
public:
|
||||
BoundingVolume();
|
||||
BoundingVolume(Extend Extend);
|
||||
BoundingVolume(T X, T Y, T Z, T Width, T Height, T Depth);
|
||||
BoundingVolume(const Box<T>& box);
|
||||
BoundingVolume(const OrientedBox<T>& orientedBox);
|
||||
BoundingVolume(const Vector3<T>& vec1, const Vector3<T>& vec2);
|
||||
template<typename U> explicit BoundingVolume(const BoundingVolume<U>& volume);
|
||||
BoundingVolume(const BoundingVolume& volume) = default;
|
||||
~BoundingVolume() = default;
|
||||
|
||||
bool IsFinite() const;
|
||||
bool IsInfinite() const;
|
||||
bool IsNull() const;
|
||||
bool IsFinite() const;
|
||||
bool IsInfinite() const;
|
||||
bool IsNull() const;
|
||||
|
||||
NzBoundingVolume& MakeInfinite();
|
||||
NzBoundingVolume& MakeNull();
|
||||
BoundingVolume& MakeInfinite();
|
||||
BoundingVolume& MakeNull();
|
||||
|
||||
NzBoundingVolume& Set(nzExtend Extend);
|
||||
NzBoundingVolume& Set(T X, T Y, T Z, T Width, T Height, T Depth);
|
||||
NzBoundingVolume& Set(const NzBoundingVolume<T>& volume);
|
||||
NzBoundingVolume& Set(const NzBox<T>& box);
|
||||
NzBoundingVolume& Set(const NzOrientedBox<T>& orientedBox);
|
||||
NzBoundingVolume& Set(const NzVector3<T>& vec1, const NzVector3<T>& vec2);
|
||||
template<typename U> NzBoundingVolume& Set(const NzBoundingVolume<U>& volume);
|
||||
BoundingVolume& Set(Extend Extend);
|
||||
BoundingVolume& Set(T X, T Y, T Z, T Width, T Height, T Depth);
|
||||
BoundingVolume& Set(const BoundingVolume<T>& volume);
|
||||
BoundingVolume& Set(const Box<T>& box);
|
||||
BoundingVolume& Set(const OrientedBox<T>& orientedBox);
|
||||
BoundingVolume& Set(const Vector3<T>& vec1, const Vector3<T>& vec2);
|
||||
template<typename U> BoundingVolume& Set(const BoundingVolume<U>& volume);
|
||||
|
||||
NzString ToString() const;
|
||||
String ToString() const;
|
||||
|
||||
void Update(const NzMatrix4<T>& transformMatrix);
|
||||
void Update(const NzVector3<T>& translation);
|
||||
void Update(const Matrix4<T>& transformMatrix);
|
||||
void Update(const Vector3<T>& translation);
|
||||
|
||||
NzBoundingVolume operator*(T scalar) const;
|
||||
BoundingVolume operator*(T scalar) const;
|
||||
|
||||
NzBoundingVolume& operator*=(T scalar);
|
||||
BoundingVolume& operator*=(T scalar);
|
||||
|
||||
bool operator==(const NzBoundingVolume& volume) const;
|
||||
bool operator!=(const NzBoundingVolume& volume) const;
|
||||
bool operator==(const BoundingVolume& volume) const;
|
||||
bool operator!=(const BoundingVolume& volume) const;
|
||||
|
||||
static NzBoundingVolume Infinite();
|
||||
static NzBoundingVolume Lerp(const NzBoundingVolume& from, const NzBoundingVolume& to, T interpolation);
|
||||
static NzBoundingVolume Null();
|
||||
static BoundingVolume Infinite();
|
||||
static BoundingVolume Lerp(const BoundingVolume& from, const BoundingVolume& to, T interpolation);
|
||||
static BoundingVolume Null();
|
||||
|
||||
nzExtend extend;
|
||||
NzBox<T> aabb;
|
||||
NzOrientedBox<T> obb;
|
||||
};
|
||||
Extend extend;
|
||||
Box<T> aabb;
|
||||
OrientedBox<T> obb;
|
||||
};
|
||||
|
||||
typedef BoundingVolume<double> BoundingVolumed;
|
||||
typedef BoundingVolume<float> BoundingVolumef;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzBoundingVolume<T>& volume);
|
||||
|
||||
typedef NzBoundingVolume<double> NzBoundingVolumed;
|
||||
typedef NzBoundingVolume<float> NzBoundingVolumef;
|
||||
std::ostream& operator<<(std::ostream& out, const Nz::BoundingVolume<T>& volume);
|
||||
|
||||
#include <Nazara/Math/BoundingVolume.inl>
|
||||
|
||||
|
||||
@@ -11,315 +11,318 @@
|
||||
|
||||
#define F(a) static_cast<T>(a)
|
||||
|
||||
template<typename T>
|
||||
NzBoundingVolume<T>::NzBoundingVolume() :
|
||||
extend(nzExtend_Null)
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzBoundingVolume<T>::NzBoundingVolume(nzExtend Extend)
|
||||
{
|
||||
Set(Extend);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzBoundingVolume<T>::NzBoundingVolume(T X, T Y, T Z, T Width, T Height, T Depth)
|
||||
{
|
||||
Set(X, Y, Z, Width, Height, Depth);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzBoundingVolume<T>::NzBoundingVolume(const NzBox<T>& box)
|
||||
{
|
||||
Set(box);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzBoundingVolume<T>::NzBoundingVolume(const NzOrientedBox<T>& orientedBox)
|
||||
{
|
||||
Set(orientedBox);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzBoundingVolume<T>::NzBoundingVolume(const NzVector3<T>& vec1, const NzVector3<T>& vec2)
|
||||
{
|
||||
Set(vec1, vec2);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzBoundingVolume<T>::NzBoundingVolume(const NzBoundingVolume<U>& volume)
|
||||
{
|
||||
Set(volume);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzBoundingVolume<T>::IsFinite() const
|
||||
{
|
||||
return extend == nzExtend_Finite;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzBoundingVolume<T>::IsInfinite() const
|
||||
{
|
||||
return extend == nzExtend_Infinite;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzBoundingVolume<T>::IsNull() const
|
||||
{
|
||||
return extend == nzExtend_Null;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzBoundingVolume<T>& NzBoundingVolume<T>::MakeInfinite()
|
||||
{
|
||||
extend = nzExtend_Infinite;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzBoundingVolume<T>& NzBoundingVolume<T>::MakeNull()
|
||||
{
|
||||
extend = nzExtend_Null;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzBoundingVolume<T>& NzBoundingVolume<T>::Set(nzExtend Extend)
|
||||
{
|
||||
extend = Extend;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzBoundingVolume<T>& NzBoundingVolume<T>::Set(T X, T Y, T Z, T Width, T Height, T Depth)
|
||||
{
|
||||
obb.Set(X, Y, Z, Width, Height, Depth);
|
||||
extend = nzExtend_Finite;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzBoundingVolume<T>& NzBoundingVolume<T>::Set(const NzBoundingVolume<T>& volume)
|
||||
{
|
||||
obb.Set(volume.obb); // Seul l'OBB est importante pour la suite
|
||||
extend = volume.extend;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzBoundingVolume<T>& NzBoundingVolume<T>::Set(const NzBox<T>& box)
|
||||
{
|
||||
obb.Set(box);
|
||||
extend = nzExtend_Finite;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzBoundingVolume<T>& NzBoundingVolume<T>::Set(const NzOrientedBox<T>& orientedBox)
|
||||
{
|
||||
obb.Set(orientedBox);
|
||||
extend = nzExtend_Finite;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzBoundingVolume<T>& NzBoundingVolume<T>::Set(const NzVector3<T>& vec1, const NzVector3<T>& vec2)
|
||||
{
|
||||
obb.Set(vec1, vec2);
|
||||
extend = nzExtend_Finite;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzBoundingVolume<T>& NzBoundingVolume<T>::Set(const NzBoundingVolume<U>& volume)
|
||||
{
|
||||
obb.Set(volume.obb);
|
||||
extend = volume.extend;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzString NzBoundingVolume<T>::ToString() const
|
||||
{
|
||||
switch (extend)
|
||||
template<typename T>
|
||||
BoundingVolume<T>::BoundingVolume() :
|
||||
extend(Extend_Null)
|
||||
{
|
||||
case nzExtend_Finite:
|
||||
return "BoundingVolume(localBox=" + obb.localBox.ToString() + ')';
|
||||
|
||||
case nzExtend_Infinite:
|
||||
return "BoundingVolume(Infinite)";
|
||||
|
||||
case nzExtend_Null:
|
||||
return "BoundingVolume(Null)";
|
||||
}
|
||||
|
||||
// Si nous arrivons ici c'est que l'extend est invalide
|
||||
NazaraError("Invalid extend type (0x" + NzString::Number(extend, 16) + ')');
|
||||
return "BoundingVolume(ERROR)";
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzBoundingVolume<T>::Update(const NzMatrix4<T>& transformMatrix)
|
||||
{
|
||||
obb.Update(transformMatrix);
|
||||
|
||||
aabb.Set(obb(0), obb(1));
|
||||
for (unsigned int i = 2; i < 8; ++i)
|
||||
aabb.ExtendTo(obb(i));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzBoundingVolume<T>::Update(const NzVector3<T>& translation)
|
||||
{
|
||||
obb.Update(translation);
|
||||
|
||||
aabb.Set(obb(0), obb(1));
|
||||
for (unsigned int i = 2; i < 8; ++i)
|
||||
aabb.ExtendTo(obb(i));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzBoundingVolume<T> NzBoundingVolume<T>::operator*(T scalar) const
|
||||
{
|
||||
NzBoundingVolume volume(*this);
|
||||
volume *= scalar;
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzBoundingVolume<T>& NzBoundingVolume<T>::operator*=(T scalar)
|
||||
{
|
||||
obb *= scalar;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzBoundingVolume<T>::operator==(const NzBoundingVolume& volume) const
|
||||
{
|
||||
if (extend == volume.extend)
|
||||
if (extend == nzExtend_Finite)
|
||||
return obb == volume.obb;
|
||||
else
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzBoundingVolume<T>::operator!=(const NzBoundingVolume& volume) const
|
||||
{
|
||||
return !operator==(volume);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzBoundingVolume<T> NzBoundingVolume<T>::Infinite()
|
||||
{
|
||||
NzBoundingVolume volume;
|
||||
volume.MakeInfinite();
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzBoundingVolume<T> NzBoundingVolume<T>::Lerp(const NzBoundingVolume& from, const NzBoundingVolume& to, T interpolation)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (interpolation < F(0.0) || interpolation > F(1.0))
|
||||
template<typename T>
|
||||
BoundingVolume<T>::BoundingVolume(Extend Extend)
|
||||
{
|
||||
NazaraError("Interpolation must be in range [0..1] (Got " + NzString::Number(interpolation) + ')');
|
||||
return Null();
|
||||
Set(Extend);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (NzNumberEquals(interpolation, F(0.0)))
|
||||
return from;
|
||||
|
||||
if (NzNumberEquals(interpolation, F(1.0)))
|
||||
return to;
|
||||
|
||||
switch (to.extend)
|
||||
template<typename T>
|
||||
BoundingVolume<T>::BoundingVolume(T X, T Y, T Z, T Width, T Height, T Depth)
|
||||
{
|
||||
case nzExtend_Finite:
|
||||
Set(X, Y, Z, Width, Height, Depth);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BoundingVolume<T>::BoundingVolume(const Box<T>& box)
|
||||
{
|
||||
Set(box);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BoundingVolume<T>::BoundingVolume(const OrientedBox<T>& orientedBox)
|
||||
{
|
||||
Set(orientedBox);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BoundingVolume<T>::BoundingVolume(const Vector3<T>& vec1, const Vector3<T>& vec2)
|
||||
{
|
||||
Set(vec1, vec2);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
BoundingVolume<T>::BoundingVolume(const BoundingVolume<U>& volume)
|
||||
{
|
||||
Set(volume);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool BoundingVolume<T>::IsFinite() const
|
||||
{
|
||||
return extend == Extend_Finite;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool BoundingVolume<T>::IsInfinite() const
|
||||
{
|
||||
return extend == Extend_Infinite;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool BoundingVolume<T>::IsNull() const
|
||||
{
|
||||
return extend == Extend_Null;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BoundingVolume<T>& BoundingVolume<T>::MakeInfinite()
|
||||
{
|
||||
extend = Extend_Infinite;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BoundingVolume<T>& BoundingVolume<T>::MakeNull()
|
||||
{
|
||||
extend = Extend_Null;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BoundingVolume<T>& BoundingVolume<T>::Set(Extend Extend)
|
||||
{
|
||||
extend = Extend;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BoundingVolume<T>& BoundingVolume<T>::Set(T X, T Y, T Z, T Width, T Height, T Depth)
|
||||
{
|
||||
obb.Set(X, Y, Z, Width, Height, Depth);
|
||||
extend = Extend_Finite;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BoundingVolume<T>& BoundingVolume<T>::Set(const BoundingVolume<T>& volume)
|
||||
{
|
||||
obb.Set(volume.obb); // Seul l'OBB est importante pour la suite
|
||||
extend = volume.extend;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BoundingVolume<T>& BoundingVolume<T>::Set(const Box<T>& box)
|
||||
{
|
||||
obb.Set(box);
|
||||
extend = Extend_Finite;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BoundingVolume<T>& BoundingVolume<T>::Set(const OrientedBox<T>& orientedBox)
|
||||
{
|
||||
obb.Set(orientedBox);
|
||||
extend = Extend_Finite;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BoundingVolume<T>& BoundingVolume<T>::Set(const Vector3<T>& vec1, const Vector3<T>& vec2)
|
||||
{
|
||||
obb.Set(vec1, vec2);
|
||||
extend = Extend_Finite;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
BoundingVolume<T>& BoundingVolume<T>::Set(const BoundingVolume<U>& volume)
|
||||
{
|
||||
obb.Set(volume.obb);
|
||||
extend = volume.extend;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
String BoundingVolume<T>::ToString() const
|
||||
{
|
||||
switch (extend)
|
||||
{
|
||||
switch (from.extend)
|
||||
{
|
||||
case nzExtend_Finite:
|
||||
{
|
||||
NzBoundingVolume volume;
|
||||
volume.Set(NzOrientedBox<T>::Lerp(from.obb, to.obb, interpolation));
|
||||
case Extend_Finite:
|
||||
return "BoundingVolume(localBox=" + obb.localBox.ToString() + ')';
|
||||
|
||||
return volume;
|
||||
case Extend_Infinite:
|
||||
return "BoundingVolume(Infinite)";
|
||||
|
||||
case Extend_Null:
|
||||
return "BoundingVolume(Null)";
|
||||
}
|
||||
|
||||
// Si nous arrivons ici c'est que l'extend est invalide
|
||||
NazaraError("Invalid extend type (0x" + String::Number(extend, 16) + ')');
|
||||
return "BoundingVolume(ERROR)";
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void BoundingVolume<T>::Update(const Matrix4<T>& transformMatrix)
|
||||
{
|
||||
obb.Update(transformMatrix);
|
||||
|
||||
aabb.Set(obb(0), obb(1));
|
||||
for (unsigned int i = 2; i < 8; ++i)
|
||||
aabb.ExtendTo(obb(i));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void BoundingVolume<T>::Update(const Vector3<T>& translation)
|
||||
{
|
||||
obb.Update(translation);
|
||||
|
||||
aabb.Set(obb(0), obb(1));
|
||||
for (unsigned int i = 2; i < 8; ++i)
|
||||
aabb.ExtendTo(obb(i));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BoundingVolume<T> BoundingVolume<T>::operator*(T scalar) const
|
||||
{
|
||||
BoundingVolume volume(*this);
|
||||
volume *= scalar;
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BoundingVolume<T>& BoundingVolume<T>::operator*=(T scalar)
|
||||
{
|
||||
obb *= scalar;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool BoundingVolume<T>::operator==(const BoundingVolume& volume) const
|
||||
{
|
||||
if (extend == volume.extend)
|
||||
if (extend == Extend_Finite)
|
||||
return obb == volume.obb;
|
||||
else
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool BoundingVolume<T>::operator!=(const BoundingVolume& volume) const
|
||||
{
|
||||
return !operator==(volume);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BoundingVolume<T> BoundingVolume<T>::Infinite()
|
||||
{
|
||||
BoundingVolume volume;
|
||||
volume.MakeInfinite();
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BoundingVolume<T> BoundingVolume<T>::Lerp(const BoundingVolume& from, const BoundingVolume& to, T interpolation)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (interpolation < F(0.0) || interpolation > F(1.0))
|
||||
{
|
||||
NazaraError("Interpolation must be in range [0..1] (Got " + String::Number(interpolation) + ')');
|
||||
return Null();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (NumberEquals(interpolation, F(0.0)))
|
||||
return from;
|
||||
|
||||
if (NumberEquals(interpolation, F(1.0)))
|
||||
return to;
|
||||
|
||||
switch (to.extend)
|
||||
{
|
||||
case Extend_Finite:
|
||||
{
|
||||
switch (from.extend)
|
||||
{
|
||||
case Extend_Finite:
|
||||
{
|
||||
BoundingVolume volume;
|
||||
volume.Set(OrientedBox<T>::Lerp(from.obb, to.obb, interpolation));
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
case Extend_Infinite:
|
||||
return Infinite();
|
||||
|
||||
case Extend_Null:
|
||||
return from.obb * interpolation;
|
||||
}
|
||||
|
||||
case nzExtend_Infinite:
|
||||
return Infinite();
|
||||
|
||||
case nzExtend_Null:
|
||||
return from.obb * interpolation;
|
||||
// Si nous arrivons ici c'est que l'extend est invalide
|
||||
NazaraError("Invalid extend type (From) (0x" + String::Number(from.extend, 16) + ')');
|
||||
return Null();
|
||||
}
|
||||
|
||||
// Si nous arrivons ici c'est que l'extend est invalide
|
||||
NazaraError("Invalid extend type (From) (0x" + NzString::Number(from.extend, 16) + ')');
|
||||
return Null();
|
||||
}
|
||||
case Extend_Infinite:
|
||||
return Infinite(); // Un petit peu d'infini est infini quand même ;)
|
||||
|
||||
case nzExtend_Infinite:
|
||||
return Infinite(); // Un petit peu d'infini est infini quand même ;)
|
||||
|
||||
case nzExtend_Null:
|
||||
{
|
||||
switch (from.extend)
|
||||
case Extend_Null:
|
||||
{
|
||||
case nzExtend_Finite:
|
||||
return from.obb * (F(1.0) - interpolation);
|
||||
switch (from.extend)
|
||||
{
|
||||
case Extend_Finite:
|
||||
return from.obb * (F(1.0) - interpolation);
|
||||
|
||||
case nzExtend_Infinite:
|
||||
return Infinite();
|
||||
case Extend_Infinite:
|
||||
return Infinite();
|
||||
|
||||
case nzExtend_Null:
|
||||
return Null();
|
||||
case Extend_Null:
|
||||
return Null();
|
||||
}
|
||||
|
||||
// Si nous arrivons ici c'est que l'extend est invalide
|
||||
NazaraError("Invalid extend type (From) (0x" + String::Number(from.extend, 16) + ')');
|
||||
return Null();
|
||||
}
|
||||
|
||||
// Si nous arrivons ici c'est que l'extend est invalide
|
||||
NazaraError("Invalid extend type (From) (0x" + NzString::Number(from.extend, 16) + ')');
|
||||
return Null();
|
||||
}
|
||||
|
||||
// Si nous arrivons ici c'est que l'extend est invalide
|
||||
NazaraError("Invalid extend type (To) (0x" + String::Number(to.extend, 16) + ')');
|
||||
return Null();
|
||||
}
|
||||
|
||||
// Si nous arrivons ici c'est que l'extend est invalide
|
||||
NazaraError("Invalid extend type (To) (0x" + NzString::Number(to.extend, 16) + ')');
|
||||
return Null();
|
||||
template<typename T>
|
||||
BoundingVolume<T> BoundingVolume<T>::Null()
|
||||
{
|
||||
BoundingVolume volume;
|
||||
volume.MakeNull();
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const BoundingVolume<T>& volume)
|
||||
{
|
||||
out << volume.ToString();
|
||||
return out;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzBoundingVolume<T> NzBoundingVolume<T>::Null()
|
||||
{
|
||||
NzBoundingVolume volume;
|
||||
volume.MakeNull();
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzBoundingVolume<T>& volume)
|
||||
{
|
||||
out << volume.ToString();
|
||||
return out;
|
||||
}
|
||||
|
||||
#undef F
|
||||
|
||||
@@ -14,89 +14,93 @@
|
||||
#include <Nazara/Math/Sphere.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
|
||||
template<typename T>
|
||||
class NzBox
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzBox() = default;
|
||||
NzBox(T Width, T Height, T Depth);
|
||||
NzBox(T X, T Y, T Z, T Width, T Height, T Depth);
|
||||
NzBox(const T box[6]);
|
||||
NzBox(const NzRect<T>& rect);
|
||||
NzBox(const NzVector3<T>& lengths);
|
||||
NzBox(const NzVector3<T>& vec1, const NzVector3<T>& vec2);
|
||||
template<typename U> explicit NzBox(const NzBox<U>& box);
|
||||
NzBox(const NzBox& box) = default;
|
||||
~NzBox() = default;
|
||||
template<typename T>
|
||||
class Box
|
||||
{
|
||||
public:
|
||||
Box() = default;
|
||||
Box(T Width, T Height, T Depth);
|
||||
Box(T X, T Y, T Z, T Width, T Height, T Depth);
|
||||
Box(const T box[6]);
|
||||
Box(const Rect<T>& rect);
|
||||
Box(const Vector3<T>& lengths);
|
||||
Box(const Vector3<T>& vec1, const Vector3<T>& vec2);
|
||||
template<typename U> explicit Box(const Box<U>& box);
|
||||
Box(const Box& box) = default;
|
||||
~Box() = default;
|
||||
|
||||
bool Contains(T X, T Y, T Z) const;
|
||||
bool Contains(const NzBox& box) const;
|
||||
bool Contains(const NzVector3<T>& point) const;
|
||||
bool Contains(T X, T Y, T Z) const;
|
||||
bool Contains(const Box& box) const;
|
||||
bool Contains(const Vector3<T>& point) const;
|
||||
|
||||
NzBox& ExtendTo(T X, T Y, T Z);
|
||||
NzBox& ExtendTo(const NzBox& box);
|
||||
NzBox& ExtendTo(const NzVector3<T>& point);
|
||||
Box& ExtendTo(T X, T Y, T Z);
|
||||
Box& ExtendTo(const Box& box);
|
||||
Box& ExtendTo(const Vector3<T>& point);
|
||||
|
||||
NzSphere<T> GetBoundingSphere() const;
|
||||
NzVector3<T> GetCorner(nzBoxCorner corner) const;
|
||||
NzVector3<T> GetCenter() const;
|
||||
NzVector3<T> GetLengths() const;
|
||||
NzVector3<T> GetMaximum() const;
|
||||
NzVector3<T> GetMinimum() const;
|
||||
NzVector3<T> GetNegativeVertex(const NzVector3<T>& normal) const;
|
||||
NzVector3<T> GetPosition() const;
|
||||
NzVector3<T> GetPositiveVertex(const NzVector3<T>& normal) const;
|
||||
T GetRadius() const;
|
||||
NzSphere<T> GetSquaredBoundingSphere() const;
|
||||
T GetSquaredRadius() const;
|
||||
Sphere<T> GetBoundingSphere() const;
|
||||
Vector3<T> GetCorner(BoxCorner corner) const;
|
||||
Vector3<T> GetCenter() const;
|
||||
Vector3<T> GetLengths() const;
|
||||
Vector3<T> GetMaximum() const;
|
||||
Vector3<T> GetMinimum() const;
|
||||
Vector3<T> GetNegativeVertex(const Vector3<T>& normal) const;
|
||||
Vector3<T> GetPosition() const;
|
||||
Vector3<T> GetPositiveVertex(const Vector3<T>& normal) const;
|
||||
T GetRadius() const;
|
||||
Sphere<T> GetSquaredBoundingSphere() const;
|
||||
T GetSquaredRadius() const;
|
||||
|
||||
bool Intersect(const NzBox& box, NzBox* intersection = nullptr) const;
|
||||
bool Intersect(const Box& box, Box* intersection = nullptr) const;
|
||||
|
||||
bool IsValid() const;
|
||||
bool IsValid() const;
|
||||
|
||||
NzBox& MakeZero();
|
||||
Box& MakeZero();
|
||||
|
||||
NzBox& Set(T Width, T Height, T Depth);
|
||||
NzBox& Set(T X, T Y, T Z, T Width, T Height, T Depth);
|
||||
NzBox& Set(const T box[6]);
|
||||
NzBox& Set(const NzBox& box);
|
||||
NzBox& Set(const NzRect<T>& rect);
|
||||
NzBox& Set(const NzVector3<T>& lengths);
|
||||
NzBox& Set(const NzVector3<T>& vec1, const NzVector3<T>& vec2);
|
||||
template<typename U> NzBox& Set(const NzBox<U>& box);
|
||||
Box& Set(T Width, T Height, T Depth);
|
||||
Box& Set(T X, T Y, T Z, T Width, T Height, T Depth);
|
||||
Box& Set(const T box[6]);
|
||||
Box& Set(const Box& box);
|
||||
Box& Set(const Rect<T>& rect);
|
||||
Box& Set(const Vector3<T>& lengths);
|
||||
Box& Set(const Vector3<T>& vec1, const Vector3<T>& vec2);
|
||||
template<typename U> Box& Set(const Box<U>& box);
|
||||
|
||||
NzString ToString() const;
|
||||
String ToString() const;
|
||||
|
||||
NzBox& Transform(const NzMatrix4<T>& matrix, bool applyTranslation = true);
|
||||
NzBox& Translate(const NzVector3<T>& translation);
|
||||
Box& Transform(const Matrix4<T>& matrix, bool applyTranslation = true);
|
||||
Box& Translate(const Vector3<T>& translation);
|
||||
|
||||
T& operator[](unsigned int i);
|
||||
T operator[](unsigned int i) const;
|
||||
T& operator[](unsigned int i);
|
||||
T operator[](unsigned int i) const;
|
||||
|
||||
NzBox operator*(T scalar) const;
|
||||
NzBox operator*(const NzVector3<T>& vec) const;
|
||||
Box operator*(T scalar) const;
|
||||
Box operator*(const Vector3<T>& vec) const;
|
||||
|
||||
NzBox& operator*=(T scalar);
|
||||
NzBox& operator*=(const NzVector3<T>& vec);
|
||||
Box& operator*=(T scalar);
|
||||
Box& operator*=(const Vector3<T>& vec);
|
||||
|
||||
bool operator==(const NzBox& box) const;
|
||||
bool operator!=(const NzBox& box) const;
|
||||
bool operator==(const Box& box) const;
|
||||
bool operator!=(const Box& box) const;
|
||||
|
||||
static NzBox Lerp(const NzBox& from, const NzBox& to, T interpolation);
|
||||
static NzBox Zero();
|
||||
static Box Lerp(const Box& from, const Box& to, T interpolation);
|
||||
static Box Zero();
|
||||
|
||||
T x, y, z, width, height, depth;
|
||||
};
|
||||
T x, y, z, width, height, depth;
|
||||
};
|
||||
|
||||
typedef Box<double> Boxd;
|
||||
typedef Box<float> Boxf;
|
||||
typedef Box<int> Boxi;
|
||||
typedef Box<unsigned int> Boxui;
|
||||
typedef Box<Int32> Boxi32;
|
||||
typedef Box<UInt32> Boxui32;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzBox<T>& box);
|
||||
std::ostream& operator<<(std::ostream& out, const Nz::Box<T>& box);
|
||||
|
||||
typedef NzBox<double> NzBoxd;
|
||||
typedef NzBox<float> NzBoxf;
|
||||
typedef NzBox<int> NzBoxi;
|
||||
typedef NzBox<unsigned int> NzBoxui;
|
||||
typedef NzBox<nzInt32> NzBoxi32;
|
||||
typedef NzBox<nzUInt32> NzBoxui32;
|
||||
|
||||
#include <Nazara/Math/Box.inl>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,58 +7,61 @@
|
||||
#ifndef NAZARA_ENUMS_MATH_HPP
|
||||
#define NAZARA_ENUMS_MATH_HPP
|
||||
|
||||
enum nzBoxCorner
|
||||
namespace Nz
|
||||
{
|
||||
nzBoxCorner_FarLeftBottom,
|
||||
nzBoxCorner_FarLeftTop,
|
||||
nzBoxCorner_FarRightBottom,
|
||||
nzBoxCorner_FarRightTop,
|
||||
nzBoxCorner_NearLeftBottom,
|
||||
nzBoxCorner_NearLeftTop,
|
||||
nzBoxCorner_NearRightBottom,
|
||||
nzBoxCorner_NearRightTop,
|
||||
enum BoxCorner
|
||||
{
|
||||
BoxCorner_FarLeftBottom,
|
||||
BoxCorner_FarLeftTop,
|
||||
BoxCorner_FarRightBottom,
|
||||
BoxCorner_FarRightTop,
|
||||
BoxCorner_NearLeftBottom,
|
||||
BoxCorner_NearLeftTop,
|
||||
BoxCorner_NearRightBottom,
|
||||
BoxCorner_NearRightTop,
|
||||
|
||||
nzBoxCorner_Max = nzBoxCorner_NearRightTop
|
||||
};
|
||||
BoxCorner_Max = BoxCorner_NearRightTop
|
||||
};
|
||||
|
||||
enum nzExtend
|
||||
{
|
||||
nzExtend_Finite,
|
||||
nzExtend_Infinite,
|
||||
nzExtend_Null,
|
||||
enum Extend
|
||||
{
|
||||
Extend_Finite,
|
||||
Extend_Infinite,
|
||||
Extend_Null,
|
||||
|
||||
nzExtend_Max = nzExtend_Null
|
||||
};
|
||||
Extend_Max = Extend_Null
|
||||
};
|
||||
|
||||
enum nzFrustumPlane
|
||||
{
|
||||
nzFrustumPlane_Bottom,
|
||||
nzFrustumPlane_Far,
|
||||
nzFrustumPlane_Left,
|
||||
nzFrustumPlane_Near,
|
||||
nzFrustumPlane_Right,
|
||||
nzFrustumPlane_Top,
|
||||
enum FrustumPlane
|
||||
{
|
||||
FrustumPlane_Bottom,
|
||||
FrustumPlane_Far,
|
||||
FrustumPlane_Left,
|
||||
FrustumPlane_Near,
|
||||
FrustumPlane_Right,
|
||||
FrustumPlane_Top,
|
||||
|
||||
nzFrustumPlane_Max = nzFrustumPlane_Top
|
||||
};
|
||||
FrustumPlane_Max = FrustumPlane_Top
|
||||
};
|
||||
|
||||
enum nzIntersectionSide
|
||||
{
|
||||
nzIntersectionSide_Inside,
|
||||
nzIntersectionSide_Intersecting,
|
||||
nzIntersectionSide_Outside,
|
||||
enum IntersectionSide
|
||||
{
|
||||
IntersectionSide_Inside,
|
||||
IntersectionSide_Intersecting,
|
||||
IntersectionSide_Outside,
|
||||
|
||||
nzIntersectionSide_Max = nzIntersectionSide_Outside
|
||||
};
|
||||
IntersectionSide_Max = IntersectionSide_Outside
|
||||
};
|
||||
|
||||
enum nzRectCorner
|
||||
{
|
||||
nzRectCorner_LeftBottom,
|
||||
nzRectCorner_LeftTop,
|
||||
nzRectCorner_RightBottom,
|
||||
nzRectCorner_RightTop,
|
||||
enum RectCorner
|
||||
{
|
||||
RectCorner_LeftBottom,
|
||||
RectCorner_LeftTop,
|
||||
RectCorner_RightBottom,
|
||||
RectCorner_RightTop,
|
||||
|
||||
nzRectCorner_Max = nzRectCorner_RightTop
|
||||
};
|
||||
RectCorner_Max = RectCorner_RightTop
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_ENUMS_MATH_HPP
|
||||
|
||||
@@ -11,55 +11,60 @@
|
||||
#include <Nazara/Math/Quaternion.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
|
||||
template<typename T> class NzEulerAngles
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzEulerAngles() = default;
|
||||
NzEulerAngles(T P, T Y, T R);
|
||||
NzEulerAngles(const T angles[3]);
|
||||
//NzEulerAngles(const NzMatrix3<T>& mat);
|
||||
NzEulerAngles(const NzQuaternion<T>& quat);
|
||||
template<typename U> explicit NzEulerAngles(const NzEulerAngles<U>& angles);
|
||||
NzEulerAngles(const NzEulerAngles& angles) = default;
|
||||
~NzEulerAngles() = default;
|
||||
template<typename T>
|
||||
class EulerAngles
|
||||
{
|
||||
public:
|
||||
EulerAngles() = default;
|
||||
EulerAngles(T P, T Y, T R);
|
||||
EulerAngles(const T angles[3]);
|
||||
//EulerAngles(const Matrix3<T>& mat);
|
||||
EulerAngles(const Quaternion<T>& quat);
|
||||
template<typename U> explicit EulerAngles(const EulerAngles<U>& angles);
|
||||
EulerAngles(const EulerAngles& angles) = default;
|
||||
~EulerAngles() = default;
|
||||
|
||||
void MakeZero();
|
||||
void MakeZero();
|
||||
|
||||
void Normalize();
|
||||
void Normalize();
|
||||
|
||||
void Set(T P, T Y, T R);
|
||||
void Set(const T angles[3]);
|
||||
void Set(const NzEulerAngles<T>& angles);
|
||||
//void Set(const NzMatrix3<T>& mat);
|
||||
void Set(const NzQuaternion<T>& quat);
|
||||
template<typename U> void Set(const NzEulerAngles<U>& angles);
|
||||
void Set(T P, T Y, T R);
|
||||
void Set(const T angles[3]);
|
||||
void Set(const EulerAngles<T>& angles);
|
||||
//void Set(const Matrix3<T>& mat);
|
||||
void Set(const Quaternion<T>& quat);
|
||||
template<typename U> void Set(const EulerAngles<U>& angles);
|
||||
|
||||
//NzMatrix3<T> ToRotationMatrix() const;
|
||||
NzQuaternion<T> ToQuaternion() const;
|
||||
NzString ToString() const;
|
||||
//Matrix3<T> ToRotationMatrix() const;
|
||||
Quaternion<T> ToQuaternion() const;
|
||||
String ToString() const;
|
||||
|
||||
NzEulerAngles operator+(const NzEulerAngles& angles) const;
|
||||
NzEulerAngles operator-(const NzEulerAngles& angles) const;
|
||||
/*NzEulerAngles operator*(const NzEulerAngles& angles) const;
|
||||
NzEulerAngles operator/(const NzEulerAngles& angles) const;*/
|
||||
EulerAngles operator+(const EulerAngles& angles) const;
|
||||
EulerAngles operator-(const EulerAngles& angles) const;
|
||||
/*EulerAngles operator*(const EulerAngles& angles) const;
|
||||
EulerAngles operator/(const EulerAngles& angles) const;*/
|
||||
|
||||
NzEulerAngles& operator+=(const NzEulerAngles& angles);
|
||||
NzEulerAngles& operator-=(const NzEulerAngles& angles);
|
||||
/*NzEulerAngles operator*=(const NzEulerAngles& angles);
|
||||
NzEulerAngles operator/=(const NzEulerAngles& angles);*/
|
||||
EulerAngles& operator+=(const EulerAngles& angles);
|
||||
EulerAngles& operator-=(const EulerAngles& angles);
|
||||
/*EulerAngles operator*=(const EulerAngles& angles);
|
||||
EulerAngles operator/=(const EulerAngles& angles);*/
|
||||
|
||||
bool operator==(const NzEulerAngles& angles) const;
|
||||
bool operator!=(const NzEulerAngles& angles) const;
|
||||
bool operator==(const EulerAngles& angles) const;
|
||||
bool operator!=(const EulerAngles& angles) const;
|
||||
|
||||
static NzEulerAngles Zero();
|
||||
static EulerAngles Zero();
|
||||
|
||||
T pitch, yaw, roll;
|
||||
};
|
||||
T pitch, yaw, roll;
|
||||
};
|
||||
|
||||
template<typename T> std::ostream& operator<<(std::ostream& out, const NzEulerAngles<T>& angles);
|
||||
typedef EulerAngles<double> EulerAnglesd;
|
||||
typedef EulerAngles<float> EulerAnglesf;
|
||||
}
|
||||
|
||||
template<typename T> std::ostream& operator<<(std::ostream& out, const Nz::EulerAngles<T>& angles);
|
||||
|
||||
typedef NzEulerAngles<double> NzEulerAnglesd;
|
||||
typedef NzEulerAngles<float> NzEulerAnglesf;
|
||||
|
||||
#include <Nazara/Math/EulerAngles.inl>
|
||||
|
||||
|
||||
@@ -12,168 +12,171 @@
|
||||
|
||||
#define F(a) static_cast<T>(a)
|
||||
|
||||
template<typename T>
|
||||
NzEulerAngles<T>::NzEulerAngles(T P, T Y, T R)
|
||||
namespace Nz
|
||||
{
|
||||
Set(P, Y, R);
|
||||
template<typename T>
|
||||
EulerAngles<T>::EulerAngles(T P, T Y, T R)
|
||||
{
|
||||
Set(P, Y, R);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
EulerAngles<T>::EulerAngles(const T angles[3])
|
||||
{
|
||||
Set(angles);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
EulerAngles<T>::EulerAngles(const Quaternion<T>& quat)
|
||||
{
|
||||
Set(quat);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
EulerAngles<T>::EulerAngles(const EulerAngles<U>& angles)
|
||||
{
|
||||
Set(angles);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void EulerAngles<T>::MakeZero()
|
||||
{
|
||||
Set(F(0.0), F(0.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void EulerAngles<T>::Normalize()
|
||||
{
|
||||
pitch = NormalizeAngle(pitch);
|
||||
yaw = NormalizeAngle(yaw);
|
||||
roll = NormalizeAngle(roll);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void EulerAngles<T>::Set(T P, T Y, T R)
|
||||
{
|
||||
pitch = P;
|
||||
yaw = Y;
|
||||
roll = R;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void EulerAngles<T>::Set(const T angles[3])
|
||||
{
|
||||
pitch = angles[0];
|
||||
yaw = angles[1];
|
||||
roll = angles[2];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void EulerAngles<T>::Set(const EulerAngles& angles)
|
||||
{
|
||||
std::memcpy(this, &angles, sizeof(EulerAngles));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void EulerAngles<T>::Set(const Quaternion<T>& quat)
|
||||
{
|
||||
Set(quat.ToEulerAngles());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
void EulerAngles<T>::Set(const EulerAngles<U>& angles)
|
||||
{
|
||||
pitch = F(angles.pitch);
|
||||
yaw = F(angles.yaw);
|
||||
roll = F(angles.roll);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T> EulerAngles<T>::ToQuaternion() const
|
||||
{
|
||||
T c1 = std::cos(ToRadians(yaw) / F(2.0));
|
||||
T c2 = std::cos(ToRadians(roll) / F(2.0));
|
||||
T c3 = std::cos(ToRadians(pitch) / F(2.0));
|
||||
|
||||
T s1 = std::sin(ToRadians(yaw) / F(2.0));
|
||||
T s2 = std::sin(ToRadians(roll) / F(2.0));
|
||||
T s3 = std::sin(ToRadians(pitch) / F(2.0));
|
||||
|
||||
return Quaternion<T>(c1 * c2 * c3 - s1 * s2 * s3,
|
||||
s1 * s2 * c3 + c1 * c2 * s3,
|
||||
s1 * c2 * c3 + c1 * s2 * s3,
|
||||
c1 * s2 * c3 - s1 * c2 * s3);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
String EulerAngles<T>::ToString() const
|
||||
{
|
||||
StringStream ss;
|
||||
|
||||
return ss << "EulerAngles(" << pitch << ", " << yaw << ", " << roll << ')';
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
EulerAngles<T> EulerAngles<T>::operator+(const EulerAngles& angles) const
|
||||
{
|
||||
return EulerAngles(pitch + angles.pitch,
|
||||
yaw + angles.yaw,
|
||||
roll + angles.roll);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
EulerAngles<T> EulerAngles<T>::operator-(const EulerAngles& angles) const
|
||||
{
|
||||
return EulerAngles(pitch - angles.pitch,
|
||||
yaw - angles.yaw,
|
||||
roll - angles.roll);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
EulerAngles<T>& EulerAngles<T>::operator+=(const EulerAngles& angles)
|
||||
{
|
||||
pitch += angles.pitch;
|
||||
yaw += angles.yaw;
|
||||
roll += angles.roll;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
EulerAngles<T>& EulerAngles<T>::operator-=(const EulerAngles& angles)
|
||||
{
|
||||
pitch -= angles.pitch;
|
||||
yaw -= angles.yaw;
|
||||
roll -= angles.roll;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool EulerAngles<T>::operator==(const EulerAngles& angles) const
|
||||
{
|
||||
return NumberEquals(pitch, angles.pitch) &&
|
||||
NumberEquals(yaw, angles.yaw) &&
|
||||
NumberEquals(roll, angles.roll);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool EulerAngles<T>::operator!=(const EulerAngles& angles) const
|
||||
{
|
||||
return !operator==(angles);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
EulerAngles<T> EulerAngles<T>::Zero()
|
||||
{
|
||||
EulerAngles angles;
|
||||
angles.MakeZero();
|
||||
|
||||
return angles;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzEulerAngles<T>::NzEulerAngles(const T angles[3])
|
||||
{
|
||||
Set(angles);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzEulerAngles<T>::NzEulerAngles(const NzQuaternion<T>& quat)
|
||||
{
|
||||
Set(quat);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzEulerAngles<T>::NzEulerAngles(const NzEulerAngles<U>& angles)
|
||||
{
|
||||
Set(angles);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzEulerAngles<T>::MakeZero()
|
||||
{
|
||||
Set(F(0.0), F(0.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzEulerAngles<T>::Normalize()
|
||||
{
|
||||
pitch = NzNormalizeAngle(pitch);
|
||||
yaw = NzNormalizeAngle(yaw);
|
||||
roll = NzNormalizeAngle(roll);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzEulerAngles<T>::Set(T P, T Y, T R)
|
||||
{
|
||||
pitch = P;
|
||||
yaw = Y;
|
||||
roll = R;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzEulerAngles<T>::Set(const T angles[3])
|
||||
{
|
||||
pitch = angles[0];
|
||||
yaw = angles[1];
|
||||
roll = angles[2];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzEulerAngles<T>::Set(const NzEulerAngles& angles)
|
||||
{
|
||||
std::memcpy(this, &angles, sizeof(NzEulerAngles));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzEulerAngles<T>::Set(const NzQuaternion<T>& quat)
|
||||
{
|
||||
Set(quat.ToEulerAngles());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
void NzEulerAngles<T>::Set(const NzEulerAngles<U>& angles)
|
||||
{
|
||||
pitch = F(angles.pitch);
|
||||
yaw = F(angles.yaw);
|
||||
roll = F(angles.roll);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T> NzEulerAngles<T>::ToQuaternion() const
|
||||
{
|
||||
T c1 = std::cos(NzToRadians(yaw) / F(2.0));
|
||||
T c2 = std::cos(NzToRadians(roll) / F(2.0));
|
||||
T c3 = std::cos(NzToRadians(pitch) / F(2.0));
|
||||
|
||||
T s1 = std::sin(NzToRadians(yaw) / F(2.0));
|
||||
T s2 = std::sin(NzToRadians(roll) / F(2.0));
|
||||
T s3 = std::sin(NzToRadians(pitch) / F(2.0));
|
||||
|
||||
return NzQuaternion<T>(c1 * c2 * c3 - s1 * s2 * s3,
|
||||
s1 * s2 * c3 + c1 * c2 * s3,
|
||||
s1 * c2 * c3 + c1 * s2 * s3,
|
||||
c1 * s2 * c3 - s1 * c2 * s3);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzString NzEulerAngles<T>::ToString() const
|
||||
{
|
||||
NzStringStream ss;
|
||||
|
||||
return ss << "EulerAngles(" << pitch << ", " << yaw << ", " << roll << ')';
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzEulerAngles<T> NzEulerAngles<T>::operator+(const NzEulerAngles& angles) const
|
||||
{
|
||||
return NzEulerAngles(pitch + angles.pitch,
|
||||
yaw + angles.yaw,
|
||||
roll + angles.roll);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzEulerAngles<T> NzEulerAngles<T>::operator-(const NzEulerAngles& angles) const
|
||||
{
|
||||
return NzEulerAngles(pitch - angles.pitch,
|
||||
yaw - angles.yaw,
|
||||
roll - angles.roll);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzEulerAngles<T>& NzEulerAngles<T>::operator+=(const NzEulerAngles& angles)
|
||||
{
|
||||
pitch += angles.pitch;
|
||||
yaw += angles.yaw;
|
||||
roll += angles.roll;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzEulerAngles<T>& NzEulerAngles<T>::operator-=(const NzEulerAngles& angles)
|
||||
{
|
||||
pitch -= angles.pitch;
|
||||
yaw -= angles.yaw;
|
||||
roll -= angles.roll;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzEulerAngles<T>::operator==(const NzEulerAngles& angles) const
|
||||
{
|
||||
return NzNumberEquals(pitch, angles.pitch) &&
|
||||
NzNumberEquals(yaw, angles.yaw) &&
|
||||
NzNumberEquals(roll, angles.roll);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzEulerAngles<T>::operator!=(const NzEulerAngles& angles) const
|
||||
{
|
||||
return !operator==(angles);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzEulerAngles<T> NzEulerAngles<T>::Zero()
|
||||
{
|
||||
NzEulerAngles angles;
|
||||
angles.MakeZero();
|
||||
|
||||
return angles;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzEulerAngles<T>& angles)
|
||||
std::ostream& operator<<(std::ostream& out, const Nz::EulerAngles<T>& angles)
|
||||
{
|
||||
return out << angles.ToString();
|
||||
}
|
||||
|
||||
@@ -16,51 +16,54 @@
|
||||
#include <Nazara/Math/Sphere.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
|
||||
template<typename T>
|
||||
class NzFrustum
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzFrustum() = default;
|
||||
template<typename U> explicit NzFrustum(const NzFrustum<U>& frustum);
|
||||
NzFrustum(const NzFrustum& frustum) = default;
|
||||
~NzFrustum() = default;
|
||||
template<typename T>
|
||||
class Frustum
|
||||
{
|
||||
public:
|
||||
Frustum() = default;
|
||||
template<typename U> explicit Frustum(const Frustum<U>& frustum);
|
||||
Frustum(const Frustum& frustum) = default;
|
||||
~Frustum() = default;
|
||||
|
||||
NzFrustum& Build(T angle, T ratio, T zNear, T zFar, const NzVector3<T>& eye, const NzVector3<T>& target, const NzVector3<T>& up = NzVector3<T>::Up());
|
||||
Frustum& Build(T angle, T ratio, T zNear, T zFar, const Vector3<T>& eye, const Vector3<T>& target, const Vector3<T>& up = Vector3<T>::Up());
|
||||
|
||||
bool Contains(const NzBoundingVolume<T>& volume) const;
|
||||
bool Contains(const NzBox<T>& box) const;
|
||||
bool Contains(const NzOrientedBox<T>& orientedBox) const;
|
||||
bool Contains(const NzSphere<T>& sphere) const;
|
||||
bool Contains(const NzVector3<T>& point) const;
|
||||
bool Contains(const NzVector3<T>* points, unsigned int pointCount) const;
|
||||
bool Contains(const BoundingVolume<T>& volume) const;
|
||||
bool Contains(const Box<T>& box) const;
|
||||
bool Contains(const OrientedBox<T>& orientedBox) const;
|
||||
bool Contains(const Sphere<T>& sphere) const;
|
||||
bool Contains(const Vector3<T>& point) const;
|
||||
bool Contains(const Vector3<T>* points, unsigned int pointCount) const;
|
||||
|
||||
NzFrustum& Extract(const NzMatrix4<T>& clipMatrix);
|
||||
NzFrustum& Extract(const NzMatrix4<T>& view, const NzMatrix4<T>& projection);
|
||||
Frustum& Extract(const Matrix4<T>& clipMatrix);
|
||||
Frustum& Extract(const Matrix4<T>& view, const Matrix4<T>& projection);
|
||||
|
||||
const NzVector3<T>& GetCorner(nzBoxCorner corner) const;
|
||||
const NzPlane<T>& GetPlane(nzFrustumPlane plane) const;
|
||||
const Vector3<T>& GetCorner(BoxCorner corner) const;
|
||||
const Plane<T>& GetPlane(FrustumPlane plane) const;
|
||||
|
||||
nzIntersectionSide Intersect(const NzBoundingVolume<T>& volume) const;
|
||||
nzIntersectionSide Intersect(const NzBox<T>& box) const;
|
||||
nzIntersectionSide Intersect(const NzOrientedBox<T>& orientedBox) const;
|
||||
nzIntersectionSide Intersect(const NzSphere<T>& sphere) const;
|
||||
nzIntersectionSide Intersect(const NzVector3<T>* points, unsigned int pointCount) const;
|
||||
IntersectionSide Intersect(const BoundingVolume<T>& volume) const;
|
||||
IntersectionSide Intersect(const Box<T>& box) const;
|
||||
IntersectionSide Intersect(const OrientedBox<T>& orientedBox) const;
|
||||
IntersectionSide Intersect(const Sphere<T>& sphere) const;
|
||||
IntersectionSide Intersect(const Vector3<T>* points, unsigned int pointCount) const;
|
||||
|
||||
NzFrustum& Set(const NzFrustum& frustum);
|
||||
template<typename U> NzFrustum& Set(const NzFrustum<U>& frustum);
|
||||
Frustum& Set(const Frustum& frustum);
|
||||
template<typename U> Frustum& Set(const Frustum<U>& frustum);
|
||||
|
||||
NzString ToString() const;
|
||||
String ToString() const;
|
||||
|
||||
private:
|
||||
NzVector3<T> m_corners[nzBoxCorner_Max+1];
|
||||
NzPlane<T> m_planes[nzFrustumPlane_Max+1];
|
||||
};
|
||||
private:
|
||||
Vector3<T> m_corners[BoxCorner_Max+1];
|
||||
Plane<T> m_planes[FrustumPlane_Max+1];
|
||||
};
|
||||
|
||||
typedef Frustum<double> Frustumd;
|
||||
typedef Frustum<float> Frustumf;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzFrustum<T>& frustum);
|
||||
|
||||
typedef NzFrustum<double> NzFrustumd;
|
||||
typedef NzFrustum<float> NzFrustumf;
|
||||
std::ostream& operator<<(std::ostream& out, const Nz::Frustum<T>& frustum);
|
||||
|
||||
#include <Nazara/Math/Frustum.inl>
|
||||
|
||||
|
||||
@@ -13,495 +13,498 @@
|
||||
|
||||
#define F(a) static_cast<T>(a)
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzFrustum<T>::NzFrustum(const NzFrustum<U>& frustum)
|
||||
namespace Nz
|
||||
{
|
||||
Set(frustum);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzFrustum<T>& NzFrustum<T>::Build(T angle, T ratio, T zNear, T zFar, const NzVector3<T>& eye, const NzVector3<T>& target, const NzVector3<T>& up)
|
||||
{
|
||||
#if NAZARA_MATH_ANGLE_RADIAN
|
||||
angle /= F(2.0);
|
||||
#else
|
||||
angle = NzDegreeToRadian(angle/F(2.0));
|
||||
#endif
|
||||
|
||||
T tangent = std::tan(angle);
|
||||
T nearH = zNear * tangent;
|
||||
T nearW = nearH * ratio;
|
||||
T farH = zFar * tangent;
|
||||
T farW = farH * ratio;
|
||||
|
||||
NzVector3<T> f = NzVector3<T>::Normalize(target - eye);
|
||||
NzVector3<T> u(up.GetNormal());
|
||||
NzVector3<T> s = NzVector3<T>::Normalize(f.CrossProduct(u));
|
||||
u = s.CrossProduct(f);
|
||||
|
||||
NzVector3<T> nc = eye + f * zNear;
|
||||
NzVector3<T> fc = eye + f * zFar;
|
||||
|
||||
// Calcul du frustum
|
||||
m_corners[nzBoxCorner_FarLeftBottom] = fc - u*farH - s*farW;
|
||||
m_corners[nzBoxCorner_FarLeftTop] = fc + u*farH - s*farW;
|
||||
m_corners[nzBoxCorner_FarRightTop] = fc + u*farH + s*farW;
|
||||
m_corners[nzBoxCorner_FarRightBottom] = fc - u*farH + s*farW;
|
||||
|
||||
m_corners[nzBoxCorner_NearLeftBottom] = nc - u*nearH - s*nearW;
|
||||
m_corners[nzBoxCorner_NearLeftTop] = nc + u*nearH - s*nearW;
|
||||
m_corners[nzBoxCorner_NearRightTop] = nc + u*nearH + s*nearW;
|
||||
m_corners[nzBoxCorner_NearRightBottom] = nc - u*nearH + s*nearW;
|
||||
|
||||
// Construction des plans du frustum
|
||||
m_planes[nzFrustumPlane_Bottom].Set(m_corners[nzBoxCorner_NearLeftBottom], m_corners[nzBoxCorner_NearRightBottom], m_corners[nzBoxCorner_FarRightBottom]);
|
||||
m_planes[nzFrustumPlane_Far].Set(m_corners[nzBoxCorner_FarRightTop], m_corners[nzBoxCorner_FarLeftTop], m_corners[nzBoxCorner_FarLeftBottom]);
|
||||
m_planes[nzFrustumPlane_Left].Set(m_corners[nzBoxCorner_NearLeftTop], m_corners[nzBoxCorner_NearLeftBottom], m_corners[nzBoxCorner_FarLeftBottom]);
|
||||
m_planes[nzFrustumPlane_Near].Set(m_corners[nzBoxCorner_NearLeftTop], m_corners[nzBoxCorner_NearRightTop], m_corners[nzBoxCorner_NearRightBottom]);
|
||||
m_planes[nzFrustumPlane_Right].Set(m_corners[nzBoxCorner_NearRightBottom], m_corners[nzBoxCorner_NearRightTop], m_corners[nzBoxCorner_FarRightBottom]);
|
||||
m_planes[nzFrustumPlane_Top].Set(m_corners[nzBoxCorner_NearRightTop], m_corners[nzBoxCorner_NearLeftTop], m_corners[nzBoxCorner_FarLeftTop]);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzFrustum<T>::Contains(const NzBoundingVolume<T>& volume) const
|
||||
{
|
||||
switch (volume.extend)
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
Frustum<T>::Frustum(const Frustum<U>& frustum)
|
||||
{
|
||||
case nzExtend_Finite:
|
||||
Set(frustum);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Frustum<T>& Frustum<T>::Build(T angle, T ratio, T zNear, T zFar, const Vector3<T>& eye, const Vector3<T>& target, const Vector3<T>& up)
|
||||
{
|
||||
#if NAZARA_MATH_ANGLE_RADIAN
|
||||
angle /= F(2.0);
|
||||
#else
|
||||
angle = DegreeToRadian(angle/F(2.0));
|
||||
#endif
|
||||
|
||||
T tangent = std::tan(angle);
|
||||
T nearH = zNear * tangent;
|
||||
T nearW = nearH * ratio;
|
||||
T farH = zFar * tangent;
|
||||
T farW = farH * ratio;
|
||||
|
||||
Vector3<T> f = Vector3<T>::Normalize(target - eye);
|
||||
Vector3<T> u(up.GetNormal());
|
||||
Vector3<T> s = Vector3<T>::Normalize(f.CrossProduct(u));
|
||||
u = s.CrossProduct(f);
|
||||
|
||||
Vector3<T> nc = eye + f * zNear;
|
||||
Vector3<T> fc = eye + f * zFar;
|
||||
|
||||
// Calcul du frustum
|
||||
m_corners[BoxCorner_FarLeftBottom] = fc - u*farH - s*farW;
|
||||
m_corners[BoxCorner_FarLeftTop] = fc + u*farH - s*farW;
|
||||
m_corners[BoxCorner_FarRightTop] = fc + u*farH + s*farW;
|
||||
m_corners[BoxCorner_FarRightBottom] = fc - u*farH + s*farW;
|
||||
|
||||
m_corners[BoxCorner_NearLeftBottom] = nc - u*nearH - s*nearW;
|
||||
m_corners[BoxCorner_NearLeftTop] = nc + u*nearH - s*nearW;
|
||||
m_corners[BoxCorner_NearRightTop] = nc + u*nearH + s*nearW;
|
||||
m_corners[BoxCorner_NearRightBottom] = nc - u*nearH + s*nearW;
|
||||
|
||||
// Construction des plans du frustum
|
||||
m_planes[FrustumPlane_Bottom].Set(m_corners[BoxCorner_NearLeftBottom], m_corners[BoxCorner_NearRightBottom], m_corners[BoxCorner_FarRightBottom]);
|
||||
m_planes[FrustumPlane_Far].Set(m_corners[BoxCorner_FarRightTop], m_corners[BoxCorner_FarLeftTop], m_corners[BoxCorner_FarLeftBottom]);
|
||||
m_planes[FrustumPlane_Left].Set(m_corners[BoxCorner_NearLeftTop], m_corners[BoxCorner_NearLeftBottom], m_corners[BoxCorner_FarLeftBottom]);
|
||||
m_planes[FrustumPlane_Near].Set(m_corners[BoxCorner_NearLeftTop], m_corners[BoxCorner_NearRightTop], m_corners[BoxCorner_NearRightBottom]);
|
||||
m_planes[FrustumPlane_Right].Set(m_corners[BoxCorner_NearRightBottom], m_corners[BoxCorner_NearRightTop], m_corners[BoxCorner_FarRightBottom]);
|
||||
m_planes[FrustumPlane_Top].Set(m_corners[BoxCorner_NearRightTop], m_corners[BoxCorner_NearLeftTop], m_corners[BoxCorner_FarLeftTop]);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Frustum<T>::Contains(const BoundingVolume<T>& volume) const
|
||||
{
|
||||
switch (volume.extend)
|
||||
{
|
||||
nzIntersectionSide side = Intersect(volume.aabb);
|
||||
switch (side)
|
||||
case Extend_Finite:
|
||||
{
|
||||
case nzIntersectionSide_Inside:
|
||||
return true;
|
||||
IntersectionSide side = Intersect(volume.aabb);
|
||||
switch (side)
|
||||
{
|
||||
case IntersectionSide_Inside:
|
||||
return true;
|
||||
|
||||
case nzIntersectionSide_Intersecting:
|
||||
return Contains(volume.obb);
|
||||
case IntersectionSide_Intersecting:
|
||||
return Contains(volume.obb);
|
||||
|
||||
case nzIntersectionSide_Outside:
|
||||
return false;
|
||||
case IntersectionSide_Outside:
|
||||
return false;
|
||||
}
|
||||
|
||||
NazaraError("Invalid intersection side (0x" + String::Number(side, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
NazaraError("Invalid intersection side (0x" + NzString::Number(side, 16) + ')');
|
||||
return false;
|
||||
case Extend_Infinite:
|
||||
return true;
|
||||
|
||||
case Extend_Null:
|
||||
return false;
|
||||
}
|
||||
|
||||
case nzExtend_Infinite:
|
||||
return true;
|
||||
|
||||
case nzExtend_Null:
|
||||
return false;
|
||||
NazaraError("Invalid extend type (0x" + String::Number(volume.extend, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
NazaraError("Invalid extend type (0x" + NzString::Number(volume.extend, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzFrustum<T>::Contains(const NzBox<T>& box) const
|
||||
{
|
||||
// http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-testing-boxes-ii/
|
||||
for(unsigned int i = 0; i <= nzFrustumPlane_Max; i++)
|
||||
template<typename T>
|
||||
bool Frustum<T>::Contains(const Box<T>& box) const
|
||||
{
|
||||
if (m_planes[i].Distance(box.GetPositiveVertex(m_planes[i].normal)) < F(0.0))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzFrustum<T>::Contains(const NzOrientedBox<T>& orientedbox) const
|
||||
{
|
||||
return Contains(&orientedbox[0], 8);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzFrustum<T>::Contains(const NzSphere<T>& sphere) const
|
||||
{
|
||||
for(unsigned int i = 0; i <= nzFrustumPlane_Max; i++)
|
||||
{
|
||||
if (m_planes[i].Distance(sphere.GetPosition()) < -sphere.radius)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzFrustum<T>::Contains(const NzVector3<T>& point) const
|
||||
{
|
||||
for(unsigned int i = 0; i <= nzFrustumPlane_Max; ++i)
|
||||
{
|
||||
if (m_planes[i].Distance(point) < F(0.0))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzFrustum<T>::Contains(const NzVector3<T>* points, unsigned int pointCount) const
|
||||
{
|
||||
for (unsigned int i = 0; i <= nzFrustumPlane_Max; ++i)
|
||||
{
|
||||
unsigned int j;
|
||||
for (j = 0; j < pointCount; j++ )
|
||||
// http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-testing-boxes-ii/
|
||||
for(unsigned int i = 0; i <= FrustumPlane_Max; i++)
|
||||
{
|
||||
if (m_planes[i].Distance(points[j]) > F(0.0))
|
||||
break;
|
||||
if (m_planes[i].Distance(box.GetPositiveVertex(m_planes[i].normal)) < F(0.0))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (j == pointCount)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzFrustum<T>& NzFrustum<T>::Extract(const NzMatrix4<T>& clipMatrix)
|
||||
{
|
||||
// http://www.crownandcutlass.com/features/technicaldetails/frustum.html
|
||||
T plane[4];
|
||||
T invLength;
|
||||
|
||||
// Extract the numbers for the RIGHT plane
|
||||
plane[0] = clipMatrix[ 3] - clipMatrix[ 0];
|
||||
plane[1] = clipMatrix[ 7] - clipMatrix[ 4];
|
||||
plane[2] = clipMatrix[11] - clipMatrix[ 8];
|
||||
plane[3] = clipMatrix[15] - clipMatrix[12];
|
||||
|
||||
// Normalize the result
|
||||
invLength = F(1.0) / std::sqrt(plane[0]*plane[0] + plane[1]*plane[1] + plane[2]*plane[2]);
|
||||
plane[0] *= invLength;
|
||||
plane[1] *= invLength;
|
||||
plane[2] *= invLength;
|
||||
plane[3] *= -invLength;
|
||||
|
||||
m_planes[nzFrustumPlane_Right].Set(plane);
|
||||
|
||||
// Extract the numbers for the LEFT plane
|
||||
plane[0] = clipMatrix[ 3] + clipMatrix[ 0];
|
||||
plane[1] = clipMatrix[ 7] + clipMatrix[ 4];
|
||||
plane[2] = clipMatrix[11] + clipMatrix[ 8];
|
||||
plane[3] = clipMatrix[15] + clipMatrix[12];
|
||||
|
||||
// Normalize the result
|
||||
invLength = F(1.0) / std::sqrt(plane[0]*plane[0] + plane[1]*plane[1] + plane[2]*plane[2]);
|
||||
plane[0] *= invLength;
|
||||
plane[1] *= invLength;
|
||||
plane[2] *= invLength;
|
||||
plane[3] *= -invLength;
|
||||
|
||||
m_planes[nzFrustumPlane_Left].Set(plane);
|
||||
|
||||
// Extract the BOTTOM plane
|
||||
plane[0] = clipMatrix[ 3] + clipMatrix[ 1];
|
||||
plane[1] = clipMatrix[ 7] + clipMatrix[ 5];
|
||||
plane[2] = clipMatrix[11] + clipMatrix[ 9];
|
||||
plane[3] = clipMatrix[15] + clipMatrix[13];
|
||||
|
||||
// Normalize the result
|
||||
invLength = F(1.0) / std::sqrt(plane[0]*plane[0] + plane[1]*plane[1] + plane[2]*plane[2]);
|
||||
plane[0] *= invLength;
|
||||
plane[1] *= invLength;
|
||||
plane[2] *= invLength;
|
||||
plane[3] *= -invLength;
|
||||
|
||||
m_planes[nzFrustumPlane_Bottom].Set(plane);
|
||||
|
||||
// Extract the TOP plane
|
||||
plane[0] = clipMatrix[ 3] - clipMatrix[ 1];
|
||||
plane[1] = clipMatrix[ 7] - clipMatrix[ 5];
|
||||
plane[2] = clipMatrix[11] - clipMatrix[ 9];
|
||||
plane[3] = clipMatrix[15] - clipMatrix[13];
|
||||
|
||||
// Normalize the result
|
||||
invLength = F(1.0) / std::sqrt(plane[0]*plane[0] + plane[1]*plane[1] + plane[2]*plane[2]);
|
||||
plane[0] *= invLength;
|
||||
plane[1] *= invLength;
|
||||
plane[2] *= invLength;
|
||||
plane[3] *= -invLength;
|
||||
|
||||
m_planes[nzFrustumPlane_Top].Set(plane);
|
||||
|
||||
// Extract the FAR plane
|
||||
plane[0] = clipMatrix[ 3] - clipMatrix[ 2];
|
||||
plane[1] = clipMatrix[ 7] - clipMatrix[ 6];
|
||||
plane[2] = clipMatrix[11] - clipMatrix[10];
|
||||
plane[3] = clipMatrix[15] - clipMatrix[14];
|
||||
|
||||
// Normalize the result
|
||||
invLength = F(1.0) / std::sqrt(plane[0]*plane[0] + plane[1]*plane[1] + plane[2]*plane[2]);
|
||||
plane[0] *= invLength;
|
||||
plane[1] *= invLength;
|
||||
plane[2] *= invLength;
|
||||
plane[3] *= -invLength;
|
||||
|
||||
m_planes[nzFrustumPlane_Far].Set(plane);
|
||||
|
||||
// Extract the NEAR plane
|
||||
plane[0] = clipMatrix[ 3] + clipMatrix[ 2];
|
||||
plane[1] = clipMatrix[ 7] + clipMatrix[ 6];
|
||||
plane[2] = clipMatrix[11] + clipMatrix[10];
|
||||
plane[3] = clipMatrix[15] + clipMatrix[14];
|
||||
|
||||
// Normalize the result
|
||||
invLength = F(1.0) / std::sqrt(plane[0]*plane[0] + plane[1]*plane[1] + plane[2]*plane[2]);
|
||||
plane[0] *= invLength;
|
||||
plane[1] *= invLength;
|
||||
plane[2] *= invLength;
|
||||
plane[3] *= -invLength;
|
||||
|
||||
m_planes[nzFrustumPlane_Near].Set(plane);
|
||||
|
||||
// Une fois les plans extraits, il faut extraire les points du frustum
|
||||
// Je me base sur cette page: http://www.gamedev.net/topic/393309-calculating-the-view-frustums-vertices/
|
||||
|
||||
NzMatrix4<T> invClipMatrix;
|
||||
if (clipMatrix.GetInverse(&invClipMatrix))
|
||||
template<typename T>
|
||||
bool Frustum<T>::Contains(const OrientedBox<T>& orientedbox) const
|
||||
{
|
||||
NzVector4<T> corner;
|
||||
|
||||
// FarLeftBottom
|
||||
corner.Set(F(-1.0), F(-1.0), F(1.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[nzBoxCorner_FarLeftBottom] = NzVector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// FarLeftTop
|
||||
corner.Set(F(-1.0), F(1.0), F(1.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[nzBoxCorner_FarLeftTop] = NzVector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// FarRightBottom
|
||||
corner.Set(F(1.0), F(-1.0), F(1.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[nzBoxCorner_FarRightBottom] = NzVector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// FarRightTop
|
||||
corner.Set(F(1.0), F(1.0), F(1.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[nzBoxCorner_FarRightTop] = NzVector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// NearLeftBottom
|
||||
corner.Set(F(-1.0), F(-1.0), F(0.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[nzBoxCorner_NearLeftBottom] = NzVector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// NearLeftTop
|
||||
corner.Set(F(-1.0), F(1.0), F(0.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[nzBoxCorner_NearLeftTop] = NzVector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// NearRightBottom
|
||||
corner.Set(F(1.0), F(-1.0), F(0.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[nzBoxCorner_NearRightBottom] = NzVector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// NearRightTop
|
||||
corner.Set(F(1.0), F(1.0), F(0.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[nzBoxCorner_NearRightTop] = NzVector3<T>(corner.x, corner.y, corner.z);
|
||||
return Contains(&orientedbox[0], 8);
|
||||
}
|
||||
else
|
||||
NazaraWarning("Clip matrix is not invertible, failed to compute frustum corners");
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzFrustum<T>& NzFrustum<T>::Extract(const NzMatrix4<T>& view, const NzMatrix4<T>& projection)
|
||||
{
|
||||
return Extract(NzMatrix4<T>::Concatenate(view, projection));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const NzVector3<T>& NzFrustum<T>::GetCorner(nzBoxCorner corner) const
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (corner > nzBoxCorner_Max)
|
||||
template<typename T>
|
||||
bool Frustum<T>::Contains(const Sphere<T>& sphere) const
|
||||
{
|
||||
NazaraError("Corner not handled (0x" + NzString::Number(corner, 16) + ')');
|
||||
|
||||
static NzVector3<T> dummy;
|
||||
return dummy;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_corners[corner];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const NzPlane<T>& NzFrustum<T>::GetPlane(nzFrustumPlane plane) const
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (plane > nzFrustumPlane_Max)
|
||||
{
|
||||
NazaraError("Frustum plane not handled (0x" + NzString::Number(plane, 16) + ')');
|
||||
|
||||
static NzPlane<T> dummy;
|
||||
return dummy;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_planes[plane];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
nzIntersectionSide NzFrustum<T>::Intersect(const NzBoundingVolume<T>& volume) const
|
||||
{
|
||||
switch (volume.extend)
|
||||
{
|
||||
case nzExtend_Finite:
|
||||
for(unsigned int i = 0; i <= FrustumPlane_Max; i++)
|
||||
{
|
||||
nzIntersectionSide side = Intersect(volume.aabb);
|
||||
switch (side)
|
||||
if (m_planes[i].Distance(sphere.GetPosition()) < -sphere.radius)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Frustum<T>::Contains(const Vector3<T>& point) const
|
||||
{
|
||||
for(unsigned int i = 0; i <= FrustumPlane_Max; ++i)
|
||||
{
|
||||
if (m_planes[i].Distance(point) < F(0.0))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Frustum<T>::Contains(const Vector3<T>* points, unsigned int pointCount) const
|
||||
{
|
||||
for (unsigned int i = 0; i <= FrustumPlane_Max; ++i)
|
||||
{
|
||||
unsigned int j;
|
||||
for (j = 0; j < pointCount; j++ )
|
||||
{
|
||||
case nzIntersectionSide_Inside:
|
||||
return nzIntersectionSide_Inside;
|
||||
|
||||
case nzIntersectionSide_Intersecting:
|
||||
return Intersect(volume.obb);
|
||||
|
||||
case nzIntersectionSide_Outside:
|
||||
return nzIntersectionSide_Outside;
|
||||
if (m_planes[i].Distance(points[j]) > F(0.0))
|
||||
break;
|
||||
}
|
||||
|
||||
NazaraError("Invalid intersection side (0x" + NzString::Number(side, 16) + ')');
|
||||
return nzIntersectionSide_Outside;
|
||||
if (j == pointCount)
|
||||
return false;
|
||||
}
|
||||
|
||||
case nzExtend_Infinite:
|
||||
return nzIntersectionSide_Intersecting; // On ne peut pas contenir l'infini
|
||||
|
||||
case nzExtend_Null:
|
||||
return nzIntersectionSide_Outside;
|
||||
return true;
|
||||
}
|
||||
|
||||
NazaraError("Invalid extend type (0x" + NzString::Number(volume.extend, 16) + ')');
|
||||
return nzIntersectionSide_Outside;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
nzIntersectionSide NzFrustum<T>::Intersect(const NzBox<T>& box) const
|
||||
{
|
||||
// http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-testing-boxes-ii/
|
||||
nzIntersectionSide side = nzIntersectionSide_Inside;
|
||||
|
||||
for(unsigned int i = 0; i <= nzFrustumPlane_Max; i++)
|
||||
template<typename T>
|
||||
Frustum<T>& Frustum<T>::Extract(const Matrix4<T>& clipMatrix)
|
||||
{
|
||||
if (m_planes[i].Distance(box.GetPositiveVertex(m_planes[i].normal)) < F(0.0))
|
||||
return nzIntersectionSide_Outside;
|
||||
else if (m_planes[i].Distance(box.GetNegativeVertex(m_planes[i].normal)) < F(0.0))
|
||||
side = nzIntersectionSide_Intersecting;
|
||||
}
|
||||
// http://www.crownandcutlass.com/features/technicaldetails/frustum.html
|
||||
T plane[4];
|
||||
T invLength;
|
||||
|
||||
return side;
|
||||
}
|
||||
// Extract the numbers for the RIGHT plane
|
||||
plane[0] = clipMatrix[ 3] - clipMatrix[ 0];
|
||||
plane[1] = clipMatrix[ 7] - clipMatrix[ 4];
|
||||
plane[2] = clipMatrix[11] - clipMatrix[ 8];
|
||||
plane[3] = clipMatrix[15] - clipMatrix[12];
|
||||
|
||||
template<typename T>
|
||||
nzIntersectionSide NzFrustum<T>::Intersect(const NzOrientedBox<T>& orientedbox) const
|
||||
{
|
||||
return Intersect(&orientedbox[0], 8);
|
||||
}
|
||||
// Normalize the result
|
||||
invLength = F(1.0) / std::sqrt(plane[0]*plane[0] + plane[1]*plane[1] + plane[2]*plane[2]);
|
||||
plane[0] *= invLength;
|
||||
plane[1] *= invLength;
|
||||
plane[2] *= invLength;
|
||||
plane[3] *= -invLength;
|
||||
|
||||
template<typename T>
|
||||
nzIntersectionSide NzFrustum<T>::Intersect(const NzSphere<T>& sphere) const
|
||||
{
|
||||
// http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-testing-points-and-spheres/
|
||||
nzIntersectionSide side = nzIntersectionSide_Inside;
|
||||
m_planes[FrustumPlane_Right].Set(plane);
|
||||
|
||||
for(unsigned int i = 0; i <= nzFrustumPlane_Max; i++)
|
||||
{
|
||||
T distance = m_planes[i].Distance(sphere.GetPosition());
|
||||
if (distance < -sphere.radius)
|
||||
return nzIntersectionSide_Outside;
|
||||
else if (distance < sphere.radius)
|
||||
side = nzIntersectionSide_Intersecting;
|
||||
}
|
||||
// Extract the numbers for the LEFT plane
|
||||
plane[0] = clipMatrix[ 3] + clipMatrix[ 0];
|
||||
plane[1] = clipMatrix[ 7] + clipMatrix[ 4];
|
||||
plane[2] = clipMatrix[11] + clipMatrix[ 8];
|
||||
plane[3] = clipMatrix[15] + clipMatrix[12];
|
||||
|
||||
return side;
|
||||
}
|
||||
// Normalize the result
|
||||
invLength = F(1.0) / std::sqrt(plane[0]*plane[0] + plane[1]*plane[1] + plane[2]*plane[2]);
|
||||
plane[0] *= invLength;
|
||||
plane[1] *= invLength;
|
||||
plane[2] *= invLength;
|
||||
plane[3] *= -invLength;
|
||||
|
||||
template<typename T>
|
||||
nzIntersectionSide NzFrustum<T>::Intersect(const NzVector3<T>* points, unsigned int pointCount) const
|
||||
{
|
||||
unsigned int c = 0;
|
||||
m_planes[FrustumPlane_Left].Set(plane);
|
||||
|
||||
for (unsigned int i = 0; i <= nzFrustumPlane_Max; ++i)
|
||||
{
|
||||
unsigned int j;
|
||||
for (j = 0; j < pointCount; j++ )
|
||||
// Extract the BOTTOM plane
|
||||
plane[0] = clipMatrix[ 3] + clipMatrix[ 1];
|
||||
plane[1] = clipMatrix[ 7] + clipMatrix[ 5];
|
||||
plane[2] = clipMatrix[11] + clipMatrix[ 9];
|
||||
plane[3] = clipMatrix[15] + clipMatrix[13];
|
||||
|
||||
// Normalize the result
|
||||
invLength = F(1.0) / std::sqrt(plane[0]*plane[0] + plane[1]*plane[1] + plane[2]*plane[2]);
|
||||
plane[0] *= invLength;
|
||||
plane[1] *= invLength;
|
||||
plane[2] *= invLength;
|
||||
plane[3] *= -invLength;
|
||||
|
||||
m_planes[FrustumPlane_Bottom].Set(plane);
|
||||
|
||||
// Extract the TOP plane
|
||||
plane[0] = clipMatrix[ 3] - clipMatrix[ 1];
|
||||
plane[1] = clipMatrix[ 7] - clipMatrix[ 5];
|
||||
plane[2] = clipMatrix[11] - clipMatrix[ 9];
|
||||
plane[3] = clipMatrix[15] - clipMatrix[13];
|
||||
|
||||
// Normalize the result
|
||||
invLength = F(1.0) / std::sqrt(plane[0]*plane[0] + plane[1]*plane[1] + plane[2]*plane[2]);
|
||||
plane[0] *= invLength;
|
||||
plane[1] *= invLength;
|
||||
plane[2] *= invLength;
|
||||
plane[3] *= -invLength;
|
||||
|
||||
m_planes[FrustumPlane_Top].Set(plane);
|
||||
|
||||
// Extract the FAR plane
|
||||
plane[0] = clipMatrix[ 3] - clipMatrix[ 2];
|
||||
plane[1] = clipMatrix[ 7] - clipMatrix[ 6];
|
||||
plane[2] = clipMatrix[11] - clipMatrix[10];
|
||||
plane[3] = clipMatrix[15] - clipMatrix[14];
|
||||
|
||||
// Normalize the result
|
||||
invLength = F(1.0) / std::sqrt(plane[0]*plane[0] + plane[1]*plane[1] + plane[2]*plane[2]);
|
||||
plane[0] *= invLength;
|
||||
plane[1] *= invLength;
|
||||
plane[2] *= invLength;
|
||||
plane[3] *= -invLength;
|
||||
|
||||
m_planes[FrustumPlane_Far].Set(plane);
|
||||
|
||||
// Extract the NEAR plane
|
||||
plane[0] = clipMatrix[ 3] + clipMatrix[ 2];
|
||||
plane[1] = clipMatrix[ 7] + clipMatrix[ 6];
|
||||
plane[2] = clipMatrix[11] + clipMatrix[10];
|
||||
plane[3] = clipMatrix[15] + clipMatrix[14];
|
||||
|
||||
// Normalize the result
|
||||
invLength = F(1.0) / std::sqrt(plane[0]*plane[0] + plane[1]*plane[1] + plane[2]*plane[2]);
|
||||
plane[0] *= invLength;
|
||||
plane[1] *= invLength;
|
||||
plane[2] *= invLength;
|
||||
plane[3] *= -invLength;
|
||||
|
||||
m_planes[FrustumPlane_Near].Set(plane);
|
||||
|
||||
// Une fois les plans extraits, il faut extraire les points du frustum
|
||||
// Je me base sur cette page: http://www.gamedev.net/topic/393309-calculating-the-view-frustums-vertices/
|
||||
|
||||
Matrix4<T> invClipMatrix;
|
||||
if (clipMatrix.GetInverse(&invClipMatrix))
|
||||
{
|
||||
if (m_planes[i].Distance(points[j]) > F(0.0))
|
||||
break;
|
||||
}
|
||||
Vector4<T> corner;
|
||||
|
||||
if (j == pointCount)
|
||||
return nzIntersectionSide_Outside;
|
||||
// FarLeftBottom
|
||||
corner.Set(F(-1.0), F(-1.0), F(1.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[BoxCorner_FarLeftBottom] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// FarLeftTop
|
||||
corner.Set(F(-1.0), F(1.0), F(1.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[BoxCorner_FarLeftTop] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// FarRightBottom
|
||||
corner.Set(F(1.0), F(-1.0), F(1.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[BoxCorner_FarRightBottom] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// FarRightTop
|
||||
corner.Set(F(1.0), F(1.0), F(1.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[BoxCorner_FarRightTop] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// NearLeftBottom
|
||||
corner.Set(F(-1.0), F(-1.0), F(0.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[BoxCorner_NearLeftBottom] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// NearLeftTop
|
||||
corner.Set(F(-1.0), F(1.0), F(0.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[BoxCorner_NearLeftTop] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// NearRightBottom
|
||||
corner.Set(F(1.0), F(-1.0), F(0.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[BoxCorner_NearRightBottom] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
|
||||
// NearRightTop
|
||||
corner.Set(F(1.0), F(1.0), F(0.0));
|
||||
corner = invClipMatrix.Transform(corner);
|
||||
corner.Normalize();
|
||||
|
||||
m_corners[BoxCorner_NearRightTop] = Vector3<T>(corner.x, corner.y, corner.z);
|
||||
}
|
||||
else
|
||||
c++;
|
||||
NazaraWarning("Clip matrix is not invertible, failed to compute frustum corners");
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
return (c == 6) ? nzIntersectionSide_Inside : nzIntersectionSide_Intersecting;
|
||||
template<typename T>
|
||||
Frustum<T>& Frustum<T>::Extract(const Matrix4<T>& view, const Matrix4<T>& projection)
|
||||
{
|
||||
return Extract(Matrix4<T>::Concatenate(view, projection));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const Vector3<T>& Frustum<T>::GetCorner(BoxCorner corner) const
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (corner > BoxCorner_Max)
|
||||
{
|
||||
NazaraError("Corner not handled (0x" + String::Number(corner, 16) + ')');
|
||||
|
||||
static Vector3<T> dummy;
|
||||
return dummy;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_corners[corner];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const Plane<T>& Frustum<T>::GetPlane(FrustumPlane plane) const
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (plane > FrustumPlane_Max)
|
||||
{
|
||||
NazaraError("Frustum plane not handled (0x" + String::Number(plane, 16) + ')');
|
||||
|
||||
static Plane<T> dummy;
|
||||
return dummy;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_planes[plane];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
IntersectionSide Frustum<T>::Intersect(const BoundingVolume<T>& volume) const
|
||||
{
|
||||
switch (volume.extend)
|
||||
{
|
||||
case Extend_Finite:
|
||||
{
|
||||
IntersectionSide side = Intersect(volume.aabb);
|
||||
switch (side)
|
||||
{
|
||||
case IntersectionSide_Inside:
|
||||
return IntersectionSide_Inside;
|
||||
|
||||
case IntersectionSide_Intersecting:
|
||||
return Intersect(volume.obb);
|
||||
|
||||
case IntersectionSide_Outside:
|
||||
return IntersectionSide_Outside;
|
||||
}
|
||||
|
||||
NazaraError("Invalid intersection side (0x" + String::Number(side, 16) + ')');
|
||||
return IntersectionSide_Outside;
|
||||
}
|
||||
|
||||
case Extend_Infinite:
|
||||
return IntersectionSide_Intersecting; // On ne peut pas contenir l'infini
|
||||
|
||||
case Extend_Null:
|
||||
return IntersectionSide_Outside;
|
||||
}
|
||||
|
||||
NazaraError("Invalid extend type (0x" + String::Number(volume.extend, 16) + ')');
|
||||
return IntersectionSide_Outside;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
IntersectionSide Frustum<T>::Intersect(const Box<T>& box) const
|
||||
{
|
||||
// http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-testing-boxes-ii/
|
||||
IntersectionSide side = IntersectionSide_Inside;
|
||||
|
||||
for(unsigned int i = 0; i <= FrustumPlane_Max; i++)
|
||||
{
|
||||
if (m_planes[i].Distance(box.GetPositiveVertex(m_planes[i].normal)) < F(0.0))
|
||||
return IntersectionSide_Outside;
|
||||
else if (m_planes[i].Distance(box.GetNegativeVertex(m_planes[i].normal)) < F(0.0))
|
||||
side = IntersectionSide_Intersecting;
|
||||
}
|
||||
|
||||
return side;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
IntersectionSide Frustum<T>::Intersect(const OrientedBox<T>& orientedbox) const
|
||||
{
|
||||
return Intersect(&orientedbox[0], 8);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
IntersectionSide Frustum<T>::Intersect(const Sphere<T>& sphere) const
|
||||
{
|
||||
// http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-testing-points-and-spheres/
|
||||
IntersectionSide side = IntersectionSide_Inside;
|
||||
|
||||
for(unsigned int i = 0; i <= FrustumPlane_Max; i++)
|
||||
{
|
||||
T distance = m_planes[i].Distance(sphere.GetPosition());
|
||||
if (distance < -sphere.radius)
|
||||
return IntersectionSide_Outside;
|
||||
else if (distance < sphere.radius)
|
||||
side = IntersectionSide_Intersecting;
|
||||
}
|
||||
|
||||
return side;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
IntersectionSide Frustum<T>::Intersect(const Vector3<T>* points, unsigned int pointCount) const
|
||||
{
|
||||
unsigned int c = 0;
|
||||
|
||||
for (unsigned int i = 0; i <= FrustumPlane_Max; ++i)
|
||||
{
|
||||
unsigned int j;
|
||||
for (j = 0; j < pointCount; j++ )
|
||||
{
|
||||
if (m_planes[i].Distance(points[j]) > F(0.0))
|
||||
break;
|
||||
}
|
||||
|
||||
if (j == pointCount)
|
||||
return IntersectionSide_Outside;
|
||||
else
|
||||
c++;
|
||||
}
|
||||
|
||||
return (c == 6) ? IntersectionSide_Inside : IntersectionSide_Intersecting;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Frustum<T>& Frustum<T>::Set(const Frustum& frustum)
|
||||
{
|
||||
std::memcpy(this, &frustum, sizeof(Frustum));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
Frustum<T>& Frustum<T>::Set(const Frustum<U>& frustum)
|
||||
{
|
||||
for (unsigned int i = 0; i <= BoxCorner_Max; ++i)
|
||||
m_corners[i].Set(frustum.m_corners[i]);
|
||||
|
||||
for (unsigned int i = 0; i <= FrustumPlane_Max; ++i)
|
||||
m_planes[i].Set(frustum.m_planes[i]);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
String Frustum<T>::ToString() const
|
||||
{
|
||||
StringStream ss;
|
||||
|
||||
return ss << "Frustum(Bottom: " << m_planes[FrustumPlane_Bottom].ToString() << "\n"
|
||||
<< " Far: " << m_planes[FrustumPlane_Far].ToString() << "\n"
|
||||
<< " Left: " << m_planes[FrustumPlane_Left].ToString() << "\n"
|
||||
<< " Near: " << m_planes[FrustumPlane_Near].ToString() << "\n"
|
||||
<< " Right: " << m_planes[FrustumPlane_Right].ToString() << "\n"
|
||||
<< " Top: " << m_planes[FrustumPlane_Top].ToString() << ")\n";
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzFrustum<T>& NzFrustum<T>::Set(const NzFrustum& frustum)
|
||||
{
|
||||
std::memcpy(this, &frustum, sizeof(NzFrustum));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzFrustum<T>& NzFrustum<T>::Set(const NzFrustum<U>& frustum)
|
||||
{
|
||||
for (unsigned int i = 0; i <= nzBoxCorner_Max; ++i)
|
||||
m_corners[i].Set(frustum.m_corners[i]);
|
||||
|
||||
for (unsigned int i = 0; i <= nzFrustumPlane_Max; ++i)
|
||||
m_planes[i].Set(frustum.m_planes[i]);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzString NzFrustum<T>::ToString() const
|
||||
{
|
||||
NzStringStream ss;
|
||||
|
||||
return ss << "Frustum(Bottom: " << m_planes[nzFrustumPlane_Bottom].ToString() << "\n"
|
||||
<< " Far: " << m_planes[nzFrustumPlane_Far].ToString() << "\n"
|
||||
<< " Left: " << m_planes[nzFrustumPlane_Left].ToString() << "\n"
|
||||
<< " Near: " << m_planes[nzFrustumPlane_Near].ToString() << "\n"
|
||||
<< " Right: " << m_planes[nzFrustumPlane_Right].ToString() << "\n"
|
||||
<< " Top: " << m_planes[nzFrustumPlane_Top].ToString() << ")\n";
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzFrustum<T>& frustum)
|
||||
std::ostream& operator<<(std::ostream& out, const Nz::Frustum<T>& frustum)
|
||||
{
|
||||
return out << frustum.ToString();
|
||||
}
|
||||
|
||||
@@ -12,134 +12,138 @@
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <Nazara/Math/Config.hpp>
|
||||
|
||||
template<typename T> class NzEulerAngles;
|
||||
template<typename T> class NzQuaternion;
|
||||
template<typename T> class NzVector2;
|
||||
template<typename T> class NzVector3;
|
||||
template<typename T> class NzVector4;
|
||||
|
||||
template<typename T>
|
||||
class NzMatrix4
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzMatrix4() = default;
|
||||
NzMatrix4(T r11, T r12, T r13, T r14,
|
||||
T r21, T r22, T r23, T r24,
|
||||
T r31, T r32, T r33, T r34,
|
||||
T r41, T r42, T r43, T r44);
|
||||
//NzMatrix4(const NzMatrix3<T>& matrix);
|
||||
NzMatrix4(const T matrix[16]);
|
||||
template<typename U> explicit NzMatrix4(const NzMatrix4<U>& matrix);
|
||||
NzMatrix4(const NzMatrix4& matrix) = default;
|
||||
~NzMatrix4() = default;
|
||||
template<typename T> class EulerAngles;
|
||||
template<typename T> class Quaternion;
|
||||
template<typename T> class Vector2;
|
||||
template<typename T> class Vector3;
|
||||
template<typename T> class Vector4;
|
||||
|
||||
NzMatrix4& ApplyRotation(const NzQuaternion<T>& rotation);
|
||||
NzMatrix4& ApplyScale(const NzVector3<T>& scale);
|
||||
NzMatrix4& ApplyTranslation(const NzVector3<T>& translation);
|
||||
template<typename T>
|
||||
class Matrix4
|
||||
{
|
||||
public:
|
||||
Matrix4() = default;
|
||||
Matrix4(T r11, T r12, T r13, T r14,
|
||||
T r21, T r22, T r23, T r24,
|
||||
T r31, T r32, T r33, T r34,
|
||||
T r41, T r42, T r43, T r44);
|
||||
//Matrix4(const Matrix3<T>& matrix);
|
||||
Matrix4(const T matrix[16]);
|
||||
template<typename U> explicit Matrix4(const Matrix4<U>& matrix);
|
||||
Matrix4(const Matrix4& matrix) = default;
|
||||
~Matrix4() = default;
|
||||
|
||||
NzMatrix4& Concatenate(const NzMatrix4& matrix);
|
||||
NzMatrix4& ConcatenateAffine(const NzMatrix4& matrix);
|
||||
Matrix4& ApplyRotation(const Quaternion<T>& rotation);
|
||||
Matrix4& ApplyScale(const Vector3<T>& scale);
|
||||
Matrix4& ApplyTranslation(const Vector3<T>& translation);
|
||||
|
||||
NzVector4<T> GetColumn(unsigned int column) const;
|
||||
T GetDeterminant() const;
|
||||
T GetDeterminantAffine() const;
|
||||
bool GetInverse(NzMatrix4* dest) const;
|
||||
bool GetInverseAffine(NzMatrix4* dest) const;
|
||||
NzQuaternion<T> GetRotation() const;
|
||||
//NzMatrix3 GetRotationMatrix() const;
|
||||
NzVector4<T> GetRow(unsigned int row) const;
|
||||
NzVector3<T> GetScale() const;
|
||||
NzVector3<T> GetSquaredScale() const;
|
||||
NzVector3<T> GetTranslation() const;
|
||||
void GetTransposed(NzMatrix4* dest) const;
|
||||
Matrix4& Concatenate(const Matrix4& matrix);
|
||||
Matrix4& ConcatenateAffine(const Matrix4& matrix);
|
||||
|
||||
bool HasNegativeScale() const;
|
||||
bool HasScale() const;
|
||||
Vector4<T> GetColumn(unsigned int column) const;
|
||||
T GetDeterminant() const;
|
||||
T GetDeterminantAffine() const;
|
||||
bool GetInverse(Matrix4* dest) const;
|
||||
bool GetInverseAffine(Matrix4* dest) const;
|
||||
Quaternion<T> GetRotation() const;
|
||||
//Matrix3 GetRotationMatrix() const;
|
||||
Vector4<T> GetRow(unsigned int row) const;
|
||||
Vector3<T> GetScale() const;
|
||||
Vector3<T> GetSquaredScale() const;
|
||||
Vector3<T> GetTranslation() const;
|
||||
void GetTransposed(Matrix4* dest) const;
|
||||
|
||||
NzMatrix4& Inverse(bool* succeeded = nullptr);
|
||||
NzMatrix4& InverseAffine(bool* succeeded = nullptr);
|
||||
bool HasNegativeScale() const;
|
||||
bool HasScale() const;
|
||||
|
||||
bool IsAffine() const;
|
||||
bool IsIdentity() const;
|
||||
Matrix4& Inverse(bool* succeeded = nullptr);
|
||||
Matrix4& InverseAffine(bool* succeeded = nullptr);
|
||||
|
||||
NzMatrix4& MakeIdentity();
|
||||
NzMatrix4& MakeLookAt(const NzVector3<T>& eye, const NzVector3<T>& target, const NzVector3<T>& up = NzVector3<T>::Up());
|
||||
NzMatrix4& MakeOrtho(T left, T right, T top, T bottom, T zNear = -1.0, T zFar = 1.0);
|
||||
NzMatrix4& MakePerspective(T angle, T ratio, T zNear, T zFar);
|
||||
NzMatrix4& MakeRotation(const NzQuaternion<T>& rotation);
|
||||
NzMatrix4& MakeScale(const NzVector3<T>& scale);
|
||||
NzMatrix4& MakeTranslation(const NzVector3<T>& translation);
|
||||
NzMatrix4& MakeTransform(const NzVector3<T>& translation, const NzQuaternion<T>& rotation);
|
||||
NzMatrix4& MakeTransform(const NzVector3<T>& translation, const NzQuaternion<T>& rotation, const NzVector3<T>& scale);
|
||||
NzMatrix4& MakeViewMatrix(const NzVector3<T>& translation, const NzQuaternion<T>& rotation);
|
||||
NzMatrix4& MakeZero();
|
||||
bool IsAffine() const;
|
||||
bool IsIdentity() const;
|
||||
|
||||
NzMatrix4& Set(T r11, T r12, T r13, T r14,
|
||||
T r21, T r22, T r23, T r24,
|
||||
T r31, T r32, T r33, T r34,
|
||||
T r41, T r42, T r43, T r44);
|
||||
NzMatrix4& Set(const T matrix[16]);
|
||||
//NzMatrix4(const NzMatrix3<T>& matrix);
|
||||
NzMatrix4& Set(const NzMatrix4& matrix);
|
||||
template<typename U> NzMatrix4& Set(const NzMatrix4<U>& matrix);
|
||||
NzMatrix4& SetRotation(const NzQuaternion<T>& rotation);
|
||||
NzMatrix4& SetScale(const NzVector3<T>& scale);
|
||||
NzMatrix4& SetTranslation(const NzVector3<T>& translation);
|
||||
Matrix4& MakeIdentity();
|
||||
Matrix4& MakeLookAt(const Vector3<T>& eye, const Vector3<T>& target, const Vector3<T>& up = Vector3<T>::Up());
|
||||
Matrix4& MakeOrtho(T left, T right, T top, T bottom, T zNear = -1.0, T zFar = 1.0);
|
||||
Matrix4& MakePerspective(T angle, T ratio, T zNear, T zFar);
|
||||
Matrix4& MakeRotation(const Quaternion<T>& rotation);
|
||||
Matrix4& MakeScale(const Vector3<T>& scale);
|
||||
Matrix4& MakeTranslation(const Vector3<T>& translation);
|
||||
Matrix4& MakeTransform(const Vector3<T>& translation, const Quaternion<T>& rotation);
|
||||
Matrix4& MakeTransform(const Vector3<T>& translation, const Quaternion<T>& rotation, const Vector3<T>& scale);
|
||||
Matrix4& MakeViewMatrix(const Vector3<T>& translation, const Quaternion<T>& rotation);
|
||||
Matrix4& MakeZero();
|
||||
|
||||
NzString ToString() const;
|
||||
Matrix4& Set(T r11, T r12, T r13, T r14,
|
||||
T r21, T r22, T r23, T r24,
|
||||
T r31, T r32, T r33, T r34,
|
||||
T r41, T r42, T r43, T r44);
|
||||
Matrix4& Set(const T matrix[16]);
|
||||
//Matrix4(const Matrix3<T>& matrix);
|
||||
Matrix4& Set(const Matrix4& matrix);
|
||||
template<typename U> Matrix4& Set(const Matrix4<U>& matrix);
|
||||
Matrix4& SetRotation(const Quaternion<T>& rotation);
|
||||
Matrix4& SetScale(const Vector3<T>& scale);
|
||||
Matrix4& SetTranslation(const Vector3<T>& translation);
|
||||
|
||||
NzVector2<T> Transform(const NzVector2<T>& vector, T z = 0.0, T w = 1.0) const;
|
||||
NzVector3<T> Transform(const NzVector3<T>& vector, T w = 1.0) const;
|
||||
NzVector4<T> Transform(const NzVector4<T>& vector) const;
|
||||
String ToString() const;
|
||||
|
||||
NzMatrix4& Transpose();
|
||||
Vector2<T> Transform(const Vector2<T>& vector, T z = 0.0, T w = 1.0) const;
|
||||
Vector3<T> Transform(const Vector3<T>& vector, T w = 1.0) const;
|
||||
Vector4<T> Transform(const Vector4<T>& vector) const;
|
||||
|
||||
operator T*();
|
||||
operator const T*() const;
|
||||
Matrix4& Transpose();
|
||||
|
||||
T& operator()(unsigned int x, unsigned int y);
|
||||
T operator()(unsigned int x, unsigned int y) const;
|
||||
operator T*();
|
||||
operator const T*() const;
|
||||
|
||||
NzMatrix4& operator=(const NzMatrix4& matrix) = default;
|
||||
T& operator()(unsigned int x, unsigned int y);
|
||||
T operator()(unsigned int x, unsigned int y) const;
|
||||
|
||||
NzMatrix4 operator*(const NzMatrix4& matrix) const;
|
||||
NzVector2<T> operator*(const NzVector2<T>& vector) const;
|
||||
NzVector3<T> operator*(const NzVector3<T>& vector) const;
|
||||
NzVector4<T> operator*(const NzVector4<T>& vector) const;
|
||||
NzMatrix4 operator*(T scalar) const;
|
||||
Matrix4& operator=(const Matrix4& matrix) = default;
|
||||
|
||||
NzMatrix4& operator*=(const NzMatrix4& matrix);
|
||||
NzMatrix4& operator*=(T scalar);
|
||||
Matrix4 operator*(const Matrix4& matrix) const;
|
||||
Vector2<T> operator*(const Vector2<T>& vector) const;
|
||||
Vector3<T> operator*(const Vector3<T>& vector) const;
|
||||
Vector4<T> operator*(const Vector4<T>& vector) const;
|
||||
Matrix4 operator*(T scalar) const;
|
||||
|
||||
bool operator==(const NzMatrix4& mat) const;
|
||||
bool operator!=(const NzMatrix4& mat) const;
|
||||
Matrix4& operator*=(const Matrix4& matrix);
|
||||
Matrix4& operator*=(T scalar);
|
||||
|
||||
static NzMatrix4 Concatenate(const NzMatrix4& left, const NzMatrix4& right);
|
||||
static NzMatrix4 ConcatenateAffine(const NzMatrix4& left, const NzMatrix4& right);
|
||||
static NzMatrix4 Identity();
|
||||
static NzMatrix4 LookAt(const NzVector3<T>& eye, const NzVector3<T>& target, const NzVector3<T>& up = NzVector3<T>::Up());
|
||||
static NzMatrix4 Ortho(T left, T right, T top, T bottom, T zNear = -1.0, T zFar = 1.0);
|
||||
static NzMatrix4 Perspective(T angle, T ratio, T zNear, T zFar);
|
||||
static NzMatrix4 Rotate(const NzQuaternion<T>& rotation);
|
||||
static NzMatrix4 Scale(const NzVector3<T>& scale);
|
||||
static NzMatrix4 Translate(const NzVector3<T>& translation);
|
||||
static NzMatrix4 Transform(const NzVector3<T>& translation, const NzQuaternion<T>& rotation);
|
||||
static NzMatrix4 Transform(const NzVector3<T>& translation, const NzQuaternion<T>& rotation, const NzVector3<T>& scale);
|
||||
static NzMatrix4 ViewMatrix(const NzVector3<T>& translation, const NzQuaternion<T>& rotation);
|
||||
static NzMatrix4 Zero();
|
||||
bool operator==(const Matrix4& mat) const;
|
||||
bool operator!=(const Matrix4& mat) const;
|
||||
|
||||
T m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
m41, m42, m43, m44;
|
||||
};
|
||||
static Matrix4 Concatenate(const Matrix4& left, const Matrix4& right);
|
||||
static Matrix4 ConcatenateAffine(const Matrix4& left, const Matrix4& right);
|
||||
static Matrix4 Identity();
|
||||
static Matrix4 LookAt(const Vector3<T>& eye, const Vector3<T>& target, const Vector3<T>& up = Vector3<T>::Up());
|
||||
static Matrix4 Ortho(T left, T right, T top, T bottom, T zNear = -1.0, T zFar = 1.0);
|
||||
static Matrix4 Perspective(T angle, T ratio, T zNear, T zFar);
|
||||
static Matrix4 Rotate(const Quaternion<T>& rotation);
|
||||
static Matrix4 Scale(const Vector3<T>& scale);
|
||||
static Matrix4 Translate(const Vector3<T>& translation);
|
||||
static Matrix4 Transform(const Vector3<T>& translation, const Quaternion<T>& rotation);
|
||||
static Matrix4 Transform(const Vector3<T>& translation, const Quaternion<T>& rotation, const Vector3<T>& scale);
|
||||
static Matrix4 ViewMatrix(const Vector3<T>& translation, const Quaternion<T>& rotation);
|
||||
static Matrix4 Zero();
|
||||
|
||||
template<typename T> std::ostream& operator<<(std::ostream& out, const NzMatrix4<T>& matrix);
|
||||
T m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
m41, m42, m43, m44;
|
||||
};
|
||||
|
||||
template<typename T> NzMatrix4<T> operator*(T scale, const NzMatrix4<T>& matrix);
|
||||
typedef Matrix4<double> Matrix4d;
|
||||
typedef Matrix4<float> Matrix4f;
|
||||
}
|
||||
|
||||
template<typename T> std::ostream& operator<<(std::ostream& out, const Nz::Matrix4<T>& matrix);
|
||||
|
||||
template<typename T> Nz::Matrix4<T> operator*(T scale, const Nz::Matrix4<T>& matrix);
|
||||
|
||||
typedef NzMatrix4<double> NzMatrix4d;
|
||||
typedef NzMatrix4<float> NzMatrix4f;
|
||||
|
||||
#include <Nazara/Math/Matrix4.inl>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,62 +12,65 @@
|
||||
#include <Nazara/Math/Matrix4.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
|
||||
template<typename T>
|
||||
class NzOrientedBox
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzOrientedBox() = default;
|
||||
NzOrientedBox(T X, T Y, T Z, T Width, T Height, T Depth);
|
||||
NzOrientedBox(const NzBox<T>& box);
|
||||
NzOrientedBox(const NzVector3<T>& vec1, const NzVector3<T>& vec2);
|
||||
template<typename U> explicit NzOrientedBox(const NzOrientedBox<U>& orientedBox);
|
||||
NzOrientedBox(const NzOrientedBox& orientedBox) = default;
|
||||
~NzOrientedBox() = default;
|
||||
template<typename T>
|
||||
class OrientedBox
|
||||
{
|
||||
public:
|
||||
OrientedBox() = default;
|
||||
OrientedBox(T X, T Y, T Z, T Width, T Height, T Depth);
|
||||
OrientedBox(const Box<T>& box);
|
||||
OrientedBox(const Vector3<T>& vec1, const Vector3<T>& vec2);
|
||||
template<typename U> explicit OrientedBox(const OrientedBox<U>& orientedBox);
|
||||
OrientedBox(const OrientedBox& orientedBox) = default;
|
||||
~OrientedBox() = default;
|
||||
|
||||
const NzVector3<T>& GetCorner(nzBoxCorner corner) const;
|
||||
const Vector3<T>& GetCorner(BoxCorner corner) const;
|
||||
|
||||
bool IsValid() const;
|
||||
bool IsValid() const;
|
||||
|
||||
NzOrientedBox& MakeZero();
|
||||
OrientedBox& MakeZero();
|
||||
|
||||
NzOrientedBox& Set(T X, T Y, T Z, T Width, T Height, T Depth);
|
||||
NzOrientedBox& Set(const NzBox<T>& box);
|
||||
NzOrientedBox& Set(const NzOrientedBox& orientedBox);
|
||||
NzOrientedBox& Set(const NzVector3<T>& vec1, const NzVector3<T>& vec2);
|
||||
template<typename U> NzOrientedBox& Set(const NzOrientedBox<U>& orientedBox);
|
||||
OrientedBox& Set(T X, T Y, T Z, T Width, T Height, T Depth);
|
||||
OrientedBox& Set(const Box<T>& box);
|
||||
OrientedBox& Set(const OrientedBox& orientedBox);
|
||||
OrientedBox& Set(const Vector3<T>& vec1, const Vector3<T>& vec2);
|
||||
template<typename U> OrientedBox& Set(const OrientedBox<U>& orientedBox);
|
||||
|
||||
NzString ToString() const;
|
||||
String ToString() const;
|
||||
|
||||
void Update(const NzMatrix4<T>& transformMatrix);
|
||||
void Update(const NzVector3<T>& transformMatrix);
|
||||
void Update(const Matrix4<T>& transformMatrix);
|
||||
void Update(const Vector3<T>& transformMatrix);
|
||||
|
||||
operator NzVector3<T>*();
|
||||
operator const NzVector3<T>*() const;
|
||||
operator Vector3<T>*();
|
||||
operator const Vector3<T>*() const;
|
||||
|
||||
NzVector3<T>& operator()(unsigned int i);
|
||||
NzVector3<T> operator()(unsigned int i) const;
|
||||
Vector3<T>& operator()(unsigned int i);
|
||||
Vector3<T> operator()(unsigned int i) const;
|
||||
|
||||
NzOrientedBox operator*(T scalar) const;
|
||||
OrientedBox operator*(T scalar) const;
|
||||
|
||||
NzOrientedBox& operator*=(T scalar);
|
||||
OrientedBox& operator*=(T scalar);
|
||||
|
||||
bool operator==(const NzOrientedBox& box) const;
|
||||
bool operator!=(const NzOrientedBox& box) const;
|
||||
bool operator==(const OrientedBox& box) const;
|
||||
bool operator!=(const OrientedBox& box) const;
|
||||
|
||||
static NzOrientedBox Lerp(const NzOrientedBox& from, const NzOrientedBox& to, T interpolation);
|
||||
static NzOrientedBox Zero();
|
||||
static OrientedBox Lerp(const OrientedBox& from, const OrientedBox& to, T interpolation);
|
||||
static OrientedBox Zero();
|
||||
|
||||
NzBox<T> localBox;
|
||||
Box<T> localBox;
|
||||
|
||||
private:
|
||||
NzVector3<T> m_corners[nzBoxCorner_Max+1]; // Ne peuvent pas être modifiés directement
|
||||
};
|
||||
private:
|
||||
Vector3<T> m_corners[BoxCorner_Max+1]; // Ne peuvent pas être modifiés directement
|
||||
};
|
||||
|
||||
typedef OrientedBox<double> OrientedBoxd;
|
||||
typedef OrientedBox<float> OrientedBoxf;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzOrientedBox<T>& orientedBox);
|
||||
|
||||
typedef NzOrientedBox<double> NzOrientedBoxd;
|
||||
typedef NzOrientedBox<float> NzOrientedBoxf;
|
||||
std::ostream& operator<<(std::ostream& out, const Nz::OrientedBox<T>& orientedBox);
|
||||
|
||||
#include <Nazara/Math/OrientedBox.inl>
|
||||
|
||||
|
||||
@@ -11,229 +11,232 @@
|
||||
|
||||
#define F(a) static_cast<T>(a)
|
||||
|
||||
template<typename T>
|
||||
NzOrientedBox<T>::NzOrientedBox(T X, T Y, T Z, T Width, T Height, T Depth)
|
||||
namespace Nz
|
||||
{
|
||||
Set(X, Y, Z, Width, Height, Depth);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzOrientedBox<T>::NzOrientedBox(const NzBox<T>& box)
|
||||
{
|
||||
Set(box);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzOrientedBox<T>::NzOrientedBox(const NzVector3<T>& vec1, const NzVector3<T>& vec2)
|
||||
{
|
||||
Set(vec1, vec2);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzOrientedBox<T>::NzOrientedBox(const NzOrientedBox<U>& orientedBox)
|
||||
{
|
||||
Set(orientedBox);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const NzVector3<T>& NzOrientedBox<T>::GetCorner(nzBoxCorner corner) const
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (corner > nzBoxCorner_Max)
|
||||
template<typename T>
|
||||
OrientedBox<T>::OrientedBox(T X, T Y, T Z, T Width, T Height, T Depth)
|
||||
{
|
||||
NazaraError("Corner not handled (0x" + NzString::Number(corner, 16) + ')');
|
||||
|
||||
static NzVector3<T> dummy;
|
||||
return dummy;
|
||||
Set(X, Y, Z, Width, Height, Depth);
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_corners[corner];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzOrientedBox<T>::IsValid() const
|
||||
{
|
||||
return localBox.IsValid();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzOrientedBox<T>& NzOrientedBox<T>::MakeZero()
|
||||
{
|
||||
localBox.MakeZero();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzOrientedBox<T>& NzOrientedBox<T>::Set(T X, T Y, T Z, T Width, T Height, T Depth)
|
||||
{
|
||||
localBox.Set(X, Y, Z, Width, Height, Depth);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzOrientedBox<T>& NzOrientedBox<T>::Set(const NzBox<T>& box)
|
||||
{
|
||||
localBox.Set(box);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzOrientedBox<T>& NzOrientedBox<T>::Set(const NzOrientedBox& orientedBox)
|
||||
{
|
||||
std::memcpy(this, &orientedBox, sizeof(NzOrientedBox));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzOrientedBox<T>& NzOrientedBox<T>::Set(const NzVector3<T>& vec1, const NzVector3<T>& vec2)
|
||||
{
|
||||
localBox.Set(vec1, vec2);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzOrientedBox<T>& NzOrientedBox<T>::Set(const NzOrientedBox<U>& orientedBox)
|
||||
{
|
||||
for (unsigned int i = 0; i <= nzBoxCorner_Max; ++i)
|
||||
m_corners[i].Set(orientedBox(i));
|
||||
|
||||
localBox.Set(orientedBox.localBox);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzString NzOrientedBox<T>::ToString() const
|
||||
{
|
||||
NzStringStream ss;
|
||||
|
||||
return ss << "OrientedBox(FLB: " << m_corners[nzBoxCorner_FarLeftBottom].ToString() << "\n"
|
||||
<< " FLT: " << m_corners[nzBoxCorner_FarLeftTop].ToString() << "\n"
|
||||
<< " FRB: " << m_corners[nzBoxCorner_FarRightBottom].ToString() << "\n"
|
||||
<< " FRT: " << m_corners[nzBoxCorner_FarRightTop].ToString() << "\n"
|
||||
<< " NLB: " << m_corners[nzBoxCorner_NearLeftBottom].ToString() << "\n"
|
||||
<< " NLT: " << m_corners[nzBoxCorner_NearLeftTop].ToString() << "\n"
|
||||
<< " NRB: " << m_corners[nzBoxCorner_NearRightBottom].ToString() << "\n"
|
||||
<< " NRT: " << m_corners[nzBoxCorner_NearRightTop].ToString() << ")\n";
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzOrientedBox<T>::Update(const NzMatrix4<T>& transformMatrix)
|
||||
{
|
||||
for (unsigned int i = 0; i <= nzBoxCorner_Max; ++i)
|
||||
m_corners[i] = transformMatrix.Transform(localBox.GetCorner(static_cast<nzBoxCorner>(i)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzOrientedBox<T>::Update(const NzVector3<T>& translation)
|
||||
{
|
||||
for (unsigned int i = 0; i <= nzBoxCorner_Max; ++i)
|
||||
m_corners[i] = localBox.GetCorner(static_cast<nzBoxCorner>(i)) + translation;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzOrientedBox<T>::operator NzVector3<T>*()
|
||||
{
|
||||
return &m_corners[0];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzOrientedBox<T>::operator const NzVector3<T>*() const
|
||||
{
|
||||
return &m_corners[0];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector3<T>& NzOrientedBox<T>::operator()(unsigned int i)
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (i > nzBoxCorner_Max)
|
||||
template<typename T>
|
||||
OrientedBox<T>::OrientedBox(const Box<T>& box)
|
||||
{
|
||||
NzStringStream ss;
|
||||
ss << "Index out of range: (" << i << " >= " << nzBoxCorner_Max << ")";
|
||||
|
||||
NazaraError(ss);
|
||||
throw std::out_of_range(ss.ToString());
|
||||
Set(box);
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_corners[i];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector3<T> NzOrientedBox<T>::operator()(unsigned int i) const
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (i > nzBoxCorner_Max)
|
||||
template<typename T>
|
||||
OrientedBox<T>::OrientedBox(const Vector3<T>& vec1, const Vector3<T>& vec2)
|
||||
{
|
||||
NzStringStream ss;
|
||||
ss << "Index out of range: (" << i << " >= " << nzBoxCorner_Max << ")";
|
||||
|
||||
NazaraError(ss);
|
||||
throw std::out_of_range(ss.ToString());
|
||||
Set(vec1, vec2);
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_corners[i];
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
OrientedBox<T>::OrientedBox(const OrientedBox<U>& orientedBox)
|
||||
{
|
||||
Set(orientedBox);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const Vector3<T>& OrientedBox<T>::GetCorner(BoxCorner corner) const
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (corner > BoxCorner_Max)
|
||||
{
|
||||
NazaraError("Corner not handled (0x" + String::Number(corner, 16) + ')');
|
||||
|
||||
static Vector3<T> dummy;
|
||||
return dummy;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_corners[corner];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool OrientedBox<T>::IsValid() const
|
||||
{
|
||||
return localBox.IsValid();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
OrientedBox<T>& OrientedBox<T>::MakeZero()
|
||||
{
|
||||
localBox.MakeZero();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
OrientedBox<T>& OrientedBox<T>::Set(T X, T Y, T Z, T Width, T Height, T Depth)
|
||||
{
|
||||
localBox.Set(X, Y, Z, Width, Height, Depth);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
OrientedBox<T>& OrientedBox<T>::Set(const Box<T>& box)
|
||||
{
|
||||
localBox.Set(box);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
OrientedBox<T>& OrientedBox<T>::Set(const OrientedBox& orientedBox)
|
||||
{
|
||||
std::memcpy(this, &orientedBox, sizeof(OrientedBox));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
OrientedBox<T>& OrientedBox<T>::Set(const Vector3<T>& vec1, const Vector3<T>& vec2)
|
||||
{
|
||||
localBox.Set(vec1, vec2);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
OrientedBox<T>& OrientedBox<T>::Set(const OrientedBox<U>& orientedBox)
|
||||
{
|
||||
for (unsigned int i = 0; i <= BoxCorner_Max; ++i)
|
||||
m_corners[i].Set(orientedBox(i));
|
||||
|
||||
localBox.Set(orientedBox.localBox);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
String OrientedBox<T>::ToString() const
|
||||
{
|
||||
StringStream ss;
|
||||
|
||||
return ss << "OrientedBox(FLB: " << m_corners[BoxCorner_FarLeftBottom].ToString() << "\n"
|
||||
<< " FLT: " << m_corners[BoxCorner_FarLeftTop].ToString() << "\n"
|
||||
<< " FRB: " << m_corners[BoxCorner_FarRightBottom].ToString() << "\n"
|
||||
<< " FRT: " << m_corners[BoxCorner_FarRightTop].ToString() << "\n"
|
||||
<< " NLB: " << m_corners[BoxCorner_NearLeftBottom].ToString() << "\n"
|
||||
<< " NLT: " << m_corners[BoxCorner_NearLeftTop].ToString() << "\n"
|
||||
<< " NRB: " << m_corners[BoxCorner_NearRightBottom].ToString() << "\n"
|
||||
<< " NRT: " << m_corners[BoxCorner_NearRightTop].ToString() << ")\n";
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void OrientedBox<T>::Update(const Matrix4<T>& transformMatrix)
|
||||
{
|
||||
for (unsigned int i = 0; i <= BoxCorner_Max; ++i)
|
||||
m_corners[i] = transformMatrix.Transform(localBox.GetCorner(static_cast<BoxCorner>(i)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void OrientedBox<T>::Update(const Vector3<T>& translation)
|
||||
{
|
||||
for (unsigned int i = 0; i <= BoxCorner_Max; ++i)
|
||||
m_corners[i] = localBox.GetCorner(static_cast<BoxCorner>(i)) + translation;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
OrientedBox<T>::operator Vector3<T>*()
|
||||
{
|
||||
return &m_corners[0];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
OrientedBox<T>::operator const Vector3<T>*() const
|
||||
{
|
||||
return &m_corners[0];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector3<T>& OrientedBox<T>::operator()(unsigned int i)
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (i > BoxCorner_Max)
|
||||
{
|
||||
StringStream ss;
|
||||
ss << "Index out of range: (" << i << " >= " << BoxCorner_Max << ")";
|
||||
|
||||
NazaraError(ss);
|
||||
throw std::out_of_range(ss.ToString());
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_corners[i];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector3<T> OrientedBox<T>::operator()(unsigned int i) const
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (i > BoxCorner_Max)
|
||||
{
|
||||
StringStream ss;
|
||||
ss << "Index out of range: (" << i << " >= " << BoxCorner_Max << ")";
|
||||
|
||||
NazaraError(ss);
|
||||
throw std::out_of_range(ss.ToString());
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_corners[i];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
OrientedBox<T> OrientedBox<T>::operator*(T scalar) const
|
||||
{
|
||||
OrientedBox box(*this);
|
||||
box *= scalar;
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
OrientedBox<T>& OrientedBox<T>::operator*=(T scalar)
|
||||
{
|
||||
localBox *= scalar;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool OrientedBox<T>::operator==(const OrientedBox& box) const
|
||||
{
|
||||
return localBox == box.localBox;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool OrientedBox<T>::operator!=(const OrientedBox& box) const
|
||||
{
|
||||
return !operator==(box);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
OrientedBox<T> OrientedBox<T>::Lerp(const OrientedBox& from, const OrientedBox& to, T interpolation)
|
||||
{
|
||||
OrientedBox orientedBox;
|
||||
orientedBox.Set(Box<T>::Lerp(from.localBox, to.localBox, interpolation));
|
||||
|
||||
return orientedBox;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
OrientedBox<T> OrientedBox<T>::Zero()
|
||||
{
|
||||
OrientedBox orientedBox;
|
||||
orientedBox.MakeZero();
|
||||
|
||||
return orientedBox;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzOrientedBox<T> NzOrientedBox<T>::operator*(T scalar) const
|
||||
{
|
||||
NzOrientedBox box(*this);
|
||||
box *= scalar;
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzOrientedBox<T>& NzOrientedBox<T>::operator*=(T scalar)
|
||||
{
|
||||
localBox *= scalar;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzOrientedBox<T>::operator==(const NzOrientedBox& box) const
|
||||
{
|
||||
return localBox == box.localBox;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzOrientedBox<T>::operator!=(const NzOrientedBox& box) const
|
||||
{
|
||||
return !operator==(box);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzOrientedBox<T> NzOrientedBox<T>::Lerp(const NzOrientedBox& from, const NzOrientedBox& to, T interpolation)
|
||||
{
|
||||
NzOrientedBox orientedBox;
|
||||
orientedBox.Set(NzBox<T>::Lerp(from.localBox, to.localBox, interpolation));
|
||||
|
||||
return orientedBox;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzOrientedBox<T> NzOrientedBox<T>::Zero()
|
||||
{
|
||||
NzOrientedBox orientedBox;
|
||||
orientedBox.MakeZero();
|
||||
|
||||
return orientedBox;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzOrientedBox<T>& orientedBox)
|
||||
std::ostream& operator<<(std::ostream& out, const Nz::OrientedBox<T>& orientedBox)
|
||||
{
|
||||
return out << orientedBox.ToString();
|
||||
}
|
||||
|
||||
@@ -10,50 +10,53 @@
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
|
||||
template<typename T>
|
||||
class NzPlane
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzPlane() = default;
|
||||
NzPlane(T normalX, T normalY, T normalZ, T Distance);
|
||||
NzPlane(const T plane[4]);
|
||||
NzPlane(const NzVector3<T>& Normal, T Distance);
|
||||
NzPlane(const NzVector3<T>& Normal, const NzVector3<T>& point);
|
||||
NzPlane(const NzVector3<T>& point1, const NzVector3<T>& point2, const NzVector3<T>& point3);
|
||||
template<typename U> explicit NzPlane(const NzPlane<U>& plane);
|
||||
NzPlane(const NzPlane& plane) = default;
|
||||
~NzPlane() = default;
|
||||
template<typename T>
|
||||
class Plane
|
||||
{
|
||||
public:
|
||||
Plane() = default;
|
||||
Plane(T normalX, T normalY, T normalZ, T Distance);
|
||||
Plane(const T plane[4]);
|
||||
Plane(const Vector3<T>& Normal, T Distance);
|
||||
Plane(const Vector3<T>& Normal, const Vector3<T>& point);
|
||||
Plane(const Vector3<T>& point1, const Vector3<T>& point2, const Vector3<T>& point3);
|
||||
template<typename U> explicit Plane(const Plane<U>& plane);
|
||||
Plane(const Plane& plane) = default;
|
||||
~Plane() = default;
|
||||
|
||||
T Distance(const NzVector3<T>& point) const;
|
||||
T Distance(T x, T y, T z) const;
|
||||
T Distance(const Vector3<T>& point) const;
|
||||
T Distance(T x, T y, T z) const;
|
||||
|
||||
NzPlane& Set(T normalX, T normalY, T normalZ, T Distance);
|
||||
NzPlane& Set(const T plane[4]);
|
||||
NzPlane& Set(const NzPlane& plane);
|
||||
NzPlane& Set(const NzVector3<T>& Normal, T Distance);
|
||||
NzPlane& Set(const NzVector3<T>& Normal, const NzVector3<T>& point);
|
||||
NzPlane& Set(const NzVector3<T>& point1, const NzVector3<T>& point2, const NzVector3<T>& point3);
|
||||
template<typename U> NzPlane& Set(const NzPlane<U>& plane);
|
||||
Plane& Set(T normalX, T normalY, T normalZ, T Distance);
|
||||
Plane& Set(const T plane[4]);
|
||||
Plane& Set(const Plane& plane);
|
||||
Plane& Set(const Vector3<T>& Normal, T Distance);
|
||||
Plane& Set(const Vector3<T>& Normal, const Vector3<T>& point);
|
||||
Plane& Set(const Vector3<T>& point1, const Vector3<T>& point2, const Vector3<T>& point3);
|
||||
template<typename U> Plane& Set(const Plane<U>& plane);
|
||||
|
||||
NzString ToString() const;
|
||||
String ToString() const;
|
||||
|
||||
bool operator==(const NzPlane& plane) const;
|
||||
bool operator!=(const NzPlane& plane) const;
|
||||
bool operator==(const Plane& plane) const;
|
||||
bool operator!=(const Plane& plane) const;
|
||||
|
||||
static NzPlane Lerp(const NzPlane& from, const NzPlane& to, T interpolation);
|
||||
static NzPlane XY();
|
||||
static NzPlane XZ();
|
||||
static NzPlane YZ();
|
||||
static Plane Lerp(const Plane& from, const Plane& to, T interpolation);
|
||||
static Plane XY();
|
||||
static Plane XZ();
|
||||
static Plane YZ();
|
||||
|
||||
NzVector3<T> normal;
|
||||
T distance;
|
||||
};
|
||||
Vector3<T> normal;
|
||||
T distance;
|
||||
};
|
||||
|
||||
typedef Plane<double> Planed;
|
||||
typedef Plane<float> Planef;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzPlane<T>& plane);
|
||||
|
||||
typedef NzPlane<double> NzPlaned;
|
||||
typedef NzPlane<float> NzPlanef;
|
||||
std::ostream& operator<<(std::ostream& out, const Nz::Plane<T>& plane);
|
||||
|
||||
#include <Nazara/Math/Plane.inl>
|
||||
|
||||
|
||||
@@ -9,181 +9,184 @@
|
||||
|
||||
#define F(a) static_cast<T>(a)
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>::NzPlane(T normalX, T normalY, T normalZ, T D)
|
||||
namespace Nz
|
||||
{
|
||||
Set(normalX, normalY, normalZ, D);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>::NzPlane(const T plane[4])
|
||||
{
|
||||
Set(plane);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>::NzPlane(const NzVector3<T>& Normal, T D)
|
||||
{
|
||||
Set(Normal, D);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>::NzPlane(const NzVector3<T>& Normal, const NzVector3<T>& point)
|
||||
{
|
||||
Set(Normal, point);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>::NzPlane(const NzVector3<T>& point1, const NzVector3<T>& point2, const NzVector3<T>& point3)
|
||||
{
|
||||
Set(point1, point2, point3);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzPlane<T>::NzPlane(const NzPlane<U>& plane)
|
||||
{
|
||||
Set(plane);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzPlane<T>::Distance(const NzVector3<T>& point) const
|
||||
{
|
||||
return normal.DotProduct(point) - distance; // ax + by + cd - d = 0.
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzPlane<T>::Distance(T x, T y, T z) const
|
||||
{
|
||||
return Distance(NzVector3<T>(x, y, z));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>& NzPlane<T>::Set(T normalX, T normalY, T normalZ, T D)
|
||||
{
|
||||
distance = D;
|
||||
normal.Set(normalX, normalY, normalZ);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>& NzPlane<T>::Set(const T plane[4])
|
||||
{
|
||||
normal.Set(plane[0], plane[1], plane[2]);
|
||||
distance = plane[3];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>& NzPlane<T>::Set(const NzPlane& plane)
|
||||
{
|
||||
std::memcpy(this, &plane, sizeof(NzPlane));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>& NzPlane<T>::Set(const NzVector3<T>& Normal, T D)
|
||||
{
|
||||
distance = D;
|
||||
normal = Normal;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>& NzPlane<T>::Set(const NzVector3<T>& Normal, const NzVector3<T>& point)
|
||||
{
|
||||
normal = Normal;
|
||||
distance = -normal.DotProduct(point);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>& NzPlane<T>::Set(const NzVector3<T>& point1, const NzVector3<T>& point2, const NzVector3<T>& point3)
|
||||
{
|
||||
NzVector3<T> edge1 = point2 - point1;
|
||||
NzVector3<T> edge2 = point3 - point1;
|
||||
normal = edge1.CrossProduct(edge2);
|
||||
normal.Normalize();
|
||||
|
||||
distance = normal.DotProduct(point3);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzPlane<T>& NzPlane<T>::Set(const NzPlane<U>& plane)
|
||||
{
|
||||
normal.Set(plane.normal);
|
||||
distance = F(plane.distance);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzString NzPlane<T>::ToString() const
|
||||
{
|
||||
NzStringStream ss;
|
||||
|
||||
return ss << "Plane(Normal: " << normal.ToString() << "; Distance: " << distance << ')';
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzPlane<T>::operator==(const NzPlane& plane) const
|
||||
{
|
||||
return (normal == plane.normal && NzNumberEquals(distance, plane.distance)) || (normal == -plane.normal && NzNumberEquals(distance, -plane.distance));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzPlane<T>::operator!=(const NzPlane& plane) const
|
||||
{
|
||||
return !operator==(plane);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T> NzPlane<T>::Lerp(const NzPlane& from, const NzPlane& to, T interpolation)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (interpolation < F(0.0) || interpolation > F(1.0))
|
||||
template<typename T>
|
||||
Plane<T>::Plane(T normalX, T normalY, T normalZ, T D)
|
||||
{
|
||||
NazaraError("Interpolation must be in range [0..1] (Got " + NzString::Number(interpolation) + ')');
|
||||
return NzPlane();
|
||||
Set(normalX, normalY, normalZ, D);
|
||||
}
|
||||
#endif
|
||||
|
||||
NzPlane plane;
|
||||
plane.distance = NzLerp(from.distance, to.distance, interpolation);
|
||||
plane.normal = NzVector3<T>::Lerp(from.normal, to.normal, interpolation);
|
||||
plane.normal.Normalize();
|
||||
template<typename T>
|
||||
Plane<T>::Plane(const T plane[4])
|
||||
{
|
||||
Set(plane);
|
||||
}
|
||||
|
||||
return plane;
|
||||
template<typename T>
|
||||
Plane<T>::Plane(const Vector3<T>& Normal, T D)
|
||||
{
|
||||
Set(Normal, D);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Plane<T>::Plane(const Vector3<T>& Normal, const Vector3<T>& point)
|
||||
{
|
||||
Set(Normal, point);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Plane<T>::Plane(const Vector3<T>& point1, const Vector3<T>& point2, const Vector3<T>& point3)
|
||||
{
|
||||
Set(point1, point2, point3);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
Plane<T>::Plane(const Plane<U>& plane)
|
||||
{
|
||||
Set(plane);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T Plane<T>::Distance(const Vector3<T>& point) const
|
||||
{
|
||||
return normal.DotProduct(point) - distance; // ax + by + cd - d = 0.
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T Plane<T>::Distance(T x, T y, T z) const
|
||||
{
|
||||
return Distance(Vector3<T>(x, y, z));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Plane<T>& Plane<T>::Set(T normalX, T normalY, T normalZ, T D)
|
||||
{
|
||||
distance = D;
|
||||
normal.Set(normalX, normalY, normalZ);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Plane<T>& Plane<T>::Set(const T plane[4])
|
||||
{
|
||||
normal.Set(plane[0], plane[1], plane[2]);
|
||||
distance = plane[3];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Plane<T>& Plane<T>::Set(const Plane& plane)
|
||||
{
|
||||
std::memcpy(this, &plane, sizeof(Plane));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Plane<T>& Plane<T>::Set(const Vector3<T>& Normal, T D)
|
||||
{
|
||||
distance = D;
|
||||
normal = Normal;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Plane<T>& Plane<T>::Set(const Vector3<T>& Normal, const Vector3<T>& point)
|
||||
{
|
||||
normal = Normal;
|
||||
distance = -normal.DotProduct(point);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Plane<T>& Plane<T>::Set(const Vector3<T>& point1, const Vector3<T>& point2, const Vector3<T>& point3)
|
||||
{
|
||||
Vector3<T> edge1 = point2 - point1;
|
||||
Vector3<T> edge2 = point3 - point1;
|
||||
normal = edge1.CrossProduct(edge2);
|
||||
normal.Normalize();
|
||||
|
||||
distance = normal.DotProduct(point3);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
Plane<T>& Plane<T>::Set(const Plane<U>& plane)
|
||||
{
|
||||
normal.Set(plane.normal);
|
||||
distance = F(plane.distance);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
String Plane<T>::ToString() const
|
||||
{
|
||||
StringStream ss;
|
||||
|
||||
return ss << "Plane(Normal: " << normal.ToString() << "; Distance: " << distance << ')';
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Plane<T>::operator==(const Plane& plane) const
|
||||
{
|
||||
return (normal == plane.normal && NumberEquals(distance, plane.distance)) || (normal == -plane.normal && NumberEquals(distance, -plane.distance));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Plane<T>::operator!=(const Plane& plane) const
|
||||
{
|
||||
return !operator==(plane);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Plane<T> Plane<T>::Lerp(const Plane& from, const Plane& to, T interpolation)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (interpolation < F(0.0) || interpolation > F(1.0))
|
||||
{
|
||||
NazaraError("Interpolation must be in range [0..1] (Got " + String::Number(interpolation) + ')');
|
||||
return Plane();
|
||||
}
|
||||
#endif
|
||||
|
||||
Plane plane;
|
||||
plane.distance = Lerp(from.distance, to.distance, interpolation);
|
||||
plane.normal = Vector3<T>::Lerp(from.normal, to.normal, interpolation);
|
||||
plane.normal.Normalize();
|
||||
|
||||
return plane;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Plane<T> Plane<T>::XY()
|
||||
{
|
||||
return Plane<T>(F(0.0), F(0.0), F(1.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Plane<T> Plane<T>::XZ()
|
||||
{
|
||||
return Plane<T>(F(0.0), F(1.0), F(0.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Plane<T> Plane<T>::YZ()
|
||||
{
|
||||
return Plane<T>(F(1.0), F(0.0), F(0.0), F(0.0));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T> NzPlane<T>::XY()
|
||||
{
|
||||
return NzPlane<T>(F(0.0), F(0.0), F(1.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T> NzPlane<T>::XZ()
|
||||
{
|
||||
return NzPlane<T>(F(0.0), F(1.0), F(0.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T> NzPlane<T>::YZ()
|
||||
{
|
||||
return NzPlane<T>(F(1.0), F(0.0), F(0.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzPlane<T>& plane)
|
||||
std::ostream& operator<<(std::ostream& out, const Nz::Plane<T>& plane)
|
||||
{
|
||||
return out << plane.ToString();
|
||||
}
|
||||
|
||||
@@ -9,85 +9,88 @@
|
||||
|
||||
#include <Nazara/Core/String.hpp>
|
||||
|
||||
template<typename T> class NzEulerAngles;
|
||||
template<typename T> class NzVector3;
|
||||
|
||||
template<typename T> class NzQuaternion
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzQuaternion() = default;
|
||||
NzQuaternion(T W, T X, T Y, T Z);
|
||||
NzQuaternion(const T quat[4]);
|
||||
NzQuaternion(T angle, const NzVector3<T>& axis);
|
||||
NzQuaternion(const NzEulerAngles<T>& angles);
|
||||
//NzQuaternion(const NzMatrix3<T>& mat);
|
||||
template<typename U> explicit NzQuaternion(const NzQuaternion<U>& quat);
|
||||
NzQuaternion(const NzQuaternion& quat) = default;
|
||||
~NzQuaternion() = default;
|
||||
template<typename T> class EulerAngles;
|
||||
template<typename T> class Vector3;
|
||||
|
||||
NzQuaternion& ComputeW();
|
||||
NzQuaternion& Conjugate();
|
||||
template<typename T> class Quaternion
|
||||
{
|
||||
public:
|
||||
Quaternion() = default;
|
||||
Quaternion(T W, T X, T Y, T Z);
|
||||
Quaternion(const T quat[4]);
|
||||
Quaternion(T angle, const Vector3<T>& axis);
|
||||
Quaternion(const EulerAngles<T>& angles);
|
||||
//Quaternion(const Matrix3<T>& mat);
|
||||
template<typename U> explicit Quaternion(const Quaternion<U>& quat);
|
||||
Quaternion(const Quaternion& quat) = default;
|
||||
~Quaternion() = default;
|
||||
|
||||
T DotProduct(const NzQuaternion& vec) const;
|
||||
Quaternion& ComputeW();
|
||||
Quaternion& Conjugate();
|
||||
|
||||
NzQuaternion GetConjugate() const;
|
||||
NzQuaternion GetInverse() const;
|
||||
NzQuaternion GetNormal(T* length = nullptr) const;
|
||||
T DotProduct(const Quaternion& vec) const;
|
||||
|
||||
NzQuaternion& Inverse();
|
||||
Quaternion GetConjugate() const;
|
||||
Quaternion GetInverse() const;
|
||||
Quaternion GetNormal(T* length = nullptr) const;
|
||||
|
||||
NzQuaternion& MakeIdentity();
|
||||
NzQuaternion& MakeRotationBetween(const NzVector3<T>& from, const NzVector3<T>& to);
|
||||
NzQuaternion& MakeZero();
|
||||
Quaternion& Inverse();
|
||||
|
||||
T Magnitude() const;
|
||||
Quaternion& MakeIdentity();
|
||||
Quaternion& MakeRotationBetween(const Vector3<T>& from, const Vector3<T>& to);
|
||||
Quaternion& MakeZero();
|
||||
|
||||
NzQuaternion& Normalize(T* length = nullptr);
|
||||
T Magnitude() const;
|
||||
|
||||
NzQuaternion& Set(T W, T X, T Y, T Z);
|
||||
NzQuaternion& Set(const T quat[4]);
|
||||
NzQuaternion& Set(T angle, const NzVector3<T>& normalizedAxis);
|
||||
NzQuaternion& Set(const NzEulerAngles<T>& angles);
|
||||
//NzQuaternion& Set(const NzMatrix3<T>& mat);
|
||||
NzQuaternion& Set(const NzQuaternion& quat);
|
||||
template<typename U> NzQuaternion& Set(const NzQuaternion<U>& quat);
|
||||
Quaternion& Normalize(T* length = nullptr);
|
||||
|
||||
T SquaredMagnitude() const;
|
||||
Quaternion& Set(T W, T X, T Y, T Z);
|
||||
Quaternion& Set(const T quat[4]);
|
||||
Quaternion& Set(T angle, const Vector3<T>& normalizedAxis);
|
||||
Quaternion& Set(const EulerAngles<T>& angles);
|
||||
//Quaternion& Set(const Matrix3<T>& mat);
|
||||
Quaternion& Set(const Quaternion& quat);
|
||||
template<typename U> Quaternion& Set(const Quaternion<U>& quat);
|
||||
|
||||
NzEulerAngles<T> ToEulerAngles() const;
|
||||
//NzMatrix3<T> ToRotationMatrix() const;
|
||||
NzString ToString() const;
|
||||
T SquaredMagnitude() const;
|
||||
|
||||
NzQuaternion& operator=(const NzQuaternion& quat);
|
||||
EulerAngles<T> ToEulerAngles() const;
|
||||
//Matrix3<T> ToRotationMatrix() const;
|
||||
String ToString() const;
|
||||
|
||||
NzQuaternion operator+(const NzQuaternion& quat) const;
|
||||
NzQuaternion operator*(const NzQuaternion& quat) const;
|
||||
NzVector3<T> operator*(const NzVector3<T>& vec) const;
|
||||
NzQuaternion operator*(T scale) const;
|
||||
NzQuaternion operator/(const NzQuaternion& quat) const;
|
||||
Quaternion& operator=(const Quaternion& quat);
|
||||
|
||||
NzQuaternion& operator+=(const NzQuaternion& quat);
|
||||
NzQuaternion& operator*=(const NzQuaternion& quat);
|
||||
NzQuaternion& operator*=(T scale);
|
||||
NzQuaternion& operator/=(const NzQuaternion& quat);
|
||||
Quaternion operator+(const Quaternion& quat) const;
|
||||
Quaternion operator*(const Quaternion& quat) const;
|
||||
Vector3<T> operator*(const Vector3<T>& vec) const;
|
||||
Quaternion operator*(T scale) const;
|
||||
Quaternion operator/(const Quaternion& quat) const;
|
||||
|
||||
bool operator==(const NzQuaternion& quat) const;
|
||||
bool operator!=(const NzQuaternion& quat) const;
|
||||
Quaternion& operator+=(const Quaternion& quat);
|
||||
Quaternion& operator*=(const Quaternion& quat);
|
||||
Quaternion& operator*=(T scale);
|
||||
Quaternion& operator/=(const Quaternion& quat);
|
||||
|
||||
static NzQuaternion Identity();
|
||||
static NzQuaternion Lerp(const NzQuaternion& from, const NzQuaternion& to, T interpolation);
|
||||
static NzQuaternion Normalize(const NzQuaternion& quat, T* length = nullptr);
|
||||
static NzQuaternion RotationBetween(const NzVector3<T>& from, const NzVector3<T>& to);
|
||||
static NzQuaternion Slerp(const NzQuaternion& from, const NzQuaternion& to, T interpolation);
|
||||
static NzQuaternion Zero();
|
||||
bool operator==(const Quaternion& quat) const;
|
||||
bool operator!=(const Quaternion& quat) const;
|
||||
|
||||
T w, x, y, z;
|
||||
};
|
||||
static Quaternion Identity();
|
||||
static Quaternion Lerp(const Quaternion& from, const Quaternion& to, T interpolation);
|
||||
static Quaternion Normalize(const Quaternion& quat, T* length = nullptr);
|
||||
static Quaternion RotationBetween(const Vector3<T>& from, const Vector3<T>& to);
|
||||
static Quaternion Slerp(const Quaternion& from, const Quaternion& to, T interpolation);
|
||||
static Quaternion Zero();
|
||||
|
||||
template<typename T> std::ostream& operator<<(std::ostream& out, const NzQuaternion<T>& quat);
|
||||
T w, x, y, z;
|
||||
};
|
||||
|
||||
typedef NzQuaternion<double> NzQuaterniond;
|
||||
typedef NzQuaternion<float> NzQuaternionf;
|
||||
typedef Quaternion<double> Quaterniond;
|
||||
typedef Quaternion<float> Quaternionf;
|
||||
}
|
||||
|
||||
template<typename T> std::ostream& operator<<(std::ostream& out, const Nz::Quaternion<T>& quat);
|
||||
|
||||
#include <Nazara/Math/Quaternion.inl>
|
||||
|
||||
|
||||
@@ -13,473 +13,476 @@
|
||||
|
||||
#define F(a) static_cast<T>(a)
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>::NzQuaternion(T W, T X, T Y, T Z)
|
||||
namespace Nz
|
||||
{
|
||||
Set(W, X, Y, Z);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>::NzQuaternion(const T quat[4])
|
||||
{
|
||||
Set(quat);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>::NzQuaternion(T angle, const NzVector3<T>& axis)
|
||||
{
|
||||
Set(angle, axis);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>::NzQuaternion(const NzEulerAngles<T>& angles)
|
||||
{
|
||||
Set(angles);
|
||||
}
|
||||
/*
|
||||
template<typename T>
|
||||
NzQuaternion<T>::NzQuaternion(const NzMatrix3<T>& mat)
|
||||
{
|
||||
Set(mat);
|
||||
}
|
||||
*/
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzQuaternion<T>::NzQuaternion(const NzQuaternion<U>& quat)
|
||||
{
|
||||
Set(quat);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>& NzQuaternion<T>::ComputeW()
|
||||
{
|
||||
T t = F(1.0) - SquaredMagnitude();
|
||||
|
||||
if (t < F(0.0))
|
||||
w = F(0.0);
|
||||
else
|
||||
w = -std::sqrt(t);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>& NzQuaternion<T>::Conjugate()
|
||||
{
|
||||
x = -x;
|
||||
y = -y;
|
||||
z = -z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzQuaternion<T>::DotProduct(const NzQuaternion& quat) const
|
||||
{
|
||||
return w*quat.w + x*quat.x + y*quat.y + z*quat.z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T> NzQuaternion<T>::GetConjugate() const
|
||||
{
|
||||
NzQuaternion<T> quat(*this);
|
||||
quat.Conjugate();
|
||||
|
||||
return quat;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T> NzQuaternion<T>::GetInverse() const
|
||||
{
|
||||
NzQuaternion<T> quat(*this);
|
||||
quat.Inverse();
|
||||
|
||||
return quat;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T> NzQuaternion<T>::GetNormal(T* length) const
|
||||
{
|
||||
NzQuaternion<T> quat(*this);
|
||||
quat.Normalize(length);
|
||||
|
||||
return quat;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>& NzQuaternion<T>::Inverse()
|
||||
{
|
||||
T norm = SquaredMagnitude();
|
||||
if (norm > F(0.0))
|
||||
template<typename T>
|
||||
Quaternion<T>::Quaternion(T W, T X, T Y, T Z)
|
||||
{
|
||||
Set(W, X, Y, Z);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T>::Quaternion(const T quat[4])
|
||||
{
|
||||
Set(quat);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T>::Quaternion(T angle, const Vector3<T>& axis)
|
||||
{
|
||||
Set(angle, axis);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T>::Quaternion(const EulerAngles<T>& angles)
|
||||
{
|
||||
Set(angles);
|
||||
}
|
||||
/*
|
||||
template<typename T>
|
||||
Quaternion<T>::Quaternion(const Matrix3<T>& mat)
|
||||
{
|
||||
Set(mat);
|
||||
}
|
||||
*/
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
Quaternion<T>::Quaternion(const Quaternion<U>& quat)
|
||||
{
|
||||
Set(quat);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T>& Quaternion<T>::ComputeW()
|
||||
{
|
||||
T t = F(1.0) - SquaredMagnitude();
|
||||
|
||||
if (t < F(0.0))
|
||||
w = F(0.0);
|
||||
else
|
||||
w = -std::sqrt(t);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T>& Quaternion<T>::Conjugate()
|
||||
{
|
||||
x = -x;
|
||||
y = -y;
|
||||
z = -z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T Quaternion<T>::DotProduct(const Quaternion& quat) const
|
||||
{
|
||||
return w*quat.w + x*quat.x + y*quat.y + z*quat.z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T> Quaternion<T>::GetConjugate() const
|
||||
{
|
||||
Quaternion<T> quat(*this);
|
||||
quat.Conjugate();
|
||||
|
||||
return quat;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T> Quaternion<T>::GetInverse() const
|
||||
{
|
||||
Quaternion<T> quat(*this);
|
||||
quat.Inverse();
|
||||
|
||||
return quat;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T> Quaternion<T>::GetNormal(T* length) const
|
||||
{
|
||||
Quaternion<T> quat(*this);
|
||||
quat.Normalize(length);
|
||||
|
||||
return quat;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T>& Quaternion<T>::Inverse()
|
||||
{
|
||||
T norm = SquaredMagnitude();
|
||||
if (norm > F(0.0))
|
||||
{
|
||||
T invNorm = F(1.0) / norm;
|
||||
|
||||
w *= invNorm;
|
||||
x *= -invNorm;
|
||||
y *= -invNorm;
|
||||
z *= -invNorm;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T>& Quaternion<T>::MakeIdentity()
|
||||
{
|
||||
return Set(F(1.0), F(0.0), F(0.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T>& Quaternion<T>::MakeRotationBetween(const Vector3<T>& from, const Vector3<T>& to)
|
||||
{
|
||||
T dot = from.DotProduct(to);
|
||||
if (NumberEquals(dot, F(-1.0)))
|
||||
{
|
||||
Vector3<T> cross = Vector3<T>::CrossProduct(Vector3<T>::UnitX(), from);
|
||||
if (NumberEquals(cross.GetLength(), F(0.0)))
|
||||
cross = Vector3<T>::CrossProduct(Vector3<T>::UnitY(), from);
|
||||
|
||||
return Set(F(180.0), cross);
|
||||
}
|
||||
else if (NumberEquals(dot, F(1.0)))
|
||||
return MakeIdentity();
|
||||
else
|
||||
{
|
||||
Vector3<T> a = from.CrossProduct(to);
|
||||
x = a.x;
|
||||
y = a.y;
|
||||
z = a.z;
|
||||
w = T(1.0) + dot;
|
||||
|
||||
return Normalize();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T>& Quaternion<T>::MakeZero()
|
||||
{
|
||||
return Set(F(0.0), F(0.0), F(0.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T Quaternion<T>::Magnitude() const
|
||||
{
|
||||
return std::sqrt(SquaredMagnitude());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T>& Quaternion<T>::Normalize(T* length)
|
||||
{
|
||||
T norm = std::sqrt(SquaredMagnitude());
|
||||
T invNorm = F(1.0) / norm;
|
||||
|
||||
w *= invNorm;
|
||||
x *= -invNorm;
|
||||
y *= -invNorm;
|
||||
z *= -invNorm;
|
||||
x *= invNorm;
|
||||
y *= invNorm;
|
||||
z *= invNorm;
|
||||
|
||||
if (length)
|
||||
*length = norm;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>& NzQuaternion<T>::MakeIdentity()
|
||||
{
|
||||
return Set(F(1.0), F(0.0), F(0.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>& NzQuaternion<T>::MakeRotationBetween(const NzVector3<T>& from, const NzVector3<T>& to)
|
||||
{
|
||||
T dot = from.DotProduct(to);
|
||||
if (NzNumberEquals(dot, F(-1.0)))
|
||||
template<typename T>
|
||||
Quaternion<T>& Quaternion<T>::Set(T W, T X, T Y, T Z)
|
||||
{
|
||||
NzVector3<T> cross = NzVector3<T>::CrossProduct(NzVector3<T>::UnitX(), from);
|
||||
if (NzNumberEquals(cross.GetLength(), F(0.0)))
|
||||
cross = NzVector3<T>::CrossProduct(NzVector3<T>::UnitY(), from);
|
||||
w = W;
|
||||
x = X;
|
||||
y = Y;
|
||||
z = Z;
|
||||
|
||||
return Set(F(180.0), cross);
|
||||
return *this;
|
||||
}
|
||||
else if (NzNumberEquals(dot, F(1.0)))
|
||||
return MakeIdentity();
|
||||
else
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T>& Quaternion<T>::Set(const T quat[4])
|
||||
{
|
||||
NzVector3<T> a = from.CrossProduct(to);
|
||||
x = a.x;
|
||||
y = a.y;
|
||||
z = a.z;
|
||||
w = T(1.0) + dot;
|
||||
w = quat[0];
|
||||
x = quat[1];
|
||||
y = quat[2];
|
||||
z = quat[3];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T>& Quaternion<T>::Set(T angle, const Vector3<T>& axis)
|
||||
{
|
||||
#if !NAZARA_MATH_ANGLE_RADIAN
|
||||
angle = DegreeToRadian(angle);
|
||||
#endif
|
||||
|
||||
angle /= F(2.0);
|
||||
|
||||
Vector3<T> normalizedAxis = axis.GetNormal();
|
||||
|
||||
T sinAngle = std::sin(angle);
|
||||
|
||||
w = std::cos(angle);
|
||||
x = normalizedAxis.x * sinAngle;
|
||||
y = normalizedAxis.y * sinAngle;
|
||||
z = normalizedAxis.z * sinAngle;
|
||||
|
||||
return Normalize();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>& NzQuaternion<T>::MakeZero()
|
||||
{
|
||||
return Set(F(0.0), F(0.0), F(0.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzQuaternion<T>::Magnitude() const
|
||||
{
|
||||
return std::sqrt(SquaredMagnitude());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>& NzQuaternion<T>::Normalize(T* length)
|
||||
{
|
||||
T norm = std::sqrt(SquaredMagnitude());
|
||||
T invNorm = F(1.0) / norm;
|
||||
|
||||
w *= invNorm;
|
||||
x *= invNorm;
|
||||
y *= invNorm;
|
||||
z *= invNorm;
|
||||
|
||||
if (length)
|
||||
*length = norm;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>& NzQuaternion<T>::Set(T W, T X, T Y, T Z)
|
||||
{
|
||||
w = W;
|
||||
x = X;
|
||||
y = Y;
|
||||
z = Z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>& NzQuaternion<T>::Set(const T quat[4])
|
||||
{
|
||||
w = quat[0];
|
||||
x = quat[1];
|
||||
y = quat[2];
|
||||
z = quat[3];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>& NzQuaternion<T>::Set(T angle, const NzVector3<T>& axis)
|
||||
{
|
||||
#if !NAZARA_MATH_ANGLE_RADIAN
|
||||
angle = NzDegreeToRadian(angle);
|
||||
#endif
|
||||
|
||||
angle /= F(2.0);
|
||||
|
||||
NzVector3<T> normalizedAxis = axis.GetNormal();
|
||||
|
||||
T sinAngle = std::sin(angle);
|
||||
|
||||
w = std::cos(angle);
|
||||
x = normalizedAxis.x * sinAngle;
|
||||
y = normalizedAxis.y * sinAngle;
|
||||
z = normalizedAxis.z * sinAngle;
|
||||
|
||||
return Normalize();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>& NzQuaternion<T>::Set(const NzEulerAngles<T>& angles)
|
||||
{
|
||||
return Set(angles.ToQuaternion());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzQuaternion<T>& NzQuaternion<T>::Set(const NzQuaternion<U>& quat)
|
||||
{
|
||||
w = F(quat.w);
|
||||
x = F(quat.x);
|
||||
y = F(quat.y);
|
||||
z = F(quat.z);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>& NzQuaternion<T>::Set(const NzQuaternion& quat)
|
||||
{
|
||||
std::memcpy(this, &quat, sizeof(NzQuaternion));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzQuaternion<T>::SquaredMagnitude() const
|
||||
{
|
||||
return w*w + x*x + y*y + z*z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzEulerAngles<T> NzQuaternion<T>::ToEulerAngles() const
|
||||
{
|
||||
T test = x*y + z*w;
|
||||
if (test > F(0.499))
|
||||
// singularity at north pole
|
||||
return NzEulerAngles<T>(NzFromDegrees(F(90.0)), NzFromRadians(F(2.0) * std::atan2(x, w)), F(0.0));
|
||||
|
||||
if (test < F(-0.499))
|
||||
return NzEulerAngles<T>(NzFromDegrees(F(-90.0)), NzFromRadians(F(-2.0) * std::atan2(x, w)), F(0.0));
|
||||
|
||||
return NzEulerAngles<T>(NzFromRadians(std::atan2(F(2.0)*x*w - F(2.0)*y*z, F(1.0) - F(2.0)*x*x - F(2.0)*z*z)),
|
||||
NzFromRadians(std::atan2(F(2.0)*y*w - F(2.0)*x*z, F(1.0) - F(2.0)*y*y - F(2.0)*z*z)),
|
||||
NzFromRadians(std::asin(F(2.0)*test)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzString NzQuaternion<T>::ToString() const
|
||||
{
|
||||
NzStringStream ss;
|
||||
|
||||
return ss << "Quaternion(" << w << " | " << x << ", " << y << ", " << z << ')';
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>& NzQuaternion<T>::operator=(const NzQuaternion& quat)
|
||||
{
|
||||
return Set(quat);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T> NzQuaternion<T>::operator+(const NzQuaternion& quat) const
|
||||
{
|
||||
NzQuaternion result;
|
||||
result.w = w + quat.w;
|
||||
result.x = x + quat.x;
|
||||
result.y = y + quat.y;
|
||||
result.z = z + quat.z;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T> NzQuaternion<T>::operator*(const NzQuaternion& quat) const
|
||||
{
|
||||
NzQuaternion result;
|
||||
result.w = w*quat.w - x*quat.x - y*quat.y - z*quat.z;
|
||||
result.x = w*quat.x + x*quat.w + y*quat.z - z*quat.y;
|
||||
result.y = w*quat.y + y*quat.w + z*quat.x - x*quat.z;
|
||||
result.z = w*quat.z + z*quat.w + x*quat.y - y*quat.x;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector3<T> NzQuaternion<T>::operator*(const NzVector3<T>& vec) const
|
||||
{
|
||||
NzVector3f quatVec(x, y, z);
|
||||
NzVector3f uv = quatVec.CrossProduct(vec);
|
||||
NzVector3f uuv = quatVec.CrossProduct(uv);
|
||||
uv *= F(2.0) * w;
|
||||
uuv *= F(2.0);
|
||||
|
||||
return vec + uv + uuv;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T> NzQuaternion<T>::operator*(T scale) const
|
||||
{
|
||||
return NzQuaternion(w * scale,
|
||||
x * scale,
|
||||
y * scale,
|
||||
z * scale);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T> NzQuaternion<T>::operator/(const NzQuaternion& quat) const
|
||||
{
|
||||
return quat.GetConjugate() * (*this);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>& NzQuaternion<T>::operator+=(const NzQuaternion& quat)
|
||||
{
|
||||
return operator=(operator+(quat));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>& NzQuaternion<T>::operator*=(const NzQuaternion& quat)
|
||||
{
|
||||
return operator=(operator*(quat));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>& NzQuaternion<T>::operator*=(T scale)
|
||||
{
|
||||
return operator=(operator*(scale));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T>& NzQuaternion<T>::operator/=(const NzQuaternion& quat)
|
||||
{
|
||||
return operator=(operator/(quat));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzQuaternion<T>::operator==(const NzQuaternion& quat) const
|
||||
{
|
||||
return NzNumberEquals(w, quat.w) &&
|
||||
NzNumberEquals(x, quat.x) &&
|
||||
NzNumberEquals(y, quat.y) &&
|
||||
NzNumberEquals(z, quat.z);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzQuaternion<T>::operator!=(const NzQuaternion& quat) const
|
||||
{
|
||||
return !operator==(quat);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T> NzQuaternion<T>::Identity()
|
||||
{
|
||||
NzQuaternion quaternion;
|
||||
quaternion.MakeIdentity();
|
||||
|
||||
return quaternion;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T> NzQuaternion<T>::Lerp(const NzQuaternion& from, const NzQuaternion& to, T interpolation)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (interpolation < F(0.0) || interpolation > F(1.0))
|
||||
template<typename T>
|
||||
Quaternion<T>& Quaternion<T>::Set(const EulerAngles<T>& angles)
|
||||
{
|
||||
NazaraError("Interpolation must be in range [0..1] (Got " + NzString::Number(interpolation) + ')');
|
||||
return Zero();
|
||||
}
|
||||
#endif
|
||||
|
||||
NzQuaternion interpolated;
|
||||
interpolated.w = NzLerp(from.w, to.w, interpolation);
|
||||
interpolated.x = NzLerp(from.x, to.x, interpolation);
|
||||
interpolated.y = NzLerp(from.y, to.y, interpolation);
|
||||
interpolated.z = NzLerp(from.z, to.z, interpolation);
|
||||
|
||||
return interpolated;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T> NzQuaternion<T>::Normalize(const NzQuaternion& quat, T* length)
|
||||
{
|
||||
return quat.GetNormal(length);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T> NzQuaternion<T>::RotationBetween(const NzVector3<T>& from, const NzVector3<T>& to)
|
||||
{
|
||||
NzQuaternion quaternion;
|
||||
quaternion.MakeRotationBetween(from, to);
|
||||
|
||||
return quaternion;
|
||||
}
|
||||
|
||||
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 = from.DotProduct(to);
|
||||
if (cosOmega < F(0.0))
|
||||
{
|
||||
// On inverse tout
|
||||
q.Set(-to.w, -to.x, -to.y, -to.z);
|
||||
cosOmega = -cosOmega;
|
||||
}
|
||||
else
|
||||
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) - interpolation;
|
||||
k1 = interpolation;
|
||||
}
|
||||
else
|
||||
{
|
||||
T sinOmega = std::sqrt(F(1.0) - cosOmega*cosOmega);
|
||||
T omega = std::atan2(sinOmega, cosOmega);
|
||||
|
||||
// Pour éviter deux divisions
|
||||
sinOmega = F(1.0)/sinOmega;
|
||||
|
||||
k0 = std::sin((F(1.0) - interpolation) * omega) * sinOmega;
|
||||
k1 = std::sin(interpolation*omega) * sinOmega;
|
||||
return Set(angles.ToQuaternion());
|
||||
}
|
||||
|
||||
NzQuaternion result(k0 * from.w, k0 * from.x, k0 * from.y, k0 * from.z);
|
||||
return result += q*k1;
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
Quaternion<T>& Quaternion<T>::Set(const Quaternion<U>& quat)
|
||||
{
|
||||
w = F(quat.w);
|
||||
x = F(quat.x);
|
||||
y = F(quat.y);
|
||||
z = F(quat.z);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T>& Quaternion<T>::Set(const Quaternion& quat)
|
||||
{
|
||||
std::memcpy(this, &quat, sizeof(Quaternion));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T Quaternion<T>::SquaredMagnitude() const
|
||||
{
|
||||
return w*w + x*x + y*y + z*z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
EulerAngles<T> Quaternion<T>::ToEulerAngles() const
|
||||
{
|
||||
T test = x*y + z*w;
|
||||
if (test > F(0.499))
|
||||
// singularity at north pole
|
||||
return EulerAngles<T>(FromDegrees(F(90.0)), FromRadians(F(2.0) * std::atan2(x, w)), F(0.0));
|
||||
|
||||
if (test < F(-0.499))
|
||||
return EulerAngles<T>(FromDegrees(F(-90.0)), FromRadians(F(-2.0) * std::atan2(x, w)), F(0.0));
|
||||
|
||||
return EulerAngles<T>(FromRadians(std::atan2(F(2.0)*x*w - F(2.0)*y*z, F(1.0) - F(2.0)*x*x - F(2.0)*z*z)),
|
||||
FromRadians(std::atan2(F(2.0)*y*w - F(2.0)*x*z, F(1.0) - F(2.0)*y*y - F(2.0)*z*z)),
|
||||
FromRadians(std::asin(F(2.0)*test)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
String Quaternion<T>::ToString() const
|
||||
{
|
||||
StringStream ss;
|
||||
|
||||
return ss << "Quaternion(" << w << " | " << x << ", " << y << ", " << z << ')';
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T>& Quaternion<T>::operator=(const Quaternion& quat)
|
||||
{
|
||||
return Set(quat);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T> Quaternion<T>::operator+(const Quaternion& quat) const
|
||||
{
|
||||
Quaternion result;
|
||||
result.w = w + quat.w;
|
||||
result.x = x + quat.x;
|
||||
result.y = y + quat.y;
|
||||
result.z = z + quat.z;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T> Quaternion<T>::operator*(const Quaternion& quat) const
|
||||
{
|
||||
Quaternion result;
|
||||
result.w = w*quat.w - x*quat.x - y*quat.y - z*quat.z;
|
||||
result.x = w*quat.x + x*quat.w + y*quat.z - z*quat.y;
|
||||
result.y = w*quat.y + y*quat.w + z*quat.x - x*quat.z;
|
||||
result.z = w*quat.z + z*quat.w + x*quat.y - y*quat.x;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector3<T> Quaternion<T>::operator*(const Vector3<T>& vec) const
|
||||
{
|
||||
Vector3f quatVec(x, y, z);
|
||||
Vector3f uv = quatVec.CrossProduct(vec);
|
||||
Vector3f uuv = quatVec.CrossProduct(uv);
|
||||
uv *= F(2.0) * w;
|
||||
uuv *= F(2.0);
|
||||
|
||||
return vec + uv + uuv;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T> Quaternion<T>::operator*(T scale) const
|
||||
{
|
||||
return Quaternion(w * scale,
|
||||
x * scale,
|
||||
y * scale,
|
||||
z * scale);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T> Quaternion<T>::operator/(const Quaternion& quat) const
|
||||
{
|
||||
return quat.GetConjugate() * (*this);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T>& Quaternion<T>::operator+=(const Quaternion& quat)
|
||||
{
|
||||
return operator=(operator+(quat));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T>& Quaternion<T>::operator*=(const Quaternion& quat)
|
||||
{
|
||||
return operator=(operator*(quat));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T>& Quaternion<T>::operator*=(T scale)
|
||||
{
|
||||
return operator=(operator*(scale));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T>& Quaternion<T>::operator/=(const Quaternion& quat)
|
||||
{
|
||||
return operator=(operator/(quat));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Quaternion<T>::operator==(const Quaternion& quat) const
|
||||
{
|
||||
return NumberEquals(w, quat.w) &&
|
||||
NumberEquals(x, quat.x) &&
|
||||
NumberEquals(y, quat.y) &&
|
||||
NumberEquals(z, quat.z);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Quaternion<T>::operator!=(const Quaternion& quat) const
|
||||
{
|
||||
return !operator==(quat);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T> Quaternion<T>::Identity()
|
||||
{
|
||||
Quaternion quaternion;
|
||||
quaternion.MakeIdentity();
|
||||
|
||||
return quaternion;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T> Quaternion<T>::Lerp(const Quaternion& from, const Quaternion& to, T interpolation)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (interpolation < F(0.0) || interpolation > F(1.0))
|
||||
{
|
||||
NazaraError("Interpolation must be in range [0..1] (Got " + String::Number(interpolation) + ')');
|
||||
return Zero();
|
||||
}
|
||||
#endif
|
||||
|
||||
Quaternion interpolated;
|
||||
interpolated.w = Lerp(from.w, to.w, interpolation);
|
||||
interpolated.x = Lerp(from.x, to.x, interpolation);
|
||||
interpolated.y = Lerp(from.y, to.y, interpolation);
|
||||
interpolated.z = Lerp(from.z, to.z, interpolation);
|
||||
|
||||
return interpolated;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T> Quaternion<T>::Normalize(const Quaternion& quat, T* length)
|
||||
{
|
||||
return quat.GetNormal(length);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T> Quaternion<T>::RotationBetween(const Vector3<T>& from, const Vector3<T>& to)
|
||||
{
|
||||
Quaternion quaternion;
|
||||
quaternion.MakeRotationBetween(from, to);
|
||||
|
||||
return quaternion;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T> Quaternion<T>::Slerp(const Quaternion& from, const Quaternion& to, T interpolation)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (interpolation < F(0.0) || interpolation > F(1.0))
|
||||
{
|
||||
NazaraError("Interpolation must be in range [0..1] (Got " + String::Number(interpolation) + ')');
|
||||
return Zero();
|
||||
}
|
||||
#endif
|
||||
|
||||
Quaternion q;
|
||||
|
||||
T cosOmega = from.DotProduct(to);
|
||||
if (cosOmega < F(0.0))
|
||||
{
|
||||
// On inverse tout
|
||||
q.Set(-to.w, -to.x, -to.y, -to.z);
|
||||
cosOmega = -cosOmega;
|
||||
}
|
||||
else
|
||||
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) - interpolation;
|
||||
k1 = interpolation;
|
||||
}
|
||||
else
|
||||
{
|
||||
T sinOmega = std::sqrt(F(1.0) - cosOmega*cosOmega);
|
||||
T omega = std::atan2(sinOmega, cosOmega);
|
||||
|
||||
// Pour éviter deux divisions
|
||||
sinOmega = F(1.0)/sinOmega;
|
||||
|
||||
k0 = std::sin((F(1.0) - interpolation) * omega) * sinOmega;
|
||||
k1 = std::sin(interpolation*omega) * sinOmega;
|
||||
}
|
||||
|
||||
Quaternion result(k0 * from.w, k0 * from.x, k0 * from.y, k0 * from.z);
|
||||
return result += q*k1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quaternion<T> Quaternion<T>::Zero()
|
||||
{
|
||||
Quaternion quaternion;
|
||||
quaternion.MakeZero();
|
||||
|
||||
return quaternion;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T> NzQuaternion<T>::Zero()
|
||||
{
|
||||
NzQuaternion quaternion;
|
||||
quaternion.MakeZero();
|
||||
|
||||
return quaternion;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzQuaternion<T>& quat)
|
||||
std::ostream& operator<<(std::ostream& out, const Nz::Quaternion<T>& quat)
|
||||
{
|
||||
return out << quat.ToString();
|
||||
}
|
||||
|
||||
@@ -16,62 +16,65 @@
|
||||
#include <Nazara/Math/Sphere.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
|
||||
template<typename T>
|
||||
class NzRay
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzRay() = default;
|
||||
NzRay(T X, T Y, T Z, T directionX, T directionY, T directionZ);
|
||||
NzRay(const T origin[3], const T direction[3]);
|
||||
NzRay(const NzPlane<T>& planeOne, const NzPlane<T>& planeTwo);
|
||||
NzRay(const NzVector3<T>& origin, const NzVector3<T>& direction);
|
||||
template<typename U> explicit NzRay(const NzRay<U>& ray);
|
||||
template<typename U> explicit NzRay(const NzVector3<U>& origin, const NzVector3<U>& direction);
|
||||
NzRay(const NzRay<T>& ray) = default;
|
||||
~NzRay() = default;
|
||||
template<typename T>
|
||||
class Ray
|
||||
{
|
||||
public:
|
||||
Ray() = default;
|
||||
Ray(T X, T Y, T Z, T directionX, T directionY, T directionZ);
|
||||
Ray(const T origin[3], const T direction[3]);
|
||||
Ray(const Plane<T>& planeOne, const Plane<T>& planeTwo);
|
||||
Ray(const Vector3<T>& origin, const Vector3<T>& direction);
|
||||
template<typename U> explicit Ray(const Ray<U>& ray);
|
||||
template<typename U> explicit Ray(const Vector3<U>& origin, const Vector3<U>& direction);
|
||||
Ray(const Ray<T>& ray) = default;
|
||||
~Ray() = default;
|
||||
|
||||
T ClosestPoint(const NzVector3<T>& point) const;
|
||||
T ClosestPoint(const Vector3<T>& point) const;
|
||||
|
||||
NzVector3<T> GetPoint(T lambda) const;
|
||||
Vector3<T> GetPoint(T lambda) const;
|
||||
|
||||
bool Intersect(const NzBoundingVolume<T>& volume, T* closestHit = nullptr, T* furthestHit = nullptr) const;
|
||||
bool Intersect(const NzBox<T>& box, T* closestHit = nullptr, T* furthestHit = nullptr) const;
|
||||
bool Intersect(const NzBox<T>& box, const NzMatrix4<T>& transform, T* closestHit = nullptr, T* furthestHit = nullptr) const;
|
||||
bool Intersect(const NzOrientedBox<T>& orientedBox, T* closestHit = nullptr, T* furthestHit = nullptr) const;
|
||||
bool Intersect(const NzPlane<T>& plane, T* hit = nullptr) const;
|
||||
bool Intersect(const NzSphere<T>& sphere, T* closestHit = nullptr, T* furthestHit = nullptr) const;
|
||||
bool Intersect(const BoundingVolume<T>& volume, T* closestHit = nullptr, T* furthestHit = nullptr) const;
|
||||
bool Intersect(const Box<T>& box, T* closestHit = nullptr, T* furthestHit = nullptr) const;
|
||||
bool Intersect(const Box<T>& box, const Matrix4<T>& transform, T* closestHit = nullptr, T* furthestHit = nullptr) const;
|
||||
bool Intersect(const OrientedBox<T>& orientedBox, T* closestHit = nullptr, T* furthestHit = nullptr) const;
|
||||
bool Intersect(const Plane<T>& plane, T* hit = nullptr) const;
|
||||
bool Intersect(const Sphere<T>& sphere, T* closestHit = nullptr, T* furthestHit = nullptr) const;
|
||||
|
||||
NzRay& MakeAxisX();
|
||||
NzRay& MakeAxisY();
|
||||
NzRay& MakeAxisZ();
|
||||
Ray& MakeAxisX();
|
||||
Ray& MakeAxisY();
|
||||
Ray& MakeAxisZ();
|
||||
|
||||
NzRay& Set(T X, T Y, T Z, T directionX, T directionY, T directionZ);
|
||||
NzRay& Set(const T origin[3], const T direction[3]);
|
||||
NzRay& Set(const NzPlane<T>& planeOne, const NzPlane<T>& planeTwo);
|
||||
NzRay& Set(const NzRay& ray);
|
||||
NzRay& Set(const NzVector3<T>& origin, const NzVector3<T>& direction);
|
||||
template<typename U> NzRay& Set(const NzRay<U>& ray);
|
||||
template<typename U> NzRay& Set(const NzVector3<U>& origin, const NzVector3<U>& direction);
|
||||
Ray& Set(T X, T Y, T Z, T directionX, T directionY, T directionZ);
|
||||
Ray& Set(const T origin[3], const T direction[3]);
|
||||
Ray& Set(const Plane<T>& planeOne, const Plane<T>& planeTwo);
|
||||
Ray& Set(const Ray& ray);
|
||||
Ray& Set(const Vector3<T>& origin, const Vector3<T>& direction);
|
||||
template<typename U> Ray& Set(const Ray<U>& ray);
|
||||
template<typename U> Ray& Set(const Vector3<U>& origin, const Vector3<U>& direction);
|
||||
|
||||
NzString ToString() const;
|
||||
String ToString() const;
|
||||
|
||||
NzVector3<T> operator*(T lambda) const;
|
||||
Vector3<T> operator*(T lambda) const;
|
||||
|
||||
bool operator==(const NzRay& ray) const;
|
||||
bool operator!=(const NzRay& ray) const;
|
||||
bool operator==(const Ray& ray) const;
|
||||
bool operator!=(const Ray& ray) const;
|
||||
|
||||
static NzRay AxisX();
|
||||
static NzRay AxisY();
|
||||
static NzRay AxisZ();
|
||||
static NzRay Lerp(const NzRay& from, const NzRay& to, T interpolation);
|
||||
static Ray AxisX();
|
||||
static Ray AxisY();
|
||||
static Ray AxisZ();
|
||||
static Ray Lerp(const Ray& from, const Ray& to, T interpolation);
|
||||
|
||||
NzVector3<T> direction, origin;
|
||||
};
|
||||
Vector3<T> direction, origin;
|
||||
};
|
||||
|
||||
template<typename T> std::ostream& operator<<(std::ostream& out, const NzRay<T>& vec);
|
||||
typedef Ray<double> Rayd;
|
||||
typedef Ray<float> Rayf;
|
||||
}
|
||||
|
||||
typedef NzRay<double> NzRayd;
|
||||
typedef NzRay<float> NzRayf;
|
||||
template<typename T> std::ostream& operator<<(std::ostream& out, const Nz::Ray<T>& vec);
|
||||
|
||||
#include <Nazara/Math/Ray.inl>
|
||||
|
||||
|
||||
@@ -8,432 +8,435 @@
|
||||
|
||||
#define F(a) static_cast<T>(a)
|
||||
|
||||
template<typename T>
|
||||
NzRay<T>::NzRay(T X, T Y, T Z, T DirectionX, T DirectionY, T DirectionZ)
|
||||
namespace Nz
|
||||
{
|
||||
Set(X, Y, Z, DirectionX, DirectionY, DirectionZ);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRay<T>::NzRay(const T Origin[3], const T Direction[3])
|
||||
{
|
||||
Set(Origin, Direction);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRay<T>::NzRay(const NzPlane<T>& planeOne, const NzPlane<T>& planeTwo)
|
||||
{
|
||||
Set(planeOne, planeTwo);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRay<T>::NzRay(const NzVector3<T>& Origin, const NzVector3<T>& Direction)
|
||||
{
|
||||
Set(Origin, Direction);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzRay<T>::NzRay(const NzRay<U>& ray)
|
||||
{
|
||||
Set(ray);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzRay<T>::NzRay(const NzVector3<U>& Origin, const NzVector3<U>& Direction)
|
||||
{
|
||||
Set(Origin, Direction);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzRay<T>::ClosestPoint(const NzVector3<T>& point) const
|
||||
{
|
||||
NzVector3<T> delta = point - origin;
|
||||
T vsq = direction.GetSquaredLength();
|
||||
T proj = delta.DotProduct(direction);
|
||||
|
||||
return proj/vsq;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector3<T> NzRay<T>::GetPoint(T lambda) const
|
||||
{
|
||||
return origin + lambda * direction;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzRay<T>::Intersect(const NzBoundingVolume<T>& volume, T* closestHit, T* furthestHit) const
|
||||
{
|
||||
switch (volume.extend)
|
||||
template<typename T>
|
||||
Ray<T>::Ray(T X, T Y, T Z, T DirectionX, T DirectionY, T DirectionZ)
|
||||
{
|
||||
case nzExtend_Finite:
|
||||
{
|
||||
if (Intersect(volume.aabb))
|
||||
return Intersect(volume.obb, closestHit, furthestHit);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
case nzExtend_Infinite:
|
||||
{
|
||||
if (closestHit)
|
||||
*closestHit = F(0.0);
|
||||
|
||||
if (furthestHit)
|
||||
*furthestHit = std::numeric_limits<T>::infinity();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case nzExtend_Null:
|
||||
return false;
|
||||
Set(X, Y, Z, DirectionX, DirectionY, DirectionZ);
|
||||
}
|
||||
|
||||
NazaraError("Invalid extend type (0x" + NzString::Number(volume.extend, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzRay<T>::Intersect(const NzBox<T>& box, T* closestHit, T* furthestHit) const
|
||||
{
|
||||
// http://www.gamedev.net/topic/429443-obb-ray-and-obb-plane-intersection/
|
||||
T tfirst = F(0.0);
|
||||
T tlast = std::numeric_limits<T>::infinity();
|
||||
|
||||
NzVector3<T> boxMin = box.GetMinimum();
|
||||
NzVector3<T> boxMax = box.GetMaximum();
|
||||
|
||||
for (unsigned int i = 0; i < 3; ++i)
|
||||
template<typename T>
|
||||
Ray<T>::Ray(const T Origin[3], const T Direction[3])
|
||||
{
|
||||
T dir = direction[i];
|
||||
T ori = origin[i];
|
||||
T max = boxMax[i];
|
||||
T min = boxMin[i];
|
||||
|
||||
if (NzNumberEquals(dir, F(0.0)))
|
||||
{
|
||||
if (ori < max && ori > min)
|
||||
continue;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
T tmin = (min - ori) / dir;
|
||||
T tmax = (max - ori) / dir;
|
||||
if (tmin > tmax)
|
||||
std::swap(tmin, tmax);
|
||||
|
||||
if (tmax < tfirst || tmin > tlast)
|
||||
return false;
|
||||
|
||||
tfirst = std::max(tfirst, tmin);
|
||||
tlast = std::min(tlast, tmax);
|
||||
Set(Origin, Direction);
|
||||
}
|
||||
|
||||
if (closestHit)
|
||||
*closestHit = tfirst;
|
||||
|
||||
if (furthestHit)
|
||||
*furthestHit = tlast;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzRay<T>::Intersect(const NzBox<T>& box, const NzMatrix4<T>& transform, T* closestHit, T* furthestHit) const
|
||||
{
|
||||
// http://www.opengl-tutorial.org/miscellaneous/clicking-on-objects/picking-with-custom-ray-obb-function/
|
||||
// Intersection method from Real-Time Rendering and Essential Mathematics for Games
|
||||
T tMin = F(0.0);
|
||||
T tMax = std::numeric_limits<T>::infinity();
|
||||
|
||||
NzVector3<T> boxMin = box.GetMinimum();
|
||||
NzVector3<T> boxMax = box.GetMaximum();
|
||||
NzVector3<T> delta = transform.GetTranslation() - origin;
|
||||
|
||||
// Test intersection with the 2 planes perpendicular to the OBB's X axis
|
||||
for (unsigned int i = 0; i < 3; ++i)
|
||||
template<typename T>
|
||||
Ray<T>::Ray(const Plane<T>& planeOne, const Plane<T>& planeTwo)
|
||||
{
|
||||
NzVector3<T> axis(transform(0, i), transform(1, i), transform(2, i));
|
||||
T e = axis.DotProduct(delta);
|
||||
T f = direction.DotProduct(axis);
|
||||
Set(planeOne, planeTwo);
|
||||
}
|
||||
|
||||
if (!NzNumberEquals(f, F(0.0)))
|
||||
template<typename T>
|
||||
Ray<T>::Ray(const Vector3<T>& Origin, const Vector3<T>& Direction)
|
||||
{
|
||||
Set(Origin, Direction);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
Ray<T>::Ray(const Ray<U>& ray)
|
||||
{
|
||||
Set(ray);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
Ray<T>::Ray(const Vector3<U>& Origin, const Vector3<U>& Direction)
|
||||
{
|
||||
Set(Origin, Direction);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T Ray<T>::ClosestPoint(const Vector3<T>& point) const
|
||||
{
|
||||
Vector3<T> delta = point - origin;
|
||||
T vsq = direction.GetSquaredLength();
|
||||
T proj = delta.DotProduct(direction);
|
||||
|
||||
return proj/vsq;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector3<T> Ray<T>::GetPoint(T lambda) const
|
||||
{
|
||||
return origin + lambda * direction;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Ray<T>::Intersect(const BoundingVolume<T>& volume, T* closestHit, T* furthestHit) const
|
||||
{
|
||||
switch (volume.extend)
|
||||
{
|
||||
T t1 = (e + boxMin[i]) / f; // Intersection with the "left" plane
|
||||
T t2 = (e + boxMax[i]) / f; // Intersection with the "right" plane
|
||||
// t1 and t2 now contain distances betwen ray origin and ray-plane intersections
|
||||
case Extend_Finite:
|
||||
{
|
||||
if (Intersect(volume.aabb))
|
||||
return Intersect(volume.obb, closestHit, furthestHit);
|
||||
|
||||
// We want t1 to represent the nearest intersection,
|
||||
// so if it's not the case, invert t1 and t2
|
||||
if (t1 > t2)
|
||||
std::swap(t1, t2);
|
||||
return false;
|
||||
}
|
||||
|
||||
// tMax is the nearest "far" intersection (amongst the X,Y and Z planes pairs)
|
||||
if (t2 < tMax)
|
||||
tMax = t2;
|
||||
case Extend_Infinite:
|
||||
{
|
||||
if (closestHit)
|
||||
*closestHit = F(0.0);
|
||||
|
||||
// tMin is the farthest "near" intersection (amongst the X,Y and Z planes pairs)
|
||||
if (t1 > tMin)
|
||||
tMin = t1;
|
||||
if (furthestHit)
|
||||
*furthestHit = std::numeric_limits<T>::infinity();
|
||||
|
||||
// And here's the trick :
|
||||
// If "far" is closer than "near", then there is NO intersection.
|
||||
if (tMax < tMin)
|
||||
return true;
|
||||
}
|
||||
|
||||
case Extend_Null:
|
||||
return false;
|
||||
}
|
||||
else
|
||||
// Rare case : the ray is almost parallel to the planes, so they don't have any "intersection"
|
||||
if (-e + boxMin[i] > F(0.0) || -e + boxMax[i] < F(0.0))
|
||||
return false;
|
||||
|
||||
NazaraError("Invalid extend type (0x" + String::Number(volume.extend, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (closestHit)
|
||||
*closestHit = tMin;
|
||||
|
||||
if (furthestHit)
|
||||
*furthestHit = tMax;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzRay<T>::Intersect(const NzOrientedBox<T>& orientedBox, T* closestHit, T* furthestHit) const
|
||||
{
|
||||
NzVector3<T> corner = orientedBox.GetCorner(nzBoxCorner_FarLeftBottom);
|
||||
NzVector3<T> oppositeCorner = orientedBox.GetCorner(nzBoxCorner_NearRightTop);
|
||||
|
||||
NzVector3<T> width = (orientedBox.GetCorner(nzBoxCorner_NearLeftBottom) - corner);
|
||||
NzVector3<T> height = (orientedBox.GetCorner(nzBoxCorner_FarLeftTop) - corner);
|
||||
NzVector3<T> depth = (orientedBox.GetCorner(nzBoxCorner_FarRightBottom) - corner);
|
||||
|
||||
// Construction de la matrice de transformation de l'OBB
|
||||
NzMatrix4<T> matrix(width.x, height.x, depth.x, corner.x,
|
||||
width.y, height.y, depth.y, corner.y,
|
||||
width.z, height.z, depth.z, corner.z,
|
||||
F(0.0), F(0.0), F(0.0), F(1.0));
|
||||
|
||||
matrix.InverseAffine();
|
||||
|
||||
corner = matrix.Transform(corner);
|
||||
oppositeCorner = matrix.Transform(oppositeCorner);
|
||||
|
||||
NzBox<T> tmpBox(corner, oppositeCorner);
|
||||
NzRay<T> tmpRay(matrix.Transform(origin), matrix.Transform(direction));
|
||||
|
||||
return tmpRay.Intersect(tmpBox, closestHit, furthestHit);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzRay<T>::Intersect(const NzPlane<T>& plane, T* hit) const
|
||||
{
|
||||
T divisor = plane.normal.DotProduct(direction);
|
||||
if (NzNumberEquals(divisor, F(0.0)))
|
||||
return false; // perpendicular
|
||||
|
||||
T lambda = -(plane.normal.DotProduct(origin) - plane.distance) / divisor; // The plane is ax + by + cz = d
|
||||
if (lambda < F(0.0))
|
||||
return false; // The plane is 'behind' the ray.
|
||||
|
||||
if (hit)
|
||||
*hit = lambda;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzRay<T>::Intersect(const NzSphere<T>& sphere, T* closestHit, T* furthestHit) const
|
||||
{
|
||||
NzVector3<T> sphereRay = sphere.GetPosition() - origin;
|
||||
T length = sphereRay.DotProduct(direction);
|
||||
|
||||
if (length < F(0.0))
|
||||
return false; // ray is perpendicular to the vector origin - center
|
||||
|
||||
T squaredDistance = sphereRay.GetSquaredLength() - length*length;
|
||||
T squaredRadius = sphere.radius*sphere.radius;
|
||||
|
||||
if (squaredDistance > squaredRadius)
|
||||
return false; // if the ray is further than the radius
|
||||
|
||||
// Calcul des points d'intersection si besoin
|
||||
if (closestHit || furthestHit)
|
||||
template<typename T>
|
||||
bool Ray<T>::Intersect(const Box<T>& box, T* closestHit, T* furthestHit) const
|
||||
{
|
||||
T deltaLambda = std::sqrt(squaredRadius - squaredDistance);
|
||||
// http://www.gamedev.net/topic/429443-obb-ray-and-obb-plane-intersection/
|
||||
T tfirst = F(0.0);
|
||||
T tlast = std::numeric_limits<T>::infinity();
|
||||
|
||||
Vector3<T> boxMin = box.GetMinimum();
|
||||
Vector3<T> boxMax = box.GetMaximum();
|
||||
|
||||
for (unsigned int i = 0; i < 3; ++i)
|
||||
{
|
||||
T dir = direction[i];
|
||||
T ori = origin[i];
|
||||
T max = boxMax[i];
|
||||
T min = boxMin[i];
|
||||
|
||||
if (NumberEquals(dir, F(0.0)))
|
||||
{
|
||||
if (ori < max && ori > min)
|
||||
continue;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
T tmin = (min - ori) / dir;
|
||||
T tmax = (max - ori) / dir;
|
||||
if (tmin > tmax)
|
||||
std::swap(tmin, tmax);
|
||||
|
||||
if (tmax < tfirst || tmin > tlast)
|
||||
return false;
|
||||
|
||||
tfirst = std::max(tfirst, tmin);
|
||||
tlast = std::min(tlast, tmax);
|
||||
}
|
||||
|
||||
if (closestHit)
|
||||
*closestHit = length - deltaLambda;
|
||||
*closestHit = tfirst;
|
||||
|
||||
if (furthestHit)
|
||||
*furthestHit = length + deltaLambda;
|
||||
*furthestHit = tlast;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRay<T>& NzRay<T>::MakeAxisX()
|
||||
{
|
||||
return Set(NzVector3<T>::Zero(), NzVector3<T>::UnitX());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRay<T>& NzRay<T>::MakeAxisY()
|
||||
{
|
||||
return Set(NzVector3<T>::Zero(), NzVector3<T>::UnitY());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRay<T>& NzRay<T>::MakeAxisZ()
|
||||
{
|
||||
return Set(NzVector3<T>::Zero(), NzVector3<T>::UnitZ());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRay<T>& NzRay<T>::Set(T X, T Y, T Z, T directionX, T directionY, T directionZ)
|
||||
{
|
||||
direction.Set(directionX, directionY, directionZ);
|
||||
origin.Set(X, Y, Z);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRay<T>& NzRay<T>::Set(const T Origin[3], const T Direction[3])
|
||||
{
|
||||
direction.Set(Direction);
|
||||
origin.Set(Origin);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRay<T>& NzRay<T>::Set(const NzPlane<T>& planeOne, const NzPlane<T>& planeTwo)
|
||||
{
|
||||
T termOne = planeOne.normal.GetLength();
|
||||
T termTwo = planeOne.normal.DotProduct(planeTwo.normal);
|
||||
T termFour = planeTwo.normal.GetLength();
|
||||
T det = termOne * termFour - termTwo * termTwo;
|
||||
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (NzNumberEquals(det, F(0.0)))
|
||||
template<typename T>
|
||||
bool Ray<T>::Intersect(const Box<T>& box, const Matrix4<T>& transform, T* closestHit, T* furthestHit) const
|
||||
{
|
||||
NzString error("Planes are parallel.");
|
||||
// http://www.opengl-tutorial.org/miscellaneous/clicking-on-objects/picking-with-custom-ray-obb-function/
|
||||
// Intersection method from Real-Time Rendering and Essential Mathematics for Games
|
||||
T tMin = F(0.0);
|
||||
T tMax = std::numeric_limits<T>::infinity();
|
||||
|
||||
NazaraError(error);
|
||||
throw std::domain_error(error);
|
||||
Vector3<T> boxMin = box.GetMinimum();
|
||||
Vector3<T> boxMax = box.GetMaximum();
|
||||
Vector3<T> delta = transform.GetTranslation() - origin;
|
||||
|
||||
// Test intersection with the 2 planes perpendicular to the OBB's X axis
|
||||
for (unsigned int i = 0; i < 3; ++i)
|
||||
{
|
||||
Vector3<T> axis(transform(0, i), transform(1, i), transform(2, i));
|
||||
T e = axis.DotProduct(delta);
|
||||
T f = direction.DotProduct(axis);
|
||||
|
||||
if (!NumberEquals(f, F(0.0)))
|
||||
{
|
||||
T t1 = (e + boxMin[i]) / f; // Intersection with the "left" plane
|
||||
T t2 = (e + boxMax[i]) / f; // Intersection with the "right" plane
|
||||
// t1 and t2 now contain distances betwen ray origin and ray-plane intersections
|
||||
|
||||
// We want t1 to represent the nearest intersection,
|
||||
// so if it's not the case, invert t1 and t2
|
||||
if (t1 > t2)
|
||||
std::swap(t1, t2);
|
||||
|
||||
// tMax is the nearest "far" intersection (amongst the X,Y and Z planes pairs)
|
||||
if (t2 < tMax)
|
||||
tMax = t2;
|
||||
|
||||
// tMin is the farthest "near" intersection (amongst the X,Y and Z planes pairs)
|
||||
if (t1 > tMin)
|
||||
tMin = t1;
|
||||
|
||||
// And here's the trick :
|
||||
// If "far" is closer than "near", then there is NO intersection.
|
||||
if (tMax < tMin)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
// Rare case : the ray is almost parallel to the planes, so they don't have any "intersection"
|
||||
if (-e + boxMin[i] > F(0.0) || -e + boxMax[i] < F(0.0))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (closestHit)
|
||||
*closestHit = tMin;
|
||||
|
||||
if (furthestHit)
|
||||
*furthestHit = tMax;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
T invdet = F(1.0) / det;
|
||||
T fc0 = (termFour * -planeOne.distance + termTwo * planeTwo.distance) * invdet;
|
||||
T fc1 = (termOne * -planeTwo.distance + termTwo * planeOne.distance) * invdet;
|
||||
template<typename T>
|
||||
bool Ray<T>::Intersect(const OrientedBox<T>& orientedBox, T* closestHit, T* furthestHit) const
|
||||
{
|
||||
Vector3<T> corner = orientedBox.GetCorner(BoxCorner_FarLeftBottom);
|
||||
Vector3<T> oppositeCorner = orientedBox.GetCorner(BoxCorner_NearRightTop);
|
||||
|
||||
direction = planeOne.normal.CrossProduct(planeTwo.normal);
|
||||
origin = planeOne.normal * fc0 + planeTwo.normal * fc1;
|
||||
Vector3<T> width = (orientedBox.GetCorner(BoxCorner_NearLeftBottom) - corner);
|
||||
Vector3<T> height = (orientedBox.GetCorner(BoxCorner_FarLeftTop) - corner);
|
||||
Vector3<T> depth = (orientedBox.GetCorner(BoxCorner_FarRightBottom) - corner);
|
||||
|
||||
return *this;
|
||||
// Construction de la matrice de transformation de l'OBB
|
||||
Matrix4<T> matrix(width.x, height.x, depth.x, corner.x,
|
||||
width.y, height.y, depth.y, corner.y,
|
||||
width.z, height.z, depth.z, corner.z,
|
||||
F(0.0), F(0.0), F(0.0), F(1.0));
|
||||
|
||||
matrix.InverseAffine();
|
||||
|
||||
corner = matrix.Transform(corner);
|
||||
oppositeCorner = matrix.Transform(oppositeCorner);
|
||||
|
||||
Box<T> tmpBox(corner, oppositeCorner);
|
||||
Ray<T> tmpRay(matrix.Transform(origin), matrix.Transform(direction));
|
||||
|
||||
return tmpRay.Intersect(tmpBox, closestHit, furthestHit);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Ray<T>::Intersect(const Plane<T>& plane, T* hit) const
|
||||
{
|
||||
T divisor = plane.normal.DotProduct(direction);
|
||||
if (NumberEquals(divisor, F(0.0)))
|
||||
return false; // perpendicular
|
||||
|
||||
T lambda = -(plane.normal.DotProduct(origin) - plane.distance) / divisor; // The plane is ax + by + cz = d
|
||||
if (lambda < F(0.0))
|
||||
return false; // The plane is 'behind' the ray.
|
||||
|
||||
if (hit)
|
||||
*hit = lambda;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Ray<T>::Intersect(const Sphere<T>& sphere, T* closestHit, T* furthestHit) const
|
||||
{
|
||||
Vector3<T> sphereRay = sphere.GetPosition() - origin;
|
||||
T length = sphereRay.DotProduct(direction);
|
||||
|
||||
if (length < F(0.0))
|
||||
return false; // ray is perpendicular to the vector origin - center
|
||||
|
||||
T squaredDistance = sphereRay.GetSquaredLength() - length*length;
|
||||
T squaredRadius = sphere.radius*sphere.radius;
|
||||
|
||||
if (squaredDistance > squaredRadius)
|
||||
return false; // if the ray is further than the radius
|
||||
|
||||
// Calcul des points d'intersection si besoin
|
||||
if (closestHit || furthestHit)
|
||||
{
|
||||
T deltaLambda = std::sqrt(squaredRadius - squaredDistance);
|
||||
|
||||
if (closestHit)
|
||||
*closestHit = length - deltaLambda;
|
||||
|
||||
if (furthestHit)
|
||||
*furthestHit = length + deltaLambda;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Ray<T>& Ray<T>::MakeAxisX()
|
||||
{
|
||||
return Set(Vector3<T>::Zero(), Vector3<T>::UnitX());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Ray<T>& Ray<T>::MakeAxisY()
|
||||
{
|
||||
return Set(Vector3<T>::Zero(), Vector3<T>::UnitY());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Ray<T>& Ray<T>::MakeAxisZ()
|
||||
{
|
||||
return Set(Vector3<T>::Zero(), Vector3<T>::UnitZ());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Ray<T>& Ray<T>::Set(T X, T Y, T Z, T directionX, T directionY, T directionZ)
|
||||
{
|
||||
direction.Set(directionX, directionY, directionZ);
|
||||
origin.Set(X, Y, Z);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Ray<T>& Ray<T>::Set(const T Origin[3], const T Direction[3])
|
||||
{
|
||||
direction.Set(Direction);
|
||||
origin.Set(Origin);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Ray<T>& Ray<T>::Set(const Plane<T>& planeOne, const Plane<T>& planeTwo)
|
||||
{
|
||||
T termOne = planeOne.normal.GetLength();
|
||||
T termTwo = planeOne.normal.DotProduct(planeTwo.normal);
|
||||
T termFour = planeTwo.normal.GetLength();
|
||||
T det = termOne * termFour - termTwo * termTwo;
|
||||
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (NumberEquals(det, F(0.0)))
|
||||
{
|
||||
String error("Planes are parallel.");
|
||||
|
||||
NazaraError(error);
|
||||
throw std::domain_error(error);
|
||||
}
|
||||
#endif
|
||||
|
||||
T invdet = F(1.0) / det;
|
||||
T fc0 = (termFour * -planeOne.distance + termTwo * planeTwo.distance) * invdet;
|
||||
T fc1 = (termOne * -planeTwo.distance + termTwo * planeOne.distance) * invdet;
|
||||
|
||||
direction = planeOne.normal.CrossProduct(planeTwo.normal);
|
||||
origin = planeOne.normal * fc0 + planeTwo.normal * fc1;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Ray<T>& Ray<T>::Set(const Ray& ray)
|
||||
{
|
||||
std::memcpy(this, &ray, sizeof(Ray));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Ray<T>& Ray<T>::Set(const Vector3<T>& Origin, const Vector3<T>& Direction)
|
||||
{
|
||||
direction = Direction;
|
||||
origin = Origin;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
Ray<T>& Ray<T>::Set(const Ray<U>& ray)
|
||||
{
|
||||
direction.Set(ray.direction);
|
||||
origin.Set(ray.origin);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
Ray<T>& Ray<T>::Set(const Vector3<U>& Origin, const Vector3<U>& Direction)
|
||||
{
|
||||
direction.Set(Direction);
|
||||
origin.Set(Origin);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
String Ray<T>::ToString() const
|
||||
{
|
||||
StringStream ss;
|
||||
|
||||
return ss << "Ray(origin: " << origin.ToString() << ", direction: " << direction.ToString() << ")";
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector3<T> Ray<T>::operator*(T lambda) const
|
||||
{
|
||||
return GetPoint(lambda);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Ray<T>::operator==(const Ray& ray) const
|
||||
{
|
||||
return direction == ray.direction && origin == ray.origin;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Ray<T>::operator!=(const Ray& ray) const
|
||||
{
|
||||
return !operator==(ray);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Ray<T> Ray<T>::AxisX()
|
||||
{
|
||||
Ray axis;
|
||||
axis.MakeAxisX();
|
||||
|
||||
return axis;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Ray<T> Ray<T>::AxisY()
|
||||
{
|
||||
Ray axis;
|
||||
axis.MakeAxisY();
|
||||
|
||||
return axis;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Ray<T> Ray<T>::AxisZ()
|
||||
{
|
||||
Ray axis;
|
||||
axis.MakeAxisZ();
|
||||
|
||||
return axis;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Ray<T> Ray<T>::Lerp(const Ray& from, const Ray& to, T interpolation)
|
||||
{
|
||||
return Ray<T>(from.origin.Lerp(to.origin, interpolation), from.direction.Lerp(to.direction, interpolation));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRay<T>& NzRay<T>::Set(const NzRay& ray)
|
||||
{
|
||||
std::memcpy(this, &ray, sizeof(NzRay));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRay<T>& NzRay<T>::Set(const NzVector3<T>& Origin, const NzVector3<T>& Direction)
|
||||
{
|
||||
direction = Direction;
|
||||
origin = Origin;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzRay<T>& NzRay<T>::Set(const NzRay<U>& ray)
|
||||
{
|
||||
direction.Set(ray.direction);
|
||||
origin.Set(ray.origin);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzRay<T>& NzRay<T>::Set(const NzVector3<U>& Origin, const NzVector3<U>& Direction)
|
||||
{
|
||||
direction.Set(Direction);
|
||||
origin.Set(Origin);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzString NzRay<T>::ToString() const
|
||||
{
|
||||
NzStringStream ss;
|
||||
|
||||
return ss << "Ray(origin: " << origin.ToString() << ", direction: " << direction.ToString() << ")";
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector3<T> NzRay<T>::operator*(T lambda) const
|
||||
{
|
||||
return GetPoint(lambda);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzRay<T>::operator==(const NzRay& ray) const
|
||||
{
|
||||
return direction == ray.direction && origin == ray.origin;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzRay<T>::operator!=(const NzRay& ray) const
|
||||
{
|
||||
return !operator==(ray);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRay<T> NzRay<T>::AxisX()
|
||||
{
|
||||
NzRay axis;
|
||||
axis.MakeAxisX();
|
||||
|
||||
return axis;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRay<T> NzRay<T>::AxisY()
|
||||
{
|
||||
NzRay axis;
|
||||
axis.MakeAxisY();
|
||||
|
||||
return axis;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRay<T> NzRay<T>::AxisZ()
|
||||
{
|
||||
NzRay axis;
|
||||
axis.MakeAxisZ();
|
||||
|
||||
return axis;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRay<T> NzRay<T>::Lerp(const NzRay& from, const NzRay& to, T interpolation)
|
||||
{
|
||||
return NzRay<T>(from.origin.Lerp(to.origin, interpolation), from.direction.Lerp(to.direction, interpolation));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzRay<T>& ray)
|
||||
std::ostream& operator<<(std::ostream& out, const Nz::Ray<T>& ray)
|
||||
{
|
||||
return out << ray.ToString();
|
||||
}
|
||||
|
||||
@@ -11,86 +11,89 @@
|
||||
#include <Nazara/Math/Enums.hpp>
|
||||
#include <Nazara/Math/Vector2.hpp>
|
||||
|
||||
template<typename T>
|
||||
class NzRect
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzRect() = default;
|
||||
NzRect(T Width, T Height);
|
||||
NzRect(T X, T Y, T Width, T Height);
|
||||
NzRect(const T rect[4]);
|
||||
NzRect(const NzVector2<T>& lengths);
|
||||
NzRect(const NzVector2<T>& vec1, const NzVector2<T>& vec2);
|
||||
template<typename U> explicit NzRect(const NzRect<U>& rect);
|
||||
NzRect(const NzRect& rect) = default;
|
||||
~NzRect() = default;
|
||||
template<typename T>
|
||||
class Rect
|
||||
{
|
||||
public:
|
||||
Rect() = default;
|
||||
Rect(T Width, T Height);
|
||||
Rect(T X, T Y, T Width, T Height);
|
||||
Rect(const T rect[4]);
|
||||
Rect(const Vector2<T>& lengths);
|
||||
Rect(const Vector2<T>& vec1, const Vector2<T>& vec2);
|
||||
template<typename U> explicit Rect(const Rect<U>& rect);
|
||||
Rect(const Rect& rect) = default;
|
||||
~Rect() = default;
|
||||
|
||||
bool Contains(T X, T Y) const;
|
||||
bool Contains(const NzVector2<T>& point) const;
|
||||
bool Contains(const NzRect& rect) const;
|
||||
bool Contains(T X, T Y) const;
|
||||
bool Contains(const Vector2<T>& point) const;
|
||||
bool Contains(const Rect& rect) const;
|
||||
|
||||
NzRect& ExtendTo(T X, T Y);
|
||||
NzRect& ExtendTo(const NzVector2<T>& point);
|
||||
NzRect& ExtendTo(const NzRect& rect);
|
||||
Rect& ExtendTo(T X, T Y);
|
||||
Rect& ExtendTo(const Vector2<T>& point);
|
||||
Rect& ExtendTo(const Rect& rect);
|
||||
|
||||
NzVector2<T> GetCenter() const;
|
||||
NzVector2<T> GetCorner(nzRectCorner corner) const;
|
||||
NzVector2<T> GetLengths() const;
|
||||
NzVector2<T> GetMaximum() const;
|
||||
NzVector2<T> GetMinimum() const;
|
||||
NzVector2<T> GetNegativeVertex(const NzVector2<T>& normal) const;
|
||||
NzVector2<T> GetPosition() const;
|
||||
NzVector2<T> GetPositiveVertex(const NzVector2<T>& normal) const;
|
||||
Vector2<T> GetCenter() const;
|
||||
Vector2<T> GetCorner(RectCorner corner) const;
|
||||
Vector2<T> GetLengths() const;
|
||||
Vector2<T> GetMaximum() const;
|
||||
Vector2<T> GetMinimum() const;
|
||||
Vector2<T> GetNegativeVertex(const Vector2<T>& normal) const;
|
||||
Vector2<T> GetPosition() const;
|
||||
Vector2<T> GetPositiveVertex(const Vector2<T>& normal) const;
|
||||
|
||||
bool Intersect(const NzRect& rect, NzRect* intersection = nullptr) const;
|
||||
bool Intersect(const Rect& rect, Rect* intersection = nullptr) const;
|
||||
|
||||
bool IsValid() const;
|
||||
bool IsValid() const;
|
||||
|
||||
NzRect& MakeZero();
|
||||
Rect& MakeZero();
|
||||
|
||||
NzRect& Set(T Width, T Height);
|
||||
NzRect& Set(T X, T Y, T Width, T Height);
|
||||
NzRect& Set(const T rect[4]);
|
||||
NzRect& Set(const NzRect<T>& rect);
|
||||
NzRect& Set(const NzVector2<T>& lengths);
|
||||
NzRect& Set(const NzVector2<T>& vec1, const NzVector2<T>& vec2);
|
||||
template<typename U> NzRect& Set(const NzRect<U>& rect);
|
||||
Rect& Set(T Width, T Height);
|
||||
Rect& Set(T X, T Y, T Width, T Height);
|
||||
Rect& Set(const T rect[4]);
|
||||
Rect& Set(const Rect<T>& rect);
|
||||
Rect& Set(const Vector2<T>& lengths);
|
||||
Rect& Set(const Vector2<T>& vec1, const Vector2<T>& vec2);
|
||||
template<typename U> Rect& Set(const Rect<U>& rect);
|
||||
|
||||
NzString ToString() const;
|
||||
String ToString() const;
|
||||
|
||||
NzRect& Translate(const NzVector2<T>& translation);
|
||||
Rect& Translate(const Vector2<T>& translation);
|
||||
|
||||
T& operator[](unsigned int i);
|
||||
T operator[](unsigned int i) const;
|
||||
T& operator[](unsigned int i);
|
||||
T operator[](unsigned int i) const;
|
||||
|
||||
NzRect operator*(T scalar) const;
|
||||
NzRect operator*(const NzVector2<T>& vec) const;
|
||||
NzRect operator/(T scalar) const;
|
||||
NzRect operator/(const NzVector2<T>& vec) const;
|
||||
Rect operator*(T scalar) const;
|
||||
Rect operator*(const Vector2<T>& vec) const;
|
||||
Rect operator/(T scalar) const;
|
||||
Rect operator/(const Vector2<T>& vec) const;
|
||||
|
||||
NzRect& operator*=(T scalar);
|
||||
NzRect& operator*=(const NzVector2<T>& vec);
|
||||
NzRect& operator/=(T scalar);
|
||||
NzRect& operator/=(const NzVector2<T>& vec);
|
||||
Rect& operator*=(T scalar);
|
||||
Rect& operator*=(const Vector2<T>& vec);
|
||||
Rect& operator/=(T scalar);
|
||||
Rect& operator/=(const Vector2<T>& vec);
|
||||
|
||||
bool operator==(const NzRect& rect) const;
|
||||
bool operator!=(const NzRect& rect) const;
|
||||
bool operator==(const Rect& rect) const;
|
||||
bool operator!=(const Rect& rect) const;
|
||||
|
||||
static NzRect Lerp(const NzRect& from, const NzRect& to, T interpolation);
|
||||
static NzRect Zero();
|
||||
static Rect Lerp(const Rect& from, const Rect& to, T interpolation);
|
||||
static Rect Zero();
|
||||
|
||||
T x, y, width, height;
|
||||
};
|
||||
T x, y, width, height;
|
||||
};
|
||||
|
||||
typedef Rect<double> Rectd;
|
||||
typedef Rect<float> Rectf;
|
||||
typedef Rect<int> Recti;
|
||||
typedef Rect<unsigned int> Rectui;
|
||||
typedef Rect<Int32> Recti32;
|
||||
typedef Rect<UInt32> Rectui32;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzRect<T>& rect);
|
||||
|
||||
typedef NzRect<double> NzRectd;
|
||||
typedef NzRect<float> NzRectf;
|
||||
typedef NzRect<int> NzRecti;
|
||||
typedef NzRect<unsigned int> NzRectui;
|
||||
typedef NzRect<nzInt32> NzRecti32;
|
||||
typedef NzRect<nzUInt32> NzRectui32;
|
||||
std::ostream& operator<<(std::ostream& out, const Nz::Rect<T>& rect);
|
||||
|
||||
#include <Nazara/Math/Rect.inl>
|
||||
|
||||
|
||||
@@ -10,446 +10,449 @@
|
||||
|
||||
#define F(a) static_cast<T>(a)
|
||||
|
||||
template<typename T>
|
||||
NzRect<T>::NzRect(T Width, T Height)
|
||||
namespace Nz
|
||||
{
|
||||
Set(Width, Height);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T>::NzRect(T X, T Y, T Width, T Height)
|
||||
{
|
||||
Set(X, Y, Width, Height);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T>::NzRect(const T vec[4])
|
||||
{
|
||||
Set(vec);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T>::NzRect(const NzVector2<T>& lengths)
|
||||
{
|
||||
Set(lengths);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T>::NzRect(const NzVector2<T>& vec1, const NzVector2<T>& vec2)
|
||||
{
|
||||
Set(vec1, vec2);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzRect<T>::NzRect(const NzRect<U>& rect)
|
||||
{
|
||||
Set(rect);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzRect<T>::Contains(T X, T Y) const
|
||||
{
|
||||
return X >= x && X <= x+width &&
|
||||
Y >= y && Y <= y+height;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzRect<T>::Contains(const NzVector2<T>& point) const
|
||||
{
|
||||
return Contains(point.x, point.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzRect<T>::Contains(const NzRect<T>& rect) const
|
||||
{
|
||||
return Contains(rect.x, rect.y) &&
|
||||
Contains(rect.x + rect.width, rect.y + rect.height);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T>& NzRect<T>::ExtendTo(T X, T Y)
|
||||
{
|
||||
width = std::max(x + width, X);
|
||||
height = std::max(y + height, Y);
|
||||
|
||||
x = std::min(x, X);
|
||||
y = std::min(y, Y);
|
||||
|
||||
width -= x;
|
||||
height -= y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T>& NzRect<T>::ExtendTo(const NzVector2<T>& point)
|
||||
{
|
||||
return ExtendTo(point.x, point.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T>& NzRect<T>::ExtendTo(const NzRect& rect)
|
||||
{
|
||||
width = std::max(x + width, rect.x + rect.width);
|
||||
height = std::max(y + height, rect.y + rect.height);
|
||||
|
||||
x = std::min(x, rect.x);
|
||||
y = std::min(y, rect.y);
|
||||
|
||||
width -= x;
|
||||
height -= y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzRect<T>::GetCenter() const
|
||||
{
|
||||
return GetPosition() + GetLengths() / F(2.0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzRect<T>::GetCorner(nzRectCorner corner) const
|
||||
{
|
||||
switch (corner)
|
||||
template<typename T>
|
||||
Rect<T>::Rect(T Width, T Height)
|
||||
{
|
||||
case nzRectCorner_LeftBottom:
|
||||
return NzVector2<T>(x, y + height);
|
||||
|
||||
case nzRectCorner_LeftTop:
|
||||
return NzVector2<T>(x, y);
|
||||
|
||||
case nzRectCorner_RightBottom:
|
||||
return NzVector2<T>(x + width, y + height);
|
||||
|
||||
case nzRectCorner_RightTop:
|
||||
return NzVector2<T>(x + width, y);
|
||||
Set(Width, Height);
|
||||
}
|
||||
|
||||
NazaraError("Corner not handled (0x" + NzString::Number(corner, 16) + ')');
|
||||
return NzVector2<T>();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzRect<T>::GetLengths() const
|
||||
{
|
||||
return NzVector2<T>(width, height);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzRect<T>::GetMaximum() const
|
||||
{
|
||||
return GetPosition() + GetLengths();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzRect<T>::GetMinimum() const
|
||||
{
|
||||
///DOC: Alias de GetPosition()
|
||||
return GetPosition();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzRect<T>::GetNegativeVertex(const NzVector2<T>& normal) const
|
||||
{
|
||||
NzVector2<T> neg(GetPosition());
|
||||
|
||||
if (normal.x < F(0.0))
|
||||
neg.x += width;
|
||||
|
||||
if (normal.y < F(0.0))
|
||||
neg.y += height;
|
||||
|
||||
return neg;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzRect<T>::GetPosition() const
|
||||
{
|
||||
return NzVector2<T>(x, y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzRect<T>::GetPositiveVertex(const NzVector2<T>& normal) const
|
||||
{
|
||||
NzVector2<T> pos(GetPosition());
|
||||
|
||||
if (normal.x > F(0.0))
|
||||
pos.x += width;
|
||||
|
||||
if (normal.y > F(0.0))
|
||||
pos.y += height;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzRect<T>::Intersect(const NzRect& rect, NzRect* intersection) const
|
||||
{
|
||||
T left = std::max(x, rect.x);
|
||||
T right = std::min(x + width, rect.x + rect.width);
|
||||
if (left >= right)
|
||||
return false;
|
||||
|
||||
T top = std::max(y, rect.y);
|
||||
T bottom = std::min(y + height, rect.y + rect.height);
|
||||
if (top >= bottom)
|
||||
return false;
|
||||
|
||||
if (intersection)
|
||||
template<typename T>
|
||||
Rect<T>::Rect(T X, T Y, T Width, T Height)
|
||||
{
|
||||
intersection->x = left;
|
||||
intersection->y = top;
|
||||
intersection->width = right - left;
|
||||
intersection->height = bottom - top;
|
||||
Set(X, Y, Width, Height);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzRect<T>::IsValid() const
|
||||
{
|
||||
return width > F(0.0) && height > F(0.0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T>& NzRect<T>::MakeZero()
|
||||
{
|
||||
x = F(0.0);
|
||||
y = F(0.0);
|
||||
width = F(0.0);
|
||||
height = F(0.0);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T>& NzRect<T>::Set(T Width, T Height)
|
||||
{
|
||||
x = F(0.0);
|
||||
y = F(0.0);
|
||||
width = Width;
|
||||
height = Height;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T>& NzRect<T>::Set(T X, T Y, T Width, T Height)
|
||||
{
|
||||
x = X;
|
||||
y = Y;
|
||||
width = Width;
|
||||
height = Height;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T>& NzRect<T>::Set(const T rect[4])
|
||||
{
|
||||
x = rect[0];
|
||||
y = rect[1];
|
||||
width = rect[2];
|
||||
height = rect[3];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T>& NzRect<T>::Set(const NzRect<T>& rect)
|
||||
{
|
||||
std::memcpy(this, &rect, sizeof(NzRect));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T>& NzRect<T>::Set(const NzVector2<T>& lengths)
|
||||
{
|
||||
return Set(lengths.x, lengths.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T>& NzRect<T>::Set(const NzVector2<T>& vec1, const NzVector2<T>& vec2)
|
||||
{
|
||||
x = std::min(vec1.x, vec2.x);
|
||||
y = std::min(vec1.y, vec2.y);
|
||||
width = (vec2.x > vec1.x) ? vec2.x-vec1.x : vec1.x-vec2.x;
|
||||
height = (vec2.y > vec1.y) ? vec2.y-vec1.y : vec1.y-vec2.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzRect<T>& NzRect<T>::Set(const NzRect<U>& rect)
|
||||
{
|
||||
x = F(rect.x);
|
||||
y = F(rect.y);
|
||||
width = F(rect.width);
|
||||
height = F(rect.height);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzString NzRect<T>::ToString() const
|
||||
{
|
||||
NzStringStream ss;
|
||||
|
||||
return ss << "Rect(" << x << ", " << y << ", " << width << ", " << height << ')';
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T>& NzRect<T>::Translate(const NzVector2<T>& translation)
|
||||
{
|
||||
x += translation.x;
|
||||
y += translation.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T& NzRect<T>::operator[](unsigned int i)
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (i >= 4)
|
||||
template<typename T>
|
||||
Rect<T>::Rect(const T vec[4])
|
||||
{
|
||||
NzStringStream ss;
|
||||
ss << "Index out of range: (" << i << " >= 4)";
|
||||
|
||||
NazaraError(ss);
|
||||
throw std::domain_error(ss.ToString());
|
||||
Set(vec);
|
||||
}
|
||||
#endif
|
||||
|
||||
return *(&x+i);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzRect<T>::operator[](unsigned int i) const
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (i >= 4)
|
||||
template<typename T>
|
||||
Rect<T>::Rect(const Vector2<T>& lengths)
|
||||
{
|
||||
NzStringStream ss;
|
||||
ss << "Index out of range: (" << i << " >= 4)";
|
||||
|
||||
NazaraError(ss);
|
||||
throw std::domain_error(ss.ToString());
|
||||
Set(lengths);
|
||||
}
|
||||
#endif
|
||||
|
||||
return *(&x+i);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T> NzRect<T>::operator*(T scalar) const
|
||||
{
|
||||
return NzRect(x, y, width*scalar, height*scalar);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T> NzRect<T>::operator*(const NzVector2<T>& vec) const
|
||||
{
|
||||
return NzRect(x, y, width*vec.x, height*vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T> NzRect<T>::operator/(T scalar) const
|
||||
{
|
||||
return NzRect(x, y, width/scalar, height/scalar);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T> NzRect<T>::operator/(const NzVector2<T>& vec) const
|
||||
{
|
||||
return NzRect(x, y, width/vec.x, height/vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T>& NzRect<T>::operator*=(T scalar)
|
||||
{
|
||||
width *= scalar;
|
||||
height *= scalar;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T>& NzRect<T>::operator*=(const NzVector2<T>& vec)
|
||||
{
|
||||
width *= vec.x;
|
||||
height *= vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T>& NzRect<T>::operator/=(T scalar)
|
||||
{
|
||||
width /= scalar;
|
||||
height /= scalar;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T>& NzRect<T>::operator/=(const NzVector2<T>& vec)
|
||||
{
|
||||
width /= vec.x;
|
||||
height /= vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzRect<T>::operator==(const NzRect& rect) const
|
||||
{
|
||||
return NzNumberEquals(x, rect.x) && NzNumberEquals(y, rect.y) &&
|
||||
NzNumberEquals(width, rect.width) && NzNumberEquals(height, rect.height);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzRect<T>::operator!=(const NzRect& rect) const
|
||||
{
|
||||
return !operator==(rect);
|
||||
}
|
||||
|
||||
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))
|
||||
template<typename T>
|
||||
Rect<T>::Rect(const Vector2<T>& vec1, const Vector2<T>& vec2)
|
||||
{
|
||||
NazaraError("Interpolation must be in range [0..1] (Got " + NzString::Number(interpolation) + ')');
|
||||
return Zero();
|
||||
Set(vec1, vec2);
|
||||
}
|
||||
#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);
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
Rect<T>::Rect(const Rect<U>& rect)
|
||||
{
|
||||
Set(rect);
|
||||
}
|
||||
|
||||
return rect;
|
||||
template<typename T>
|
||||
bool Rect<T>::Contains(T X, T Y) const
|
||||
{
|
||||
return X >= x && X <= x+width &&
|
||||
Y >= y && Y <= y+height;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Rect<T>::Contains(const Vector2<T>& point) const
|
||||
{
|
||||
return Contains(point.x, point.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Rect<T>::Contains(const Rect<T>& rect) const
|
||||
{
|
||||
return Contains(rect.x, rect.y) &&
|
||||
Contains(rect.x + rect.width, rect.y + rect.height);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T>& Rect<T>::ExtendTo(T X, T Y)
|
||||
{
|
||||
width = std::max(x + width, X);
|
||||
height = std::max(y + height, Y);
|
||||
|
||||
x = std::min(x, X);
|
||||
y = std::min(y, Y);
|
||||
|
||||
width -= x;
|
||||
height -= y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T>& Rect<T>::ExtendTo(const Vector2<T>& point)
|
||||
{
|
||||
return ExtendTo(point.x, point.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T>& Rect<T>::ExtendTo(const Rect& rect)
|
||||
{
|
||||
width = std::max(x + width, rect.x + rect.width);
|
||||
height = std::max(y + height, rect.y + rect.height);
|
||||
|
||||
x = std::min(x, rect.x);
|
||||
y = std::min(y, rect.y);
|
||||
|
||||
width -= x;
|
||||
height -= y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> Rect<T>::GetCenter() const
|
||||
{
|
||||
return GetPosition() + GetLengths() / F(2.0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> Rect<T>::GetCorner(RectCorner corner) const
|
||||
{
|
||||
switch (corner)
|
||||
{
|
||||
case RectCorner_LeftBottom:
|
||||
return Vector2<T>(x, y + height);
|
||||
|
||||
case RectCorner_LeftTop:
|
||||
return Vector2<T>(x, y);
|
||||
|
||||
case RectCorner_RightBottom:
|
||||
return Vector2<T>(x + width, y + height);
|
||||
|
||||
case RectCorner_RightTop:
|
||||
return Vector2<T>(x + width, y);
|
||||
}
|
||||
|
||||
NazaraError("Corner not handled (0x" + String::Number(corner, 16) + ')');
|
||||
return Vector2<T>();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> Rect<T>::GetLengths() const
|
||||
{
|
||||
return Vector2<T>(width, height);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> Rect<T>::GetMaximum() const
|
||||
{
|
||||
return GetPosition() + GetLengths();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> Rect<T>::GetMinimum() const
|
||||
{
|
||||
///DOC: Alias de GetPosition()
|
||||
return GetPosition();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> Rect<T>::GetNegativeVertex(const Vector2<T>& normal) const
|
||||
{
|
||||
Vector2<T> neg(GetPosition());
|
||||
|
||||
if (normal.x < F(0.0))
|
||||
neg.x += width;
|
||||
|
||||
if (normal.y < F(0.0))
|
||||
neg.y += height;
|
||||
|
||||
return neg;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> Rect<T>::GetPosition() const
|
||||
{
|
||||
return Vector2<T>(x, y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> Rect<T>::GetPositiveVertex(const Vector2<T>& normal) const
|
||||
{
|
||||
Vector2<T> pos(GetPosition());
|
||||
|
||||
if (normal.x > F(0.0))
|
||||
pos.x += width;
|
||||
|
||||
if (normal.y > F(0.0))
|
||||
pos.y += height;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Rect<T>::Intersect(const Rect& rect, Rect* intersection) const
|
||||
{
|
||||
T left = std::max(x, rect.x);
|
||||
T right = std::min(x + width, rect.x + rect.width);
|
||||
if (left >= right)
|
||||
return false;
|
||||
|
||||
T top = std::max(y, rect.y);
|
||||
T bottom = std::min(y + height, rect.y + rect.height);
|
||||
if (top >= bottom)
|
||||
return false;
|
||||
|
||||
if (intersection)
|
||||
{
|
||||
intersection->x = left;
|
||||
intersection->y = top;
|
||||
intersection->width = right - left;
|
||||
intersection->height = bottom - top;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Rect<T>::IsValid() const
|
||||
{
|
||||
return width > F(0.0) && height > F(0.0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T>& Rect<T>::MakeZero()
|
||||
{
|
||||
x = F(0.0);
|
||||
y = F(0.0);
|
||||
width = F(0.0);
|
||||
height = F(0.0);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T>& Rect<T>::Set(T Width, T Height)
|
||||
{
|
||||
x = F(0.0);
|
||||
y = F(0.0);
|
||||
width = Width;
|
||||
height = Height;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T>& Rect<T>::Set(T X, T Y, T Width, T Height)
|
||||
{
|
||||
x = X;
|
||||
y = Y;
|
||||
width = Width;
|
||||
height = Height;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T>& Rect<T>::Set(const T rect[4])
|
||||
{
|
||||
x = rect[0];
|
||||
y = rect[1];
|
||||
width = rect[2];
|
||||
height = rect[3];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T>& Rect<T>::Set(const Rect<T>& rect)
|
||||
{
|
||||
std::memcpy(this, &rect, sizeof(Rect));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T>& Rect<T>::Set(const Vector2<T>& lengths)
|
||||
{
|
||||
return Set(lengths.x, lengths.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T>& Rect<T>::Set(const Vector2<T>& vec1, const Vector2<T>& vec2)
|
||||
{
|
||||
x = std::min(vec1.x, vec2.x);
|
||||
y = std::min(vec1.y, vec2.y);
|
||||
width = (vec2.x > vec1.x) ? vec2.x-vec1.x : vec1.x-vec2.x;
|
||||
height = (vec2.y > vec1.y) ? vec2.y-vec1.y : vec1.y-vec2.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
Rect<T>& Rect<T>::Set(const Rect<U>& rect)
|
||||
{
|
||||
x = F(rect.x);
|
||||
y = F(rect.y);
|
||||
width = F(rect.width);
|
||||
height = F(rect.height);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
String Rect<T>::ToString() const
|
||||
{
|
||||
StringStream ss;
|
||||
|
||||
return ss << "Rect(" << x << ", " << y << ", " << width << ", " << height << ')';
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T>& Rect<T>::Translate(const Vector2<T>& translation)
|
||||
{
|
||||
x += translation.x;
|
||||
y += translation.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T& Rect<T>::operator[](unsigned int i)
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (i >= 4)
|
||||
{
|
||||
StringStream ss;
|
||||
ss << "Index out of range: (" << i << " >= 4)";
|
||||
|
||||
NazaraError(ss);
|
||||
throw std::domain_error(ss.ToString());
|
||||
}
|
||||
#endif
|
||||
|
||||
return *(&x+i);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T Rect<T>::operator[](unsigned int i) const
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (i >= 4)
|
||||
{
|
||||
StringStream ss;
|
||||
ss << "Index out of range: (" << i << " >= 4)";
|
||||
|
||||
NazaraError(ss);
|
||||
throw std::domain_error(ss.ToString());
|
||||
}
|
||||
#endif
|
||||
|
||||
return *(&x+i);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T> Rect<T>::operator*(T scalar) const
|
||||
{
|
||||
return Rect(x, y, width*scalar, height*scalar);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T> Rect<T>::operator*(const Vector2<T>& vec) const
|
||||
{
|
||||
return Rect(x, y, width*vec.x, height*vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T> Rect<T>::operator/(T scalar) const
|
||||
{
|
||||
return Rect(x, y, width/scalar, height/scalar);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T> Rect<T>::operator/(const Vector2<T>& vec) const
|
||||
{
|
||||
return Rect(x, y, width/vec.x, height/vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T>& Rect<T>::operator*=(T scalar)
|
||||
{
|
||||
width *= scalar;
|
||||
height *= scalar;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T>& Rect<T>::operator*=(const Vector2<T>& vec)
|
||||
{
|
||||
width *= vec.x;
|
||||
height *= vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T>& Rect<T>::operator/=(T scalar)
|
||||
{
|
||||
width /= scalar;
|
||||
height /= scalar;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T>& Rect<T>::operator/=(const Vector2<T>& vec)
|
||||
{
|
||||
width /= vec.x;
|
||||
height /= vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Rect<T>::operator==(const Rect& rect) const
|
||||
{
|
||||
return NumberEquals(x, rect.x) && NumberEquals(y, rect.y) &&
|
||||
NumberEquals(width, rect.width) && NumberEquals(height, rect.height);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Rect<T>::operator!=(const Rect& rect) const
|
||||
{
|
||||
return !operator==(rect);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T> Rect<T>::Lerp(const Rect& from, const Rect& to, T interpolation)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (interpolation < F(0.0) || interpolation > F(1.0))
|
||||
{
|
||||
NazaraError("Interpolation must be in range [0..1] (Got " + String::Number(interpolation) + ')');
|
||||
return Zero();
|
||||
}
|
||||
#endif
|
||||
|
||||
Rect rect;
|
||||
rect.x = Lerp(from.x, to.x, interpolation);
|
||||
rect.y = Lerp(from.y, to.y, interpolation);
|
||||
rect.width = Lerp(from.width, to.width, interpolation);
|
||||
rect.height = Lerp(from.height, to.height, interpolation);
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Rect<T> Rect<T>::Zero()
|
||||
{
|
||||
Rect rect;
|
||||
rect.MakeZero();
|
||||
|
||||
return rect;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzRect<T> NzRect<T>::Zero()
|
||||
{
|
||||
NzRect rect;
|
||||
rect.MakeZero();
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzRect<T>& rect)
|
||||
std::ostream& operator<<(std::ostream& out, const Nz::Rect<T>& rect)
|
||||
{
|
||||
return out << rect.ToString();
|
||||
}
|
||||
|
||||
@@ -10,76 +10,78 @@
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
|
||||
template<typename T>
|
||||
class NzBox;
|
||||
|
||||
template<typename T>
|
||||
class NzSphere
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzSphere() = default;
|
||||
NzSphere(T X, T Y, T Z, T Radius);
|
||||
//NzSphere(const NzCircle<T>& circle);
|
||||
NzSphere(const NzVector3<T>& center, T Radius);
|
||||
NzSphere(const T sphere[4]);
|
||||
template<typename U> explicit NzSphere(const NzSphere<U>& sphere);
|
||||
NzSphere(const NzSphere& sphere) = default;
|
||||
~NzSphere() = default;
|
||||
template<typename T> class Box;
|
||||
|
||||
bool Contains(T X, T Y, T Z) const;
|
||||
bool Contains(const NzBox<T>& box) const;
|
||||
bool Contains(const NzVector3<T>& point) const;
|
||||
template<typename T>
|
||||
class Sphere
|
||||
{
|
||||
public:
|
||||
Sphere() = default;
|
||||
Sphere(T X, T Y, T Z, T Radius);
|
||||
//Sphere(const Circle<T>& circle);
|
||||
Sphere(const Vector3<T>& center, T Radius);
|
||||
Sphere(const T sphere[4]);
|
||||
template<typename U> explicit Sphere(const Sphere<U>& sphere);
|
||||
Sphere(const Sphere& sphere) = default;
|
||||
~Sphere() = default;
|
||||
|
||||
T Distance(T X, T Y, T Z) const;
|
||||
T Distance(const NzVector3<T>& point) const;
|
||||
bool Contains(T X, T Y, T Z) const;
|
||||
bool Contains(const Box<T>& box) const;
|
||||
bool Contains(const Vector3<T>& point) const;
|
||||
|
||||
NzSphere& ExtendTo(T X, T Y, T Z);
|
||||
NzSphere& ExtendTo(const NzVector3<T>& point);
|
||||
T Distance(T X, T Y, T Z) const;
|
||||
T Distance(const Vector3<T>& point) const;
|
||||
|
||||
NzVector3<T> GetNegativeVertex(const NzVector3<T>& normal) const;
|
||||
NzVector3<T> GetPosition() const;
|
||||
NzVector3<T> GetPositiveVertex(const NzVector3<T>& normal) const;
|
||||
Sphere& ExtendTo(T X, T Y, T Z);
|
||||
Sphere& ExtendTo(const Vector3<T>& point);
|
||||
|
||||
bool Intersect(const NzBox<T>& box) const;
|
||||
bool Intersect(const NzSphere& sphere) const;
|
||||
Vector3<T> GetNegativeVertex(const Vector3<T>& normal) const;
|
||||
Vector3<T> GetPosition() const;
|
||||
Vector3<T> GetPositiveVertex(const Vector3<T>& normal) const;
|
||||
|
||||
bool IsValid() const;
|
||||
bool Intersect(const Box<T>& box) const;
|
||||
bool Intersect(const Sphere& sphere) const;
|
||||
|
||||
NzSphere& MakeZero();
|
||||
bool IsValid() const;
|
||||
|
||||
NzSphere& Set(T X, T Y, T Z, T Radius);
|
||||
//NzSphere& Set(const NzCircle<T>& rect);
|
||||
NzSphere& Set(const NzSphere& sphere);
|
||||
NzSphere& Set(const NzVector3<T>& center, T Radius);
|
||||
NzSphere& Set(const T sphere[4]);
|
||||
template<typename U> NzSphere& Set(const NzSphere<U>& sphere);
|
||||
Sphere& MakeZero();
|
||||
|
||||
T SquaredDistance(T X, T Y, T Z) const;
|
||||
T SquaredDistance(const NzVector3<T>& point) const;
|
||||
Sphere& Set(T X, T Y, T Z, T Radius);
|
||||
//Sphere& Set(const Circle<T>& rect);
|
||||
Sphere& Set(const Sphere& sphere);
|
||||
Sphere& Set(const Vector3<T>& center, T Radius);
|
||||
Sphere& Set(const T sphere[4]);
|
||||
template<typename U> Sphere& Set(const Sphere<U>& sphere);
|
||||
|
||||
NzString ToString() const;
|
||||
T SquaredDistance(T X, T Y, T Z) const;
|
||||
T SquaredDistance(const Vector3<T>& point) const;
|
||||
|
||||
T& operator[](unsigned int i);
|
||||
T operator[](unsigned int i) const;
|
||||
String ToString() const;
|
||||
|
||||
NzSphere operator*(T scalar) const;
|
||||
T& operator[](unsigned int i);
|
||||
T operator[](unsigned int i) const;
|
||||
|
||||
NzSphere& operator*=(T scalar);
|
||||
Sphere operator*(T scalar) const;
|
||||
|
||||
bool operator==(const NzSphere& sphere) const;
|
||||
bool operator!=(const NzSphere& sphere) const;
|
||||
Sphere& operator*=(T scalar);
|
||||
|
||||
static NzSphere Lerp(const NzSphere& from, const NzSphere& to, T interpolation);
|
||||
static NzSphere Zero();
|
||||
bool operator==(const Sphere& sphere) const;
|
||||
bool operator!=(const Sphere& sphere) const;
|
||||
|
||||
T x, y, z, radius;
|
||||
};
|
||||
static Sphere Lerp(const Sphere& from, const Sphere& to, T interpolation);
|
||||
static Sphere Zero();
|
||||
|
||||
T x, y, z, radius;
|
||||
};
|
||||
|
||||
typedef Sphere<double> Sphered;
|
||||
typedef Sphere<float> Spheref;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzSphere<T>& sphere);
|
||||
|
||||
typedef NzSphere<double> NzSphered;
|
||||
typedef NzSphere<float> NzSpheref;
|
||||
std::ostream& operator<<(std::ostream& out, const Nz::Sphere<T>& sphere);
|
||||
|
||||
#include <Nazara/Math/Sphere.inl>
|
||||
|
||||
|
||||
@@ -11,350 +11,356 @@
|
||||
|
||||
#define F(a) static_cast<T>(a)
|
||||
|
||||
template<typename T>
|
||||
NzSphere<T>::NzSphere(T X, T Y, T Z, T Radius)
|
||||
namespace Nz
|
||||
{
|
||||
Set(X, Y, Z, Radius);
|
||||
}
|
||||
/*
|
||||
template<typename T>
|
||||
NzSphere<T>::NzSphere(const NzCircle<T>& circle)
|
||||
{
|
||||
Set(rect);
|
||||
}
|
||||
*/
|
||||
template<typename T>
|
||||
NzSphere<T>::NzSphere(const NzVector3<T>& center, T Radius)
|
||||
{
|
||||
Set(center, Radius);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzSphere<T>::NzSphere(const T sphere[4])
|
||||
{
|
||||
Set(sphere);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzSphere<T>::NzSphere(const NzSphere<U>& sphere)
|
||||
{
|
||||
Set(sphere);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzSphere<T>::Contains(T X, T Y, T Z) const
|
||||
{
|
||||
return SquaredDistance(X, Y, Z) <= radius*radius;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzSphere<T>::Contains(const NzBox<T>& box) const
|
||||
{
|
||||
if (box.GetMinimum().SquaredDistance(GetPosition()) <= radius * radius)
|
||||
template<typename T>
|
||||
Sphere<T>::Sphere(T X, T Y, T Z, T Radius)
|
||||
{
|
||||
if (box.GetMaximum().SquaredDistance(GetPosition()) <= radius * radius)
|
||||
return true;
|
||||
Set(X, Y, Z, Radius);
|
||||
}
|
||||
/*
|
||||
template<typename T>
|
||||
Sphere<T>::Sphere(const Circle<T>& circle)
|
||||
{
|
||||
Set(rect);
|
||||
}
|
||||
*/
|
||||
template<typename T>
|
||||
Sphere<T>::Sphere(const Vector3<T>& center, T Radius)
|
||||
{
|
||||
Set(center, Radius);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
template<typename T>
|
||||
bool NzSphere<T>::Contains(const NzVector3<T>& point) const
|
||||
{
|
||||
return Contains(point.x, point.y, point.z);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzSphere<T>::Distance(T X, T Y, T Z) const
|
||||
{
|
||||
return Distance({X, Y, Z});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzSphere<T>::Distance(const NzVector3<T>& point) const
|
||||
{
|
||||
return NzVector3f::Distance(point, GetPosition()) - radius;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzSphere<T>& NzSphere<T>::ExtendTo(T X, T Y, T Z)
|
||||
{
|
||||
T distance = SquaredDistance(X, Y, Z);
|
||||
if (distance > radius*radius)
|
||||
radius = std::sqrt(distance);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzSphere<T>& NzSphere<T>::ExtendTo(const NzVector3<T>& point)
|
||||
{
|
||||
return ExtendTo(point.x, point.y, point.z);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector3<T> NzSphere<T>::GetNegativeVertex(const NzVector3<T>& normal) const
|
||||
{
|
||||
NzVector3<T> neg(GetPosition());
|
||||
neg -= normal * radius;
|
||||
|
||||
return neg;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector3<T> NzSphere<T>::GetPosition() const
|
||||
{
|
||||
return NzVector3<T>(x, y, z);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector3<T> NzSphere<T>::GetPositiveVertex(const NzVector3<T>& normal) const
|
||||
{
|
||||
NzVector3<T> pos(GetPosition());
|
||||
pos += normal * radius;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzSphere<T>::Intersect(const NzBox<T>& box) const
|
||||
{
|
||||
// Arvo's algorithm.
|
||||
T squaredDistance = T(0.0);
|
||||
if (x < box.x)
|
||||
template<typename T>
|
||||
Sphere<T>::Sphere(const T sphere[4])
|
||||
{
|
||||
T diff = x - box.x;
|
||||
squaredDistance += diff*diff;
|
||||
}
|
||||
else if (x > box.x + box.width)
|
||||
{
|
||||
T diff = x - (box.x + box.width);
|
||||
squaredDistance += diff*diff;
|
||||
Set(sphere);
|
||||
}
|
||||
|
||||
if (y < box.y)
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
Sphere<T>::Sphere(const Sphere<U>& sphere)
|
||||
{
|
||||
T diff = y - box.y;
|
||||
squaredDistance += diff*diff;
|
||||
}
|
||||
else if (y > box.y + box.height)
|
||||
{
|
||||
T diff = y - (box.y + box.height);
|
||||
squaredDistance += diff*diff;
|
||||
Set(sphere);
|
||||
}
|
||||
|
||||
if (z < box.z)
|
||||
template<typename T>
|
||||
bool Sphere<T>::Contains(T X, T Y, T Z) const
|
||||
{
|
||||
T diff = z - box.z;
|
||||
squaredDistance += diff*diff;
|
||||
}
|
||||
else if (z > box.z + box.depth)
|
||||
{
|
||||
T diff = z - (box.z + box.depth);
|
||||
squaredDistance += diff*diff;
|
||||
return SquaredDistance(X, Y, Z) <= radius*radius;
|
||||
}
|
||||
|
||||
return squaredDistance <= radius * radius;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzSphere<T>::Intersect(const NzSphere& sphere) const
|
||||
{
|
||||
return SquaredDistance(sphere.x, sphere.y, sphere.z) - radius*radius <= sphere.radius*sphere.radius;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzSphere<T>::IsValid() const
|
||||
{
|
||||
return radius > F(0.0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzSphere<T>& NzSphere<T>::MakeZero()
|
||||
{
|
||||
x = F(0.0);
|
||||
y = F(0.0);
|
||||
z = F(0.0);
|
||||
radius = F(0.0);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzSphere<T>& NzSphere<T>::Set(T X, T Y, T Z, T Radius)
|
||||
{
|
||||
x = X;
|
||||
y = Y;
|
||||
z = Z;
|
||||
radius = Radius;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzSphere<T>& NzSphere<T>::Set(const NzVector3<T>& center, T Radius)
|
||||
{
|
||||
x = center.x;
|
||||
y = center.y;
|
||||
z = center.z;
|
||||
radius = Radius;
|
||||
|
||||
return *this;
|
||||
}
|
||||
/*
|
||||
template<typename T>
|
||||
NzSphere<T>& NzSphere<T>::Set(const NzCircle<T>& circle)
|
||||
{
|
||||
x = circle.x;
|
||||
y = circle.y;
|
||||
z = F(0.0);
|
||||
radius = circle.radius;
|
||||
|
||||
return *this;
|
||||
}
|
||||
*/
|
||||
template<typename T>
|
||||
NzSphere<T>& NzSphere<T>::Set(const NzSphere& sphere)
|
||||
{
|
||||
std::memcpy(this, &sphere, sizeof(NzSphere));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzSphere<T>& NzSphere<T>::Set(const T sphere[4])
|
||||
{
|
||||
x = sphere[0];
|
||||
y = sphere[1];
|
||||
z = sphere[2];
|
||||
radius = sphere[3];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzSphere<T>& NzSphere<T>::Set(const NzSphere<U>& sphere)
|
||||
{
|
||||
x = F(sphere.x);
|
||||
y = F(sphere.y);
|
||||
z = F(sphere.z);
|
||||
radius = F(sphere.radius);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzSphere<T>::SquaredDistance(T X, T Y, T Z) const
|
||||
{
|
||||
return SquaredDistance({X, Y, Z});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzSphere<T>::SquaredDistance(const NzVector3<T>& point) const
|
||||
{
|
||||
return NzVector3f::Distance(point, GetPosition()) - radius * radius;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzString NzSphere<T>::ToString() const
|
||||
{
|
||||
NzStringStream ss;
|
||||
|
||||
return ss << "Sphere(" << x << ", " << y << ", " << z << "; " << radius << ')';
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T& NzSphere<T>::operator[](unsigned int i)
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (i >= 4)
|
||||
template<typename T>
|
||||
bool Sphere<T>::Contains(const Box<T>& box) const
|
||||
{
|
||||
NzStringStream ss;
|
||||
ss << "Index out of range: (" << i << " >= 4)";
|
||||
if (box.GetMinimum().SquaredDistance(GetPosition()) <= radius * radius)
|
||||
{
|
||||
if (box.GetMaximum().SquaredDistance(GetPosition()) <= radius * radius)
|
||||
return true;
|
||||
}
|
||||
|
||||
NazaraError(ss);
|
||||
throw std::domain_error(ss.ToString());
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return *(&x+i);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzSphere<T>::operator[](unsigned int i) const
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (i >= 4)
|
||||
template<typename T>
|
||||
bool Sphere<T>::Contains(const Vector3<T>& point) const
|
||||
{
|
||||
NzStringStream ss;
|
||||
ss << "Index out of range: (" << i << " >= 4)";
|
||||
|
||||
NazaraError(ss);
|
||||
throw std::domain_error(ss.ToString());
|
||||
return Contains(point.x, point.y, point.z);
|
||||
}
|
||||
#endif
|
||||
|
||||
return *(&x+i);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzSphere<T> NzSphere<T>::operator*(T scalar) const
|
||||
{
|
||||
return NzSphere(x, y, z, radius*scalar);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzSphere<T>& NzSphere<T>::operator*=(T scalar)
|
||||
{
|
||||
radius *= scalar;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzSphere<T>::operator==(const NzSphere& sphere) const
|
||||
{
|
||||
return NzNumberEquals(x, sphere.x) && NzNumberEquals(y, sphere.y) && NzNumberEquals(z, sphere.z) &&
|
||||
NzNumberEquals(radius, sphere.radius);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzSphere<T>::operator!=(const NzSphere& sphere) const
|
||||
{
|
||||
return !operator==(sphere);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzSphere<T> NzSphere<T>::Lerp(const NzSphere& from, const NzSphere& to, T interpolation)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (interpolation < F(0.0) || interpolation > F(1.0))
|
||||
template<typename T>
|
||||
T Sphere<T>::Distance(T X, T Y, T Z) const
|
||||
{
|
||||
NazaraError("Interpolation must be in range [0..1] (Got " + NzString::Number(interpolation) + ')');
|
||||
return Zero();
|
||||
return Distance({X, Y, Z});
|
||||
}
|
||||
#endif
|
||||
|
||||
NzSphere sphere;
|
||||
sphere.x = NzLerp(from.x, to.x, interpolation);
|
||||
sphere.y = NzLerp(from.y, to.y, interpolation);
|
||||
sphere.z = NzLerp(from.z, to.z, interpolation);
|
||||
sphere.radius = NzLerp(from.radius, to.radius, interpolation);
|
||||
template<typename T>
|
||||
T Sphere<T>::Distance(const Vector3<T>& point) const
|
||||
{
|
||||
return Vector3f::Distance(point, GetPosition()) - radius;
|
||||
}
|
||||
|
||||
return sphere;
|
||||
template<typename T>
|
||||
Sphere<T>& Sphere<T>::ExtendTo(T X, T Y, T Z)
|
||||
{
|
||||
T distance = SquaredDistance(X, Y, Z);
|
||||
if (distance > radius*radius)
|
||||
radius = std::sqrt(distance);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Sphere<T>& Sphere<T>::ExtendTo(const Vector3<T>& point)
|
||||
{
|
||||
return ExtendTo(point.x, point.y, point.z);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector3<T> Sphere<T>::GetNegativeVertex(const Vector3<T>& normal) const
|
||||
{
|
||||
Vector3<T> neg(GetPosition());
|
||||
neg -= normal * radius;
|
||||
|
||||
return neg;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector3<T> Sphere<T>::GetPosition() const
|
||||
{
|
||||
return Vector3<T>(x, y, z);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector3<T> Sphere<T>::GetPositiveVertex(const Vector3<T>& normal) const
|
||||
{
|
||||
Vector3<T> pos(GetPosition());
|
||||
pos += normal * radius;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Sphere<T>::Intersect(const Box<T>& box) const
|
||||
{
|
||||
// Arvo's algorithm.
|
||||
T squaredDistance = T(0.0);
|
||||
if (x < box.x)
|
||||
{
|
||||
T diff = x - box.x;
|
||||
squaredDistance += diff*diff;
|
||||
}
|
||||
else if (x > box.x + box.width)
|
||||
{
|
||||
T diff = x - (box.x + box.width);
|
||||
squaredDistance += diff*diff;
|
||||
}
|
||||
|
||||
if (y < box.y)
|
||||
{
|
||||
T diff = y - box.y;
|
||||
squaredDistance += diff*diff;
|
||||
}
|
||||
else if (y > box.y + box.height)
|
||||
{
|
||||
T diff = y - (box.y + box.height);
|
||||
squaredDistance += diff*diff;
|
||||
}
|
||||
|
||||
if (z < box.z)
|
||||
{
|
||||
T diff = z - box.z;
|
||||
squaredDistance += diff*diff;
|
||||
}
|
||||
else if (z > box.z + box.depth)
|
||||
{
|
||||
T diff = z - (box.z + box.depth);
|
||||
squaredDistance += diff*diff;
|
||||
}
|
||||
|
||||
return squaredDistance <= radius * radius;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Sphere<T>::Intersect(const Sphere& sphere) const
|
||||
{
|
||||
return SquaredDistance(sphere.x, sphere.y, sphere.z) - radius*radius <= sphere.radius*sphere.radius;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Sphere<T>::IsValid() const
|
||||
{
|
||||
return radius > F(0.0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Sphere<T>& Sphere<T>::MakeZero()
|
||||
{
|
||||
x = F(0.0);
|
||||
y = F(0.0);
|
||||
z = F(0.0);
|
||||
radius = F(0.0);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Sphere<T>& Sphere<T>::Set(T X, T Y, T Z, T Radius)
|
||||
{
|
||||
x = X;
|
||||
y = Y;
|
||||
z = Z;
|
||||
radius = Radius;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Sphere<T>& Sphere<T>::Set(const Vector3<T>& center, T Radius)
|
||||
{
|
||||
x = center.x;
|
||||
y = center.y;
|
||||
z = center.z;
|
||||
radius = Radius;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
template<typename T>
|
||||
Sphere<T>& Sphere<T>::Set(const Circle<T>& circle)
|
||||
{
|
||||
x = circle.x;
|
||||
y = circle.y;
|
||||
z = F(0.0);
|
||||
radius = circle.radius;
|
||||
|
||||
return *this;
|
||||
}
|
||||
*/
|
||||
|
||||
template<typename T>
|
||||
Sphere<T>& Sphere<T>::Set(const Sphere& sphere)
|
||||
{
|
||||
std::memcpy(this, &sphere, sizeof(Sphere));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Sphere<T>& Sphere<T>::Set(const T sphere[4])
|
||||
{
|
||||
x = sphere[0];
|
||||
y = sphere[1];
|
||||
z = sphere[2];
|
||||
radius = sphere[3];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
Sphere<T>& Sphere<T>::Set(const Sphere<U>& sphere)
|
||||
{
|
||||
x = F(sphere.x);
|
||||
y = F(sphere.y);
|
||||
z = F(sphere.z);
|
||||
radius = F(sphere.radius);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T Sphere<T>::SquaredDistance(T X, T Y, T Z) const
|
||||
{
|
||||
return SquaredDistance({X, Y, Z});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T Sphere<T>::SquaredDistance(const Vector3<T>& point) const
|
||||
{
|
||||
return Vector3f::Distance(point, GetPosition()) - radius * radius;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
String Sphere<T>::ToString() const
|
||||
{
|
||||
StringStream ss;
|
||||
|
||||
return ss << "Sphere(" << x << ", " << y << ", " << z << "; " << radius << ')';
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T& Sphere<T>::operator[](unsigned int i)
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (i >= 4)
|
||||
{
|
||||
StringStream ss;
|
||||
ss << "Index out of range: (" << i << " >= 4)";
|
||||
|
||||
NazaraError(ss);
|
||||
throw std::domain_error(ss.ToString());
|
||||
}
|
||||
#endif
|
||||
|
||||
return *(&x+i);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T Sphere<T>::operator[](unsigned int i) const
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (i >= 4)
|
||||
{
|
||||
StringStream ss;
|
||||
ss << "Index out of range: (" << i << " >= 4)";
|
||||
|
||||
NazaraError(ss);
|
||||
throw std::domain_error(ss.ToString());
|
||||
}
|
||||
#endif
|
||||
|
||||
return *(&x+i);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Sphere<T> Sphere<T>::operator*(T scalar) const
|
||||
{
|
||||
return Sphere(x, y, z, radius*scalar);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Sphere<T>& Sphere<T>::operator*=(T scalar)
|
||||
{
|
||||
radius *= scalar;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Sphere<T>::operator==(const Sphere& sphere) const
|
||||
{
|
||||
return NumberEquals(x, sphere.x) && NumberEquals(y, sphere.y) && NumberEquals(z, sphere.z) &&
|
||||
NumberEquals(radius, sphere.radius);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Sphere<T>::operator!=(const Sphere& sphere) const
|
||||
{
|
||||
return !operator==(sphere);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Sphere<T> Sphere<T>::Lerp(const Sphere& from, const Sphere& to, T interpolation)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (interpolation < F(0.0) || interpolation > F(1.0))
|
||||
{
|
||||
NazaraError("Interpolation must be in range [0..1] (Got " + String::Number(interpolation) + ')');
|
||||
return Zero();
|
||||
}
|
||||
#endif
|
||||
|
||||
Sphere sphere;
|
||||
sphere.x = Lerp(from.x, to.x, interpolation);
|
||||
sphere.y = Lerp(from.y, to.y, interpolation);
|
||||
sphere.z = Lerp(from.z, to.z, interpolation);
|
||||
sphere.radius = Lerp(from.radius, to.radius, interpolation);
|
||||
|
||||
return sphere;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Sphere<T> Sphere<T>::Zero()
|
||||
{
|
||||
Sphere sphere;
|
||||
sphere.MakeZero();
|
||||
|
||||
return sphere;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzSphere<T> NzSphere<T>::Zero()
|
||||
{
|
||||
NzSphere sphere;
|
||||
sphere.MakeZero();
|
||||
|
||||
return sphere;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzSphere<T>& sphere)
|
||||
std::ostream& operator<<(std::ostream& out, const Nz::Sphere<T>& sphere)
|
||||
{
|
||||
return out << sphere.ToString();
|
||||
}
|
||||
|
||||
@@ -9,104 +9,107 @@
|
||||
|
||||
#include <Nazara/Core/String.hpp>
|
||||
|
||||
template<typename T> class NzVector3;
|
||||
template<typename T> class NzVector4;
|
||||
|
||||
template<typename T>
|
||||
class NzVector2
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzVector2() = default;
|
||||
NzVector2(T X, T Y);
|
||||
explicit NzVector2(T scale);
|
||||
NzVector2(const T vec[2]);
|
||||
template<typename U> explicit NzVector2(const NzVector2<U>& vec);
|
||||
NzVector2(const NzVector2& vec) = default;
|
||||
explicit NzVector2(const NzVector3<T>& vec);
|
||||
explicit NzVector2(const NzVector4<T>& vec);
|
||||
~NzVector2() = default;
|
||||
template<typename T> class Vector3;
|
||||
template<typename T> class Vector4;
|
||||
|
||||
T AbsDotProduct(const NzVector2& vec) const;
|
||||
T AngleBetween(const NzVector2& vec) const;
|
||||
template<typename T>
|
||||
class Vector2
|
||||
{
|
||||
public:
|
||||
Vector2() = default;
|
||||
Vector2(T X, T Y);
|
||||
explicit Vector2(T scale);
|
||||
Vector2(const T vec[2]);
|
||||
template<typename U> explicit Vector2(const Vector2<U>& vec);
|
||||
Vector2(const Vector2& vec) = default;
|
||||
explicit Vector2(const Vector3<T>& vec);
|
||||
explicit Vector2(const Vector4<T>& vec);
|
||||
~Vector2() = default;
|
||||
|
||||
T Distance(const NzVector2& vec) const;
|
||||
float Distancef(const NzVector2& vec) const;
|
||||
T DotProduct(const NzVector2& vec) const;
|
||||
T AbsDotProduct(const Vector2& vec) const;
|
||||
T AngleBetween(const Vector2& vec) const;
|
||||
|
||||
T GetLength() const;
|
||||
float GetLengthf() const;
|
||||
NzVector2 GetNormal(T* length = nullptr) const;
|
||||
T GetSquaredLength() const;
|
||||
T Distance(const Vector2& vec) const;
|
||||
float Distancef(const Vector2& vec) const;
|
||||
T DotProduct(const Vector2& vec) const;
|
||||
|
||||
NzVector2& MakeUnit();
|
||||
NzVector2& MakeUnitX();
|
||||
NzVector2& MakeUnitY();
|
||||
NzVector2& MakeZero();
|
||||
T GetLength() const;
|
||||
float GetLengthf() const;
|
||||
Vector2 GetNormal(T* length = nullptr) const;
|
||||
T GetSquaredLength() const;
|
||||
|
||||
NzVector2& Maximize(const NzVector2& vec);
|
||||
NzVector2& Minimize(const NzVector2& vec);
|
||||
Vector2& MakeUnit();
|
||||
Vector2& MakeUnitX();
|
||||
Vector2& MakeUnitY();
|
||||
Vector2& MakeZero();
|
||||
|
||||
NzVector2& Normalize(T* length = nullptr);
|
||||
Vector2& Maximize(const Vector2& vec);
|
||||
Vector2& Minimize(const Vector2& vec);
|
||||
|
||||
NzVector2& Set(T X, T Y);
|
||||
NzVector2& Set(T scale);
|
||||
NzVector2& Set(const T vec[2]);
|
||||
NzVector2& Set(const NzVector2& vec);
|
||||
NzVector2& Set(const NzVector3<T>& vec);
|
||||
NzVector2& Set(const NzVector4<T>& vec);
|
||||
template<typename U> NzVector2& Set(const NzVector2<U>& vec);
|
||||
Vector2& Normalize(T* length = nullptr);
|
||||
|
||||
T SquaredDistance(const NzVector2& vec) const;
|
||||
Vector2& Set(T X, T Y);
|
||||
Vector2& Set(T scale);
|
||||
Vector2& Set(const T vec[2]);
|
||||
Vector2& Set(const Vector2& vec);
|
||||
Vector2& Set(const Vector3<T>& vec);
|
||||
Vector2& Set(const Vector4<T>& vec);
|
||||
template<typename U> Vector2& Set(const Vector2<U>& vec);
|
||||
|
||||
NzString ToString() const;
|
||||
T SquaredDistance(const Vector2& vec) const;
|
||||
|
||||
operator T*();
|
||||
operator const T*() const;
|
||||
String ToString() const;
|
||||
|
||||
const NzVector2& operator+() const;
|
||||
NzVector2 operator-() const;
|
||||
operator T*();
|
||||
operator const T*() const;
|
||||
|
||||
NzVector2 operator+(const NzVector2& vec) const;
|
||||
NzVector2 operator-(const NzVector2& vec) const;
|
||||
NzVector2 operator*(const NzVector2& vec) const;
|
||||
NzVector2 operator*(T scale) const;
|
||||
NzVector2 operator/(const NzVector2& vec) const;
|
||||
NzVector2 operator/(T scale) const;
|
||||
const Vector2& operator+() const;
|
||||
Vector2 operator-() const;
|
||||
|
||||
NzVector2& operator+=(const NzVector2& vec);
|
||||
NzVector2& operator-=(const NzVector2& vec);
|
||||
NzVector2& operator*=(const NzVector2& vec);
|
||||
NzVector2& operator*=(T scale);
|
||||
NzVector2& operator/=(const NzVector2& vec);
|
||||
NzVector2& operator/=(T scale);
|
||||
Vector2 operator+(const Vector2& vec) const;
|
||||
Vector2 operator-(const Vector2& vec) const;
|
||||
Vector2 operator*(const Vector2& vec) const;
|
||||
Vector2 operator*(T scale) const;
|
||||
Vector2 operator/(const Vector2& vec) const;
|
||||
Vector2 operator/(T scale) const;
|
||||
|
||||
bool operator==(const NzVector2& vec) const;
|
||||
bool operator!=(const NzVector2& vec) const;
|
||||
bool operator<(const NzVector2& vec) const;
|
||||
bool operator<=(const NzVector2& vec) const;
|
||||
bool operator>(const NzVector2& vec) const;
|
||||
bool operator>=(const NzVector2& vec) const;
|
||||
Vector2& operator+=(const Vector2& vec);
|
||||
Vector2& operator-=(const Vector2& vec);
|
||||
Vector2& operator*=(const Vector2& vec);
|
||||
Vector2& operator*=(T scale);
|
||||
Vector2& operator/=(const Vector2& vec);
|
||||
Vector2& operator/=(T scale);
|
||||
|
||||
static NzVector2 Lerp(const NzVector2& from, const NzVector2& to, T interpolation);
|
||||
static NzVector2 Unit();
|
||||
static NzVector2 UnitX();
|
||||
static NzVector2 UnitY();
|
||||
static NzVector2 Zero();
|
||||
bool operator==(const Vector2& vec) const;
|
||||
bool operator!=(const Vector2& vec) const;
|
||||
bool operator<(const Vector2& vec) const;
|
||||
bool operator<=(const Vector2& vec) const;
|
||||
bool operator>(const Vector2& vec) const;
|
||||
bool operator>=(const Vector2& vec) const;
|
||||
|
||||
T x, y;
|
||||
};
|
||||
static Vector2 Lerp(const Vector2& from, const Vector2& to, T interpolation);
|
||||
static Vector2 Unit();
|
||||
static Vector2 UnitX();
|
||||
static Vector2 UnitY();
|
||||
static Vector2 Zero();
|
||||
|
||||
template<typename T> std::ostream& operator<<(std::ostream& out, const NzVector2<T>& vec);
|
||||
T x, y;
|
||||
};
|
||||
|
||||
template<typename T> NzVector2<T> operator*(T scale, const NzVector2<T>& vec);
|
||||
template<typename T> NzVector2<T> operator/(T scale, const NzVector2<T>& vec);
|
||||
template<typename T> std::ostream& operator<<(std::ostream& out, const Vector2<T>& vec);
|
||||
|
||||
typedef NzVector2<double> NzVector2d;
|
||||
typedef NzVector2<float> NzVector2f;
|
||||
typedef NzVector2<int> NzVector2i;
|
||||
typedef NzVector2<unsigned int> NzVector2ui;
|
||||
typedef NzVector2<nzInt32> NzVector2i32;
|
||||
typedef NzVector2<nzUInt32> NzVector2ui32;
|
||||
template<typename T> Vector2<T> operator*(T scale, const Vector2<T>& vec);
|
||||
template<typename T> Vector2<T> operator/(T scale, const Vector2<T>& vec);
|
||||
|
||||
typedef Vector2<double> Vector2d;
|
||||
typedef Vector2<float> Vector2f;
|
||||
typedef Vector2<int> Vector2i;
|
||||
typedef Vector2<unsigned int> Vector2ui;
|
||||
typedef Vector2<Int32> Vector2i32;
|
||||
typedef Vector2<UInt32> Vector2ui32;
|
||||
}
|
||||
|
||||
#include <Nazara/Math/Vector2.inl>
|
||||
|
||||
|
||||
@@ -11,506 +11,509 @@
|
||||
|
||||
#define F(a) static_cast<T>(a)
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>::NzVector2(T X, T Y)
|
||||
namespace Nz
|
||||
{
|
||||
Set(X, Y);
|
||||
}
|
||||
template<typename T>
|
||||
Vector2<T>::Vector2(T X, T Y)
|
||||
{
|
||||
Set(X, Y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>::NzVector2(T scale)
|
||||
{
|
||||
Set(scale);
|
||||
}
|
||||
template<typename T>
|
||||
Vector2<T>::Vector2(T scale)
|
||||
{
|
||||
Set(scale);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>::NzVector2(const T vec[2])
|
||||
{
|
||||
Set(vec);
|
||||
}
|
||||
template<typename T>
|
||||
Vector2<T>::Vector2(const T vec[2])
|
||||
{
|
||||
Set(vec);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzVector2<T>::NzVector2(const NzVector2<U>& vec)
|
||||
{
|
||||
Set(vec);
|
||||
}
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
Vector2<T>::Vector2(const Vector2<U>& vec)
|
||||
{
|
||||
Set(vec);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>::NzVector2(const NzVector3<T>& vec)
|
||||
{
|
||||
Set(vec);
|
||||
}
|
||||
template<typename T>
|
||||
Vector2<T>::Vector2(const Vector3<T>& vec)
|
||||
{
|
||||
Set(vec);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>::NzVector2(const NzVector4<T>& vec)
|
||||
{
|
||||
Set(vec);
|
||||
}
|
||||
template<typename T>
|
||||
Vector2<T>::Vector2(const Vector4<T>& vec)
|
||||
{
|
||||
Set(vec);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzVector2<T>::AbsDotProduct(const NzVector2& vec) const
|
||||
{
|
||||
return std::abs(x * vec.x) + std::abs(y * vec.y);
|
||||
}
|
||||
template<typename T>
|
||||
T Vector2<T>::AbsDotProduct(const Vector2& vec) const
|
||||
{
|
||||
return std::abs(x * vec.x) + std::abs(y * vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzVector2<T>::AngleBetween(const NzVector2& vec) const
|
||||
{
|
||||
return NzFromRadians(std::atan2(vec.y, vec.x) - std::atan2(y, x));
|
||||
}
|
||||
template<typename T>
|
||||
T Vector2<T>::AngleBetween(const Vector2& vec) const
|
||||
{
|
||||
return FromRadians(std::atan2(vec.y, vec.x) - std::atan2(y, x));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzVector2<T>::Distance(const NzVector2& vec) const
|
||||
{
|
||||
return std::sqrt(SquaredDistance(vec));
|
||||
}
|
||||
template<typename T>
|
||||
T Vector2<T>::Distance(const Vector2& vec) const
|
||||
{
|
||||
return std::sqrt(SquaredDistance(vec));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
float NzVector2<T>::Distancef(const NzVector2& vec) const
|
||||
{
|
||||
return std::sqrt(static_cast<float>(SquaredDistance(vec)));
|
||||
}
|
||||
template<typename T>
|
||||
float Vector2<T>::Distancef(const Vector2& vec) const
|
||||
{
|
||||
return std::sqrt(static_cast<float>(SquaredDistance(vec)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzVector2<T>::DotProduct(const NzVector2& vec) const
|
||||
{
|
||||
return x*vec.x + y*vec.y;
|
||||
}
|
||||
template<typename T>
|
||||
T Vector2<T>::DotProduct(const Vector2& vec) const
|
||||
{
|
||||
return x*vec.x + y*vec.y;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzVector2<T>::GetLength() const
|
||||
{
|
||||
return std::sqrt(GetSquaredLength());
|
||||
}
|
||||
template<typename T>
|
||||
T Vector2<T>::GetLength() const
|
||||
{
|
||||
return std::sqrt(GetSquaredLength());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
float NzVector2<T>::GetLengthf() const
|
||||
{
|
||||
return std::sqrt(static_cast<float>(GetSquaredLength()));
|
||||
}
|
||||
template<typename T>
|
||||
float Vector2<T>::GetLengthf() const
|
||||
{
|
||||
return std::sqrt(static_cast<float>(GetSquaredLength()));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzVector2<T>::GetNormal(T* length) const
|
||||
{
|
||||
NzVector2 vec(*this);
|
||||
vec.Normalize(length);
|
||||
template<typename T>
|
||||
Vector2<T> Vector2<T>::GetNormal(T* length) const
|
||||
{
|
||||
Vector2 vec(*this);
|
||||
vec.Normalize(length);
|
||||
|
||||
return vec;
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzVector2<T>::GetSquaredLength() const
|
||||
{
|
||||
return x*x + y*y;
|
||||
}
|
||||
template<typename T>
|
||||
T Vector2<T>::GetSquaredLength() const
|
||||
{
|
||||
return x*x + y*y;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>& NzVector2<T>::MakeUnit()
|
||||
{
|
||||
return Set(F(1.0), F(1.0));
|
||||
}
|
||||
template<typename T>
|
||||
Vector2<T>& Vector2<T>::MakeUnit()
|
||||
{
|
||||
return Set(F(1.0), F(1.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>& NzVector2<T>::MakeUnitX()
|
||||
{
|
||||
return Set(F(1.0), F(0.0));
|
||||
}
|
||||
template<typename T>
|
||||
Vector2<T>& Vector2<T>::MakeUnitX()
|
||||
{
|
||||
return Set(F(1.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>& NzVector2<T>::MakeUnitY()
|
||||
{
|
||||
return Set(F(0.0), F(1.0));
|
||||
}
|
||||
template<typename T>
|
||||
Vector2<T>& Vector2<T>::MakeUnitY()
|
||||
{
|
||||
return Set(F(0.0), F(1.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>& NzVector2<T>::MakeZero()
|
||||
{
|
||||
return Set(F(0.0), F(0.0));
|
||||
}
|
||||
template<typename T>
|
||||
Vector2<T>& Vector2<T>::MakeZero()
|
||||
{
|
||||
return Set(F(0.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>& NzVector2<T>::Maximize(const NzVector2& vec)
|
||||
{
|
||||
if (vec.x > x)
|
||||
template<typename T>
|
||||
Vector2<T>& Vector2<T>::Maximize(const Vector2& vec)
|
||||
{
|
||||
if (vec.x > x)
|
||||
x = vec.x;
|
||||
|
||||
if (vec.y > y)
|
||||
y = vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T>& Vector2<T>::Minimize(const Vector2& vec)
|
||||
{
|
||||
if (vec.x < x)
|
||||
x = vec.x;
|
||||
|
||||
if (vec.y < y)
|
||||
y = vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T>& Vector2<T>::Normalize(T* length)
|
||||
{
|
||||
T norm = GetLength();
|
||||
if (norm > F(0.0))
|
||||
{
|
||||
T invNorm = F(1.0) / norm;
|
||||
x *= invNorm;
|
||||
y *= invNorm;
|
||||
}
|
||||
|
||||
if (length)
|
||||
*length = norm;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T>& Vector2<T>::Set(T X, T Y)
|
||||
{
|
||||
x = X;
|
||||
y = Y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T>& Vector2<T>::Set(T scale)
|
||||
{
|
||||
x = scale;
|
||||
y = scale;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T>& Vector2<T>::Set(const T vec[2])
|
||||
{
|
||||
std::memcpy(&x, vec, 2*sizeof(T));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T>& Vector2<T>::Set(const Vector2& vec)
|
||||
{
|
||||
std::memcpy(this, &vec, sizeof(Vector2));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
Vector2<T>& Vector2<T>::Set(const Vector2<U>& vec)
|
||||
{
|
||||
x = F(vec.x);
|
||||
y = F(vec.y);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T>& Vector2<T>::Set(const Vector3<T>& vec)
|
||||
{
|
||||
x = vec.x;
|
||||
|
||||
if (vec.y > y)
|
||||
y = vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>& NzVector2<T>::Minimize(const NzVector2& vec)
|
||||
{
|
||||
if (vec.x < x)
|
||||
template<typename T>
|
||||
Vector2<T>& Vector2<T>::Set(const Vector4<T>& vec)
|
||||
{
|
||||
x = vec.x;
|
||||
|
||||
if (vec.y < y)
|
||||
y = vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>& NzVector2<T>::Normalize(T* length)
|
||||
{
|
||||
T norm = GetLength();
|
||||
if (norm > F(0.0))
|
||||
{
|
||||
T invNorm = F(1.0) / norm;
|
||||
x *= invNorm;
|
||||
y *= invNorm;
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (length)
|
||||
*length = norm;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>& NzVector2<T>::Set(T X, T Y)
|
||||
{
|
||||
x = X;
|
||||
y = Y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>& NzVector2<T>::Set(T scale)
|
||||
{
|
||||
x = scale;
|
||||
y = scale;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>& NzVector2<T>::Set(const T vec[2])
|
||||
{
|
||||
std::memcpy(&x, vec, 2*sizeof(T));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>& NzVector2<T>::Set(const NzVector2& vec)
|
||||
{
|
||||
std::memcpy(this, &vec, sizeof(NzVector2));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzVector2<T>& NzVector2<T>::Set(const NzVector2<U>& vec)
|
||||
{
|
||||
x = F(vec.x);
|
||||
y = F(vec.y);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>& NzVector2<T>::Set(const NzVector3<T>& vec)
|
||||
{
|
||||
x = vec.x;
|
||||
y = vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>& NzVector2<T>::Set(const NzVector4<T>& vec)
|
||||
{
|
||||
x = vec.x;
|
||||
y = vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzVector2<T>::SquaredDistance(const NzVector2& vec) const
|
||||
{
|
||||
return (*this - vec).GetSquaredLength();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzString NzVector2<T>::ToString() const
|
||||
{
|
||||
NzStringStream ss;
|
||||
|
||||
return ss << "Vector2(" << x << ", " << y << ')';
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>::operator T*()
|
||||
{
|
||||
return &x;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>::operator const T*() const
|
||||
{
|
||||
return &x;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const NzVector2<T>& NzVector2<T>::operator+() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzVector2<T>::operator-() const
|
||||
{
|
||||
return NzVector2(-x, -y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzVector2<T>::operator+(const NzVector2& vec) const
|
||||
{
|
||||
return NzVector2(x + vec.x, y + vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzVector2<T>::operator-(const NzVector2& vec) const
|
||||
{
|
||||
return NzVector2(x - vec.x, y - vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzVector2<T>::operator*(const NzVector2& vec) const
|
||||
{
|
||||
return NzVector2(x * vec.x, y * vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzVector2<T>::operator*(T scale) const
|
||||
{
|
||||
return NzVector2(x * scale, y * scale);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzVector2<T>::operator/(const NzVector2& vec) const
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (NzNumberEquals(vec.x, F(0.0)) || NzNumberEquals(vec.y, F(0.0)))
|
||||
template<typename T>
|
||||
T Vector2<T>::SquaredDistance(const Vector2& vec) const
|
||||
{
|
||||
NzString error("Division by zero");
|
||||
|
||||
NazaraError(error);
|
||||
throw std::domain_error(error);
|
||||
return (*this - vec).GetSquaredLength();
|
||||
}
|
||||
#endif
|
||||
|
||||
return NzVector2(x / vec.x, y / vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzVector2<T>::operator/(T scale) const
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (NzNumberEquals(scale, F(0.0)))
|
||||
template<typename T>
|
||||
String Vector2<T>::ToString() const
|
||||
{
|
||||
NzString error("Division by zero");
|
||||
StringStream ss;
|
||||
|
||||
NazaraError(error);
|
||||
throw std::domain_error(error);
|
||||
return ss << "Vector2(" << x << ", " << y << ')';
|
||||
}
|
||||
#endif
|
||||
|
||||
return NzVector2(x / scale, y / scale);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>& NzVector2<T>::operator+=(const NzVector2& vec)
|
||||
{
|
||||
x += vec.x;
|
||||
y += vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>& NzVector2<T>::operator-=(const NzVector2& vec)
|
||||
{
|
||||
x -= vec.x;
|
||||
y -= vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>& NzVector2<T>::operator*=(const NzVector2& vec)
|
||||
{
|
||||
x *= vec.x;
|
||||
y *= vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>& NzVector2<T>::operator*=(T scale)
|
||||
{
|
||||
x *= scale;
|
||||
y *= scale;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>& NzVector2<T>::operator/=(const NzVector2& vec)
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (NzNumberEquals(vec.x, F(0.0)) || NzNumberEquals(vec.y, F(0.0)))
|
||||
template<typename T>
|
||||
Vector2<T>::operator T*()
|
||||
{
|
||||
NzString error("Division by zero");
|
||||
|
||||
NazaraError(error);
|
||||
throw std::domain_error(error);
|
||||
return &x;
|
||||
}
|
||||
#endif
|
||||
|
||||
x /= vec.x;
|
||||
y /= vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T>& NzVector2<T>::operator/=(T scale)
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (NzNumberEquals(scale, F(0.0)))
|
||||
template<typename T>
|
||||
Vector2<T>::operator const T*() const
|
||||
{
|
||||
NzString error("Division by zero");
|
||||
|
||||
NazaraError(error);
|
||||
throw std::domain_error(error);
|
||||
return &x;
|
||||
}
|
||||
#endif
|
||||
|
||||
x /= scale;
|
||||
y /= scale;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzVector2<T>::operator==(const NzVector2& vec) const
|
||||
{
|
||||
return NzNumberEquals(x, vec.x) &&
|
||||
NzNumberEquals(y, vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzVector2<T>::operator!=(const NzVector2& vec) const
|
||||
{
|
||||
return !operator==(vec);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzVector2<T>::operator<(const NzVector2& vec) const
|
||||
{
|
||||
if (x == vec.x)
|
||||
return y < vec.y;
|
||||
else
|
||||
return x < vec.x;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzVector2<T>::operator<=(const NzVector2& vec) const
|
||||
{
|
||||
if (x == vec.x)
|
||||
return y <= vec.y;
|
||||
else
|
||||
return x < vec.x;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzVector2<T>::operator>(const NzVector2& vec) const
|
||||
{
|
||||
return !operator<=(vec);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
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>::Unit()
|
||||
{
|
||||
NzVector2 vector;
|
||||
vector.MakeUnit();
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzVector2<T>::UnitX()
|
||||
{
|
||||
NzVector2 vector;
|
||||
vector.MakeUnitX();
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzVector2<T>::UnitY()
|
||||
{
|
||||
NzVector2 vector;
|
||||
vector.MakeUnitY();
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> NzVector2<T>::Zero()
|
||||
{
|
||||
NzVector2 vector;
|
||||
vector.MakeZero();
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzVector2<T>& vec)
|
||||
{
|
||||
return out << vec.ToString();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> operator*(T scale, const NzVector2<T>& vec)
|
||||
{
|
||||
return NzVector2<T>(scale * vec.x, scale * vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector2<T> operator/(T scale, const NzVector2<T>& vec)
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (NzNumberEquals(vec.x, F(0.0)) || NzNumberEquals(vec.y, F(0.0)))
|
||||
template<typename T>
|
||||
const Vector2<T>& Vector2<T>::operator+() const
|
||||
{
|
||||
NzString error("Division by zero");
|
||||
|
||||
NazaraError(error);
|
||||
throw std::domain_error(error);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NzVector2<T>(scale/vec.x, scale/vec.y);
|
||||
template<typename T>
|
||||
Vector2<T> Vector2<T>::operator-() const
|
||||
{
|
||||
return Vector2(-x, -y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> Vector2<T>::operator+(const Vector2& vec) const
|
||||
{
|
||||
return Vector2(x + vec.x, y + vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> Vector2<T>::operator-(const Vector2& vec) const
|
||||
{
|
||||
return Vector2(x - vec.x, y - vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> Vector2<T>::operator*(const Vector2& vec) const
|
||||
{
|
||||
return Vector2(x * vec.x, y * vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> Vector2<T>::operator*(T scale) const
|
||||
{
|
||||
return Vector2(x * scale, y * scale);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> Vector2<T>::operator/(const Vector2& vec) const
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (NumberEquals(vec.x, F(0.0)) || NumberEquals(vec.y, F(0.0)))
|
||||
{
|
||||
String error("Division by zero");
|
||||
|
||||
NazaraError(error);
|
||||
throw std::domain_error(error);
|
||||
}
|
||||
#endif
|
||||
|
||||
return Vector2(x / vec.x, y / vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> Vector2<T>::operator/(T scale) const
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (NumberEquals(scale, F(0.0)))
|
||||
{
|
||||
String error("Division by zero");
|
||||
|
||||
NazaraError(error);
|
||||
throw std::domain_error(error);
|
||||
}
|
||||
#endif
|
||||
|
||||
return Vector2(x / scale, y / scale);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T>& Vector2<T>::operator+=(const Vector2& vec)
|
||||
{
|
||||
x += vec.x;
|
||||
y += vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T>& Vector2<T>::operator-=(const Vector2& vec)
|
||||
{
|
||||
x -= vec.x;
|
||||
y -= vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T>& Vector2<T>::operator*=(const Vector2& vec)
|
||||
{
|
||||
x *= vec.x;
|
||||
y *= vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T>& Vector2<T>::operator*=(T scale)
|
||||
{
|
||||
x *= scale;
|
||||
y *= scale;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T>& Vector2<T>::operator/=(const Vector2& vec)
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (NumberEquals(vec.x, F(0.0)) || NumberEquals(vec.y, F(0.0)))
|
||||
{
|
||||
String error("Division by zero");
|
||||
|
||||
NazaraError(error);
|
||||
throw std::domain_error(error);
|
||||
}
|
||||
#endif
|
||||
|
||||
x /= vec.x;
|
||||
y /= vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T>& Vector2<T>::operator/=(T scale)
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (NumberEquals(scale, F(0.0)))
|
||||
{
|
||||
String error("Division by zero");
|
||||
|
||||
NazaraError(error);
|
||||
throw std::domain_error(error);
|
||||
}
|
||||
#endif
|
||||
|
||||
x /= scale;
|
||||
y /= scale;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Vector2<T>::operator==(const Vector2& vec) const
|
||||
{
|
||||
return NumberEquals(x, vec.x) &&
|
||||
NumberEquals(y, vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Vector2<T>::operator!=(const Vector2& vec) const
|
||||
{
|
||||
return !operator==(vec);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Vector2<T>::operator<(const Vector2& vec) const
|
||||
{
|
||||
if (x == vec.x)
|
||||
return y < vec.y;
|
||||
else
|
||||
return x < vec.x;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Vector2<T>::operator<=(const Vector2& vec) const
|
||||
{
|
||||
if (x == vec.x)
|
||||
return y <= vec.y;
|
||||
else
|
||||
return x < vec.x;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Vector2<T>::operator>(const Vector2& vec) const
|
||||
{
|
||||
return !operator<=(vec);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Vector2<T>::operator>=(const Vector2& vec) const
|
||||
{
|
||||
return !operator<(vec);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> Vector2<T>::Lerp(const Vector2& from, const Vector2& to, T interpolation)
|
||||
{
|
||||
return Lerp(from, to, interpolation);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> Vector2<T>::Unit()
|
||||
{
|
||||
Vector2 vector;
|
||||
vector.MakeUnit();
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> Vector2<T>::UnitX()
|
||||
{
|
||||
Vector2 vector;
|
||||
vector.MakeUnitX();
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> Vector2<T>::UnitY()
|
||||
{
|
||||
Vector2 vector;
|
||||
vector.MakeUnitY();
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> Vector2<T>::Zero()
|
||||
{
|
||||
Vector2 vector;
|
||||
vector.MakeZero();
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const Vector2<T>& vec)
|
||||
{
|
||||
return out << vec.ToString();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> operator*(T scale, const Vector2<T>& vec)
|
||||
{
|
||||
return Vector2<T>(scale * vec.x, scale * vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector2<T> operator/(T scale, const Vector2<T>& vec)
|
||||
{
|
||||
#if NAZARA_MATH_SAFE
|
||||
if (NumberEquals(vec.x, F(0.0)) || NumberEquals(vec.y, F(0.0)))
|
||||
{
|
||||
String error("Division by zero");
|
||||
|
||||
NazaraError(error);
|
||||
throw std::domain_error(error);
|
||||
}
|
||||
#endif
|
||||
|
||||
return Vector2<T>(scale/vec.x, scale/vec.y);
|
||||
}
|
||||
}
|
||||
|
||||
#undef F
|
||||
|
||||
@@ -9,128 +9,131 @@
|
||||
|
||||
#include <Nazara/Core/String.hpp>
|
||||
|
||||
template<typename T> class NzVector2;
|
||||
template<typename T> class NzVector4;
|
||||
|
||||
template<typename T>
|
||||
class NzVector3
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzVector3() = default;
|
||||
NzVector3(T X, T Y, T Z);
|
||||
NzVector3(T X, const NzVector2<T>& vec);
|
||||
explicit NzVector3(T scale);
|
||||
NzVector3(const T vec[3]);
|
||||
NzVector3(const NzVector2<T>& vec, T Z = 0.0);
|
||||
template<typename U> explicit NzVector3(const NzVector3<U>& vec);
|
||||
NzVector3(const NzVector3& vec) = default;
|
||||
explicit NzVector3(const NzVector4<T>& vec);
|
||||
~NzVector3() = default;
|
||||
template<typename T> class Vector2;
|
||||
template<typename T> class Vector4;
|
||||
|
||||
T AbsDotProduct(const NzVector3& vec) const;
|
||||
T AngleBetween(const NzVector3& vec) const;
|
||||
template<typename T>
|
||||
class Vector3
|
||||
{
|
||||
public:
|
||||
Vector3() = default;
|
||||
Vector3(T X, T Y, T Z);
|
||||
Vector3(T X, const Vector2<T>& vec);
|
||||
explicit Vector3(T scale);
|
||||
Vector3(const T vec[3]);
|
||||
Vector3(const Vector2<T>& vec, T Z = 0.0);
|
||||
template<typename U> explicit Vector3(const Vector3<U>& vec);
|
||||
Vector3(const Vector3& vec) = default;
|
||||
explicit Vector3(const Vector4<T>& vec);
|
||||
~Vector3() = default;
|
||||
|
||||
NzVector3 CrossProduct(const NzVector3& vec) const;
|
||||
T AbsDotProduct(const Vector3& vec) const;
|
||||
T AngleBetween(const Vector3& vec) const;
|
||||
|
||||
T Distance(const NzVector3& vec) const;
|
||||
float Distancef(const NzVector3& vec) const;
|
||||
T DotProduct(const NzVector3& vec) const;
|
||||
Vector3 CrossProduct(const Vector3& vec) const;
|
||||
|
||||
T GetLength() const;
|
||||
float GetLengthf() const;
|
||||
NzVector3 GetNormal(T* length = nullptr) const;
|
||||
T GetSquaredLength() const;
|
||||
T Distance(const Vector3& vec) const;
|
||||
float Distancef(const Vector3& vec) const;
|
||||
T DotProduct(const Vector3& vec) const;
|
||||
|
||||
NzVector3& MakeBackward();
|
||||
NzVector3& MakeDown();
|
||||
NzVector3& MakeForward();
|
||||
NzVector3& MakeLeft();
|
||||
NzVector3& MakeRight();
|
||||
NzVector3& MakeUnit();
|
||||
NzVector3& MakeUnitX();
|
||||
NzVector3& MakeUnitY();
|
||||
NzVector3& MakeUnitZ();
|
||||
NzVector3& MakeUp();
|
||||
NzVector3& MakeZero();
|
||||
T GetLength() const;
|
||||
float GetLengthf() const;
|
||||
Vector3 GetNormal(T* length = nullptr) const;
|
||||
T GetSquaredLength() const;
|
||||
|
||||
NzVector3& Maximize(const NzVector3& vec);
|
||||
NzVector3& Minimize(const NzVector3& vec);
|
||||
Vector3& MakeBackward();
|
||||
Vector3& MakeDown();
|
||||
Vector3& MakeForward();
|
||||
Vector3& MakeLeft();
|
||||
Vector3& MakeRight();
|
||||
Vector3& MakeUnit();
|
||||
Vector3& MakeUnitX();
|
||||
Vector3& MakeUnitY();
|
||||
Vector3& MakeUnitZ();
|
||||
Vector3& MakeUp();
|
||||
Vector3& MakeZero();
|
||||
|
||||
NzVector3& Normalize(T* length = nullptr);
|
||||
Vector3& Maximize(const Vector3& vec);
|
||||
Vector3& Minimize(const Vector3& vec);
|
||||
|
||||
NzVector3& Set(T X, T Y, T Z);
|
||||
NzVector3& Set(T X, const NzVector2<T>& vec);
|
||||
NzVector3& Set(T scale);
|
||||
NzVector3& Set(const T vec[3]);
|
||||
NzVector3& Set(const NzVector2<T>& vec, T Z = 0.0);
|
||||
NzVector3& Set(const NzVector3<T>& vec);
|
||||
template<typename U> NzVector3& Set(const NzVector3<U>& vec);
|
||||
NzVector3& Set(const NzVector4<T>& vec);
|
||||
Vector3& Normalize(T* length = nullptr);
|
||||
|
||||
T SquaredDistance(const NzVector3& vec) const;
|
||||
Vector3& Set(T X, T Y, T Z);
|
||||
Vector3& Set(T X, const Vector2<T>& vec);
|
||||
Vector3& Set(T scale);
|
||||
Vector3& Set(const T vec[3]);
|
||||
Vector3& Set(const Vector2<T>& vec, T Z = 0.0);
|
||||
Vector3& Set(const Vector3<T>& vec);
|
||||
template<typename U> Vector3& Set(const Vector3<U>& vec);
|
||||
Vector3& Set(const Vector4<T>& vec);
|
||||
|
||||
NzString ToString() const;
|
||||
T SquaredDistance(const Vector3& vec) const;
|
||||
|
||||
operator T*();
|
||||
operator const T*() const;
|
||||
String ToString() const;
|
||||
|
||||
const NzVector3& operator+() const;
|
||||
NzVector3 operator-() const;
|
||||
operator T*();
|
||||
operator const T*() const;
|
||||
|
||||
NzVector3 operator+(const NzVector3& vec) const;
|
||||
NzVector3 operator-(const NzVector3& vec) const;
|
||||
NzVector3 operator*(const NzVector3& vec) const;
|
||||
NzVector3 operator*(T scale) const;
|
||||
NzVector3 operator/(const NzVector3& vec) const;
|
||||
NzVector3 operator/(T scale) const;
|
||||
const Vector3& operator+() const;
|
||||
Vector3 operator-() const;
|
||||
|
||||
NzVector3& operator+=(const NzVector3& vec);
|
||||
NzVector3& operator-=(const NzVector3& vec);
|
||||
NzVector3& operator*=(const NzVector3& vec);
|
||||
NzVector3& operator*=(T scale);
|
||||
NzVector3& operator/=(const NzVector3& vec);
|
||||
NzVector3& operator/=(T scale);
|
||||
Vector3 operator+(const Vector3& vec) const;
|
||||
Vector3 operator-(const Vector3& vec) const;
|
||||
Vector3 operator*(const Vector3& vec) const;
|
||||
Vector3 operator*(T scale) const;
|
||||
Vector3 operator/(const Vector3& vec) const;
|
||||
Vector3 operator/(T scale) const;
|
||||
|
||||
bool operator==(const NzVector3& vec) const;
|
||||
bool operator!=(const NzVector3& vec) const;
|
||||
bool operator<(const NzVector3& vec) const;
|
||||
bool operator<=(const NzVector3& vec) const;
|
||||
bool operator>(const NzVector3& vec) const;
|
||||
bool operator>=(const NzVector3& vec) const;
|
||||
Vector3& operator+=(const Vector3& vec);
|
||||
Vector3& operator-=(const Vector3& vec);
|
||||
Vector3& operator*=(const Vector3& vec);
|
||||
Vector3& operator*=(T scale);
|
||||
Vector3& operator/=(const Vector3& vec);
|
||||
Vector3& operator/=(T scale);
|
||||
|
||||
static NzVector3 Backward();
|
||||
static NzVector3 CrossProduct(const NzVector3& vec1, const NzVector3& vec2);
|
||||
static T DotProduct(const NzVector3& vec1, const NzVector3& vec2);
|
||||
static T Distance(const NzVector3& vec1, const NzVector3& vec2);
|
||||
static float Distancef(const NzVector3& vec1, const NzVector3& vec2);
|
||||
static NzVector3 Down();
|
||||
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 Right();
|
||||
static T SquaredDistance(const NzVector3& vec1, const NzVector3& vec2);
|
||||
static NzVector3 Unit();
|
||||
static NzVector3 UnitX();
|
||||
static NzVector3 UnitY();
|
||||
static NzVector3 UnitZ();
|
||||
static NzVector3 Up();
|
||||
static NzVector3 Zero();
|
||||
bool operator==(const Vector3& vec) const;
|
||||
bool operator!=(const Vector3& vec) const;
|
||||
bool operator<(const Vector3& vec) const;
|
||||
bool operator<=(const Vector3& vec) const;
|
||||
bool operator>(const Vector3& vec) const;
|
||||
bool operator>=(const Vector3& vec) const;
|
||||
|
||||
T x, y, z;
|
||||
};
|
||||
static Vector3 Backward();
|
||||
static Vector3 CrossProduct(const Vector3& vec1, const Vector3& vec2);
|
||||
static T DotProduct(const Vector3& vec1, const Vector3& vec2);
|
||||
static T Distance(const Vector3& vec1, const Vector3& vec2);
|
||||
static float Distancef(const Vector3& vec1, const Vector3& vec2);
|
||||
static Vector3 Down();
|
||||
static Vector3 Forward();
|
||||
static Vector3 Left();
|
||||
static Vector3 Lerp(const Vector3& from, const Vector3& to, T interpolation);
|
||||
static Vector3 Normalize(const Vector3& vec);
|
||||
static Vector3 Right();
|
||||
static T SquaredDistance(const Vector3& vec1, const Vector3& vec2);
|
||||
static Vector3 Unit();
|
||||
static Vector3 UnitX();
|
||||
static Vector3 UnitY();
|
||||
static Vector3 UnitZ();
|
||||
static Vector3 Up();
|
||||
static Vector3 Zero();
|
||||
|
||||
template<typename T> std::ostream& operator<<(std::ostream& out, const NzVector3<T>& vec);
|
||||
T x, y, z;
|
||||
};
|
||||
|
||||
template<typename T> NzVector3<T> operator*(T scale, const NzVector3<T>& vec);
|
||||
template<typename T> NzVector3<T> operator/(T scale, const NzVector3<T>& vec);
|
||||
template<typename T> std::ostream& operator<<(std::ostream& out, const Vector3<T>& vec);
|
||||
|
||||
typedef NzVector3<double> NzVector3d;
|
||||
typedef NzVector3<float> NzVector3f;
|
||||
typedef NzVector3<int> NzVector3i;
|
||||
typedef NzVector3<unsigned int> NzVector3ui;
|
||||
typedef NzVector3<nzInt32> NzVector3i32;
|
||||
typedef NzVector3<nzUInt32> NzVector3ui32;
|
||||
template<typename T> Vector3<T> operator*(T scale, const Vector3<T>& vec);
|
||||
template<typename T> Vector3<T> operator/(T scale, const Vector3<T>& vec);
|
||||
|
||||
typedef Vector3<double> Vector3d;
|
||||
typedef Vector3<float> Vector3f;
|
||||
typedef Vector3<int> Vector3i;
|
||||
typedef Vector3<unsigned int> Vector3ui;
|
||||
typedef Vector3<Int32> Vector3i32;
|
||||
typedef Vector3<UInt32> Vector3ui32;
|
||||
}
|
||||
|
||||
#include <Nazara/Math/Vector3.inl>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,101 +9,104 @@
|
||||
|
||||
#include <Nazara/Core/String.hpp>
|
||||
|
||||
template<typename T> class NzVector2;
|
||||
template<typename T> class NzVector3;
|
||||
|
||||
template<typename T>
|
||||
class NzVector4
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzVector4() = default;
|
||||
NzVector4(T X, T Y, T Z, T W = 1.0);
|
||||
NzVector4(T X, T Y, const NzVector2<T>& vec);
|
||||
NzVector4(T X, const NzVector2<T>& vec, T W);
|
||||
NzVector4(T X, const NzVector3<T>& vec);
|
||||
explicit NzVector4(T scale);
|
||||
NzVector4(const T vec[4]);
|
||||
NzVector4(const NzVector2<T>& vec, T Z = 0.0, T W = 1.0);
|
||||
NzVector4(const NzVector3<T>& vec, T W = 0.0);
|
||||
template<typename U> explicit NzVector4(const NzVector4<U>& vec);
|
||||
NzVector4(const NzVector4& vec) = default;
|
||||
~NzVector4() = default;
|
||||
template<typename T> class Vector2;
|
||||
template<typename T> class Vector3;
|
||||
|
||||
T AbsDotProduct(const NzVector4& vec) const;
|
||||
template<typename T>
|
||||
class Vector4
|
||||
{
|
||||
public:
|
||||
Vector4() = default;
|
||||
Vector4(T X, T Y, T Z, T W = 1.0);
|
||||
Vector4(T X, T Y, const Vector2<T>& vec);
|
||||
Vector4(T X, const Vector2<T>& vec, T W);
|
||||
Vector4(T X, const Vector3<T>& vec);
|
||||
explicit Vector4(T scale);
|
||||
Vector4(const T vec[4]);
|
||||
Vector4(const Vector2<T>& vec, T Z = 0.0, T W = 1.0);
|
||||
Vector4(const Vector3<T>& vec, T W = 0.0);
|
||||
template<typename U> explicit Vector4(const Vector4<U>& vec);
|
||||
Vector4(const Vector4& vec) = default;
|
||||
~Vector4() = default;
|
||||
|
||||
T DotProduct(const NzVector4& vec) const;
|
||||
T AbsDotProduct(const Vector4& vec) const;
|
||||
|
||||
NzVector4 GetNormal(T* length = nullptr) const;
|
||||
T DotProduct(const Vector4& vec) const;
|
||||
|
||||
NzVector4& MakeUnitX();
|
||||
NzVector4& MakeUnitY();
|
||||
NzVector4& MakeUnitZ();
|
||||
NzVector4& MakeZero();
|
||||
Vector4 GetNormal(T* length = nullptr) const;
|
||||
|
||||
NzVector4& Maximize(const NzVector4& vec);
|
||||
NzVector4& Minimize(const NzVector4& vec);
|
||||
Vector4& MakeUnitX();
|
||||
Vector4& MakeUnitY();
|
||||
Vector4& MakeUnitZ();
|
||||
Vector4& MakeZero();
|
||||
|
||||
NzVector4& Normalize(T* length = nullptr);
|
||||
Vector4& Maximize(const Vector4& vec);
|
||||
Vector4& Minimize(const Vector4& vec);
|
||||
|
||||
NzVector4& Set(T X, T Y, T Z, T W = 1.0);
|
||||
NzVector4& Set(T X, T Y, const NzVector2<T>& vec);
|
||||
NzVector4& Set(T X, const NzVector2<T>& vec, T W);
|
||||
NzVector4& Set(T X, const NzVector3<T>& vec);
|
||||
NzVector4& Set(T scale);
|
||||
NzVector4& Set(const T vec[4]);
|
||||
NzVector4& Set(const NzVector2<T>& vec, T Z = 0.0, T W = 1.0);
|
||||
NzVector4& Set(const NzVector3<T>& vec, T W = 1.0);
|
||||
NzVector4& Set(const NzVector4<T>& vec);
|
||||
template<typename U> NzVector4& Set(const NzVector4<U>& vec);
|
||||
Vector4& Normalize(T* length = nullptr);
|
||||
|
||||
NzString ToString() const;
|
||||
Vector4& Set(T X, T Y, T Z, T W = 1.0);
|
||||
Vector4& Set(T X, T Y, const Vector2<T>& vec);
|
||||
Vector4& Set(T X, const Vector2<T>& vec, T W);
|
||||
Vector4& Set(T X, const Vector3<T>& vec);
|
||||
Vector4& Set(T scale);
|
||||
Vector4& Set(const T vec[4]);
|
||||
Vector4& Set(const Vector2<T>& vec, T Z = 0.0, T W = 1.0);
|
||||
Vector4& Set(const Vector3<T>& vec, T W = 1.0);
|
||||
Vector4& Set(const Vector4<T>& vec);
|
||||
template<typename U> Vector4& Set(const Vector4<U>& vec);
|
||||
|
||||
operator T*();
|
||||
operator const T*() const;
|
||||
String ToString() const;
|
||||
|
||||
const NzVector4& operator+() const;
|
||||
NzVector4 operator-() const;
|
||||
operator T*();
|
||||
operator const T*() const;
|
||||
|
||||
NzVector4 operator+(const NzVector4& vec) const;
|
||||
NzVector4 operator-(const NzVector4& vec) const;
|
||||
NzVector4 operator*(const NzVector4& vec) const;
|
||||
NzVector4 operator*(T scale) const;
|
||||
NzVector4 operator/(const NzVector4& vec) const;
|
||||
NzVector4 operator/(T scale) const;
|
||||
const Vector4& operator+() const;
|
||||
Vector4 operator-() const;
|
||||
|
||||
NzVector4& operator+=(const NzVector4& vec);
|
||||
NzVector4& operator-=(const NzVector4& vec);
|
||||
NzVector4& operator*=(const NzVector4& vec);
|
||||
NzVector4& operator*=(T scale);
|
||||
NzVector4& operator/=(const NzVector4& vec);
|
||||
NzVector4& operator/=(T scale);
|
||||
Vector4 operator+(const Vector4& vec) const;
|
||||
Vector4 operator-(const Vector4& vec) const;
|
||||
Vector4 operator*(const Vector4& vec) const;
|
||||
Vector4 operator*(T scale) const;
|
||||
Vector4 operator/(const Vector4& vec) const;
|
||||
Vector4 operator/(T scale) const;
|
||||
|
||||
bool operator==(const NzVector4& vec) const;
|
||||
bool operator!=(const NzVector4& vec) const;
|
||||
bool operator<(const NzVector4& vec) const;
|
||||
bool operator<=(const NzVector4& vec) const;
|
||||
bool operator>(const NzVector4& vec) const;
|
||||
bool operator>=(const NzVector4& vec) const;
|
||||
Vector4& operator+=(const Vector4& vec);
|
||||
Vector4& operator-=(const Vector4& vec);
|
||||
Vector4& operator*=(const Vector4& vec);
|
||||
Vector4& operator*=(T scale);
|
||||
Vector4& operator/=(const Vector4& vec);
|
||||
Vector4& operator/=(T scale);
|
||||
|
||||
static NzVector4 UnitX();
|
||||
static NzVector4 UnitY();
|
||||
static NzVector4 UnitZ();
|
||||
static NzVector4 Zero();
|
||||
bool operator==(const Vector4& vec) const;
|
||||
bool operator!=(const Vector4& vec) const;
|
||||
bool operator<(const Vector4& vec) const;
|
||||
bool operator<=(const Vector4& vec) const;
|
||||
bool operator>(const Vector4& vec) const;
|
||||
bool operator>=(const Vector4& vec) const;
|
||||
|
||||
T x, y, z, w;
|
||||
};
|
||||
static Vector4 UnitX();
|
||||
static Vector4 UnitY();
|
||||
static Vector4 UnitZ();
|
||||
static Vector4 Zero();
|
||||
|
||||
template<typename T> std::ostream& operator<<(std::ostream& out, const NzVector4<T>& vec);
|
||||
T x, y, z, w;
|
||||
};
|
||||
|
||||
template<typename T> NzVector4<T> operator*(T scale, const NzVector4<T>& vec);
|
||||
template<typename T> NzVector4<T> operator/(T scale, const NzVector4<T>& vec);
|
||||
template<typename T> std::ostream& operator<<(std::ostream& out, const Vector4<T>& vec);
|
||||
|
||||
typedef NzVector4<double> NzVector4d;
|
||||
typedef NzVector4<float> NzVector4f;
|
||||
typedef NzVector4<int> NzVector4i;
|
||||
typedef NzVector4<unsigned int> NzVector4ui;
|
||||
typedef NzVector4<nzInt32> NzVector4i32;
|
||||
typedef NzVector4<nzUInt32> NzVector4ui32;
|
||||
template<typename T> Vector4<T> operator*(T scale, const Vector4<T>& vec);
|
||||
template<typename T> Vector4<T> operator/(T scale, const Vector4<T>& vec);
|
||||
|
||||
typedef Vector4<double> Vector4d;
|
||||
typedef Vector4<float> Vector4f;
|
||||
typedef Vector4<int> Vector4i;
|
||||
typedef Vector4<unsigned int> Vector4ui;
|
||||
typedef Vector4<Int32> Vector4i32;
|
||||
typedef Vector4<UInt32> Vector4ui32;
|
||||
}
|
||||
|
||||
#include <Nazara/Math/Vector4.inl>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user