Merge pull request #38 from Gawaboumga/UnitTest-Update-Merge

Unit test update

Former-commit-id: 477b048c87b4f4cdb9ec1fce433ad088b0a8ef18
This commit is contained in:
Lynix 2015-08-21 12:45:38 +02:00
commit 4176f1e019
77 changed files with 2627 additions and 703 deletions

View File

@ -100,7 +100,7 @@ int main()
std::cout << oss.str() << std::endl; std::cout << oss.str() << std::endl;
NzFile reportFile("RapportHardwareInfo.txt"); NzFile reportFile("RapportHardwareInfo.txt");
if (reportFile.Open(NzFile::Text | NzFile::Truncate | NzFile::WriteOnly)) if (reportFile.Open(nzOpenMode_Text | nzOpenMode_Truncate | nzOpenMode_WriteOnly))
{ {
reportFile.Write(oss.str()); // Conversion implicite en NzString reportFile.Write(oss.str()); // Conversion implicite en NzString
reportFile.Close(); reportFile.Close();

View File

@ -45,7 +45,6 @@
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Core/ErrorFlags.hpp> #include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Core/File.hpp> #include <Nazara/Core/File.hpp>
#include <Nazara/Core/Format.hpp>
#include <Nazara/Core/Functor.hpp> #include <Nazara/Core/Functor.hpp>
#include <Nazara/Core/GuillotineBinPack.hpp> #include <Nazara/Core/GuillotineBinPack.hpp>
#include <Nazara/Core/HardwareInfo.hpp> #include <Nazara/Core/HardwareInfo.hpp>

View File

@ -14,7 +14,7 @@ template<unsigned int N>
struct NzImplTupleUnpack struct NzImplTupleUnpack
{ {
template <typename F, typename... ArgsT, typename... Args> template <typename F, typename... ArgsT, typename... Args>
void operator()(F func, const std::tuple<ArgsT...>& t, Args&... args) void operator()(F func, const std::tuple<ArgsT...>& t, Args&... args)
{ {
NzImplTupleUnpack<N-1>()(func, t, std::get<N-1>(t), args...); NzImplTupleUnpack<N-1>()(func, t, std::get<N-1>(t), args...);
} }

View File

@ -8,120 +8,156 @@
#define NAZARA_BYTEARRAY_HPP #define NAZARA_BYTEARRAY_HPP
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Hashable.hpp> #include <Nazara/Core/Hashable.hpp>
#include <atomic> #include <Nazara/Core/String.hpp>
#include <memory>
#include <vector>
class NzAbstractHash; class NzAbstractHash;
class NzHashDigest;
class NAZARA_API NzByteArray : public NzHashable class NAZARA_API NzByteArray : public NzHashable
{ {
using Container = std::vector<nzUInt8>;
public: public:
struct SharedArray; // types:
using value_type = typename Container::value_type;
using allocator_type = typename Container::allocator_type;
using size_type = typename Container::size_type;
using difference_type = typename Container::difference_type;
using reference = typename Container::reference;
using const_reference = typename Container::const_reference;
using pointer = typename Container::pointer;
using const_pointer = typename Container::const_pointer;
using iterator = typename Container::iterator;
using const_iterator = typename Container::const_iterator;
using reverse_iterator = typename Container::reverse_iterator;
using const_reverse_iterator = typename Container::const_reverse_iterator;
// iterators:
iterator begin() noexcept;
const_iterator begin() const noexcept;
iterator end() noexcept;
const_iterator end() const noexcept;
reverse_iterator rbegin() noexcept;
const_reverse_iterator rbegin() const noexcept;
reverse_iterator rend() noexcept;
const_reverse_iterator rend() const noexcept;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator crend() const noexcept;
// construct/destroy:
NzByteArray(); NzByteArray();
explicit NzByteArray(unsigned int size); explicit NzByteArray(size_type n);
NzByteArray(const void* buffer, unsigned int size); NzByteArray(const void* buffer, size_type n);
NzByteArray(const NzByteArray& buffer); NzByteArray(size_type n, const value_type value);
NzByteArray(NzByteArray&& buffer) noexcept; template <class InputIterator>
NzByteArray(SharedArray* sharedArray); NzByteArray(InputIterator first, InputIterator last);
~NzByteArray(); NzByteArray(const NzByteArray& other);
NzByteArray(NzByteArray&& other);
virtual ~NzByteArray();
NzByteArray& Append(const void* buffer, unsigned int size); iterator Append(const void* buffer, size_type size);
NzByteArray& Append(const NzByteArray& array); iterator Append(const NzByteArray& other);
template <class InputIterator>
void Assign(InputIterator first, InputIterator last);
void Assign(size_type n, const value_type value);
reference Back();
const_reference Back() const;
void Clear(bool keepBuffer = false); void Clear(bool keepBuffer = false);
nzUInt8* GetBuffer(); pointer data();
unsigned int GetCapacity() const; const_pointer data() const;
const nzUInt8* GetConstBuffer() const;
unsigned int GetSize() const;
NzByteArray& Insert(int pos, const void* buffer, unsigned int size); bool empty() const noexcept;
NzByteArray& Insert(int pos, const NzByteArray& array); iterator Erase(const_iterator pos);
iterator Erase(const_iterator first, const_iterator last);
bool IsEmpty() const; reference Front();
const_reference Front() const;
NzByteArray& Prepend(const void* buffer, unsigned int size); iterator Insert(const_iterator pos, const void* buffer, size_type n);
NzByteArray& Prepend(const NzByteArray& array); iterator Insert(const_iterator pos, const NzByteArray& other);
iterator Insert(const_iterator pos, size_type n, const value_type byte);
template <class InputIterator>
iterator Insert(const_iterator pos, InputIterator first, InputIterator last);
bool IsEmpty() const noexcept;
void Reserve(unsigned int bufferSize); allocator_type GetAllocator() const;
pointer GetBuffer();
size_type GetCapacity() const noexcept;
const_pointer GetConstBuffer() const;
size_type GetSize() const noexcept;
NzByteArray& Resize(int size); size_type MaxSize() const noexcept;
NzByteArray& Resize(int size, nzUInt8 byte);
NzByteArray Resized(int size) const;
NzByteArray Resized(int size, nzUInt8 byte) const;
NzByteArray SubArray(int startPos, int endPos = -1) const;
void Swap(NzByteArray& array);
// Méthodes compatibles STD
nzUInt8* begin();
const nzUInt8* begin() const;
nzUInt8* end();
const nzUInt8* end() const;
void push_front(nzUInt8 byte);
void push_back(nzUInt8 byte);
/*nzUInt8* rbegin();
const nzUInt8* rbegin() const;
nzUInt8* rend();
const nzUInt8* rend() const;*/
typedef const nzUInt8& const_reference;
typedef nzUInt8* iterator;
//typedef nzUInt8* reverse_iterator;
typedef nzUInt8 value_type;
// Méthodes compatibles STD
nzUInt8& operator[](unsigned int pos);
nzUInt8 operator[](unsigned int pos) const;
// operators:
reference operator[](size_type pos);
const_reference operator[](size_type pos) const;
NzByteArray& operator=(const NzByteArray& array); NzByteArray& operator=(const NzByteArray& array);
NzByteArray& operator=(NzByteArray&& array) noexcept; NzByteArray& operator=(NzByteArray&& array);
NzByteArray operator+(const NzByteArray& array) const; NzByteArray operator+(const NzByteArray& array) const;
NzByteArray& operator+=(const NzByteArray& array); NzByteArray& operator+=(const NzByteArray& array);
static int Compare(const NzByteArray& first, const NzByteArray& second); bool operator==(const NzByteArray& rhs) const;
bool operator!=(const NzByteArray& rhs) const;
bool operator<(const NzByteArray& rhs) const;
bool operator<=(const NzByteArray& rhs) const;
bool operator>(const NzByteArray& rhs) const;
bool operator>=(const NzByteArray& rhs) const;
struct NAZARA_API SharedArray void PopBack();
{ void PopFront();
SharedArray() : iterator Prepend(const void* buffer, size_type size);
refCount(1) iterator Prepend(const NzByteArray& other);
{ void PushBack(const value_type byte);
} void PushFront(const value_type byte);
SharedArray(unsigned short referenceCount, unsigned int bufferSize, unsigned int arraySize, nzUInt8* ptr) : void Reserve(size_type bufferSize);
capacity(bufferSize), void Resize(size_type newSize);
size(arraySize), void Resize(size_type newSize, const value_type byte);
buffer(ptr),
refCount(referenceCount)
{
}
unsigned int capacity; size_type size() const noexcept;
unsigned int size; void ShrinkToFit();
nzUInt8* buffer; NzByteArray SubArray(const_iterator startPos, const_iterator endPos) const;
void Swap(NzByteArray& other);
std::atomic_ushort refCount; NzString ToString() const;
};
static SharedArray emptyArray;
static unsigned int npos;
private: private:
void EnsureOwnership();
bool FillHash(NzAbstractHash* hash) const;
void ReleaseArray();
SharedArray* m_sharedArray; bool FillHash(NzAbstractHash* hash) const;
Container m_array;
}; };
NAZARA_API std::ostream& operator<<(std::ostream& out, const NzByteArray& byteArray);
namespace std namespace std
{ {
NAZARA_API void swap(NzByteArray& lhs, NzByteArray& rhs); NAZARA_API void swap(NzByteArray& lhs, NzByteArray& rhs);
} }
template <class InputIterator>
NzByteArray::NzByteArray(InputIterator first, InputIterator last) :
m_array(first, last)
{
}
template <class InputIterator>
void NzByteArray::Assign(InputIterator first, InputIterator last)
{
m_array.assign(first, last);
}
template <class InputIterator>
NzByteArray::iterator NzByteArray::Insert(const_iterator pos, InputIterator first, InputIterator last)
{
return m_array.insert(pos, first, last);
}
#endif // NAZARA_BYTEARRAY_HPP #endif // NAZARA_BYTEARRAY_HPP

View File

@ -312,8 +312,8 @@ inline void NzColor::ToHSV(const NzColor& color, float* hue, float* saturation,
float g = color.g / 255.f; float g = color.g / 255.f;
float b = color.b / 255.f; float b = color.b / 255.f;
float min = std::min(std::min(r, g), b); //Min. value of RGB float min = std::min({r, g, b}); //Min. value of RGB
float max = std::max(std::max(r, g), b); //Max. value of RGB float max = std::max({r, g, b}); //Max. value of RGB
float deltaMax = max - min; //Delta RGB value float deltaMax = max - min; //Delta RGB value

View File

@ -27,7 +27,7 @@
#include <Nazara/Core/ThreadSafetyOff.hpp> #include <Nazara/Core/ThreadSafetyOff.hpp>
#endif #endif
using NzDynLibFunc = int (*)(); // Type "générique" de pointeur sur fonction using NzDynLibFunc = int (*)(); // Type "générique" de pointeur sur fonction
class NzDynLibImpl; class NzDynLibImpl;

View File

@ -15,6 +15,15 @@ enum nzCoordSys
nzCoordSys_Max = nzCoordSys_Local nzCoordSys_Max = nzCoordSys_Local
}; };
enum nzCursorPosition
{
nzCursorPosition_AtBegin, // Début du fichier
nzCursorPosition_AtCurrent, // Position du pointeur
nzCursorPosition_AtEnd, // Fin du fichier
nzCursorPosition_Max = nzCursorPosition_AtEnd
};
enum nzEndianness enum nzEndianness
{ {
nzEndianness_Unknown = -1, nzEndianness_Unknown = -1,
@ -57,7 +66,24 @@ enum nzHash
nzHash_SHA256, nzHash_SHA256,
nzHash_SHA384, nzHash_SHA384,
nzHash_SHA512, nzHash_SHA512,
nzHash_Whirlpool nzHash_Whirlpool,
nzHash_Max = nzHash_Whirlpool
};
enum nzOpenModeFlags
{
nzOpenMode_Current = 0x00, // Utilise le mode d'ouverture actuel
nzOpenMode_Append = 0x01, // Empêche l'écriture sur la partie déjà existante et met le curseur à la fin
nzOpenMode_Lock = 0x02, // Empêche le fichier d'être modifié tant qu'il est ouvert
nzOpenMode_ReadOnly = 0x04, // Ouvre uniquement en lecture
nzOpenMode_ReadWrite = 0x08, // Ouvre en lecture/écriture
nzOpenMode_Text = 0x10, // Ouvre en mode texte
nzOpenMode_Truncate = 0x20, // Créé le fichier s'il n'existe pas et le vide s'il existe
nzOpenMode_WriteOnly = 0x40, // Ouvre uniquement en écriture, créé le fichier s'il n'existe pas
nzOpenMode_Max = nzOpenMode_WriteOnly
}; };
enum nzParameterType enum nzParameterType

View File

@ -30,29 +30,9 @@ class NzFileImpl;
class NAZARA_API NzFile : public NzHashable, public NzInputStream, NzNonCopyable class NAZARA_API NzFile : public NzHashable, public NzInputStream, NzNonCopyable
{ {
public: public:
enum CursorPosition
{
AtBegin, // Début du fichier
AtCurrent, // Position du pointeur
AtEnd // Fin du fichier
};
enum OpenMode
{
Current = 0x00, // Utilise le mode d'ouverture actuel
Append = 0x01, // Empêche l'écriture sur la partie déjà existante et met le curseur à la fin
Lock = 0x02, // Empêche le fichier d'être modifié tant qu'il est ouvert
ReadOnly = 0x04, // Ouvre uniquement en lecture
ReadWrite = 0x08, // Ouvre en lecture/écriture
Text = 0x10, // Ouvre en mode texte
Truncate = 0x20, // Créé le fichier s'il n'existe pas et le vide s'il existe
WriteOnly = 0x40 // Ouvre uniquement en écriture, créé le fichier s'il n'existe pas
};
NzFile(); NzFile();
NzFile(const NzString& filePath); NzFile(const NzString& filePath);
NzFile(const NzString& filePath, unsigned long openMode); NzFile(const NzString& filePath, unsigned int openMode);
NzFile(NzFile&& file) noexcept; NzFile(NzFile&& file) noexcept;
~NzFile(); ~NzFile();
@ -79,14 +59,14 @@ class NAZARA_API NzFile : public NzHashable, public NzInputStream, NzNonCopyable
bool IsOpen() const; bool IsOpen() const;
bool Open(unsigned long openMode = Current); bool Open(unsigned int openMode = nzOpenMode_Current);
bool Open(const NzString& filePath, unsigned long openMode = Current); bool Open(const NzString& filePath, unsigned int openMode = nzOpenMode_Current);
std::size_t Read(void* buffer, std::size_t size); std::size_t Read(void* buffer, std::size_t size);
std::size_t Read(void* buffer, std::size_t typeSize, unsigned int count); std::size_t Read(void* buffer, std::size_t typeSize, unsigned int count);
bool Rename(const NzString& newFilePath); bool Rename(const NzString& newFilePath);
bool SetCursorPos(CursorPosition pos, nzInt64 offset = 0); bool SetCursorPos(nzCursorPosition pos, nzInt64 offset = 0);
bool SetCursorPos(nzUInt64 offset); bool SetCursorPos(nzUInt64 offset);
void SetEndianness(nzEndianness endianness); void SetEndianness(nzEndianness endianness);
bool SetFile(const NzString& filePath); bool SetFile(const NzString& filePath);

View File

@ -1,14 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_FORMAT_HPP
#define NAZARA_FORMAT_HPP
#include <Nazara/Core/String.hpp>
template<typename... Args> NzString NzFormat(const NzString& str, Args... args);
#endif // NAZARA_FORMAT_HPP

View File

@ -57,7 +57,7 @@ bool NzResourceLoader<Type, Parameters>::LoadFromFile(Type* resource, const NzSt
if (checkFunc && !file.IsOpen()) if (checkFunc && !file.IsOpen())
{ {
if (!file.Open(NzFile::ReadOnly)) if (!file.Open(nzOpenMode_ReadOnly))
{ {
NazaraError("Failed to load file: unable to open \"" + filePath + '"'); NazaraError("Failed to load file: unable to open \"" + filePath + '"');
return false; return false;

View File

@ -22,9 +22,9 @@ class NAZARA_API NzString : public NzHashable
public: public:
enum Flags enum Flags
{ {
None = 0x00, // Mode par défaut None = 0x00, // Mode par défaut
CaseInsensitive = 0x01, // Insensible à la casse CaseInsensitive = 0x01, // Insensible à la casse
HandleUtf8 = 0x02, // Traite les octets comme une suite de caractères UTF-8 HandleUtf8 = 0x02, // Traite les octets comme une suite de caractères UTF-8
TrimOnlyLeft = 0x04, // Trim(med), ne coupe que la partie gauche de la chaîne TrimOnlyLeft = 0x04, // Trim(med), ne coupe que la partie gauche de la chaîne
TrimOnlyRight = 0x08 // Trim(med), ne coupe que la partie droite de la chaîne TrimOnlyRight = 0x08 // Trim(med), ne coupe que la partie droite de la chaîne
}; };

View File

@ -6,9 +6,9 @@
namespace std namespace std
{ {
template<> template<>
struct hash<NzString> struct hash<NzString>
{ {
size_t operator()(const NzString& str) const size_t operator()(const NzString& str) const
{ {
// Algorithme DJB2 // Algorithme DJB2
@ -26,7 +26,7 @@ namespace std
return h; return h;
} }
}; };
} }
#include <Nazara/Core/DebugOff.hpp> #include <Nazara/Core/DebugOff.hpp>

View File

@ -16,6 +16,10 @@
#define M_PI 3.141592653589793238462643 #define M_PI 3.141592653589793238462643
#endif #endif
#ifndef M_PI_2
#define M_PI_2 1.5707963267948966192313217
#endif
#ifndef M_SQRT2 #ifndef M_SQRT2
#define M_SQRT2 1.4142135623730950488016887 #define M_SQRT2 1.4142135623730950488016887
#endif #endif

View File

@ -223,10 +223,10 @@ T NzNormalizeAngle(T angle)
template<typename T> template<typename T>
bool NzNumberEquals(T a, T b, T maxDifference) bool NzNumberEquals(T a, T b, T maxDifference)
{ {
T diff = a - b; if (b > a)
if (diff < F(0.0)) std::swap(a, b);
diff = -diff;
T diff = a - b;
return diff <= maxDifference; return diff <= maxDifference;
} }

View File

@ -202,7 +202,10 @@ template<typename T>
bool NzBoundingVolume<T>::operator==(const NzBoundingVolume& volume) const bool NzBoundingVolume<T>::operator==(const NzBoundingVolume& volume) const
{ {
if (extend == volume.extend) if (extend == volume.extend)
return obb == volume.obb; if (extend == nzExtend_Finite)
return obb == volume.obb;
else
return true;
else else
return false; return false;
} }

View File

@ -65,7 +65,7 @@ template<typename T>
bool NzBox<T>::Contains(const NzBox<T>& box) const bool NzBox<T>::Contains(const NzBox<T>& box) const
{ {
return Contains(box.x, box.y, box.z) && return Contains(box.x, box.y, box.z) &&
Contains(box.x + box.width, box.y + box.height, box.z + box.depth); Contains(box.x + box.width, box.y + box.height, box.z + box.depth);
} }
template<typename T> template<typename T>
@ -399,9 +399,9 @@ NzBox<T>& NzBox<T>::Transform(const NzMatrix4<T>& matrix, bool applyTranslation)
NzVector3<T> center = matrix.Transform(GetCenter(), (applyTranslation) ? F(1.0) : F(0.0)); // Valeur multipliant la translation NzVector3<T> center = matrix.Transform(GetCenter(), (applyTranslation) ? F(1.0) : F(0.0)); // Valeur multipliant la translation
NzVector3<T> halfSize = GetLengths()/F(2.0); NzVector3<T> halfSize = GetLengths()/F(2.0);
halfSize.Set(std::fabs(matrix(0,0))*halfSize.x + std::fabs(matrix(1,0))*halfSize.y + std::fabs(matrix(2,0))*halfSize.z, halfSize.Set(std::abs(matrix(0,0))*halfSize.x + std::abs(matrix(1,0))*halfSize.y + std::abs(matrix(2,0))*halfSize.z,
std::fabs(matrix(0,1))*halfSize.x + std::fabs(matrix(1,1))*halfSize.y + std::fabs(matrix(2,1))*halfSize.z, std::abs(matrix(0,1))*halfSize.x + std::abs(matrix(1,1))*halfSize.y + std::abs(matrix(2,1))*halfSize.z,
std::fabs(matrix(0,2))*halfSize.x + std::fabs(matrix(1,2))*halfSize.y + std::fabs(matrix(2,2))*halfSize.z); std::abs(matrix(0,2))*halfSize.x + std::abs(matrix(1,2))*halfSize.y + std::abs(matrix(2,2))*halfSize.z);
return Set(center - halfSize, center + halfSize); return Set(center - halfSize, center + halfSize);
} }
@ -486,7 +486,7 @@ template<typename T>
bool NzBox<T>::operator==(const NzBox& box) const bool NzBox<T>::operator==(const NzBox& box) const
{ {
return NzNumberEquals(x, box.x) && NzNumberEquals(y, box.y) && NzNumberEquals(z, box.z) && return NzNumberEquals(x, box.x) && NzNumberEquals(y, box.y) && NzNumberEquals(z, box.z) &&
NzNumberEquals(width, box.width) && NzNumberEquals(height, box.height) && NzNumberEquals(depth, box.depth); NzNumberEquals(width, box.width) && NzNumberEquals(height, box.height) && NzNumberEquals(depth, box.depth);
} }
template<typename T> template<typename T>

View File

@ -91,11 +91,18 @@ void NzEulerAngles<T>::Set(const NzEulerAngles<U>& angles)
template<typename T> template<typename T>
NzQuaternion<T> NzEulerAngles<T>::ToQuaternion() const NzQuaternion<T> NzEulerAngles<T>::ToQuaternion() const
{ {
NzQuaternion<T> rotX(pitch, NzVector3<T>::UnitX()); T c1 = std::cos(NzToRadians(yaw) / F(2.0));
NzQuaternion<T> rotY(yaw, NzVector3<T>::UnitY()); T c2 = std::cos(NzToRadians(roll) / F(2.0));
NzQuaternion<T> rotZ(roll, NzVector3<T>::UnitZ()); T c3 = std::cos(NzToRadians(pitch) / F(2.0));
return rotY * rotX * rotZ; 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> template<typename T>

View File

@ -180,7 +180,7 @@ NzFrustum<T>& NzFrustum<T>::Extract(const NzMatrix4<T>& clipMatrix)
plane[0] *= invLength; plane[0] *= invLength;
plane[1] *= invLength; plane[1] *= invLength;
plane[2] *= invLength; plane[2] *= invLength;
plane[3] *= invLength; plane[3] *= -invLength;
m_planes[nzFrustumPlane_Right].Set(plane); m_planes[nzFrustumPlane_Right].Set(plane);
@ -195,7 +195,7 @@ NzFrustum<T>& NzFrustum<T>::Extract(const NzMatrix4<T>& clipMatrix)
plane[0] *= invLength; plane[0] *= invLength;
plane[1] *= invLength; plane[1] *= invLength;
plane[2] *= invLength; plane[2] *= invLength;
plane[3] *= invLength; plane[3] *= -invLength;
m_planes[nzFrustumPlane_Left].Set(plane); m_planes[nzFrustumPlane_Left].Set(plane);
@ -210,7 +210,7 @@ NzFrustum<T>& NzFrustum<T>::Extract(const NzMatrix4<T>& clipMatrix)
plane[0] *= invLength; plane[0] *= invLength;
plane[1] *= invLength; plane[1] *= invLength;
plane[2] *= invLength; plane[2] *= invLength;
plane[3] *= invLength; plane[3] *= -invLength;
m_planes[nzFrustumPlane_Bottom].Set(plane); m_planes[nzFrustumPlane_Bottom].Set(plane);
@ -225,7 +225,7 @@ NzFrustum<T>& NzFrustum<T>::Extract(const NzMatrix4<T>& clipMatrix)
plane[0] *= invLength; plane[0] *= invLength;
plane[1] *= invLength; plane[1] *= invLength;
plane[2] *= invLength; plane[2] *= invLength;
plane[3] *= invLength; plane[3] *= -invLength;
m_planes[nzFrustumPlane_Top].Set(plane); m_planes[nzFrustumPlane_Top].Set(plane);
@ -240,7 +240,7 @@ NzFrustum<T>& NzFrustum<T>::Extract(const NzMatrix4<T>& clipMatrix)
plane[0] *= invLength; plane[0] *= invLength;
plane[1] *= invLength; plane[1] *= invLength;
plane[2] *= invLength; plane[2] *= invLength;
plane[3] *= invLength; plane[3] *= -invLength;
m_planes[nzFrustumPlane_Far].Set(plane); m_planes[nzFrustumPlane_Far].Set(plane);
@ -255,7 +255,7 @@ NzFrustum<T>& NzFrustum<T>::Extract(const NzMatrix4<T>& clipMatrix)
plane[0] *= invLength; plane[0] *= invLength;
plane[1] *= invLength; plane[1] *= invLength;
plane[2] *= invLength; plane[2] *= invLength;
plane[3] *= invLength; plane[3] *= -invLength;
m_planes[nzFrustumPlane_Near].Set(plane); m_planes[nzFrustumPlane_Near].Set(plane);
@ -332,10 +332,7 @@ NzFrustum<T>& NzFrustum<T>::Extract(const NzMatrix4<T>& clipMatrix)
template<typename T> template<typename T>
NzFrustum<T>& NzFrustum<T>::Extract(const NzMatrix4<T>& view, const NzMatrix4<T>& projection) NzFrustum<T>& NzFrustum<T>::Extract(const NzMatrix4<T>& view, const NzMatrix4<T>& projection)
{ {
NzMatrix4<T> clipMatrix(view); return Extract(NzMatrix4<T>::Concatenate(view, projection));
clipMatrix *= projection;
return Extract(clipMatrix);
} }
template<typename T> template<typename T>

View File

@ -80,7 +80,6 @@ class NzMatrix4
NzMatrix4& Set(const T matrix[16]); NzMatrix4& Set(const T matrix[16]);
//NzMatrix4(const NzMatrix3<T>& matrix); //NzMatrix4(const NzMatrix3<T>& matrix);
NzMatrix4& Set(const NzMatrix4& matrix); NzMatrix4& Set(const NzMatrix4& matrix);
NzMatrix4& Set(NzMatrix4&& matrix);
template<typename U> NzMatrix4& Set(const NzMatrix4<U>& matrix); template<typename U> NzMatrix4& Set(const NzMatrix4<U>& matrix);
NzMatrix4& SetRotation(const NzQuaternion<T>& rotation); NzMatrix4& SetRotation(const NzQuaternion<T>& rotation);
NzMatrix4& SetScale(const NzVector3<T>& scale); NzMatrix4& SetScale(const NzVector3<T>& scale);

View File

@ -578,6 +578,21 @@ NzMatrix4<T>& NzMatrix4<T>::MakeIdentity()
return *this; return *this;
} }
template<typename T>
NzMatrix4<T>& NzMatrix4<T>::MakeLookAt(const NzVector3<T>& eye, const NzVector3<T>& target, const NzVector3<T>& up)
{
NzVector3<T> f = NzVector3<T>::Normalize(target - eye);
NzVector3<T> s = NzVector3<T>::Normalize(f.CrossProduct(up));
NzVector3<T> u = s.CrossProduct(f);
Set(s.x, u.x, -f.x, T(0.0),
s.y, u.y, -f.y, T(0.0),
s.z, u.z, -f.z, T(0.0),
-s.DotProduct(eye), -u.DotProduct(eye), f.DotProduct(eye), T(1.0));
return *this;
}
template<typename T> template<typename T>
NzMatrix4<T>& NzMatrix4<T>::MakeOrtho(T left, T right, T top, T bottom, T zNear, T zFar) NzMatrix4<T>& NzMatrix4<T>::MakeOrtho(T left, T right, T top, T bottom, T zNear, T zFar)
{ {
@ -590,22 +605,6 @@ NzMatrix4<T>& NzMatrix4<T>::MakeOrtho(T left, T right, T top, T bottom, T zNear,
return *this; return *this;
} }
template<typename T>
NzMatrix4<T>& NzMatrix4<T>::MakeLookAt(const NzVector3<T>& eye, const NzVector3<T>& target, const NzVector3<T>& up)
{
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);
Set(s.x, u.x, -f.x, T(0.0),
s.y, u.y, -f.y, T(0.0),
s.z, u.z, -f.z, T(0.0),
-s.DotProduct(eye), -u.DotProduct(eye), f.DotProduct(eye), T(1.0));
return *this;
}
template<typename T> template<typename T>
NzMatrix4<T>& NzMatrix4<T>::MakePerspective(T angle, T ratio, T zNear, T zFar) NzMatrix4<T>& NzMatrix4<T>::MakePerspective(T angle, T ratio, T zNear, T zFar)
{ {
@ -616,12 +615,12 @@ NzMatrix4<T>& NzMatrix4<T>::MakePerspective(T angle, T ratio, T zNear, T zFar)
angle = NzDegreeToRadian(angle/F(2.0)); angle = NzDegreeToRadian(angle/F(2.0));
#endif #endif
T yScale = F(1.0) / std::tan(angle); T yScale = std::tan(M_PI_2 - angle);
Set(yScale / ratio, F(0.0), F(0.0), F(0.0), Set(yScale / ratio, F(0.0), F(0.0), F(0.0),
F(0.0), yScale, F(0.0), F(0.0), F(0.0), yScale, F(0.0), F(0.0),
F(0.0), F(0.0), zFar / (zNear-zFar), F(-1.0), F(0.0), F(0.0), - (zFar + zNear) / (zFar - zNear), F(-1.0),
F(0.0), F(0.0), (zNear*zFar) / (zNear-zFar), F(0.0)); F(0.0), F(0.0), F(-2.0) * (zNear * zFar) / (zFar - zNear), F(0.0));
return *this; return *this;
} }
@ -696,7 +695,7 @@ NzMatrix4<T>& NzMatrix4<T>::MakeViewMatrix(const NzVector3<T>& translation, cons
// Une matrice de vue doit appliquer une transformation opposée à la matrice "monde" // Une matrice de vue doit appliquer une transformation opposée à la matrice "monde"
NzQuaternion<T> invRot = rotation.GetConjugate(); // Inverse de la rotation NzQuaternion<T> invRot = rotation.GetConjugate(); // Inverse de la rotation
return MakeTransform(-(invRot*translation), invRot); return MakeTransform(-(invRot * translation), invRot);
} }
template<typename T> template<typename T>
@ -821,9 +820,9 @@ NzString NzMatrix4<T>::ToString() const
{ {
NzStringStream ss; NzStringStream ss;
return ss << "Matrix4(" << m11 << ", " << m12 << ", " << m13 << ", " << m14 << ",\n" return ss << "Matrix4(" << m11 << ", " << m12 << ", " << m13 << ", " << m14 << ",\n"
<< " " << m21 << ", " << m22 << ", " << m23 << ", " << m24 << ",\n" << " " << m21 << ", " << m22 << ", " << m23 << ", " << m24 << ",\n"
<< " " << m31 << ", " << m32 << ", " << m33 << ", " << m34 << ",\n" << " " << m31 << ", " << m32 << ", " << m33 << ", " << m34 << ",\n"
<< " " << m41 << ", " << m42 << ", " << m43 << ", " << m44 << ')'; << " " << m41 << ", " << m42 << ", " << m43 << ", " << m44 << ')';
} }
template<typename T> template<typename T>

View File

@ -103,9 +103,9 @@ template<typename U>
NzOrientedBox<T>& NzOrientedBox<T>::Set(const NzOrientedBox<U>& orientedBox) NzOrientedBox<T>& NzOrientedBox<T>::Set(const NzOrientedBox<U>& orientedBox)
{ {
for (unsigned int i = 0; i <= nzBoxCorner_Max; ++i) for (unsigned int i = 0; i <= nzBoxCorner_Max; ++i)
m_corners[i].Set(orientedBox.m_corners[i]); m_corners[i].Set(orientedBox(i));
localBox = orientedBox.localBox; localBox.Set(orientedBox.localBox);
return *this; return *this;
} }
@ -151,7 +151,7 @@ NzVector3<T>& NzOrientedBox<T>::operator()(unsigned int i)
if (i > nzBoxCorner_Max) if (i > nzBoxCorner_Max)
{ {
NzStringStream ss; NzStringStream ss;
ss << "Index out of range: (" << i << " >= 3)"; ss << "Index out of range: (" << i << " >= " << nzBoxCorner_Max << ")";
NazaraError(ss); NazaraError(ss);
throw std::out_of_range(ss.ToString()); throw std::out_of_range(ss.ToString());
@ -168,7 +168,7 @@ NzVector3<T> NzOrientedBox<T>::operator()(unsigned int i) const
if (i > nzBoxCorner_Max) if (i > nzBoxCorner_Max)
{ {
NzStringStream ss; NzStringStream ss;
ss << "Index out of range: (" << i << " >= 3)"; ss << "Index out of range: (" << i << " >= " << nzBoxCorner_Max << ")";
NazaraError(ss); NazaraError(ss);
throw std::out_of_range(ss.ToString()); throw std::out_of_range(ss.ToString());

View File

@ -37,6 +37,9 @@ class NzPlane
NzString ToString() const; NzString ToString() const;
bool operator==(const NzPlane& plane) const;
bool operator!=(const NzPlane& plane) const;
static NzPlane Lerp(const NzPlane& from, const NzPlane& to, T interpolation); static NzPlane Lerp(const NzPlane& from, const NzPlane& to, T interpolation);
static NzPlane XY(); static NzPlane XY();
static NzPlane XZ(); static NzPlane XZ();

View File

@ -49,7 +49,7 @@ NzPlane<T>::NzPlane(const NzPlane<U>& plane)
template<typename T> template<typename T>
T NzPlane<T>::Distance(const NzVector3<T>& point) const T NzPlane<T>::Distance(const NzVector3<T>& point) const
{ {
return normal.DotProduct(point) + distance; return normal.DotProduct(point) - distance; // ax + by + cd - d = 0.
} }
template<typename T> template<typename T>
@ -110,7 +110,7 @@ NzPlane<T>& NzPlane<T>::Set(const NzVector3<T>& point1, const NzVector3<T>& poin
normal = edge1.CrossProduct(edge2); normal = edge1.CrossProduct(edge2);
normal.Normalize(); normal.Normalize();
distance = -normal.DotProduct(point3); distance = normal.DotProduct(point3);
return *this; return *this;
} }
@ -133,6 +133,18 @@ NzString NzPlane<T>::ToString() const
return ss << "Plane(Normal: " << normal.ToString() << "; Distance: " << distance << ')'; 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> template<typename T>
NzPlane<T> NzPlane<T>::Lerp(const NzPlane& from, const NzPlane& to, T interpolation) NzPlane<T> NzPlane<T>::Lerp(const NzPlane& from, const NzPlane& to, T interpolation)
{ {
@ -155,19 +167,19 @@ NzPlane<T> NzPlane<T>::Lerp(const NzPlane& from, const NzPlane& to, T interpolat
template<typename T> template<typename T>
NzPlane<T> NzPlane<T>::XY() NzPlane<T> NzPlane<T>::XY()
{ {
return NzPlane<T>(F(0.0), F(0.0), F(1.0), F(0.0)); return NzPlane<T>(F(0.0), F(0.0), F(1.0), F(0.0));
} }
template<typename T> template<typename T>
NzPlane<T> NzPlane<T>::XZ() NzPlane<T> NzPlane<T>::XZ()
{ {
return NzPlane<T>(F(0.0), F(1.0), F(0.0), F(0.0)); return NzPlane<T>(F(0.0), F(1.0), F(0.0), F(0.0));
} }
template<typename T> template<typename T>
NzPlane<T> NzPlane<T>::YZ() NzPlane<T> NzPlane<T>::YZ()
{ {
return NzPlane<T>(F(1.0), F(0.0), F(0.0), F(0.0)); return NzPlane<T>(F(1.0), F(0.0), F(0.0), F(0.0));
} }
template<typename T> template<typename T>

View File

@ -237,10 +237,10 @@ template<typename T>
template<typename U> template<typename U>
NzQuaternion<T>& NzQuaternion<T>::Set(const NzQuaternion<U>& quat) NzQuaternion<T>& NzQuaternion<T>::Set(const NzQuaternion<U>& quat)
{ {
w = static_cast<T>(quat.w); w = F(quat.w);
x = static_cast<T>(quat.x); x = F(quat.x);
y = static_cast<T>(quat.y); y = F(quat.y);
z = static_cast<T>(quat.z); z = F(quat.z);
return *this; return *this;
} }
@ -270,9 +270,9 @@ NzEulerAngles<T> NzQuaternion<T>::ToEulerAngles() const
if (test < F(-0.499)) 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>(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* - F(2.0)*z*z)), 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::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))); NzFromRadians(std::asin(F(2.0)*test)));
} }
template<typename T> template<typename T>
@ -329,9 +329,9 @@ template<typename T>
NzQuaternion<T> NzQuaternion<T>::operator*(T scale) const NzQuaternion<T> NzQuaternion<T>::operator*(T scale) const
{ {
return NzQuaternion(w * scale, return NzQuaternion(w * scale,
x * scale, x * scale,
y * scale, y * scale,
z * scale); z * scale);
} }
template<typename T> template<typename T>
@ -368,9 +368,9 @@ template<typename T>
bool NzQuaternion<T>::operator==(const NzQuaternion& quat) const bool NzQuaternion<T>::operator==(const NzQuaternion& quat) const
{ {
return NzNumberEquals(w, quat.w) && return NzNumberEquals(w, quat.w) &&
NzNumberEquals(x, quat.x) && NzNumberEquals(x, quat.x) &&
NzNumberEquals(y, quat.y) && NzNumberEquals(y, quat.y) &&
NzNumberEquals(z, quat.z); NzNumberEquals(z, quat.z);
} }
template<typename T> template<typename T>
@ -450,23 +450,23 @@ NzQuaternion<T> NzQuaternion<T>::Slerp(const NzQuaternion& from, const NzQuatern
if (cosOmega > F(0.9999)) if (cosOmega > F(0.9999))
{ {
// Interpolation linéaire pour éviter une division par zéro // Interpolation linéaire pour éviter une division par zéro
k0 = F(1.0) - interpolation; k0 = F(1.0) - interpolation;
k1 = interpolation; k1 = interpolation;
} }
else else
{ {
T sinOmega = std::sqrt(F(1.0) - cosOmega*cosOmega); T sinOmega = std::sqrt(F(1.0) - cosOmega*cosOmega);
T omega = std::atan2(sinOmega, cosOmega); T omega = std::atan2(sinOmega, cosOmega);
// Pour éviter deux divisions // Pour éviter deux divisions
sinOmega = F(1.0)/sinOmega; sinOmega = F(1.0)/sinOmega;
k0 = std::sin((F(1.0) - interpolation) * omega) * sinOmega; k0 = std::sin((F(1.0) - interpolation) * omega) * sinOmega;
k1 = std::sin(interpolation*omega) * sinOmega; k1 = std::sin(interpolation*omega) * sinOmega;
} }
NzQuaternion result(k0 * from.w, k0 * from.x, k0 * from.y, k0 * from.z); NzQuaternion result(k0 * from.w, k0 * from.x, k0 * from.y, k0 * from.z);
return result += q*k1; return result += q*k1;
} }
template<typename T> template<typename T>

View File

@ -34,12 +34,12 @@ class NzRay
NzVector3<T> GetPoint(T lambda) const; NzVector3<T> GetPoint(T lambda) const;
//bool Intersect(const NzBoundingVolume<T>& volume, T* closestHit = nullptr, T* farthestHit = nullptr) const; bool Intersect(const NzBoundingVolume<T>& volume, T* closestHit = nullptr, T* furthestHit = nullptr) const;
bool Intersect(const NzBox<T>& box, T* closestHit = nullptr, T* farthestHit = 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* farthestHit = 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* farthestHit = 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 NzPlane<T>& plane, T* hit = nullptr) const;
bool Intersect(const NzSphere<T>& sphere, T* closestHit = nullptr, T* farthestHit = nullptr) const; bool Intersect(const NzSphere<T>& sphere, T* closestHit = nullptr, T* furthestHit = nullptr) const;
NzRay& MakeAxisX(); NzRay& MakeAxisX();
NzRay& MakeAxisY(); NzRay& MakeAxisY();
@ -57,6 +57,9 @@ class NzRay
NzVector3<T> operator*(T lambda) const; NzVector3<T> operator*(T lambda) const;
bool operator==(const NzRay& ray) const;
bool operator!=(const NzRay& ray) const;
static NzRay AxisX(); static NzRay AxisX();
static NzRay AxisY(); static NzRay AxisY();
static NzRay AxisZ(); static NzRay AxisZ();

View File

@ -59,18 +59,18 @@ T NzRay<T>::ClosestPoint(const NzVector3<T>& point) const
template<typename T> template<typename T>
NzVector3<T> NzRay<T>::GetPoint(T lambda) const NzVector3<T> NzRay<T>::GetPoint(T lambda) const
{ {
return origin + lambda*direction; return origin + lambda * direction;
} }
/*
template<typename T> template<typename T>
bool NzRay<T>::Intersect(const NzBoundingVolume<T>& volume, T* closestHit, T* farthestHit) const bool NzRay<T>::Intersect(const NzBoundingVolume<T>& volume, T* closestHit, T* furthestHit) const
{ {
switch (volume.extend) switch (volume.extend)
{ {
case nzExtend_Finite: case nzExtend_Finite:
{ {
if (Intersect(volume.aabb)) if (Intersect(volume.aabb))
return Intersect(volume.obb, closestHit, farthestHit); return Intersect(volume.obb, closestHit, furthestHit);
return false; return false;
} }
@ -80,8 +80,8 @@ bool NzRay<T>::Intersect(const NzBoundingVolume<T>& volume, T* closestHit, T* fa
if (closestHit) if (closestHit)
*closestHit = F(0.0); *closestHit = F(0.0);
if (farthestHit) if (furthestHit)
*farthestHit = std::numeric_limits<T>::infinity(); *furthestHit = std::numeric_limits<T>::infinity();
return true; return true;
} }
@ -93,9 +93,9 @@ bool NzRay<T>::Intersect(const NzBoundingVolume<T>& volume, T* closestHit, T* fa
NazaraError("Invalid extend type (0x" + NzString::Number(volume.extend, 16) + ')'); NazaraError("Invalid extend type (0x" + NzString::Number(volume.extend, 16) + ')');
return false; return false;
} }
*/
template<typename T> template<typename T>
bool NzRay<T>::Intersect(const NzBox<T>& box, T* closestHit, T* farthestHit) const 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/ // http://www.gamedev.net/topic/429443-obb-ray-and-obb-plane-intersection/
T tfirst = F(0.0); T tfirst = F(0.0);
@ -134,14 +134,14 @@ bool NzRay<T>::Intersect(const NzBox<T>& box, T* closestHit, T* farthestHit) con
if (closestHit) if (closestHit)
*closestHit = tfirst; *closestHit = tfirst;
if (farthestHit) if (furthestHit)
*farthestHit = tlast; *furthestHit = tlast;
return true; return true;
} }
template<typename T> template<typename T>
bool NzRay<T>::Intersect(const NzBox<T>& box, const NzMatrix4<T>& transform, T* closestHit, T* farthestHit) const 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/ // 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 // Intersection method from Real-Time Rendering and Essential Mathematics for Games
@ -192,32 +192,39 @@ bool NzRay<T>::Intersect(const NzBox<T>& box, const NzMatrix4<T>& transform, T*
if (closestHit) if (closestHit)
*closestHit = tMin; *closestHit = tMin;
if (farthestHit) if (furthestHit)
*farthestHit = tMax; *furthestHit = tMax;
return true; return true;
} }
///FIXME: Le test ci-dessous est beaucoup trop approximatif pour être vraiment utile
/// Mais le vrai problème vient certainement des OrientedBox en elles-mêmes, peut-être faut-il envisager de les refaire ?
/*
template<typename T> template<typename T>
bool NzRay<T>::Intersect(const NzOrientedBox<T>& orientedBox, T* closestHit, T* farthestHit) const bool NzRay<T>::Intersect(const NzOrientedBox<T>& orientedBox, T* closestHit, T* furthestHit) const
{ {
NzVector3<T> width = (orientedBox.GetCorner(nzBoxCorner_NearLeftBottom) - orientedBox.GetCorner(nzBoxCorner_FarLeftBottom)).Normalize(); NzVector3<T> corner = orientedBox.GetCorner(nzBoxCorner_FarLeftBottom);
NzVector3<T> height = (orientedBox.GetCorner(nzBoxCorner_FarLeftTop) - orientedBox.GetCorner(nzBoxCorner_FarLeftBottom)).Normalize(); NzVector3<T> oppositeCorner = orientedBox.GetCorner(nzBoxCorner_NearRightTop);
NzVector3<T> depth = (orientedBox.GetCorner(nzBoxCorner_FarRightBottom) - orientedBox.GetCorner(nzBoxCorner_FarLeftBottom)).Normalize();
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 // Construction de la matrice de transformation de l'OBB
NzMatrix4<T> matrix(width.x, height.x, depth.x, F(0.0), NzMatrix4<T> matrix(width.x, height.x, depth.x, corner.x,
width.y, height.y, depth.y, F(0.0), width.y, height.y, depth.y, corner.y,
width.z, height.z, depth.z, F(0.0), width.z, height.z, depth.z, corner.z,
F(0.0), F(0.0), F(0.0), F(1.0)); F(0.0), F(0.0), F(0.0), F(1.0));
// Test en tant qu'AABB avec une matrice de rotation matrix.InverseAffine();
return Intersect(orientedBox.localBox, matrix, closestHit, farthestHit);
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> template<typename T>
bool NzRay<T>::Intersect(const NzPlane<T>& plane, T* hit) const bool NzRay<T>::Intersect(const NzPlane<T>& plane, T* hit) const
{ {
@ -225,9 +232,9 @@ bool NzRay<T>::Intersect(const NzPlane<T>& plane, T* hit) const
if (NzNumberEquals(divisor, F(0.0))) if (NzNumberEquals(divisor, F(0.0)))
return false; // perpendicular return false; // perpendicular
T lambda = -(plane.normal.DotProduct(origin) + plane.distance) / divisor; // The plane is ax+by+cz=d T lambda = -(plane.normal.DotProduct(origin) - plane.distance) / divisor; // The plane is ax + by + cz = d
if (lambda < F(0.0)) if (lambda < F(0.0))
return false; // Le plan est derrière le rayon return false; // The plane is 'behind' the ray.
if (hit) if (hit)
*hit = lambda; *hit = lambda;
@ -236,7 +243,7 @@ bool NzRay<T>::Intersect(const NzPlane<T>& plane, T* hit) const
} }
template<typename T> template<typename T>
bool NzRay<T>::Intersect(const NzSphere<T>& sphere, T* closestHit, T* farthestHit) const bool NzRay<T>::Intersect(const NzSphere<T>& sphere, T* closestHit, T* furthestHit) const
{ {
NzVector3<T> sphereRay = sphere.GetPosition() - origin; NzVector3<T> sphereRay = sphere.GetPosition() - origin;
T length = sphereRay.DotProduct(direction); T length = sphereRay.DotProduct(direction);
@ -251,15 +258,15 @@ bool NzRay<T>::Intersect(const NzSphere<T>& sphere, T* closestHit, T* farthestHi
return false; // if the ray is further than the radius return false; // if the ray is further than the radius
// Calcul des points d'intersection si besoin // Calcul des points d'intersection si besoin
if (closestHit || farthestHit) if (closestHit || furthestHit)
{ {
T deltaLambda = std::sqrt(squaredRadius - squaredDistance); T deltaLambda = std::sqrt(squaredRadius - squaredDistance);
if (closestHit) if (closestHit)
*closestHit = length - deltaLambda; *closestHit = length - deltaLambda;
if (farthestHit) if (furthestHit)
*farthestHit = length + deltaLambda; *furthestHit = length + deltaLambda;
} }
return true; return true;
@ -380,6 +387,18 @@ NzVector3<T> NzRay<T>::operator*(T lambda) const
return GetPoint(lambda); 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> template<typename T>
NzRay<T> NzRay<T>::AxisX() NzRay<T> NzRay<T>::AxisX()
{ {

View File

@ -64,7 +64,7 @@ template<typename T>
bool NzRect<T>::Contains(const NzRect<T>& rect) const bool NzRect<T>::Contains(const NzRect<T>& rect) const
{ {
return Contains(rect.x, rect.y) && return Contains(rect.x, rect.y) &&
Contains(rect.x + rect.width, rect.y + rect.height); Contains(rect.x + rect.width, rect.y + rect.height);
} }
template<typename T> template<typename T>
@ -410,7 +410,7 @@ template<typename T>
bool NzRect<T>::operator==(const NzRect& rect) const bool NzRect<T>::operator==(const NzRect& rect) const
{ {
return NzNumberEquals(x, rect.x) && NzNumberEquals(y, rect.y) && return NzNumberEquals(x, rect.x) && NzNumberEquals(y, rect.y) &&
NzNumberEquals(width, rect.width) && NzNumberEquals(height, rect.height); NzNumberEquals(width, rect.width) && NzNumberEquals(height, rect.height);
} }
template<typename T> template<typename T>

View File

@ -51,13 +51,13 @@ bool NzSphere<T>::Contains(T X, T Y, T Z) const
template<typename T> template<typename T>
bool NzSphere<T>::Contains(const NzBox<T>& box) const bool NzSphere<T>::Contains(const NzBox<T>& box) const
{ {
if (box.GetMinimum().SquaredDistance(GetPosition()) <= radius * radius) if (box.GetMinimum().SquaredDistance(GetPosition()) <= radius * radius)
{ {
if (box.GetMaximum().SquaredDistance(GetPosition()) <= radius * radius) if (box.GetMaximum().SquaredDistance(GetPosition()) <= radius * radius)
return true; return true;
} }
return false; return false;
} }
template<typename T> template<typename T>
bool NzSphere<T>::Contains(const NzVector3<T>& point) const bool NzSphere<T>::Contains(const NzVector3<T>& point) const
@ -156,7 +156,7 @@ bool NzSphere<T>::Intersect(const NzBox<T>& box) const
squaredDistance += diff*diff; squaredDistance += diff*diff;
} }
return squaredDistance <= radius * radius; return squaredDistance <= radius * radius;
} }
template<typename T> template<typename T>

View File

@ -27,12 +27,10 @@ class NzVector2
~NzVector2() = default; ~NzVector2() = default;
T AbsDotProduct(const NzVector2& vec) const; T AbsDotProduct(const NzVector2& vec) const;
T AngleBetween(const NzVector2& vec) const; T AngleBetween(const NzVector2& vec) const;
T Distance(const NzVector2& vec) const; T Distance(const NzVector2& vec) const;
float Distancef(const NzVector2& vec) const; float Distancef(const NzVector2& vec) const;
T DotProduct(const NzVector2& vec) const; T DotProduct(const NzVector2& vec) const;
T GetLength() const; T GetLength() const;
@ -40,6 +38,7 @@ class NzVector2
NzVector2 GetNormal(T* length = nullptr) const; NzVector2 GetNormal(T* length = nullptr) const;
T GetSquaredLength() const; T GetSquaredLength() const;
NzVector2& MakeUnit();
NzVector2& MakeUnitX(); NzVector2& MakeUnitX();
NzVector2& MakeUnitY(); NzVector2& MakeUnitY();
NzVector2& MakeZero(); NzVector2& MakeZero();
@ -89,6 +88,7 @@ class NzVector2
bool operator>=(const NzVector2& vec) const; bool operator>=(const NzVector2& vec) const;
static NzVector2 Lerp(const NzVector2& from, const NzVector2& to, T interpolation); static NzVector2 Lerp(const NzVector2& from, const NzVector2& to, T interpolation);
static NzVector2 Unit();
static NzVector2 UnitX(); static NzVector2 UnitX();
static NzVector2 UnitY(); static NzVector2 UnitY();
static NzVector2 Zero(); static NzVector2 Zero();

View File

@ -105,6 +105,12 @@ T NzVector2<T>::GetSquaredLength() const
return x*x + y*y; return x*x + y*y;
} }
template<typename T>
NzVector2<T>& NzVector2<T>::MakeUnit()
{
return Set(F(1.0), F(1.0));
}
template<typename T> template<typename T>
NzVector2<T>& NzVector2<T>::MakeUnitX() NzVector2<T>& NzVector2<T>::MakeUnitX()
{ {
@ -129,7 +135,7 @@ NzVector2<T>& NzVector2<T>::Maximize(const NzVector2& vec)
if (vec.x > x) if (vec.x > x)
x = vec.x; x = vec.x;
if (vec.y > y) if (vec.y > y)
y = vec.y; y = vec.y;
return *this; return *this;
@ -141,7 +147,7 @@ NzVector2<T>& NzVector2<T>::Minimize(const NzVector2& vec)
if (vec.x < x) if (vec.x < x)
x = vec.x; x = vec.x;
if (vec.y < y) if (vec.y < y)
y = vec.y; y = vec.y;
return *this; return *this;
@ -229,7 +235,7 @@ NzVector2<T>& NzVector2<T>::Set(const NzVector4<T>& vec)
template<typename T> template<typename T>
T NzVector2<T>::SquaredDistance(const NzVector2& vec) const T NzVector2<T>::SquaredDistance(const NzVector2& vec) const
{ {
return operator-(vec).GetSquaredLength(); return (*this - vec).GetSquaredLength();
} }
template<typename T> template<typename T>
@ -398,7 +404,7 @@ template<typename T>
bool NzVector2<T>::operator==(const NzVector2& vec) const bool NzVector2<T>::operator==(const NzVector2& vec) const
{ {
return NzNumberEquals(x, vec.x) && return NzNumberEquals(x, vec.x) &&
NzNumberEquals(y, vec.y); NzNumberEquals(y, vec.y);
} }
template<typename T> template<typename T>
@ -443,6 +449,15 @@ NzVector2<T> NzVector2<T>::Lerp(const NzVector2& from, const NzVector2& to, T in
return NzLerp(from, to, interpolation); return NzLerp(from, to, interpolation);
} }
template<typename T>
NzVector2<T> NzVector2<T>::Unit()
{
NzVector2 vector;
vector.MakeUnit();
return vector;
}
template<typename T> template<typename T>
NzVector2<T> NzVector2<T>::UnitX() NzVector2<T> NzVector2<T>::UnitX()
{ {

View File

@ -28,14 +28,12 @@ class NzVector3
~NzVector3() = default; ~NzVector3() = default;
T AbsDotProduct(const NzVector3& vec) const; T AbsDotProduct(const NzVector3& vec) const;
T AngleBetween(const NzVector3& vec) const; T AngleBetween(const NzVector3& vec) const;
NzVector3 CrossProduct(const NzVector3& vec) const; NzVector3 CrossProduct(const NzVector3& vec) const;
T Distance(const NzVector3& vec) const; T Distance(const NzVector3& vec) const;
float Distancef(const NzVector3& vec) const; float Distancef(const NzVector3& vec) const;
T DotProduct(const NzVector3& vec) const; T DotProduct(const NzVector3& vec) const;
T GetLength() const; T GetLength() const;

View File

@ -64,9 +64,9 @@ template<typename T>
T NzVector3<T>::AngleBetween(const NzVector3& vec) const T NzVector3<T>::AngleBetween(const NzVector3& vec) const
{ {
// sqrt(a) * sqrt(b) = sqrt(a*b) // sqrt(a) * sqrt(b) = sqrt(a*b)
T divisor = std::sqrt(GetSquaredLength() * vec.GetSquaredLength()); T divisor = std::sqrt(GetSquaredLength() * vec.GetSquaredLength());
#if NAZARA_MATH_SAFE #if NAZARA_MATH_SAFE
if (NzNumberEquals(divisor, F(0.0))) if (NzNumberEquals(divisor, F(0.0)))
{ {
NzString error("Division by zero"); NzString error("Division by zero");
@ -325,7 +325,7 @@ NzVector3<T>& NzVector3<T>::Set(const NzVector4<T>& vec)
template<typename T> template<typename T>
T NzVector3<T>::SquaredDistance(const NzVector3& vec) const T NzVector3<T>::SquaredDistance(const NzVector3& vec) const
{ {
return operator-(vec).GetSquaredLength(); return (*this - vec).GetSquaredLength();
} }
template<typename T> template<typename T>

View File

@ -121,11 +121,11 @@ NzVector4<T>& NzVector4<T>::Maximize(const NzVector4& vec)
if (vec.y > y) if (vec.y > y)
y = vec.y; y = vec.y;
if (vec.z > z) if (vec.z > z)
z = vec.z; z = vec.z;
if (vec.w > w) if (vec.w > w)
w = vec.w; w = vec.w;
return *this; return *this;
} }
@ -139,11 +139,11 @@ NzVector4<T>& NzVector4<T>::Minimize(const NzVector4& vec)
if (vec.y < y) if (vec.y < y)
y = vec.y; y = vec.y;
if (vec.z < z) if (vec.z < z)
z = vec.z; z = vec.z;
if (vec.w < w) if (vec.w < w)
w = vec.w; w = vec.w;
return *this; return *this;
} }
@ -447,9 +447,9 @@ template<typename T>
bool NzVector4<T>::operator==(const NzVector4& vec) const bool NzVector4<T>::operator==(const NzVector4& vec) const
{ {
return NzNumberEquals(x, vec.x) && return NzNumberEquals(x, vec.x) &&
NzNumberEquals(y, vec.y) && NzNumberEquals(y, vec.y) &&
NzNumberEquals(z, vec.z) && NzNumberEquals(z, vec.z) &&
NzNumberEquals(w, vec.w); NzNumberEquals(w, vec.w);
} }
template<typename T> template<typename T>

View File

@ -28,6 +28,7 @@ class NAZARA_API NzDebugDrawer
static void Draw(const NzOrientedBoxf& orientedBox); static void Draw(const NzOrientedBoxf& orientedBox);
static void Draw(const NzSkeleton* skeleton); static void Draw(const NzSkeleton* skeleton);
static void Draw(const NzVector3f& position, float size = 0.1f); static void Draw(const NzVector3f& position, float size = 0.1f);
static void DrawAxes(const NzVector3f& position = NzVector3f::Zero(), float size = 1.f);
static void DrawBinormals(const NzStaticMesh* subMesh); static void DrawBinormals(const NzStaticMesh* subMesh);
static void DrawCone(const NzVector3f& origin, const NzQuaternionf& rotation, float angle, float length); static void DrawCone(const NzVector3f& origin, const NzQuaternionf& rotation, float angle, float length);
static void DrawLine(const NzVector3f& p1, const NzVector3f& p2); static void DrawLine(const NzVector3f& p1, const NzVector3f& p2);

View File

@ -110,7 +110,7 @@ namespace
// Nous devons gérer nous-même le flux car il doit rester ouvert après le passage du loader // Nous devons gérer nous-même le flux car il doit rester ouvert après le passage du loader
// (les flux automatiquement ouverts par le ResourceLoader étant fermés après celui-ci) // (les flux automatiquement ouverts par le ResourceLoader étant fermés après celui-ci)
std::unique_ptr<NzFile> file(new NzFile); std::unique_ptr<NzFile> file(new NzFile);
if (!file->Open(filePath, NzFile::ReadOnly)) if (!file->Open(filePath, nzOpenMode_ReadOnly))
{ {
NazaraError("Failed to open stream from file: " + NzError::GetLastError()); NazaraError("Failed to open stream from file: " + NzError::GetLastError());
return false; return false;

View File

@ -3,492 +3,387 @@
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/ByteArray.hpp> #include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/AbstractHash.hpp> #include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Math/Algorithm.hpp> #include <Nazara/Core/Error.hpp>
#include <algorithm> #include <Nazara/Core/StringStream.hpp>
#include <cstring>
#include <limits>
#include <Nazara/Core/Debug.hpp> #include <Nazara/Core/Debug.hpp>
// Cet algorithme est inspiré de la documentation de Qt NzByteArray::iterator NzByteArray::begin() noexcept
inline unsigned int nzGetNewSize(unsigned int newSize)
{ {
if (newSize < 20) return m_array.begin();
return newSize+4; }
else
{ NzByteArray::const_iterator NzByteArray::begin() const noexcept
if (newSize < (1 << 12)-12) {
return NzGetNearestPowerOfTwo(newSize << 1)-12; return m_array.begin();
else }
return newSize + (1 << 11);
} NzByteArray::iterator NzByteArray::end() noexcept
{
return m_array.end();
}
NzByteArray::const_iterator NzByteArray::end() const noexcept
{
return m_array.end();
}
NzByteArray::reverse_iterator NzByteArray::rbegin() noexcept
{
return m_array.rbegin();
}
NzByteArray::const_reverse_iterator NzByteArray::rbegin() const noexcept
{
return m_array.rbegin();
}
NzByteArray::reverse_iterator NzByteArray::rend() noexcept
{
return m_array.rend();
}
NzByteArray::const_iterator NzByteArray::cbegin() const noexcept
{
return m_array.cbegin();
}
NzByteArray::const_iterator NzByteArray::cend() const noexcept
{
return m_array.cend();
}
NzByteArray::const_reverse_iterator NzByteArray::crbegin() const noexcept
{
return m_array.crbegin();
}
NzByteArray::const_reverse_iterator NzByteArray::crend() const noexcept
{
return m_array.crend();
} }
NzByteArray::NzByteArray() : NzByteArray::NzByteArray() :
m_sharedArray(&emptyArray) m_array()
{ {
} }
NzByteArray::NzByteArray(unsigned int size) NzByteArray::NzByteArray(size_type n) :
m_array()
{ {
if (size > 0) m_array.reserve(n);
{
m_sharedArray = new SharedArray;
m_sharedArray->buffer = new nzUInt8[size];
m_sharedArray->capacity = size;
m_sharedArray->size = size;
}
else
m_sharedArray = &emptyArray;
} }
NzByteArray::NzByteArray(const void* buffer, unsigned int size) NzByteArray::NzByteArray(const void* buffer, size_type n) :
m_array(static_cast<const_pointer>(buffer), static_cast<const_pointer>(buffer) + n)
{ {
if (size > 0)
{
m_sharedArray = new SharedArray;
m_sharedArray->buffer = new nzUInt8[size];
m_sharedArray->capacity = size;
m_sharedArray->size = size;
std::memcpy(m_sharedArray->buffer, buffer, size);
}
else
m_sharedArray = &emptyArray;
} }
NzByteArray::NzByteArray(const NzByteArray& buffer) : NzByteArray::NzByteArray(size_type n, const value_type value) :
m_sharedArray(buffer.m_sharedArray) m_array(n, value)
{ {
if (m_sharedArray != &emptyArray)
m_sharedArray->refCount++;
} }
NzByteArray::NzByteArray(NzByteArray&& buffer) noexcept : NzByteArray::NzByteArray(const NzByteArray& other) :
m_sharedArray(buffer.m_sharedArray) m_array(other.m_array)
{ {
buffer.m_sharedArray = &emptyArray;
} }
NzByteArray::NzByteArray(SharedArray* sharedArray) : NzByteArray::NzByteArray(NzByteArray&& other) :
m_sharedArray(sharedArray) m_array(std::move(other.m_array))
{ {
} }
NzByteArray::~NzByteArray() NzByteArray::~NzByteArray()
{ {
ReleaseArray();
} }
NzByteArray& NzByteArray::Append(const void* buffer, unsigned int size) NzByteArray::iterator NzByteArray::Append(const void* buffer, size_type n)
{ {
return Insert(m_sharedArray->size, buffer, size); return Insert(end(), static_cast<const_pointer>(buffer), static_cast<const_pointer>(buffer) + n);
} }
NzByteArray& NzByteArray::Append(const NzByteArray& array) NzByteArray::iterator NzByteArray::Append(const NzByteArray& other)
{ {
return Insert(m_sharedArray->size, array); return Insert(end(), other.begin(), other.end());
}
void NzByteArray::Assign(size_type n, const value_type value)
{
m_array.assign(n, value);
}
NzByteArray::reference NzByteArray::Back()
{
return m_array.back();
}
NzByteArray::const_reference NzByteArray::Back() const
{
return m_array.back();
} }
void NzByteArray::Clear(bool keepBuffer) void NzByteArray::Clear(bool keepBuffer)
{ {
if (keepBuffer) m_array.clear();
{
EnsureOwnership(); if (!keepBuffer)
m_sharedArray->size = 0; ShrinkToFit();
}
else
ReleaseArray();
} }
nzUInt8* NzByteArray::GetBuffer() NzByteArray::pointer NzByteArray::data()
{ {
EnsureOwnership(); return GetBuffer();
return m_sharedArray->buffer;
} }
unsigned int NzByteArray::GetCapacity() const NzByteArray::const_pointer NzByteArray::data() const
{ {
return m_sharedArray->capacity; return GetConstBuffer();
} }
const nzUInt8* NzByteArray::GetConstBuffer() const bool NzByteArray::empty() const noexcept
{ {
return m_sharedArray->buffer; return IsEmpty();
} }
unsigned int NzByteArray::GetSize() const NzByteArray::iterator NzByteArray::Erase(const_iterator pos)
{ {
return m_sharedArray->size; return m_array.erase(pos);
} }
NzByteArray& NzByteArray::Insert(int pos, const void* buffer, unsigned int size) NzByteArray::iterator NzByteArray::Erase(const_iterator first, const_iterator last)
{ {
if (size == 0) return m_array.erase(first, last);
return *this;
if (pos < 0)
pos = std::max(static_cast<int>(m_sharedArray->size + pos), 0);
unsigned int start = std::min(static_cast<unsigned int>(pos), m_sharedArray->size);
// Si le buffer est déjà suffisamment grand
if (m_sharedArray->capacity >= m_sharedArray->size + size)
{
EnsureOwnership();
std::memmove(&m_sharedArray->buffer[start+size], &m_sharedArray->buffer[start], m_sharedArray->size - start);
std::memcpy(&m_sharedArray->buffer[start], buffer, size);
m_sharedArray->size += size;
}
else
{
unsigned int newSize = m_sharedArray->size + size;
nzUInt8* newBuffer = new nzUInt8[newSize];
nzUInt8* ptr = newBuffer;
if (start > 0)
{
std::memcpy(ptr, m_sharedArray->buffer, start*sizeof(nzUInt8));
ptr += start;
}
std::memcpy(ptr, buffer, size*sizeof(nzUInt8));
ptr += size;
if (m_sharedArray->size > 0)
std::memcpy(ptr, &m_sharedArray->buffer[start], m_sharedArray->size - start);
ReleaseArray();
m_sharedArray = new SharedArray;
m_sharedArray->buffer = newBuffer;
m_sharedArray->capacity = newSize;
m_sharedArray->size = newSize;
}
return *this;
} }
NzByteArray& NzByteArray::Insert(int pos, const NzByteArray& array) NzByteArray::reference NzByteArray::Front()
{ {
return Insert(pos, array.m_sharedArray->buffer, array.m_sharedArray->size); return m_array.front();
} }
bool NzByteArray::IsEmpty() const NzByteArray::const_reference NzByteArray::Front() const
{ {
return m_sharedArray->size == 0; return m_array.front();
} }
NzByteArray& NzByteArray::Prepend(const void* buffer, unsigned int size) NzByteArray::iterator NzByteArray::Insert(const_iterator pos, const void* buffer, size_type n)
{ {
return Insert(0, buffer, size); return Insert(pos, static_cast<const_pointer>(buffer), static_cast<const_pointer>(buffer) + n);
} }
NzByteArray& NzByteArray::Prepend(const NzByteArray& array) NzByteArray::iterator NzByteArray::Insert(const_iterator pos, const NzByteArray& other)
{ {
return Insert(0, array); return Insert(pos, other.begin(), other.end());
} }
void NzByteArray::Reserve(unsigned int bufferSize) NzByteArray::iterator NzByteArray::Insert(const_iterator pos, size_type n, const value_type byte)
{ {
if (m_sharedArray->capacity >= bufferSize) return Insert(pos, n, byte);
return;
nzUInt8* newBuffer = new nzUInt8[bufferSize];
if (m_sharedArray->size > 0)
std::memcpy(newBuffer, m_sharedArray->buffer, m_sharedArray->size);
unsigned int size = m_sharedArray->size;
ReleaseArray();
m_sharedArray = new SharedArray;
m_sharedArray->buffer = newBuffer;
m_sharedArray->capacity = bufferSize;
m_sharedArray->size = size;
} }
NzByteArray& NzByteArray::Resize(int size) bool NzByteArray::IsEmpty() const noexcept
{ {
if (size == 0) return m_array.empty();
{
Clear(true);
return *this;
}
if (size < 0)
size = std::max(static_cast<int>(m_sharedArray->size + size), 0);
unsigned int newSize = static_cast<unsigned int>(size);
if (m_sharedArray->capacity >= newSize)
{
EnsureOwnership();
// Nous avons déjà la place requise
m_sharedArray->size = newSize;
}
else // On veut forcément agrandir la chaine
{
nzUInt8* newBuffer = new nzUInt8[newSize];
if (m_sharedArray->size != 0)
std::memcpy(newBuffer, m_sharedArray->buffer, newSize);
ReleaseArray();
m_sharedArray = new SharedArray;
m_sharedArray->buffer = newBuffer;
m_sharedArray->capacity = newSize;
m_sharedArray->size = newSize;
}
return *this;
} }
NzByteArray& NzByteArray::Resize(int size, nzUInt8 byte) NzByteArray::allocator_type NzByteArray::GetAllocator() const
{ {
if (size == 0) return m_array.get_allocator();
{
Clear(true);
return *this;
}
if (size < 0)
size = std::max(static_cast<int>(m_sharedArray->size + size), 0);
unsigned int newSize = static_cast<unsigned int>(size);
if (m_sharedArray->capacity >= newSize)
{
EnsureOwnership();
// Nous avons déjà la place requise, contentons-nous de remplir le buffer
if (newSize > m_sharedArray->size)
std::memset(&m_sharedArray->buffer[m_sharedArray->size], byte, newSize-m_sharedArray->size);
m_sharedArray->size = newSize;
}
else // On veut forcément agrandir la chaine
{
nzUInt8* newBuffer = new nzUInt8[newSize];
if (m_sharedArray->size != 0)
std::memcpy(newBuffer, m_sharedArray->buffer, newSize);
std::memset(&newBuffer[m_sharedArray->size], byte, newSize-m_sharedArray->size);
ReleaseArray();
m_sharedArray = new SharedArray;
m_sharedArray->buffer = newBuffer;
m_sharedArray->capacity = newSize;
m_sharedArray->size = newSize;
}
return *this;
} }
NzByteArray NzByteArray::Resized(int size) const NzByteArray::pointer NzByteArray::GetBuffer()
{ {
if (size < 0) return m_array.data();
size = m_sharedArray->size + size;
if (size <= 0)
return NzByteArray();
unsigned int newSize = static_cast<unsigned int>(size);
if (newSize == m_sharedArray->size)
return *this;
nzUInt8* buffer = new nzUInt8[newSize];
std::memcpy(buffer, m_sharedArray->buffer, (newSize > m_sharedArray->size) ? m_sharedArray->size : newSize);
return NzByteArray(new SharedArray(1, newSize, newSize, buffer));
} }
NzByteArray NzByteArray::Resized(int size, nzUInt8 byte) const NzByteArray::size_type NzByteArray::GetCapacity() const noexcept
{ {
if (size < 0) return m_array.capacity();
size = m_sharedArray->size + size;
if (size <= 0)
return NzByteArray();
unsigned int newSize = static_cast<unsigned int>(size);
if (newSize == m_sharedArray->size)
return *this;
nzUInt8* buffer = new nzUInt8[newSize];
if (newSize > m_sharedArray->size)
{
std::memcpy(buffer, m_sharedArray->buffer, m_sharedArray->size);
std::memset(&buffer[m_sharedArray->size], byte, newSize - m_sharedArray->size);
}
else
std::memcpy(buffer, m_sharedArray->buffer, newSize);
return NzByteArray(new SharedArray(1, newSize, newSize, buffer));
} }
NzByteArray NzByteArray::SubArray(int startPos, int endPos) const NzByteArray::const_pointer NzByteArray::GetConstBuffer() const
{ {
if (startPos < 0) return m_array.data();
startPos = std::max(m_sharedArray->size+startPos, 0U);
unsigned int start = static_cast<unsigned int>(startPos);
if (endPos < 0)
{
endPos = m_sharedArray->size + endPos;
if (endPos < 0)
return NzByteArray();
}
unsigned int minEnd = std::min(static_cast<unsigned int>(endPos), m_sharedArray->size-1);
if (start > minEnd || start >= m_sharedArray->size)
return NzByteArray();
unsigned int size = minEnd - start + 1;
nzUInt8* buffer = new nzUInt8[size];
std::memcpy(buffer, &m_sharedArray->buffer[start], size);
return NzByteArray(new SharedArray(1, size, size, buffer));
} }
void NzByteArray::Swap(NzByteArray& array) NzByteArray::size_type NzByteArray::GetSize() const noexcept
{ {
std::swap(m_sharedArray, array.m_sharedArray); return m_array.size();
} }
nzUInt8* NzByteArray::begin() NzByteArray::size_type NzByteArray::MaxSize() const noexcept
{ {
return m_sharedArray->buffer; return m_array.max_size();
} }
const nzUInt8* NzByteArray::begin() const NzByteArray::reference NzByteArray::operator[](size_type pos)
{
return m_sharedArray->buffer;
}
nzUInt8* NzByteArray::end()
{
return &m_sharedArray->buffer[m_sharedArray->size];
}
const nzUInt8* NzByteArray::end() const
{
return &m_sharedArray->buffer[m_sharedArray->size];
}
nzUInt8& NzByteArray::operator[](unsigned int pos)
{
EnsureOwnership();
if (pos >= m_sharedArray->size)
Resize(pos+1);
return m_sharedArray->buffer[pos];
}
nzUInt8 NzByteArray::operator[](unsigned int pos) const
{ {
#if NAZARA_CORE_SAFE #if NAZARA_CORE_SAFE
if (pos >= m_sharedArray->size) if (pos >= GetSize())
{ NazaraError("Index out of range (" + NzString::Number(pos) + " >= " + NzString::Number(GetSize()) + ')');
NazaraError("Index out of range (" + NzString::Number(pos) + " >= " + NzString::Number(m_sharedArray->size) + ')');
return 0;
}
#endif #endif
return m_sharedArray->buffer[pos]; return m_array[pos];
} }
NzByteArray& NzByteArray::operator=(const NzByteArray& array) NzByteArray::const_reference NzByteArray::operator[](size_type pos) const
{ {
if (this != &array) #if NAZARA_CORE_SAFE
{ if (pos >= GetSize())
ReleaseArray(); NazaraError("Index out of range (" + NzString::Number(pos) + " >= " + NzString::Number(GetSize()) + ')');
#endif
m_sharedArray = array.m_sharedArray; return m_array[pos];
if (m_sharedArray != &emptyArray) }
m_sharedArray->refCount++;
} NzByteArray& NzByteArray::operator=(const NzByteArray& other)
{
m_array = other.m_array;
return *this; return *this;
} }
NzByteArray& NzByteArray::operator=(NzByteArray&& array) noexcept NzByteArray& NzByteArray::operator=(NzByteArray&& other)
{ {
std::swap(m_sharedArray, array.m_sharedArray); m_array = std::move(other.m_array);
return *this; return *this;
} }
NzByteArray NzByteArray::operator+(const NzByteArray& array) const NzByteArray NzByteArray::operator+(const NzByteArray& other) const
{ {
if (array.m_sharedArray->size == 0) NzByteArray tmp(*this);
return *this; tmp += other;
if (m_sharedArray->size == 0) return tmp;
return array;
unsigned int totalSize = m_sharedArray->size + array.m_sharedArray->size;
nzUInt8* buffer = new nzUInt8[totalSize];
std::memcpy(buffer, m_sharedArray->buffer, m_sharedArray->size);
std::memcpy(&buffer[m_sharedArray->size], array.m_sharedArray->buffer, array.m_sharedArray->size);
return NzByteArray(new SharedArray(1, totalSize, totalSize, buffer));
} }
NzByteArray& NzByteArray::operator+=(const NzByteArray& array) NzByteArray& NzByteArray::operator+=(const NzByteArray& other)
{ {
return Append(array); Append(other);
return *this;
} }
int NzByteArray::Compare(const NzByteArray& first, const NzByteArray& second) bool NzByteArray::operator==(const NzByteArray& rhs) const
{ {
return std::memcmp(first.m_sharedArray->buffer, second.m_sharedArray->buffer, std::min(first.m_sharedArray->size, second.m_sharedArray->size)); return m_array == rhs.m_array;
} }
void NzByteArray::EnsureOwnership() bool NzByteArray::operator!=(const NzByteArray& rhs) const
{ {
if (m_sharedArray == &emptyArray) return !operator==(rhs);
return; }
if (m_sharedArray->refCount > 1) bool NzByteArray::operator<(const NzByteArray& rhs) const
{ {
m_sharedArray->refCount--; return m_array < rhs.m_array;
}
nzUInt8* buffer = new nzUInt8[m_sharedArray->capacity]; bool NzByteArray::operator<=(const NzByteArray& rhs) const
std::memcpy(buffer, m_sharedArray->buffer, m_sharedArray->size); {
return m_array <= rhs.m_array;
}
m_sharedArray = new SharedArray(1, m_sharedArray->capacity, m_sharedArray->size, buffer); bool NzByteArray::operator>(const NzByteArray& rhs) const
} {
return m_array > rhs.m_array;
}
bool NzByteArray::operator>=(const NzByteArray& rhs) const
{
return m_array >= rhs.m_array;
}
void NzByteArray::PopBack()
{
Erase(end() - 1);
}
void NzByteArray::PopFront()
{
Erase(begin());
}
NzByteArray::iterator NzByteArray::Prepend(const void* buffer, size_type n)
{
return Insert(begin(), buffer, n);
}
NzByteArray::iterator NzByteArray::Prepend(const NzByteArray& other)
{
return Insert(begin(), other);
}
void NzByteArray::PushBack(const value_type byte)
{
m_array.push_back(byte);
}
void NzByteArray::PushFront(const value_type byte)
{
m_array.insert(begin(), 1, byte);
}
void NzByteArray::Reserve(size_type bufferSize)
{
m_array.reserve(bufferSize);
}
void NzByteArray::Resize(size_type newSize)
{
m_array.resize(newSize);
}
void NzByteArray::Resize(size_type newSize, const value_type byte)
{
m_array.resize(newSize, byte);
}
NzByteArray::size_type NzByteArray::size() const noexcept
{
return GetSize();
}
void NzByteArray::ShrinkToFit()
{
m_array.shrink_to_fit();
}
NzByteArray NzByteArray::SubArray(const_iterator startPos, const_iterator endPos) const
{
return NzByteArray(startPos, endPos);
}
void NzByteArray::Swap(NzByteArray& other)
{
m_array.swap(other.m_array);
}
NzString NzByteArray::ToString() const
{
NzStringStream ss;
for (const auto& it : m_array)
ss << it;
return ss;
} }
bool NzByteArray::FillHash(NzAbstractHash* hash) const bool NzByteArray::FillHash(NzAbstractHash* hash) const
{ {
hash->Append(m_sharedArray->buffer, m_sharedArray->size); hash->Append(GetConstBuffer(), GetSize());
return true; return true;
} }
void NzByteArray::ReleaseArray() std::ostream& operator<<(std::ostream& out, const NzByteArray& byteArray)
{ {
if (m_sharedArray == &emptyArray) out << byteArray.ToString();
return; return out;
if (--m_sharedArray->refCount == 0)
{
delete[] m_sharedArray->buffer;
delete m_sharedArray;
}
m_sharedArray = &emptyArray;
} }
NzByteArray::SharedArray NzByteArray::emptyArray(0, 0, 0, nullptr);
unsigned int NzByteArray::npos(std::numeric_limits<unsigned int>::max());
namespace std namespace std
{ {
void swap(NzByteArray& lhs, NzByteArray& rhs) void swap(NzByteArray& lhs, NzByteArray& rhs)

View File

@ -32,22 +32,22 @@
NzFile::NzFile() : NzFile::NzFile() :
m_endianness(nzEndianness_Unknown), m_endianness(nzEndianness_Unknown),
m_impl(nullptr), m_impl(nullptr),
m_openMode(0) m_openMode(nzOpenMode_Current)
{ {
} }
NzFile::NzFile(const NzString& filePath) : NzFile::NzFile(const NzString& filePath) :
m_endianness(nzEndianness_Unknown), m_endianness(nzEndianness_Unknown),
m_impl(nullptr), m_impl(nullptr),
m_openMode(0) m_openMode(nzOpenMode_Current)
{ {
SetFile(filePath); SetFile(filePath);
} }
NzFile::NzFile(const NzString& filePath, unsigned long openMode) : NzFile::NzFile(const NzString& filePath, unsigned int openMode) :
m_endianness(nzEndianness_Unknown), m_endianness(nzEndianness_Unknown),
m_impl(nullptr), m_impl(nullptr),
m_openMode(0) m_openMode(openMode)
{ {
Open(filePath, openMode); Open(filePath, openMode);
} }
@ -133,7 +133,7 @@ void NzFile::Flush()
return; return;
} }
if ((m_openMode & ReadWrite) == 0 && (m_openMode & WriteOnly) == 0) if ((m_openMode & nzOpenMode_ReadWrite) == 0 && (m_openMode & nzOpenMode_WriteOnly) == 0)
{ {
NazaraError("Cannot flush file without write access"); NazaraError("Cannot flush file without write access");
return; return;
@ -225,7 +225,7 @@ std::size_t NzFile::Read(void* buffer, std::size_t size)
return 0; return 0;
} }
if ((m_openMode & ReadOnly) == 0 && (m_openMode & ReadWrite) == 0) if ((m_openMode & nzOpenMode_ReadOnly) == 0 && (m_openMode & nzOpenMode_ReadWrite) == 0)
{ {
NazaraError("File not opened with read access"); NazaraError("File not opened with read access");
return 0; return 0;
@ -242,7 +242,7 @@ std::size_t NzFile::Read(void* buffer, std::size_t size)
// Si nous ne devons rien lire, nous avançons simplement // Si nous ne devons rien lire, nous avançons simplement
nzUInt64 currentPos = m_impl->GetCursorPos(); nzUInt64 currentPos = m_impl->GetCursorPos();
m_impl->SetCursorPos(NzFile::AtCurrent, size); m_impl->SetCursorPos(nzCursorPosition_AtCurrent, size);
return static_cast<std::size_t>(m_impl->GetCursorPos()-currentPos); return static_cast<std::size_t>(m_impl->GetCursorPos()-currentPos);
} }
@ -281,7 +281,7 @@ bool NzFile::Rename(const NzString& newFilePath)
return success; return success;
} }
bool NzFile::Open(unsigned long openMode) bool NzFile::Open(unsigned int openMode)
{ {
NazaraLock(m_mutex) NazaraLock(m_mutex)
@ -306,13 +306,13 @@ bool NzFile::Open(unsigned long openMode)
m_impl = impl.release(); m_impl = impl.release();
if (m_openMode & Text) if (m_openMode & nzOpenMode_Text)
m_streamOptions |= nzStreamOption_Text; m_streamOptions |= nzStreamOption_Text;
return true; return true;
} }
bool NzFile::Open(const NzString& filePath, unsigned long openMode) bool NzFile::Open(const NzString& filePath, unsigned int openMode)
{ {
NazaraLock(m_mutex) NazaraLock(m_mutex)
@ -322,7 +322,7 @@ bool NzFile::Open(const NzString& filePath, unsigned long openMode)
return Open(openMode); return Open(openMode);
} }
bool NzFile::SetCursorPos(CursorPosition pos, nzInt64 offset) bool NzFile::SetCursorPos(nzCursorPosition pos, nzInt64 offset)
{ {
NazaraLock(m_mutex) NazaraLock(m_mutex)
@ -349,7 +349,7 @@ bool NzFile::SetCursorPos(nzUInt64 offset)
} }
#endif #endif
return m_impl->SetCursorPos(AtBegin, offset); return m_impl->SetCursorPos(nzCursorPosition_AtBegin, offset);
} }
void NzFile::SetEndianness(nzEndianness endianness) void NzFile::SetEndianness(nzEndianness endianness)
@ -389,7 +389,7 @@ bool NzFile::SetOpenMode(unsigned int openMode)
{ {
NazaraLock(m_mutex) NazaraLock(m_mutex)
if (openMode == 0 || openMode == m_openMode) if (openMode == nzOpenMode_Current || openMode == m_openMode)
return true; return true;
if (IsOpen()) if (IsOpen())
@ -406,7 +406,7 @@ bool NzFile::SetOpenMode(unsigned int openMode)
m_impl = impl.release(); m_impl = impl.release();
if (m_openMode & Text) if (m_openMode & nzOpenMode_Text)
m_streamOptions |= nzStreamOption_Text; m_streamOptions |= nzStreamOption_Text;
} }
@ -417,7 +417,7 @@ bool NzFile::SetOpenMode(unsigned int openMode)
bool NzFile::Write(const NzByteArray& byteArray) bool NzFile::Write(const NzByteArray& byteArray)
{ {
unsigned int size = byteArray.GetSize(); NzByteArray::size_type size = byteArray.GetSize();
return Write(byteArray.GetConstBuffer(), 1, size) == size; return Write(byteArray.GetConstBuffer(), 1, size) == size;
} }
@ -455,7 +455,7 @@ std::size_t NzFile::Write(const void* buffer, std::size_t typeSize, unsigned int
return 0; return 0;
} }
if ((m_openMode & ReadWrite) == 0 && (m_openMode & WriteOnly) == 0) if ((m_openMode & nzOpenMode_ReadWrite) == 0 && (m_openMode & nzOpenMode_WriteOnly) == 0)
{ {
NazaraError("File not opened with write access"); NazaraError("File not opened with write access");
return 0; return 0;
@ -721,7 +721,7 @@ bool NzFile::Rename(const NzString& sourcePath, const NzString& targetPath)
bool NzFile::FillHash(NzAbstractHash* hash) const bool NzFile::FillHash(NzAbstractHash* hash) const
{ {
NzFile file(m_filePath); NzFile file(m_filePath);
if (!file.Open(NzFile::ReadOnly)) if (!file.Open(nzOpenMode_ReadOnly))
{ {
NazaraError("Unable to open file"); NazaraError("Unable to open file");
return false; return false;

View File

@ -114,7 +114,7 @@ void NzLog::Write(const NzString& string)
if (m_enabled) if (m_enabled)
{ {
if (!m_file) if (!m_file)
m_file = new NzFile(m_filePath, NzFile::Text | NzFile::WriteOnly | ((m_append) ? NzFile::Append : NzFile::Truncate)); m_file = new NzFile(m_filePath, nzOpenMode_Text | nzOpenMode_WriteOnly | ((m_append) ? nzOpenMode_Append : nzOpenMode_Truncate));
NzString line; NzString line;

View File

@ -51,33 +51,33 @@ bool NzFileImpl::Open(const NzString& filePath, unsigned int mode)
int flags; int flags;
mode_t permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; mode_t permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
if (mode & NzFile::ReadOnly) if (mode & nzOpenMode_ReadOnly)
flags = O_RDONLY; flags = O_RDONLY;
else if (mode & NzFile::ReadWrite) else if (mode & nzOpenMode_ReadWrite)
{ {
flags = O_CREAT | O_RDWR; flags = O_CREAT | O_RDWR;
if (mode & NzFile::Append) if (mode & nzOpenMode_Append)
flags |= O_APPEND; flags |= O_APPEND;
if (mode & NzFile::Truncate) if (mode & nzOpenMode_Truncate)
flags |= O_TRUNC; flags |= O_TRUNC;
} }
else if (mode & NzFile::WriteOnly) else if (mode & nzOpenMode_WriteOnly)
{ {
flags = O_CREAT | O_WRONLY; flags = O_CREAT | O_WRONLY;
if (mode & NzFile::Append) if (mode & nzOpenMode_Append)
flags |= O_APPEND; flags |= O_APPEND;
if (mode & NzFile::Truncate) if (mode & nzOpenMode_Truncate)
flags |= O_TRUNC; flags |= O_TRUNC;
} }
else else
return false; return false;
///TODO: lock ///TODO: lock
// if ((mode & NzFile::Lock) == 0) // if ((mode & nzOpenMode_Lock) == 0)
// shareMode |= FILE_SHARE_WRITE; // shareMode |= FILE_SHARE_WRITE;
m_fileDescriptor = open64(filePath.GetConstBuffer(), flags, permissions); m_fileDescriptor = open64(filePath.GetConstBuffer(), flags, permissions);
@ -98,20 +98,20 @@ std::size_t NzFileImpl::Read(void* buffer, std::size_t size)
return 0; return 0;
} }
bool NzFileImpl::SetCursorPos(NzFile::CursorPosition pos, nzInt64 offset) bool NzFileImpl::SetCursorPos(nzCursorPosition pos, nzInt64 offset)
{ {
int moveMethod; int moveMethod;
switch (pos) switch (pos)
{ {
case NzFile::AtBegin: case nzCursorPosition_AtBegin:
moveMethod = SEEK_SET; moveMethod = SEEK_SET;
break; break;
case NzFile::AtCurrent: case nzCursorPosition_AtCurrent:
moveMethod = SEEK_CUR; moveMethod = SEEK_CUR;
break; break;
case NzFile::AtEnd: case nzCursorPosition_AtEnd:
moveMethod = SEEK_END; moveMethod = SEEK_END;
break; break;

View File

@ -35,7 +35,7 @@ class NzFileImpl : NzNonCopyable
nzUInt64 GetCursorPos() const; nzUInt64 GetCursorPos() const;
bool Open(const NzString& filePath, unsigned int mode); bool Open(const NzString& filePath, unsigned int mode);
std::size_t Read(void* buffer, std::size_t size); std::size_t Read(void* buffer, std::size_t size);
bool SetCursorPos(NzFile::CursorPosition pos, nzInt64 offset); bool SetCursorPos(nzCursorPosition pos, nzInt64 offset);
std::size_t Write(const void* buffer, std::size_t size); std::size_t Write(const void* buffer, std::size_t size);
static bool Copy(const NzString& sourcePath, const NzString& targetPath); static bool Copy(const NzString& sourcePath, const NzString& targetPath);

View File

@ -11,6 +11,7 @@
#include <Nazara/Core/Unicode.hpp> #include <Nazara/Core/Unicode.hpp>
#include <Nazara/Math/Algorithm.hpp> #include <Nazara/Math/Algorithm.hpp>
#include <algorithm> #include <algorithm>
#include <cctype>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <limits> #include <limits>
@ -50,24 +51,24 @@ inline char nzToUpper(char character)
inline int nzStrcasecmp(const char* s1, const char* s2) inline int nzStrcasecmp(const char* s1, const char* s2)
{ {
int ret = 0; int ret = 0;
while (!(ret = static_cast<unsigned char>(nzToLower(*s1)) - static_cast<unsigned char>(nzToLower(*s2))) && *s2) while (!(ret = static_cast<unsigned char>(nzToLower(*s1)) - static_cast<unsigned char>(nzToLower(*s2))) && *s2)
++s1, ++s2; ++s1, ++s2;
return ret != 0 ? (ret > 0 ? 1 : -1) : 0; return ret != 0 ? (ret > 0 ? 1 : -1) : 0;
} }
inline int nzUnicodecasecmp(const char* s1, const char* s2) inline int nzUnicodecasecmp(const char* s1, const char* s2)
{ {
int ret = 0; int ret = 0;
utf8::unchecked::iterator<const char*> it1(s1); utf8::unchecked::iterator<const char*> it1(s1);
utf8::unchecked::iterator<const char*> it2(s2); utf8::unchecked::iterator<const char*> it2(s2);
while (!(ret = NzUnicode::GetLowercase(*it1) - NzUnicode::GetLowercase(*it2)) && *it2) while (!(ret = NzUnicode::GetLowercase(*it1) - NzUnicode::GetLowercase(*it2)) && *it2)
++it1, ++it2; ++it1, ++it2;
return ret != 0 ? (ret > 0 ? 1 : -1) : 0; return ret != 0 ? (ret > 0 ? 1 : -1) : 0;
} }
NzString::NzString() : NzString::NzString() :
@ -2087,8 +2088,8 @@ bool NzString::Match(const char* pattern) const
if (!*++pattern) if (!*++pattern)
return true; return true;
mp = pattern; mp = pattern;
cp = str+1; cp = str+1;
} }
else if (*pattern == *str || *pattern == '?') else if (*pattern == *str || *pattern == '?')
{ {
@ -3977,7 +3978,7 @@ NzString NzString::Unicode(char32_t character)
count = 2; count = 2;
else if (character < 0x10000) else if (character < 0x10000)
count = 3; count = 3;
else else
count = 4; count = 4;
char* str = new char[count+1]; char* str = new char[count+1];
@ -4028,7 +4029,7 @@ NzString NzString::Unicode(const char32_t* u32String)
count += 2; count += 2;
else if (cp < 0x10000) else if (cp < 0x10000)
count += 3; count += 3;
else else
count += 4; count += 4;
} }
while (*++ptr); while (*++ptr);
@ -4056,7 +4057,7 @@ NzString NzString::Unicode(const wchar_t* wString)
count += 2; count += 2;
else if (cp < 0x10000) else if (cp < 0x10000)
count += 3; count += 3;
else else
count += 4; count += 4;
} }
while (*++ptr); while (*++ptr);

View File

@ -57,31 +57,31 @@ bool NzFileImpl::Open(const NzString& filePath, unsigned int mode)
DWORD access; DWORD access;
DWORD shareMode = FILE_SHARE_READ; DWORD shareMode = FILE_SHARE_READ;
DWORD openMode; DWORD openMode;
if (mode & NzFile::ReadOnly) if (mode & nzOpenMode_ReadOnly)
{ {
access = GENERIC_READ; access = GENERIC_READ;
openMode = OPEN_EXISTING; openMode = OPEN_EXISTING;
} }
else if (mode & NzFile::ReadWrite) else if (mode & nzOpenMode_ReadWrite)
{ {
if (mode & NzFile::Append) if (mode & nzOpenMode_Append)
access = FILE_APPEND_DATA; access = FILE_APPEND_DATA;
else else
access = GENERIC_READ | GENERIC_WRITE; access = GENERIC_READ | GENERIC_WRITE;
if (mode & NzFile::Truncate) if (mode & nzOpenMode_Truncate)
openMode = CREATE_ALWAYS; openMode = CREATE_ALWAYS;
else else
openMode = OPEN_ALWAYS; openMode = OPEN_ALWAYS;
} }
else if (mode & NzFile::WriteOnly) else if (mode & nzOpenMode_WriteOnly)
{ {
if (mode & NzFile::Append) if (mode & nzOpenMode_Append)
access = FILE_APPEND_DATA; access = FILE_APPEND_DATA;
else else
access = GENERIC_WRITE; access = GENERIC_WRITE;
if (mode & NzFile::Truncate) if (mode & nzOpenMode_Truncate)
openMode = CREATE_ALWAYS; openMode = CREATE_ALWAYS;
else else
openMode = OPEN_ALWAYS; openMode = OPEN_ALWAYS;
@ -89,7 +89,7 @@ bool NzFileImpl::Open(const NzString& filePath, unsigned int mode)
else else
return false; return false;
if ((mode & NzFile::Lock) == 0) if ((mode & nzOpenMode_Lock) == 0)
shareMode |= FILE_SHARE_WRITE; shareMode |= FILE_SHARE_WRITE;
m_handle = CreateFileW(filePath.GetWideString().data(), access, shareMode, nullptr, openMode, 0, nullptr); m_handle = CreateFileW(filePath.GetWideString().data(), access, shareMode, nullptr, openMode, 0, nullptr);
@ -134,20 +134,20 @@ std::size_t NzFileImpl::Read(void* buffer, std::size_t size)
return 0; return 0;
} }
bool NzFileImpl::SetCursorPos(NzFile::CursorPosition pos, nzInt64 offset) bool NzFileImpl::SetCursorPos(nzCursorPosition pos, nzInt64 offset)
{ {
DWORD moveMethod; DWORD moveMethod;
switch (pos) switch (pos)
{ {
case NzFile::AtBegin: case nzCursorPosition_AtBegin:
moveMethod = FILE_BEGIN; moveMethod = FILE_BEGIN;
break; break;
case NzFile::AtCurrent: case nzCursorPosition_AtCurrent:
moveMethod = FILE_CURRENT; moveMethod = FILE_CURRENT;
break; break;
case NzFile::AtEnd: case nzCursorPosition_AtEnd:
moveMethod = FILE_END; moveMethod = FILE_END;
break; break;

View File

@ -28,7 +28,7 @@ class NzFileImpl : NzNonCopyable
nzUInt64 GetCursorPos() const; nzUInt64 GetCursorPos() const;
bool Open(const NzString& filePath, unsigned int mode); bool Open(const NzString& filePath, unsigned int mode);
std::size_t Read(void* buffer, std::size_t size); std::size_t Read(void* buffer, std::size_t size);
bool SetCursorPos(NzFile::CursorPosition pos, nzInt64 offset); bool SetCursorPos(nzCursorPosition pos, nzInt64 offset);
std::size_t Write(const void* buffer, std::size_t size); std::size_t Write(const void* buffer, std::size_t size);
static bool Copy(const NzString& sourcePath, const NzString& targetPath); static bool Copy(const NzString& sourcePath, const NzString& targetPath);

View File

@ -38,7 +38,7 @@ namespace
bool LoadMaterials(NzModel* model, const NzString& filePath, const NzMaterialParams& parameters, const NzString* materials, const NzOBJParser::Mesh* meshes, unsigned int meshCount) bool LoadMaterials(NzModel* model, const NzString& filePath, const NzMaterialParams& parameters, const NzString* materials, const NzOBJParser::Mesh* meshes, unsigned int meshCount)
{ {
NzFile file(filePath); NzFile file(filePath);
if (!file.Open(NzFile::ReadOnly | NzFile::Text)) if (!file.Open(nzOpenMode_ReadOnly | nzOpenMode_Text))
{ {
NazaraError("Failed to open MTL file (" + file.GetPath() + ')'); NazaraError("Failed to open MTL file (" + file.GetPath() + ')');
return false; return false;
@ -121,6 +121,8 @@ namespace
model->SetMaterial(meshes[i].material, it->second); model->SetMaterial(meshes[i].material, it->second);
} }
return true;
} }
bool Load(NzModel* model, NzInputStream& stream, const NzModelParameters& parameters) bool Load(NzModel* model, NzInputStream& stream, const NzModelParameters& parameters)

View File

@ -86,7 +86,8 @@ namespace
"void main()\n" "void main()\n"
"{\n" "{\n"
" gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);\n" " vec4 WVPVertex = WorldViewProjMatrix * vec4(VertexPosition, 1.0);\n"
" gl_Position = WVPVertex.xyww;\n"
" vTexCoord = vec3(VertexPosition.x, VertexPosition.y, -VertexPosition.z);\n" " vTexCoord = vec3(VertexPosition.x, VertexPosition.y, -VertexPosition.z);\n"
"}\n"; "}\n";
@ -101,7 +102,8 @@ namespace
"void main()\n" "void main()\n"
"{\n" "{\n"
" gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);\n" " vec4 WVPVertex = WorldViewProjMatrix * vec4(VertexPosition, 1.0);\n"
" gl_Position = WVPVertex.xyww;\n"
" vTexCoord = vec3(VertexPosition.x, VertexPosition.y, -VertexPosition.z);\n" " vTexCoord = vec3(VertexPosition.x, VertexPosition.y, -VertexPosition.z);\n"
"}\n"; "}\n";

View File

@ -393,7 +393,7 @@ bool NzLuaInstance::Execute(const NzString& code)
bool NzLuaInstance::ExecuteFromFile(const NzString& filePath) bool NzLuaInstance::ExecuteFromFile(const NzString& filePath)
{ {
NzFile file(filePath); NzFile file(filePath);
if (!file.Open(NzFile::ReadOnly | NzFile::Text)) if (!file.Open(nzOpenMode_ReadOnly | nzOpenMode_Text))
{ {
NazaraError("Failed to open file"); NazaraError("Failed to open file");
return false; return false;

View File

@ -367,6 +367,25 @@ void NzDebugDrawer::Draw(const NzVector3f& position, float size)
Draw(NzBoxf(position.x - size*0.5f, position.y - size*0.5f, position.z - size*0.5f, size, size, size)); Draw(NzBoxf(position.x - size*0.5f, position.y - size*0.5f, position.z - size*0.5f, size, size, size));
} }
void NzDebugDrawer::DrawAxes(const NzVector3f& position, float size)
{
NzColor oldPrimaryColor = s_primaryColor;
s_primaryColor = NzColor::Red;
DrawLine(position, position + NzVector3f::UnitX() * 3.f * size / 4.f);
s_primaryColor = NzColor::Green;
DrawLine(position, position + NzVector3f::UnitY() * 3.f * size / 4.f);
s_primaryColor = NzColor::Blue;
DrawLine(position, position + NzVector3f::UnitZ() * 3.f * size / 4.f);
s_primaryColor = NzColor::Red;
DrawCone(position + NzVector3f::UnitX() * size, NzEulerAnglesf(0.f, 90.f, 0.f), 15, size / 4.f);
s_primaryColor = NzColor::Green;
DrawCone(position + NzVector3f::UnitY() * size, NzEulerAnglesf(-90.f, 0.f, 0.f), 15, size / 4.f);
s_primaryColor = NzColor::Blue;
DrawCone(position + NzVector3f::UnitZ() * size, NzEulerAnglesf(0.f, 0.f, 0.f), 15, size / 4.f);
s_primaryColor = oldPrimaryColor;
}
void NzDebugDrawer::DrawBinormals(const NzStaticMesh* subMesh) void NzDebugDrawer::DrawBinormals(const NzStaticMesh* subMesh)
{ {
if (!Initialize()) if (!Initialize())

View File

@ -2027,7 +2027,8 @@ void NzRenderer::UpdateMatrix(nzMatrixType type)
// Matrices combinées // Matrices combinées
case nzMatrixType_ViewProj: case nzMatrixType_ViewProj:
s_matrices[nzMatrixType_ViewProj].matrix = s_matrices[nzMatrixType_View].matrix * s_matrices[nzMatrixType_Projection].matrix; s_matrices[nzMatrixType_ViewProj].matrix = s_matrices[nzMatrixType_View].matrix;
s_matrices[nzMatrixType_ViewProj].matrix.Concatenate(s_matrices[nzMatrixType_Projection].matrix);
s_matrices[nzMatrixType_ViewProj].updated = true; s_matrices[nzMatrixType_ViewProj].updated = true;
break; break;

View File

@ -192,7 +192,7 @@ NzByteArray NzShader::GetBinary() const
if (binaryLength > 0) if (binaryLength > 0)
{ {
byteArray.Resize(sizeof(nzUInt64) + binaryLength); byteArray.Reserve(sizeof(nzUInt64) + binaryLength);
nzUInt8* buffer = byteArray.GetBuffer(); nzUInt8* buffer = byteArray.GetBuffer();

View File

@ -174,7 +174,7 @@ bool NzShaderStage::SetSourceFromFile(const NzString& filePath)
#endif #endif
NzFile file(filePath); NzFile file(filePath);
if (!file.Open(NzFile::ReadOnly | NzFile::Text)) if (!file.Open(nzOpenMode_ReadOnly | nzOpenMode_Text))
{ {
NazaraError("Failed to open \"" + filePath + '"'); NazaraError("Failed to open \"" + filePath + '"');
return false; return false;

View File

@ -151,7 +151,7 @@ void NzUberShaderPreprocessor::SetShader(nzShaderStage stage, const NzString& so
bool NzUberShaderPreprocessor::SetShaderFromFile(nzShaderStage stage, const NzString& filePath, const NzString& shaderFlags, const NzString& requiredFlags) bool NzUberShaderPreprocessor::SetShaderFromFile(nzShaderStage stage, const NzString& filePath, const NzString& shaderFlags, const NzString& requiredFlags)
{ {
NzFile file(filePath); NzFile file(filePath);
if (!file.Open(NzFile::ReadOnly | NzFile::Text)) if (!file.Open(nzOpenMode_ReadOnly | nzOpenMode_Text))
{ {
NazaraError("Failed to open \"" + filePath + '"'); NazaraError("Failed to open \"" + filePath + '"');
return false; return false;

View File

@ -280,7 +280,7 @@ namespace
bool SetFile(const NzString& filePath) bool SetFile(const NzString& filePath)
{ {
std::unique_ptr<NzFile> file(new NzFile); std::unique_ptr<NzFile> file(new NzFile);
if (!file->Open(filePath, NzFile::ReadOnly)) if (!file->Open(filePath, nzOpenMode_ReadOnly))
{ {
NazaraError("Failed to open stream from file: " + NzError::GetLastError()); NazaraError("Failed to open stream from file: " + NzError::GetLastError());
return false; return false;

View File

@ -53,7 +53,7 @@ bool NzVertexBuffer::FillRaw(const void* data, unsigned int offset, unsigned int
if (!m_buffer) if (!m_buffer)
{ {
NazaraError("No buffer"); NazaraError("No buffer");
return nullptr; return false;
} }
if (m_startOffset + offset + size > m_endOffset) if (m_startOffset + offset + size > m_endOffset)

View File

@ -0,0 +1,216 @@
#include <Nazara/Core/ByteArray.hpp>
#include <catch.hpp>
#include <string>
SCENARIO("ByteArray", "[CORE][BYTEARRAY]")
{
GIVEN("Allocate and raw constructor")
{
NzByteArray byteArray(3);
THEN("Capacity is 3 and size is 0")
{
REQUIRE(byteArray.GetSize() == 0);
REQUIRE(byteArray.GetCapacity() >= 3);
}
WHEN("We add 'data'")
{
byteArray.Append("data", 4);
THEN("We get 'data'")
{
REQUIRE(byteArray.GetSize() == 4);
REQUIRE(byteArray.GetCapacity() >= 4);
REQUIRE(byteArray == NzByteArray("data", 4));
REQUIRE(byteArray.ToString() == "data");
}
}
}
GIVEN("Iterator and default constructor")
{
std::string anotherDataString("anotherData");
NzByteArray defaultByte;
NzByteArray anotherData(anotherDataString.begin(), anotherDataString.end());
WHEN("We assign 'anotherData' with iterator")
{
defaultByte.Assign(anotherData.begin(), anotherData.end());
REQUIRE(anotherData == defaultByte);
REQUIRE(defaultByte.GetSize() == 11);
REQUIRE(defaultByte.GetCapacity() >= 11);
REQUIRE(anotherData.GetSize() == 11);
REQUIRE(anotherData.GetCapacity() >= 11);
}
}
GIVEN("Copy and Move constructor")
{
NzByteArray originalArray(3, 64);
WHEN("We copy")
{
NzByteArray copyByteArray(originalArray);
THEN("We get a copy")
{
REQUIRE(copyByteArray == originalArray);
AND_WHEN("We modify one")
{
for (NzByteArray::size_type i = 0; i < copyByteArray.GetSize(); ++i)
copyByteArray[i] = 46;
THEN("They are no more equal")
{
REQUIRE(copyByteArray != originalArray);
REQUIRE(copyByteArray == NzByteArray(3, 46));
REQUIRE(copyByteArray.GetConstBuffer() != originalArray.GetConstBuffer());
}
}
}
}
WHEN("We move")
{
NzByteArray moveByteArray(std::move(originalArray));
THEN("These results are expected")
{
REQUIRE(moveByteArray == NzByteArray(3, 64));
CHECK(originalArray.IsEmpty());
REQUIRE(originalArray.GetCapacity() == 0);
REQUIRE(moveByteArray.GetConstBuffer() != originalArray.GetConstBuffer());
AND_WHEN("We modify the empty one")
{
originalArray.Prepend(NzByteArray(3, 64));
THEN("They are no more equal")
{
REQUIRE(moveByteArray == originalArray);
REQUIRE(moveByteArray.GetConstBuffer() != originalArray.GetConstBuffer());
}
}
}
}
}
GIVEN("Two byte array (abc) and (cba)")
{
NzByteArray abc("abc", 3);
NzByteArray cba;
cba = std::move(NzByteArray("cba", 3));
WHEN("We do some antagonists operations")
{
THEN("These results are expected")
{
REQUIRE(abc.Back() == cba.Front());
abc.Erase(abc.begin(), abc.begin() + 1);
abc.Erase(abc.begin());
cba.Erase(cba.end() - 1, cba.end());
cba.Erase(cba.end() - 1);
REQUIRE(abc == NzByteArray("c", 1));
REQUIRE(cba == NzByteArray("c", 1));
std::string ab("ab");
abc.Insert(abc.begin(), ab.begin(), ab.end());
cba += NzByteArray("ba", 2);
REQUIRE(abc == NzByteArray("abc", 3));
REQUIRE(cba == NzByteArray("cba", 3));
abc.PopBack();
cba.PopFront();
REQUIRE(abc == NzByteArray("ab", 2));
REQUIRE(cba == NzByteArray("ba", 2));
abc.PushBack('c');
cba.PushFront('c');
REQUIRE(abc == NzByteArray("abc", 3));
REQUIRE(cba == NzByteArray("cba", 3));
}
}
}
GIVEN("One byte array of capacity 10")
{
NzByteArray capacityArray(10);
WHEN("We reserve for 100")
{
capacityArray.Reserve(100);
THEN("Capacity is 100")
{
REQUIRE(capacityArray.GetCapacity() == 100);
}
AND_WHEN("We add information and then shrink to fit")
{
capacityArray.Prepend("information", 11);
capacityArray.ShrinkToFit();
THEN("Capacity is 11")
{
REQUIRE(capacityArray.GetCapacity() == 11);
REQUIRE(capacityArray.GetSize() == 11);
}
}
}
NzByteArray::const_pointer oldBuffer = capacityArray.GetConstBuffer();
WHEN("We reserve for 5, add 'data' for 4 and then shrink to fit")
{
capacityArray.Reserve(5);
THEN("Capacity is still 10")
{
REQUIRE(capacityArray.GetCapacity() == 10);
REQUIRE(capacityArray.GetSize() == 0);
REQUIRE(capacityArray.GetConstBuffer() == oldBuffer);
}
capacityArray.Append("data", 4);
capacityArray.ShrinkToFit();
THEN("Capacity is 4")
{
REQUIRE(capacityArray.GetConstBuffer() != oldBuffer);
REQUIRE(capacityArray.GetCapacity() == 4);
REQUIRE(capacityArray.GetSize() == 4);
}
}
}
GIVEN("Three byte array")
{
NzByteArray first("hello", 5);
NzByteArray second("world", 5);
NzByteArray third;
WHEN("We swap first and third, then second and third and finally third and first")
{
NzByteArray oldFirst(first);
NzByteArray oldSecond(second);
first.Swap(third);
std::swap(second, third);
third.Swap(first);
THEN("First and second have been swapped and third is still empty.")
{
REQUIRE(oldFirst == second);
REQUIRE(oldSecond == first);
REQUIRE(third.IsEmpty());
}
}
}
}

View File

@ -0,0 +1,31 @@
#include <Nazara/Core/Clock.hpp>
#include <catch.hpp>
#include <thread>
SCENARIO("Clock", "[CORE][CLOCK]")
{
GIVEN("A clock paused")
{
nzUInt64 initialTime = 1;
NzClock clock(initialTime, true);
WHEN("We get time")
{
THEN("Time must be the initialTime")
{
REQUIRE(clock.GetMicroseconds() == initialTime);
}
AND_WHEN("We unpause it")
{
clock.Unpause();
THEN("Time must not be the initialTime")
{
std::this_thread::sleep_for(std::chrono::microseconds(10));
REQUIRE(clock.GetMicroseconds() != initialTime);
}
}
}
}
}

View File

@ -0,0 +1,22 @@
#include <Nazara/Core/Color.hpp>
#include <catch.hpp>
SCENARIO("Color", "[CORE][COLOR]")
{
GIVEN("Two colors, one red (255) and one gray (128)")
{
NzColor red(255, 0, 0);
NzColor grey(128);
WHEN("We do operations")
{
THEN("These results are expected")
{
red += NzColor(0, 0, 0);
grey *= NzColor(255);
REQUIRE((red + grey) == NzColor(255, 128, 128));
REQUIRE((red * grey) == NzColor(128, 0, 0));
}
}
}
}

View File

@ -0,0 +1,34 @@
#include <Nazara/Core/Directory.hpp>
#include <catch.hpp>
SCENARIO("Directory", "[CORE][DIRECTORY]")
{
GIVEN("The current directory")
{
NzDirectory currentDirectory(NzDirectory::GetCurrent());
CHECK(currentDirectory.Exists());
currentDirectory.Open();
WHEN("We create a new directory Test Directory")
{
NzDirectory::Create("Test Directory");
THEN("A new directory has been created")
{
CHECK(NzDirectory::Exists(currentDirectory.GetCurrent() + "/Test Directory"));
CHECK(currentDirectory.IsOpen());
}
}
AND_WHEN("We delete it")
{
NzDirectory::Remove(currentDirectory.GetCurrent() + "/Test Directory", true);
THEN("It doesn't exist anymore")
{
CHECK(!NzDirectory::Exists(currentDirectory.GetCurrent() + "/Test Directory"));
}
}
}
}

View File

@ -0,0 +1,28 @@
#include <Nazara/Core/Error.hpp>
#include <catch.hpp>
SCENARIO("Error", "[CORE][ERROR]")
{
nzUInt32 oldFlags = NzError::GetFlags();
GIVEN("Multiple errors")
{
WHEN("Calling to error")
{
THEN("These errors should be written in the log file")
{
NzError::Error(nzErrorType_Internal, "nzErrorType_Internal");
NzError::Error(nzErrorType_Internal, "nzErrorType_Internal", 2, "Error.cpp", "2nd place Internal");
REQUIRE("nzErrorType_Internal" == NzError::GetLastError());
NzError::Error(nzErrorType_Normal, "nzErrorType_Normal");
NzError::Error(nzErrorType_Normal, "nzErrorType_Normal", 2, "Error.cpp", "2nd place Normal");
REQUIRE("nzErrorType_Normal" == NzError::GetLastError());
NzError::Error(nzErrorType_Warning, "nzErrorType_Warning");
NzError::Error(nzErrorType_Warning, "nzErrorType_Warning", 2, "Error.cpp", "2nd place Warning");
REQUIRE("nzErrorType_Warning" == NzError::GetLastError());
}
}
}
NzError::SetFlags(oldFlags);
}

View File

@ -0,0 +1,53 @@
#include <Nazara/Core/File.hpp>
#include <catch.hpp>
SCENARIO("File", "[CORE][FILE]")
{
GIVEN("One file")
{
WHEN("We create a new file")
{
NzFile file("Test File.txt", nzOpenMode_ReadWrite);
REQUIRE(file.GetDirectory() == NzDirectory::GetCurrent() + NAZARA_DIRECTORY_SEPARATOR);
CHECK(file.IsOpen());
THEN("We are allowed to write 3 times 'Test String'")
{
const char message[12] = "Test String"; // 11 + '\0'
NzByteArray byteArray(message, 11);
file.Write("Test String");
file.Write(byteArray);
file.Write(message, sizeof(char), 11);
}
AND_THEN("We can retrieve 3 times 'Test String'")
{
char message[12];
REQUIRE(file.Read(message, 11) == 11);
message[11] = '\0';
REQUIRE(NzString(message) == "Test String");
REQUIRE(file.Read(message, sizeof(char), 11) == 11);
message[11] = '\0';
REQUIRE(NzString(message) == "Test String");
}
AND_THEN("We close it")
{
file.Close();
REQUIRE(file.GetSize() == 33U);
CHECK(!file.IsOpen());
}
}
WHEN("We delete this file")
{
NzFile::Delete("Test File.txt");
THEN("It doesn't exist anymore")
{
CHECK(!NzFile::Exists("Test File.txt"));
}
}
}
}

View File

@ -0,0 +1,111 @@
#include <Nazara/Core/String.hpp>
#include <catch.hpp>
SCENARIO("String", "[CORE][STRING]")
{
GIVEN("One string 'a'")
{
NzString aDefaultString(1, 'a');
WHEN("We add information")
{
aDefaultString.Append("Default");
aDefaultString.Insert(aDefaultString.GetSize(), "String");
THEN("The result should be 'aDefaultString'")
{
REQUIRE(aDefaultString == "aDefaultString");
REQUIRE(aDefaultString.GetSize() == 14);
REQUIRE(aDefaultString.GetCapacity() >= 14);
}
AND_WHEN("We test Contains and Find")
{
THEN("These results are expected")
{
CHECK(aDefaultString.Contains('D'));
CHECK(aDefaultString.Contains("String", 3));
CHECK(aDefaultString.Contains(NzString("sTRING"), 3, NzString::CaseInsensitive));
REQUIRE(aDefaultString.FindLast('g') == aDefaultString.GetSize() - 1);
CHECK(aDefaultString.EndsWith('G', NzString::CaseInsensitive));
aDefaultString.Append(" ng bla");
REQUIRE(aDefaultString.FindWord("ng") == aDefaultString.GetSize() - 6);
//TODO REQUIRE(aDefaultString.FindWord(NzString("ng")) == aDefaultString.GetSize() - 6);
CHECK(aDefaultString.StartsWith("aD"));
}
}
}
WHEN("We do operators")
{
aDefaultString[0] = 'a';
aDefaultString += "Default";
aDefaultString = aDefaultString + "String";
THEN("The result should be 'aDefaultString'")
{
REQUIRE(aDefaultString == "aDefaultString");
REQUIRE(aDefaultString.GetSize() == 14);
REQUIRE(aDefaultString.GetCapacity() >= 14);
}
AND_WHEN("We test Count")
{
THEN("These results are expected")
{
REQUIRE(aDefaultString.Count('D') == 1);
REQUIRE(aDefaultString.Count("t", 2) == 2);
}
}
}
}
GIVEN("The string of number 16 in base 16")
{
NzString number16;
CHECK(number16.IsEmpty());
CHECK(number16.IsNull());
WHEN("We assign to number 16")
{
number16 = NzString::Number(16, 16);
THEN("These results are expected")
{
CHECK(number16.IsNumber(16));
number16.Prepend("0x");
REQUIRE(number16.GetSize() == 4);
REQUIRE(number16.GetCapacity() >= 4);
REQUIRE(number16.SubStringFrom('x', 1) == "10");
}
}
}
/* TODO
GIVEN("One unicode string")
{
NzString unicodeString = NzString::Unicode(U"àéçœÂ官話");
WHEN("We convert to other UTF")
{
REQUIRE(unicodeString.GetSize() == 7);
REQUIRE(unicodeString.GetCapacity() >= 7);
CHECK(unicodeString.Contains(""));
THEN("The result should be the identity")
{
char* utf8 = unicodeString.GetUtf8Buffer();
NzString utf8String = NzString::Unicode(utf8);
char16_t* utf16 = unicodeString.GetUtf16Buffer();
NzString utf16String = NzString::Unicode(utf16);
char32_t* utf32 = unicodeString.GetUtf32Buffer();
NzString utf32String = NzString::Unicode(utf32);
REQUIRE(utf8String == utf16String);
REQUIRE(utf16String == utf32String);
}
}
}*/
}

View File

@ -0,0 +1,71 @@
#include <Nazara/Core/StringStream.hpp>
#include <catch.hpp>
SCENARIO("StringStream", "[CORE][STRINGSTREAM]")
{
GIVEN("A string stream")
{
NzStringStream stringstream("default");
WHEN("We add bool and char")
{
stringstream << true;
char valueCharSigned = 64;
stringstream << valueCharSigned;
unsigned char valueCharUnsigned = 64;
stringstream << valueCharUnsigned;
REQUIRE(stringstream.ToString() == "defaulttrue@@");
}
AND_WHEN("We add short and int")
{
short valueShortSigned = -3;
stringstream << valueShortSigned;
unsigned short valueShortUnsigned = 3;
stringstream << valueShortUnsigned;
int valueIntSigned = -3;
stringstream << valueIntSigned;
unsigned int valueIntUnsigned = 3;
stringstream << valueIntUnsigned;
REQUIRE(stringstream.ToString() == "default-33-33");
}
AND_WHEN("We add long and long long")
{
long valueLongSigned = -3;
stringstream << valueLongSigned;
unsigned long valueLongUnsigned = 3;
stringstream << valueLongUnsigned;
long long valueLongLongSigned = -3;
stringstream << valueLongLongSigned;
unsigned long long valueLongLongUnsigned = 3;
stringstream << valueLongLongUnsigned;
REQUIRE(stringstream.ToString() == "default-33-33");
}
AND_WHEN("We add floating points")
{
stringstream << 3.f;
stringstream << 3.0;
stringstream << 3.0L;
REQUIRE(stringstream.ToString() == "default333");
}
AND_WHEN("We add string and pointer")
{
stringstream << "3";
stringstream << std::string("3");
stringstream << NzString("3");
stringstream << static_cast<void*>(nullptr);
REQUIRE(stringstream.ToString() == (NzString("default3330x") + NzString(sizeof(void*) * 2, "0")));
}
}
}

View File

@ -0,0 +1,197 @@
#include <Nazara/Math/Algorithm.hpp>
#include <catch.hpp>
TEST_CASE("Approach", "[MATH][ALGORITHM]" )
{
SECTION("Approach 8 with 5 by 2")
{
REQUIRE(NzApproach(5, 8, 2) == 7);
}
SECTION("Approach 5 with 8 by 2")
{
REQUIRE(NzApproach(8, 5, 2) == 6);
}
SECTION("Approach 8 with 8 by 2")
{
REQUIRE(NzApproach(8, 8, 2) == 8);
}
}
TEST_CASE("Clamp", "[ALGORITHM]" )
{
SECTION("Clamp 8 between 5 and 10")
{
REQUIRE(NzClamp(8, 5, 10) == 8);
}
SECTION("Clamp 4 between 5 and 10")
{
REQUIRE(NzClamp(4, 5, 10) == 5);
}
SECTION("Clamp 12 between 5 and 10")
{
REQUIRE(NzClamp(12, 5, 10) == 10);
}
}
TEST_CASE("DegreeToRadian", "[ALGORITHM]" )
{
SECTION("Convert 45.f degree to radian")
{
REQUIRE(NzDegreeToRadian(45.f) == Approx(M_PI / 4));
}
}
TEST_CASE("GetNearestPowerOfTwo", "[ALGORITHM]" )
{
SECTION("Nearest power of two of 16 = 16")
{
REQUIRE(NzGetNearestPowerOfTwo(16) == 16);
}
SECTION("Nearest power of two of 17 = 32")
{
REQUIRE(NzGetNearestPowerOfTwo(17) == 32);
}
}
TEST_CASE("GetNumberLength", "[ALGORITHM]" )
{
SECTION("GetNumberLength of -127 signed char")
{
signed char minus127 = -127;
REQUIRE(NzGetNumberLength(minus127) == 4);
}
SECTION("GetNumberLength of 255 unsigned char")
{
unsigned char plus255 = 255;
REQUIRE(NzGetNumberLength(plus255) == 3);
}
SECTION("GetNumberLength of -1270 signed int")
{
signed int minus1270 = -1270;
REQUIRE(NzGetNumberLength(minus1270) == 5);
}
SECTION("GetNumberLength of 2550 unsigned int")
{
unsigned int plus2550 = 2550;
REQUIRE(NzGetNumberLength(plus2550) == 4);
}
SECTION("GetNumberLength of -1270 signed long long")
{
signed long long minus12700 = -12700;
REQUIRE(NzGetNumberLength(minus12700) == 6);
}
SECTION("GetNumberLength of 2550 unsigned long long")
{
unsigned long long plus25500 = 25500;
REQUIRE(NzGetNumberLength(plus25500) == 5);
}
SECTION("GetNumberLength of -2.456f float")
{
float minus2P456 = -2.456f;
REQUIRE(NzGetNumberLength(minus2P456, 3) == 6);
}
SECTION("GetNumberLength of -2.456 double")
{
double minus2P456 = -2.456;
REQUIRE(NzGetNumberLength(minus2P456, 3) == 6);
}
SECTION("GetNumberLength of -2.456 long double")
{
long double minus2P456 = -2.456L;
REQUIRE(NzGetNumberLength(minus2P456, 3) == 6);
}
}
TEST_CASE("IntegralPow", "[ALGORITHM]" )
{
SECTION("2 to power 4")
{
REQUIRE(NzIntegralPow(2, 4) == 16);
}
}
TEST_CASE("Lerp", "[ALGORITHM]" )
{
SECTION("Lerp 2 to 6 with 0.5")
{
REQUIRE(NzLerp(2, 6, 0.5) == 4);
}
}
TEST_CASE("MultiplyAdd", "[ALGORITHM]" )
{
SECTION("2 * 3 + 1")
{
REQUIRE(NzMultiplyAdd(2, 3, 1) == 7);
}
}
TEST_CASE("NumberEquals", "[ALGORITHM]" )
{
SECTION("2.35 and 2.351 should be the same at 0.01")
{
CHECK(NzNumberEquals(2.35, 2.35, 0.01));
}
SECTION("3 and 4 unsigned should be the same at 1")
{
CHECK(NzNumberEquals(3U, 4U, 1U));
}
}
TEST_CASE("NumberToString", "[ALGORITHM]" )
{
SECTION("235 to string")
{
REQUIRE(NzNumberToString(235) == "235");
}
SECTION("-235 to string")
{
REQUIRE(NzNumberToString(-235) == "-235");
}
SECTION("16 in base 16 to string")
{
REQUIRE(NzNumberToString(16, 16) == "10");
}
}
TEST_CASE("RadianToDegree", "[ALGORITHM]" )
{
SECTION("PI / 4 to degree")
{
REQUIRE(NzRadianToDegree(M_PI / 4) == Approx(45.f));
}
}
TEST_CASE("StringToNumber", "[ALGORITHM]" )
{
SECTION("235 in string")
{
REQUIRE(NzStringToNumber("235") == 235);
}
SECTION("-235 in string")
{
REQUIRE(NzStringToNumber("-235") == -235);
}
SECTION("16 in base 16 in string")
{
REQUIRE(NzStringToNumber("10", 16) == 16);
}
}

View File

@ -0,0 +1,103 @@
#include <Nazara/Math/BoundingVolume.hpp>
#include <catch.hpp>
SCENARIO("BoundingVolume", "[MATH][BOUNDINGVOLUME]")
{
GIVEN("With a null bounding volume and an infinite")
{
NzBoundingVolumef nullVolume = NzBoundingVolumef::Null();
NzBoundingVolumef infiniteVolume = NzBoundingVolumef::Infinite();
WHEN("We compare them")
{
THEN("They should be different")
{
REQUIRE(nullVolume != infiniteVolume);
}
}
WHEN("We ask for the characteristic")
{
THEN("They should be respectively null and infinite")
{
CHECK(nullVolume.IsNull());
CHECK(infiniteVolume.IsInfinite());
}
}
WHEN("If we multiply them")
{
THEN("They should still be different")
{
nullVolume *= 5.f;
infiniteVolume = infiniteVolume * 0.5f;
REQUIRE(nullVolume != infiniteVolume);
AND_WHEN("We ask for the characteristic (infinite and null)")
{
THEN("They should still be respectively null and infinite")
{
CHECK(nullVolume.IsNull());
CHECK(infiniteVolume.IsInfinite());
}
}
}
}
WHEN("We compare two null or two infinite")
{
THEN("Everything should be ok")
{
REQUIRE(NzBoundingVolumef::Null() == NzBoundingVolumef::Null());
REQUIRE(NzBoundingVolumef::Infinite() == NzBoundingVolumef::Infinite());
}
}
}
GIVEN("Two same bounding volume with different constructor")
{
NzBoundingVolumef firstCenterAndUnit(0.f, 0.f, 0.f, 1.f, 1.f, 1.f);
NzBoundingVolumef secondCenterAndUnit(NzVector3f::Zero(), NzVector3f::Unit());
firstCenterAndUnit.Update(NzMatrix4f::Identity());
secondCenterAndUnit.Update(NzMatrix4f::Identity());
WHEN("We compare them")
{
THEN("Then the should be equal")
{
REQUIRE(firstCenterAndUnit == secondCenterAndUnit);
}
}
WHEN("We ask for the characteristic")
{
THEN("They should be finite")
{
CHECK(firstCenterAndUnit.IsFinite());
CHECK(secondCenterAndUnit.IsFinite());
}
}
WHEN("We use a constructor of conversion")
{
THEN("There's no problem")
{
NzBoundingVolume<int> intVolumeCenterAndUnit(NzBoxi(NzVector3i::Zero(), NzVector3i::Unit()));
NzBoundingVolumef thirdCenterAndUnit(intVolumeCenterAndUnit);
REQUIRE(thirdCenterAndUnit == secondCenterAndUnit);
}
}
WHEN("We make one twice bigger with a matrix")
{
firstCenterAndUnit.Update(NzMatrix4f::Scale(NzVector3f::Unit() * 2.f));
THEN("The local box should be the same but the aabb different")
{
REQUIRE(firstCenterAndUnit.obb.localBox == secondCenterAndUnit.obb.localBox);
REQUIRE(firstCenterAndUnit.aabb != secondCenterAndUnit.aabb);
}
}
}
}

113
tests/Nazara/Math/Box.cpp Normal file
View File

@ -0,0 +1,113 @@
#include <Nazara/Math/Box.hpp>
#include <catch.hpp>
SCENARIO("Box", "[MATH][BOX]")
{
GIVEN("Two zero boxes")
{
NzBoxf firstZero(NzBoxf::Zero());
NzBoxf secondZero(NzVector3f::Zero(), NzVector3f::Zero());
WHEN("We multiply them")
{
firstZero = firstZero * 1.f;
secondZero = secondZero * NzVector3f::Unit() * 3.f;
THEN("They should stay the same")
{
REQUIRE(firstZero == secondZero);
CHECK(!firstZero.IsValid());
CHECK(!secondZero.IsValid());
}
}
}
GIVEN("Two unit and center boxes")
{
NzBoxf firstCenterAndUnit(NzRectf(NzVector2f::Zero(), NzVector2f::Unit()));
NzBoxf secondCenterAndUnit(1.f, 1.f, 1.f);
WHEN("We ask for some informations")
{
THEN("These results are expected")
{
REQUIRE(firstCenterAndUnit.GetBoundingSphere() == NzSpheref(NzVector3f::Unit() * 0.5f, std::sqrt(3.f * 0.5f * 0.5f)));
REQUIRE(firstCenterAndUnit.GetCenter() == (NzVector3f::Unit() * 0.5f));
REQUIRE(firstCenterAndUnit.GetCorner(nzBoxCorner_FarLeftTop) == NzVector3f::UnitY());
REQUIRE(firstCenterAndUnit.GetLengths() == NzVector3f::Unit());
REQUIRE(firstCenterAndUnit.GetMaximum() == NzVector3f::Unit());
REQUIRE(firstCenterAndUnit.GetMinimum() == NzVector3f::Zero());
REQUIRE(firstCenterAndUnit.GetNegativeVertex(NzVector3f::Unit()) == NzVector3f::Zero());
REQUIRE(firstCenterAndUnit.GetPosition() == NzVector3f::Zero());
REQUIRE(firstCenterAndUnit.GetPositiveVertex(NzVector3f::Unit()) == NzVector3f::Unit());
REQUIRE(firstCenterAndUnit.GetRadius() == Approx(std::sqrt(3.f * 0.5f * 0.5f)));
REQUIRE(firstCenterAndUnit.GetSquaredBoundingSphere() == NzSpheref(NzVector3f::Unit() * 0.5f, 3.f * 0.5f * 0.5f));
REQUIRE(firstCenterAndUnit.GetSquaredRadius() == Approx(3.f * 0.5f * 0.5f));
}
}
WHEN("We ask for the intersection between the two")
{
THEN("We should have a center and unit")
{
NzBoxf thirdCenterAndUnit;
CHECK(firstCenterAndUnit.Intersect(secondCenterAndUnit, &thirdCenterAndUnit));
REQUIRE(firstCenterAndUnit == secondCenterAndUnit);
}
}
WHEN("We use the constructor of conversion")
{
THEN("Shouldn't be a problem")
{
NzBoxf tmp(NzBoxi(0, 0, 0, 1, 1, 1));
REQUIRE(tmp == firstCenterAndUnit);
}
}
}
GIVEN("Two wrong box (negative width, height and depth")
{
NzBoxf firstWrongBox(-NzVector3f::Unit());
NzBoxf secondWrongBox(-NzVector3f::Unit());
WHEN("We check if valid")
{
THEN("Result if false")
{
CHECK(!firstWrongBox.IsValid());
CHECK(!secondWrongBox.IsValid());
}
}
WHEN("We correct them")
{
firstWrongBox.ExtendTo(NzVector3f::Unit());
secondWrongBox.Transform(NzMatrix4f::Scale(-NzVector3f::Unit()));
THEN("They should be valid")
{
CHECK(firstWrongBox.IsValid());
CHECK(secondWrongBox.IsValid());
}
AND_WHEN("We ask if they contain boxes")
{
THEN("These results are expected")
{
CHECK(firstWrongBox.Contains(0.f, 0.f, 0.f));
CHECK(secondWrongBox.Contains(0.f, 0.f, 0.f));
secondWrongBox = secondWrongBox.Lerp(NzBoxf::Zero(), secondWrongBox, 0.f); // Zeroed
secondWrongBox.ExtendTo(NzBoxf(NzVector3f(0.1f, 0.1f, 0.1f), NzVector3f(0.9f, 0.9f, 0.9f)));
secondWrongBox.Translate(NzVector3f(0.05f, 0.05f, 0.05f)); // Box 0.15 to 0.95
CHECK(firstWrongBox.Contains(secondWrongBox));
NzBoxf test(1.f, -500.f, -500.f, 1000.f, 1000.f, 1000.f);
CHECK(test.Contains(NzBoxf(500.f, -0.5f, -0.5f, 1.f, 1.f, 1.f)));
CHECK(test.Contains(500.f, 0.f, 0.f));
}
}
}
}
}

View File

@ -0,0 +1,83 @@
#include <Nazara/Math/EulerAngles.hpp>
#include <catch.hpp>
SCENARIO("EulerAngles", "[MATH][EULERANGLES]")
{
GIVEN("Two zero euler angles")
{
NzEulerAnglesf firstZero(0.f, 0.f, 0.f);
NzEulerAnglesf secondZero(NzEulerAngles<int>::Zero());
THEN("They should be equal")
{
REQUIRE(firstZero == secondZero);
}
WHEN("We do some operations")
{
NzEulerAnglesf euler90(90.f, 90.f, 90.f);
NzEulerAnglesf euler270(270.f, 270.f, 270.f);
NzEulerAnglesf euler360 = euler90 + euler270;
euler360.Normalize();
NzEulerAnglesf euler0 = euler270 - euler90;
euler0 -= euler90;
euler0 -= euler90;
THEN("They should still be equal")
{
REQUIRE(euler360 == firstZero);
REQUIRE(euler0 == secondZero);
}
}
WHEN("We ask for conversion to quaternion")
{
THEN("They are the same")
{
REQUIRE(firstZero.ToQuaternion() == secondZero.ToQuaternion());
REQUIRE(firstZero.ToQuaternion() == NzEulerAnglesf(NzQuaternionf(1.f, 0.f, 0.f, 0.f)));
REQUIRE(secondZero.ToQuaternion() == NzEulerAnglesf(NzQuaternionf(1.f, 0.f, 0.f, 0.f)));
}
}
}
GIVEN("Euler angles with rotation 45 on each axis")
{
WHEN("We convert to quaternion")
{
THEN("These results are expected")
{
REQUIRE(NzEulerAnglesf(NzFromDegrees(45.f), 0.f, 0.f) == NzQuaternionf(0.923879504204f, 0.382683455944f, 0.f, 0.f).ToEulerAngles());
REQUIRE(NzEulerAnglesf(0.f, NzFromDegrees(45.f), 0.f) == NzQuaternionf(0.923879504204f, 0.f, 0.382683455944f, 0.f).ToEulerAngles());
//REQUIRE(NzEulerAnglesf(0.f, 0.f, NzFromDegrees(45.f)) == NzQuaternionf(0.923879504204f, 0.f, 0.f, 0.382683455944f).ToEulerAngles());
}
}
}
GIVEN("Three euler angles: (0, 22.5, 22.5), (90, 90, 0) and (30, 0, 30)")
{
NzEulerAnglesf euler45(NzFromDegrees(0.f), NzFromDegrees(22.5f), NzFromDegrees(22.5f));
NzEulerAnglesf euler90(NzFromDegrees(90.f), NzFromDegrees(90.f), NzFromDegrees(0.f));
NzEulerAnglesf euler30(NzFromDegrees(30.f), NzFromDegrees(0.f), NzFromDegrees(30.f));
WHEN("We convert them to quaternion")
{
THEN("And then convert to euler angles, we have identity")
{
NzEulerAnglesf tmp = NzQuaternionf(euler45.ToQuaternion()).ToEulerAngles();
REQUIRE(tmp.pitch == Approx(0.f));
REQUIRE(tmp.yaw == Approx(22.5f));
REQUIRE(tmp.roll == Approx(22.5f));
tmp = NzQuaternionf(euler90.ToQuaternion()).ToEulerAngles();
REQUIRE(tmp.pitch == Approx(90.f));
REQUIRE(tmp.yaw == Approx(90.f));
REQUIRE(tmp.roll == Approx(0.f));
tmp = NzQuaternionf(euler30.ToQuaternion()).ToEulerAngles();
REQUIRE(tmp.pitch == Approx(30.f));
REQUIRE(tmp.yaw == Approx(0.f));
REQUIRE(tmp.roll == Approx(30.f));
}
}
}
}

View File

@ -0,0 +1,82 @@
#include <Nazara/Math/Frustum.hpp>
#include <catch.hpp>
SCENARIO("Frustum", "[MATH][FRUSTUM]")
{
GIVEN("One frustum (90, 1, 1, 1000, (0, 0, 0), (1, 0, 0))")
{
NzFrustumf frustum;
frustum.Build(NzFromDegrees(90.f), 1.f, 1.f, 1000.f, NzVector3f::Zero(), NzVector3f::UnitX());
WHEN("We ask for intersection with objects outside the frustum")
{
THEN("These results are expected")
{
NzBoundingVolumef bv(NzVector3f::Zero(), NzVector3f::Unit());
bv.Update(NzMatrix4f::Identity());
REQUIRE(nzIntersectionSide_Outside == frustum.Intersect(bv));
REQUIRE(nzIntersectionSide_Outside == frustum.Intersect(NzBoxf(NzVector3f::Zero(), NzVector3f::Unit() * 0.9f)));
NzOrientedBoxf obb(NzVector3f::Zero(), NzVector3f::Unit() * 0.9f);
obb.Update(NzMatrix4f::Identity());
REQUIRE(nzIntersectionSide_Outside == frustum.Intersect(obb));
REQUIRE(nzIntersectionSide_Outside == frustum.Intersect(NzSpheref(NzVector3f::Zero(), 0.5f)));
NzVector3f tmp = NzVector3f::Zero();
REQUIRE(nzIntersectionSide_Outside == frustum.Intersect(&tmp, 1));
tmp = NzVector3f::UnitX() * -10.f;
REQUIRE(nzIntersectionSide_Outside == frustum.Intersect(&tmp, 1));
}
}
WHEN("We ask for intersection with objects inside the frustum")
{
THEN("These results are expected")
{
NzBoundingVolumef bv(500.f, -0.5f, -0.5f, 1.f, 1.f, 1.f);
bv.Update(NzMatrix4f::Identity());
REQUIRE(nzIntersectionSide_Inside == frustum.Intersect(bv));
REQUIRE(nzIntersectionSide_Inside == frustum.Intersect(NzBoxf(NzVector3f::UnitX() * 500.f, NzVector3f::Unit())));
NzOrientedBoxf obb(NzVector3f::UnitX() * 100.f, NzVector3f::Unit());
obb.Update(NzMatrix4f::Identity());
REQUIRE(nzIntersectionSide_Inside == frustum.Intersect(obb));
REQUIRE(nzIntersectionSide_Inside == frustum.Intersect(NzSpheref(NzVector3f::UnitX() * 100.f, 0.5f)));
NzVector3f tmp = NzVector3f::UnitX() * 100.f;
REQUIRE(nzIntersectionSide_Inside == frustum.Intersect(&tmp, 1));
}
}
WHEN("We ask for contains with objects outside the frustum")
{
THEN("These results are expected")
{
NzBoundingVolumef bv(0.f, -0.25f, -0.25f, 0.5f, 0.5f, 0.5f);
bv.Update(NzMatrix4f::Identity());
CHECK(!frustum.Contains(bv));
CHECK(!frustum.Contains(NzBoxf(0.f, -0.25f, -0.25f, 0.5f, 0.5f, 0.5f)));
NzOrientedBoxf obb(0.f, -0.25f, -0.25f, 0.5f, 0.5f, 0.5f);
obb.Update(NzMatrix4f::Identity());
CHECK(!frustum.Contains(obb));
CHECK(!frustum.Contains(NzSpheref(NzVector3f::Zero(), 0.5f)));
NzVector3f tmp = NzVector3f::Zero();
CHECK(!frustum.Contains(&tmp, 1));
}
}
WHEN("We ask for contains with objects inside the frustum")
{
THEN("These results are expected")
{
NzBoundingVolumef bv(500.f, -0.5f, -0.5f, 1.f, 1.f, 1.f);
bv.Update(NzMatrix4f::Identity());
CHECK(frustum.Contains(bv));
CHECK(frustum.Contains(NzBoxf(500.f, -0.5f, -0.5f, 1.f, 1.f, 1.f)));
NzOrientedBoxf obb(500.f, -0.5f, -0.5f, 1.f, 1.f, 1.f);
obb.Update(NzMatrix4f::Identity());
CHECK(frustum.Contains(obb));
CHECK(frustum.Contains(NzSpheref(NzVector3f::UnitX() * 500.f, 1.f)));
NzVector3f tmp = NzVector3f::UnitX() * 500.f;
CHECK(frustum.Contains(&tmp, 1));
}
}
}
}

View File

@ -0,0 +1,134 @@
#include <Nazara/Math/Matrix4.hpp>
#include <catch.hpp>
SCENARIO("Matrix4", "[MATH][MATRIX4]")
{
GIVEN("Two identity matrix")
{
NzMatrix4f firstIdentity(NzMatrix4<int>::Identity());
NzMatrix4f secondIdentity(1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f);
WHEN("We compare them")
{
THEN("They are equal")
{
REQUIRE(firstIdentity == secondIdentity);
}
}
WHEN("We multiply the first with a vector")
{
THEN("Vector stay the same")
{
REQUIRE(firstIdentity.Transform(NzVector2f::Unit()) == NzVector2f::Unit());
REQUIRE(firstIdentity.Transform(NzVector3f::Unit()) == NzVector3f::Unit());
REQUIRE(firstIdentity.Transform(NzVector4f(1.f, 1.f, 1.f, 1.f)) == NzVector4f(1.f, 1.f, 1.f, 1.f));
}
}
WHEN("We multiply them")
{
THEN("It keeps being a identity")
{
REQUIRE(firstIdentity.Concatenate(secondIdentity) == firstIdentity);
REQUIRE(firstIdentity.ConcatenateAffine(secondIdentity) == firstIdentity);
REQUIRE((firstIdentity * secondIdentity) == firstIdentity);
REQUIRE((1.f * firstIdentity) == firstIdentity);
REQUIRE(firstIdentity.Inverse() == secondIdentity.InverseAffine());
}
}
}
GIVEN("Two different matrix")
{
NzMatrix4f matrix1(1.0f, 0.0f, 0.0f, 0.0f,
7.0f, 2.0f, 0.0f, 0.0f,
1.0f, 5.0f, 3.0f, 0.0f,
8.0f, 9.0f, 2.0f, 4.0f);
NzMatrix4f matrix2(1.0f, 1.0f, 2.0f, -1.0f,
-2.0f, -1.0f, -2.0f, 2.0f,
4.0f, 2.0f, 5.0f, -4.0f,
5.0f, -3.0f, -7.0f, -6.0f);
WHEN("We ask for determinant")
{
THEN("These results are expected")
{
REQUIRE(matrix1.GetDeterminant() == Approx(24.f));
REQUIRE(matrix2.GetDeterminant() == Approx(-1.f));
}
}
WHEN("We multiply the matrix and its inverse")
{
NzMatrix4f invMatrix1;
matrix1.GetInverse(&invMatrix1);
NzMatrix4f invMatrix2;
matrix2.GetInverse(&invMatrix2);
THEN("We get the identity")
{
NzMatrix4f tmp = matrix1 * invMatrix1;
REQUIRE(tmp.m32 == Approx(0.f));
REQUIRE(tmp.m42 == Approx(0.f));
tmp.m32 = 0.f;
tmp.m42 = 0.f;
REQUIRE(tmp == NzMatrix4f::Identity());
REQUIRE((matrix2 * invMatrix2) == NzMatrix4f::Identity());
}
}
}
GIVEN("One transformed matrix from rotation 45 and translation 0")
{
NzMatrix4f transformedMatrix = NzMatrix4f::Transform(NzVector3f::Zero(), NzQuaternionf::Identity());
REQUIRE(transformedMatrix == NzMatrix4f::Identity());
WHEN("We compare with the right matrix")
{
THEN("Rotation around X")
{
transformedMatrix.MakeTransform(NzVector3f::Zero(), NzEulerAnglesf(NzFromDegrees(45.f), 0.f, 0.f).ToQuaternion());
NzMatrix4f rotation45X(1.f, 0.f, 0.f, 0.f,
0.f, std::sqrt(2.f) / 2.f, std::sqrt(2.f) / 2.f, 0.f,
0.f, -std::sqrt(2.f) / 2.f, std::sqrt(2.f) / 2.f, 0.f,
0.f, 0.f, 0.f, 1.f);
REQUIRE(transformedMatrix == rotation45X);
transformedMatrix.MakeTransform(NzVector3f::Unit(), NzEulerAnglesf(NzFromDegrees(45.f), 0.f, 0.f).ToQuaternion());
rotation45X.ApplyTranslation(NzVector3f::Unit());
REQUIRE(transformedMatrix == rotation45X);
}
THEN("Rotation around Y")
{
transformedMatrix.MakeTransform(NzVector3f::Zero(), NzEulerAnglesf(0.f, NzFromDegrees(45.f), 0.f).ToQuaternion());
NzMatrix4f rotation45Y(std::sqrt(2.f) / 2.f, 0.f, -std::sqrt(2.f) / 2.f, 0.f,
0.f, 1.f, 0.f, 0.f,
std::sqrt(2.f) / 2.f, 0.f, std::sqrt(2.f) / 2.f, 0.f,
0.f, 0.f, 0.f, 1.f);
REQUIRE(transformedMatrix == rotation45Y);
transformedMatrix.MakeTransform(NzVector3f::Unit(), NzEulerAnglesf(0.f, NzFromDegrees(45.f), 0.f).ToQuaternion());
rotation45Y.ApplyTranslation(NzVector3f::Unit());
REQUIRE(transformedMatrix == rotation45Y);
}
THEN("Rotation around Z")
{
transformedMatrix.MakeTransform(NzVector3f::Zero(), NzEulerAnglesf(0.f, 0.f, NzFromDegrees(45.f)).ToQuaternion());
NzMatrix4f rotation45Z( std::sqrt(2.f) / 2.f, std::sqrt(2.f) / 2.f, 0.f, 0.f,
-std::sqrt(2.f) / 2.f, std::sqrt(2.f) / 2.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f);
REQUIRE(transformedMatrix == rotation45Z);
transformedMatrix.MakeTransform(NzVector3f::Unit(), NzEulerAnglesf(NzEulerAnglesf(0.f, 0.f, NzFromDegrees(45.f)).ToQuaternion()));
rotation45Z.ApplyTranslation(NzVector3f::Unit());
REQUIRE(transformedMatrix == rotation45Z);
}
}
}
}

View File

@ -0,0 +1,46 @@
#include <Nazara/Math/OrientedBox.hpp>
#include <catch.hpp>
SCENARIO("OrientedBox", "[MATH][ORIENTEDBOX]")
{
GIVEN("Two center and unit oriented boxes")
{
NzOrientedBoxf firstCenterAndUnit(0.f, 0.f, 0.f, 1.f, 1.f, 1.f);
NzOrientedBoxf secondCenterAndUnit(NzOrientedBox<int>(NzVector3i::Zero(), NzVector3i::Unit()));
firstCenterAndUnit.Update(NzMatrix4f::Identity());
WHEN("We compare them")
{
THEN("They are the same")
{
REQUIRE(firstCenterAndUnit == secondCenterAndUnit);
}
}
WHEN("We ask if they are valid")
{
THEN("They are valid")
{
CHECK(firstCenterAndUnit.IsValid());
CHECK(secondCenterAndUnit.IsValid());
}
}
WHEN("We multiply them")
{
THEN("Results are different between operator * and update(ScaleMatrix) but corners are the same")
{
firstCenterAndUnit *= 2.f;
firstCenterAndUnit.Update(NzMatrix4f::Identity());
secondCenterAndUnit.Update(NzMatrix4f::Scale(NzVector3f::Unit() * 2.f));
REQUIRE(firstCenterAndUnit != secondCenterAndUnit);
for (unsigned int i = 0; i <= nzBoxCorner_Max; ++i)
{
REQUIRE(firstCenterAndUnit(i) == secondCenterAndUnit(i));
}
}
}
}
}

View File

@ -0,0 +1,75 @@
#include <Nazara/Math/Plane.hpp>
#include <catch.hpp>
SCENARIO("Plane", "[MATH][PLANE]")
{
GIVEN("Two planes normal(1, 1, 1), distance 1")
{
NzPlanef firstPlane(NzVector3f::Unit().Normalize(), 1.f);
NzPlanef secondPlane(NzPlaned(NzVector3d::Unit().Normalize(), 1.0));
WHEN("We compare them")
{
THEN("They are equal")
{
REQUIRE(firstPlane == secondPlane);
}
AND_THEN("We compare with normal(-1, -1, -1), distance -1")
{
REQUIRE(firstPlane == NzPlanef(-NzVector3f::Unit().Normalize(), -1.f));
}
AND_THEN("They have the same distance from the same point")
{
NzVector3f point(-2.f, 3.f, 1.f);
REQUIRE(firstPlane.Distance(point) == Approx(secondPlane.Distance(point)));
REQUIRE(firstPlane.Distance(-2.f, 3.f, 1.f) == Approx(0.1547f));
}
AND_THEN("Distance between Plane (0, 1, 0), distance 1 and point (0, 2, 0) should be 1")
{
REQUIRE(NzPlanef(NzVector3f::UnitY(), 1.f).Distance(NzVector3f::UnitY() * 2.f) == Approx(1.f));
}
AND_THEN("Distance between Plane (0, 1, 0), distance 5 and point (0, 2, 0) should be -3")
{
REQUIRE(NzPlanef(NzVector3f::UnitY(), 5.f).Distance(NzVector3f::UnitY() * 2.f) == Approx(-3.f));
}
AND_THEN("Distance between Plane (0, 1, 0), distance 1000 and point (0, 500, 0) and (0, 1500, 0)")
{
REQUIRE(NzPlanef(NzVector3f::UnitY(), 1000.f).Distance(NzVector3f::UnitY() * 500.f) == Approx(-500.f));
REQUIRE(NzPlanef(NzVector3f::UnitY(), 1000.f).Distance(NzVector3f::UnitY() * 1500.f) == Approx(500.f));
}
AND_THEN("Distance between Plane (0, -1, 0), distance -1000 and point (0, 500, 0) and (0, 1500, 0)")
{
REQUIRE(NzPlanef(-NzVector3f::UnitY(), -1000.f).Distance(NzVector3f::UnitY() * 500.f) == Approx(500.f));
REQUIRE(NzPlanef(-NzVector3f::UnitY(), -1000.f).Distance(NzVector3f::UnitY() * 1500.f) == Approx(-500.f));
}
}
}
GIVEN("The plane XZ, distance 1 with 3 points (0, 1, 0), (1, 1, 1), (-1, 1, 0)")
{
WHEN("We do a positive plane")
{
NzPlanef xy(NzVector3f(2.f, 1.f, 0.f), NzVector3f(-1.f, 1.f, -1.f), NzVector3f(-1.f, 1.f, 0.f));
THEN("It must be equal to XZ distance 1")
{
REQUIRE(xy == NzPlanef(NzVector3f::UnitY(), 1.f));
}
}
WHEN("We do a negative plane")
{
NzPlanef xy(NzVector3f(0.f, 1.f, 0.f), NzVector3f(1.f, 1.f, 1.f), NzVector3f(-1.f, 1.f, 0.f));
THEN("It must be equal to XZ distance 1")
{
REQUIRE(xy == NzPlanef(-NzVector3f::UnitY(), -1.f));
}
}
}
}

View File

@ -0,0 +1,154 @@
#include <Nazara/Math/Quaternion.hpp>
#include <catch.hpp>
SCENARIO("Quaternion", "[MATH][QUATERNION]")
{
GIVEN("Two quaternions (0, 1, 0, 0)")
{
NzQuaternionf firstQuaternion(NzFromDegrees(180.f), NzVector3f::UnitX());
NzQuaternionf secondQuaternion(0.f, 1.f, 0.f, 0.f);
WHEN("We compare them")
{
THEN("They are the same and the proprieties of quaternions are respected")
{
REQUIRE(firstQuaternion == secondQuaternion);
REQUIRE(firstQuaternion.ComputeW() == secondQuaternion.Normalize());
REQUIRE(firstQuaternion.Conjugate() == secondQuaternion.Inverse());
REQUIRE(firstQuaternion.DotProduct(secondQuaternion) == Approx(1.f));
}
}
WHEN("We do some operations")
{
THEN("Multiply with a vectorX is identity")
{
REQUIRE((firstQuaternion * NzVector3f::UnitX()) == NzVector3f::UnitX());
}
AND_THEN("Multiply with a vectorY or Z is opposite")
{
REQUIRE((firstQuaternion * NzVector3f::UnitY()) == -NzVector3f::UnitY());
REQUIRE((firstQuaternion * NzVector3f::UnitZ()) == -NzVector3f::UnitZ());
}
}
}
GIVEN("The four unit quaternions")
{
NzQuaternionf w(1.f, 0.f, 0.f, 0.f);
NzQuaternionf x(0.f, 1.f, 0.f, 0.f);
NzQuaternionf y(0.f, 0.f, 1.f, 0.f);
NzQuaternionf z(0.f, 0.f, 0.f, 1.f);
NzQuaternionf xyzw = x * y * z * w;
WHEN("We ask for the norm")
{
THEN("They are all equal to 1")
{
REQUIRE(w.Magnitude() == Approx(1.f));
REQUIRE(x.Magnitude() == Approx(1.f));
REQUIRE(y.Magnitude() == Approx(1.f));
REQUIRE(z.Magnitude() == Approx(1.f));
REQUIRE(xyzw.Magnitude() == Approx(1.f));
}
}
WHEN("We multiply them")
{
THEN("Results shoud follow")
{
NzQuaternionf oppositeOfW(-1.f, 0.f, 0.f, 0.f);
NzQuaternionf oppositeOfX = x.GetConjugate();
NzQuaternionf oppositeOfY = y.GetConjugate();
NzQuaternionf oppositeOfZ = z.GetConjugate();
REQUIRE((x * x) == oppositeOfW);
REQUIRE((y * y) == oppositeOfW);
REQUIRE((z * z) == oppositeOfW);
REQUIRE((x * y * z) == oppositeOfW);
REQUIRE((x * y) == z);
REQUIRE((y * x) == oppositeOfZ);
REQUIRE((y * z) == x);
REQUIRE((z * y) == oppositeOfX);
REQUIRE((z * x) == y);
REQUIRE((x * z) == oppositeOfY);
}
}
}
GIVEN("Two different quaternions (10, (1, 0, 0) and (20, (1, 0, 0))")
{
NzQuaternionf x10 = NzQuaternionf(NzFromDegrees(10.f), NzVector3f::UnitX());
NzQuaternionf x20 = x10 * x10;
NzQuaternionf x30a = x10 * x20;
NzQuaternionf x30b = x20 * x10;
WHEN("We multiply them")
{
THEN("These results are expected")
{
REQUIRE(x20 == NzQuaternionf(NzFromDegrees(20.f), NzVector3f::UnitX()));
REQUIRE(x30a == x30b);
}
}
WHEN("Convert euler to quaternion")
{
NzQuaternionf X45(NzEulerAnglesf(NzFromDegrees(45.f), 0.f, 0.f));
NzQuaternionf Y45(NzEulerAnglesf(0.f, NzFromDegrees(45.f), 0.f));
NzQuaternionf Z45(NzEulerAnglesf(0.f, 0.f, NzFromDegrees(45.f)));
THEN("They must be equal")
{
REQUIRE(X45 == NzQuaternionf(0.9238795f, 0.38268346f, 0.f, 0.f));
REQUIRE(Y45 == NzQuaternionf(0.9238795f, 0.f, 0.38268346f, 0.f));
REQUIRE(Z45 == NzQuaternionf(0.9238795f, 0.f, 0.f, 0.38268346f));
}
}
WHEN("We convert to euler angles and then to quaternions")
{
THEN("These results are expected")
{
REQUIRE(x30a.ToEulerAngles() == x30b.ToEulerAngles());
REQUIRE(x30a.ToEulerAngles().ToQuaternion() == x30b.ToEulerAngles().ToQuaternion());
NzQuaternionf tmp(1.f, 1.f, 0.f, 0.f);
tmp.Normalize();
REQUIRE(tmp == tmp.ToEulerAngles().ToQuaternion());
}
}
WHEN("We slerp")
{
THEN("The half of 10 and 30 is 20")
{
NzQuaternionf slerpx10x30a = NzQuaternionf::Slerp(x10, x30a, 0.5f);
REQUIRE(slerpx10x30a.w == Approx(x20.w));
REQUIRE(slerpx10x30a.x == Approx(x20.x));
REQUIRE(slerpx10x30a.y == Approx(x20.y));
REQUIRE(slerpx10x30a.z == Approx(x20.z));
NzQuaternionf slerpx10x30b = NzQuaternionf::Slerp(x10, x30b, 0.5f);
REQUIRE(slerpx10x30b.w == Approx(x20.w));
REQUIRE(slerpx10x30b.x == Approx(x20.x));
REQUIRE(slerpx10x30b.y == Approx(x20.y));
REQUIRE(slerpx10x30b.z == Approx(x20.z));
REQUIRE(NzQuaternionf::Slerp(x10, x30a, 0.f) == x10);
REQUIRE(NzQuaternionf::Slerp(x10, x30a, 1.f) == x30a);
}
AND_THEN("The half of 45 is 22.5")
{
NzQuaternionf quaterionA(NzFromDegrees(0.f), NzVector3f::UnitZ());
NzQuaternionf quaterionB(NzFromDegrees(45.f), NzVector3f::UnitZ());
NzQuaternionf quaternionC = NzQuaternionf::Slerp(quaterionA, quaterionB, 0.5f);
REQUIRE(quaternionC == NzQuaternionf(NzFromDegrees(22.5f), NzVector3f::UnitZ()));
}
}
}
}

95
tests/Nazara/Math/Ray.cpp Normal file
View File

@ -0,0 +1,95 @@
#include <Nazara/Math/Ray.hpp>
#include <catch.hpp>
SCENARIO("Ray", "[RAY]")
{
GIVEN("Two same rays (0, 0, 0) -> (0, 1, 0)")
{
NzRayf firstRay(NzRay<int>(NzPlane<int>::XY(), NzPlane<int>::YZ()));
NzRayf secondRay(0.f, 0.f, 0.f, 0.f, 1.f, 0.f);
WHEN("We compare them")
{
THEN("They are the same and Y axis")
{
REQUIRE(firstRay == secondRay);
REQUIRE(firstRay == NzRayf::AxisY());
}
}
WHEN("We ask for the closest point")
{
THEN("The point that is multiple on the ray, is at multiple")
{
REQUIRE(firstRay.ClosestPoint(secondRay.GetPoint(1.f)) == Approx(1.f));
}
}
WHEN("We ask for intersection")
{
THEN("For the Box collision's")
{
float tmpClosest;
float tmpFurthest;
CHECK(firstRay.Intersect(NzBoxf(-0.5f, 1.f, -0.5f, 1.f, 1.f, 1.f), &tmpClosest, &tmpFurthest));
REQUIRE(firstRay.GetPoint(tmpClosest) == NzVector3f::UnitY());
REQUIRE(firstRay.GetPoint(tmpFurthest) == (NzVector3f::UnitY() * 2.f));
CHECK(!firstRay.Intersect(NzBoxf(-10.f, 1.f, -10.f, 1.f, 1.f, 1.f), &tmpClosest, &tmpFurthest));
}
THEN("For the Plane collision's")
{
float tmpHit;
CHECK(firstRay.Intersect(NzPlanef(NzVector3f::UnitY(), 1.f), &tmpHit));
REQUIRE(firstRay.GetPoint(tmpHit) == NzVector3f::UnitY());
CHECK(firstRay.Intersect(NzPlanef::XZ(), &tmpHit));
REQUIRE(firstRay.GetPoint(tmpHit) == NzVector3f::Zero());
CHECK(firstRay.Intersect(NzPlanef(NzVector3f::UnitY(), 2.f), &tmpHit));
REQUIRE(firstRay.GetPoint(tmpHit) == 2.f * NzVector3f::UnitY());
CHECK(!firstRay.Intersect(NzPlanef(NzVector3f::UnitX(), 1.f)));
}
THEN("For the Sphere collision's")
{
float tmpClosest;
float tmpFurthest;
CHECK(firstRay.Intersect(NzSpheref(NzVector3f::UnitY(), 0.1f), &tmpClosest, &tmpFurthest));
REQUIRE(firstRay.GetPoint(tmpClosest) == NzVector3f::UnitY() * 0.9f);
REQUIRE(firstRay.GetPoint(tmpFurthest) == (NzVector3f::UnitY() * 1.1f));
CHECK(!firstRay.Intersect(NzSpheref(NzVector3f::UnitX(), 0.9f)));
}
THEN("For the OBB collision's")
{
float tmpClosest;
float tmpFurthest;
NzOrientedBoxf obb(-0.5f, 1.f, -0.5f, 1.f, 1.f, 1.f);
obb.Update(NzMatrix4f::Rotate(NzEulerAnglesf(0.f, 90.f, 0.f).ToQuaternion()));
CHECK(firstRay.Intersect(obb, &tmpClosest, &tmpFurthest));
REQUIRE(firstRay.GetPoint(tmpClosest) == NzVector3f::UnitY());
REQUIRE(firstRay.GetPoint(tmpFurthest) == (NzVector3f::UnitY() * 2.f));
obb = NzOrientedBoxf(-10.f, 1.f, -10.f, 1.f, 1.f, 1.f);
obb.Update(NzMatrix4f::Rotate(NzEulerAnglesf(0.f, 0.f, 90.f).ToQuaternion()));
CHECK(!firstRay.Intersect(obb, &tmpClosest, &tmpFurthest));
}
THEN("For the bounding volume collision's")
{
NzBoundingVolumef nullVolume(nzExtend_Null);
CHECK(!firstRay.Intersect(nullVolume));
NzBoundingVolumef infiniteVolume(nzExtend_Infinite);
CHECK(firstRay.Intersect(infiniteVolume));
}
}
}
}

View File

@ -0,0 +1,56 @@
#include <Nazara/Math/Rect.hpp>
#include <catch.hpp>
SCENARIO("Rect", "[MATH][RECT]")
{
GIVEN("Two same rectangles center and unit lengths")
{
NzRectf firstCenterAndUnit(0.f, 0.f, 1.f, 1.f);
NzRectf secondCenterAndUnit(NzRecti(NzVector2i::Unit(), NzVector2i::Zero()));
WHEN("We ask if they are the same")
{
THEN("They should be")
{
REQUIRE(firstCenterAndUnit == secondCenterAndUnit);
REQUIRE(firstCenterAndUnit.GetCenter() == secondCenterAndUnit.GetCenter());
REQUIRE(firstCenterAndUnit.GetCorner(nzRectCorner_LeftBottom) == secondCenterAndUnit.GetCorner(nzRectCorner_LeftBottom));
CHECK(firstCenterAndUnit.IsValid());
}
}
WHEN("We move one from (0.5, 0.5)")
{
firstCenterAndUnit.Translate(NzVector2f(0.5f, 0.5f));
THEN("The collision should be (0.5, 0.5) -> (0.5, 0.5)")
{
NzRectf tmp;
CHECK(firstCenterAndUnit.Intersect(secondCenterAndUnit, &tmp));
REQUIRE(tmp == NzRectf(0.5f, 0.5f, 0.5f, 0.5f));
}
}
WHEN("We make an empty")
{
THEN("It's not valid")
{
CHECK(!(firstCenterAndUnit * 0.f).IsValid());
}
}
WHEN("We ask for infos")
{
THEN("These results are expected")
{
REQUIRE(firstCenterAndUnit.GetLengths() == NzVector2f::Unit());
REQUIRE(firstCenterAndUnit.GetMaximum() == NzVector2f::Unit());
REQUIRE(firstCenterAndUnit.GetMinimum() == NzVector2f::Zero());
REQUIRE(firstCenterAndUnit.GetNegativeVertex(NzVector2f::Unit()) == NzVector2f::Zero());
REQUIRE(firstCenterAndUnit.GetPosition() == NzVector2f::Zero());
REQUIRE(firstCenterAndUnit.GetPositiveVertex(NzVector2f::Unit()) == NzVector2f::Unit());
}
}
}
}

View File

@ -0,0 +1,63 @@
#include <Nazara/Math/Sphere.hpp>
#include <catch.hpp>
SCENARIO("Sphere", "[MATH][SPHERE]")
{
GIVEN("Two same sphere center and unit")
{
NzSpheref firstCenterAndUnit(0.f, 0.f, 0.f, 1.f);
NzSpheref secondCenterAndUnit(NzSphere<int>(NzVector3i::Zero(), 1));
WHEN("We compare them")
{
THEN("They are the same")
{
REQUIRE(firstCenterAndUnit == secondCenterAndUnit);
}
}
WHEN("We ask if they intersect or contain")
{
THEN("These results are expected for Contains")
{
CHECK(firstCenterAndUnit.Contains(0.5f, 0.5f, 0.5f));
CHECK(firstCenterAndUnit.Contains(NzBoxf(NzVector3f::Zero(), NzVector3f::Unit() * 0.5f)));
CHECK(!firstCenterAndUnit.Contains(NzBoxf(NzVector3f::Zero(), NzVector3f::Unit() * 5.f)));
}
THEN("There are for Intersect")
{
CHECK(firstCenterAndUnit.Intersect(NzBoxf(NzVector3f::Zero(), NzVector3f::Unit() * 0.5f)));
CHECK(firstCenterAndUnit.Intersect(NzBoxf(NzVector3f::Zero(), NzVector3f::Unit() * 5.f)));
CHECK(!firstCenterAndUnit.Intersect(NzBoxf(NzVector3f::Unit() * 5.f, NzVector3f::Unit())));
CHECK(firstCenterAndUnit.Intersect(NzSpheref(NzVector3f::Zero(), 0.5f)));
CHECK(firstCenterAndUnit.Intersect(NzSpheref(NzVector3f::Zero(), 5.f)));
CHECK(!firstCenterAndUnit.Intersect(NzSpheref(NzVector3f::Unit() * 5.f, 1.f)));
}
}
WHEN("We ask for distance")
{
THEN("These results are expected")
{
REQUIRE(firstCenterAndUnit.Distance(NzVector3f::UnitX()) == Approx(1.f));
REQUIRE(firstCenterAndUnit.SquaredDistance(NzVector3f::UnitX()) == Approx(1.f));
NzSpheref tmp(NzVector3f::UnitX(), 1.f);
REQUIRE(tmp.Distance(NzVector3f::UnitX() * 4.f) == Approx(3.f));
REQUIRE(tmp.SquaredDistance(NzVector3f::UnitX() * 4.f) == Approx(9.f));
}
}
WHEN("We get sphere from box unit and center")
{
NzBoxf centerUnitBox(NzVector3f::Unit() * -0.5f, NzVector3f::Unit() * 0.5f);
THEN("This is equal to sphere center and radius 0.75")
{
REQUIRE(centerUnitBox.GetSquaredBoundingSphere() == NzSpheref(NzVector3f::Zero(), 0.75f));
}
}
}
}

View File

@ -0,0 +1,49 @@
#include <Nazara/Math/Vector2.hpp>
#include <catch.hpp>
#include <Nazara/Math/Vector4.hpp>
SCENARIO("Vector2", "[MATH][VECTOR2]")
{
GIVEN("Two same vectors (1, 1)")
{
NzVector2f firstUnit(1.f);
NzVector2f secondUnit(NzVector2i(NzVector4i(1, 1, 3, 5)));
WHEN("We compare them")
{
THEN("They are the same")
{
REQUIRE(firstUnit == secondUnit);
}
}
WHEN("We test the dot product")
{
NzVector2f tmp(-1.f, 1.f);
THEN("These results are expected")
{
REQUIRE(firstUnit.AbsDotProduct(tmp) == Approx(2.f));
REQUIRE(firstUnit.DotProduct(tmp) == Approx(0.f));
REQUIRE(firstUnit.AngleBetween(tmp) == Approx(90.f));
}
}
WHEN("We ask for distance from (-2, -3)")
{
NzVector2f tmp(-2.f, -3.f);
NzVector2f tmp2(-1.f, -1.f);
THEN("These are expected")
{
REQUIRE(firstUnit.Distance(tmp2) == Approx(2.f * std::sqrt(2.f)));
REQUIRE(firstUnit.Distance(tmp) == Approx(5.f));
REQUIRE(firstUnit.SquaredDistance(tmp) == Approx(25.f));
REQUIRE(firstUnit.GetSquaredLength() == Approx(2.f));
REQUIRE(firstUnit.GetLength() == Approx(std::sqrt(2.f)));
}
}
}
}

View File

@ -0,0 +1,56 @@
#include <Nazara/Math/Vector3.hpp>
#include <catch.hpp>
#include <Nazara/Math/Vector4.hpp>
SCENARIO("Vector3", "[MATH][VECTOR3]")
{
GIVEN("Two same unit vector")
{
NzVector3f firstUnit(1.f, 1.f, 1.f);
NzVector3f secondUnit(NzVector3i(NzVector4i(1, 1, 1, 5)));
WHEN("We compare them")
{
THEN("They are the same")
{
REQUIRE(firstUnit == secondUnit);
}
}
WHEN("We test the dot product")
{
NzVector3f tmp(-1.f, 0.f, 1.f);
THEN("These results are expected")
{
REQUIRE(firstUnit.AbsDotProduct(tmp) == Approx(2.f));
REQUIRE(firstUnit.DotProduct(tmp) == Approx(0.f));
REQUIRE(firstUnit.AngleBetween(tmp) == Approx(90.f));
}
}
WHEN("We test the cross product")
{
THEN("These results are expected")
{
REQUIRE(NzVector3f::CrossProduct(NzVector3f::UnitX(), NzVector3f::UnitY()) == NzVector3f::UnitZ());
REQUIRE(NzVector3f::CrossProduct(NzVector3f(1.f, 2.f, 3.f), NzVector3f(3.f, 2.f, 1.f)) == NzVector3f(-4.f, 8.f, -4.f));
}
}
WHEN("We ask for distance")
{
NzVector3f tmp(-1.f, -5.f, -8.f);
THEN("These are expected")
{
REQUIRE(firstUnit.Distance(tmp) == Approx(11.f));
REQUIRE(firstUnit.SquaredDistance(tmp) == Approx(121.f));
REQUIRE(firstUnit.GetSquaredLength() == Approx(3.f));
REQUIRE(firstUnit.GetLength() == Approx(std::sqrt(3.f)));
}
}
}
}

View File

@ -0,0 +1,43 @@
#include <Nazara/Math/Vector4.hpp>
#include <catch.hpp>
#include <Nazara/Math/Vector3.hpp>
SCENARIO("Vector4", "[MATH][VECTOR4]")
{
GIVEN("Two same unit vector")
{
NzVector4f firstUnit(1.f, 1.f, 1.f);
NzVector4f secondUnit(NzVector4i(1, 1, 1, 1));
WHEN("We compare them")
{
THEN("They are the same")
{
REQUIRE(firstUnit == secondUnit);
}
}
WHEN("We test the dot product")
{
NzVector4f tmp(-1.f, 0.f, 1.f, 0.f);
THEN("These results are expected")
{
REQUIRE(firstUnit.AbsDotProduct(tmp) == Approx(2.f));
REQUIRE(firstUnit.DotProduct(tmp) == Approx(0.f));
}
}
WHEN("We normalize")
{
NzVector4f tmp(1.f, 1.f, 1.f, 3.f);
THEN("These results are expected")
{
REQUIRE(firstUnit.Normalize() == NzVector4f(1.f, NzVector3f::Unit()));
REQUIRE(tmp.Normalize() == NzVector4f(NzVector3f::Unit() * (1.f / 3.f), 1.f));
}
}
}
}

2
tests/main.cpp Normal file
View File

@ -0,0 +1,2 @@
#define CATCH_CONFIG_MAIN
#include <catch.hpp>