Switch from Nz prefix to namespace Nz

What a huge commit


Former-commit-id: 38ac5eebf70adc1180f571f6006192d28fb99897
This commit is contained in:
Lynix
2015-09-25 19:20:05 +02:00
parent c214251ecf
commit df8da275c4
609 changed files with 68265 additions and 66534 deletions

View File

@@ -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 NzDegreeToRadian(T degrees);
unsigned int GetNearestPowerOfTwo(unsigned int 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>

View File

@@ -11,451 +11,456 @@
#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 NzDegreeToRadian(T degrees)
{
return degrees * T(M_PI/180.0);
}
template<typename T>
constexpr T FromDegrees(T degrees)
{
#if NAZARA_MATH_ANGLE_RADIAN
return NzDegreeToRadian(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
}
inline unsigned int GetNearestPowerOfTwo(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 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 NzDegreeToRadian(angle);
}
#endif
}

View File

@@ -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>

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -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();
}

View File

@@ -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>

View File

@@ -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 = 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;
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();
}

View File

@@ -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

View File

@@ -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>

View File

@@ -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();
}

View File

@@ -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>

View File

@@ -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();
}

View File

@@ -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>

View File

@@ -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 = NzDegreeToRadian(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();
}

View File

@@ -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>

View File

@@ -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();
}

View File

@@ -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>

View File

@@ -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();
}

View File

@@ -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 NzCircle<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 NzCircle<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>

View File

@@ -11,352 +11,355 @@
#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 NzCircle<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
{
NzVector3<T> distance(X-x, Y-y, Z-z);
return distance.GetLength();
}
template<typename T>
T NzSphere<T>::Distance(const NzVector3<T>& point) const
{
return Distance(point.x, point.y, point.z);
}
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
{
NzVector3<T> distance(X-x, Y-y, Z-z);
return distance.GetSquaredLength();
}
template<typename T>
T NzSphere<T>::SquaredDistance(const NzVector3<T>& point) const
{
return SquaredDistance(point.x, point.y, point.z);
}
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();
Vector3<T> distance(X-x, Y-y, Z-z);
return distance.GetLength();
}
#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 Distance(point.x, point.y, point.z);
}
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 NzCircle<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
{
Vector3<T> distance(X-x, Y-y, Z-z);
return distance.GetSquaredLength();
}
template<typename T>
T Sphere<T>::SquaredDistance(const Vector3<T>& point) const
{
return SquaredDistance(point.x, point.y, point.z);
}
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();
}

View File

@@ -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);
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;
}
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> std::ostream& operator<<(std::ostream& out, const Nz::Vector2<T>& vec);
template<typename T> Nz::Vector2<T> operator*(T scale, const Nz::Vector2<T>& vec);
template<typename T> Nz::Vector2<T> operator/(T scale, const Nz::Vector2<T>& vec);
#include <Nazara/Math/Vector2.inl>

View File

@@ -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;
template<typename T>
const Vector2<T>& Vector2<T>::operator+() const
{
return *this;
}
return *this;
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>
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)
std::ostream& operator<<(std::ostream& out, const Nz::Vector2<T>& vec)
{
return out << vec.ToString();
}
template<typename T>
NzVector2<T> operator*(T scale, const NzVector2<T>& vec)
Nz::Vector2<T> operator*(T scale, const Nz::Vector2<T>& vec)
{
return NzVector2<T>(scale * vec.x, scale * vec.y);
return Nz::Vector2<T>(scale * vec.x, scale * vec.y);
}
template<typename T>
NzVector2<T> operator/(T scale, const NzVector2<T>& vec)
Nz::Vector2<T> operator/(T scale, const Nz::Vector2<T>& vec)
{
#if NAZARA_MATH_SAFE
if (NzNumberEquals(vec.x, F(0.0)) || NzNumberEquals(vec.y, F(0.0)))
if (Nz::NumberEquals(vec.x, F(0.0)) || Nz::NumberEquals(vec.y, F(0.0)))
{
NzString error("Division by zero");
Nz::String error("Division by zero");
NazaraError(error);
throw std::domain_error(error);
}
#endif
return NzVector2<T>(scale/vec.x, scale/vec.y);
return Nz::Vector2<T>(scale/vec.x, scale/vec.y);
}
#undef F

View File

@@ -9,125 +9,128 @@
#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 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 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 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 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);
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;
}
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> std::ostream& operator<<(std::ostream& out, const Nz::Vector3<T>& vec);
template<typename T> Nz::Vector3<T> operator*(T scale, const Nz::Vector3<T>& vec);
template<typename T> Nz::Vector3<T> operator/(T scale, const Nz::Vector3<T>& vec);
#include <Nazara/Math/Vector3.inl>

File diff suppressed because it is too large Load Diff

View File

@@ -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);
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;
}
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> std::ostream& operator<<(std::ostream& out, const Nz::Vector4<T>& vec);
template<typename T> Nz::Vector4<T> operator*(T scale, const Nz::Vector4<T>& vec);
template<typename T> Nz::Vector4<T> operator/(T scale, const Nz::Vector4<T>& vec);
#include <Nazara/Math/Vector4.inl>

File diff suppressed because it is too large Load Diff