Merge branch 'NDK' into NDK-ShadowMapping

Conflicts:
	include/Nazara/Math/Matrix4.inl

Former-commit-id: e4b7d178a7acba17c03de2b585af86324b8d75a6
This commit is contained in:
Lynix 2015-09-13 12:10:30 +02:00
commit aa303f9028
100 changed files with 3553 additions and 1359 deletions

View File

@ -35,6 +35,9 @@ function NazaraBuild:Execute()
libdirs("../extlibs/lib/mingw/x64")
targetdir("../extlibs/lib/mingw/x64")
configuration("vs*")
buildoptions("/MP")
configuration({"vs*", "x32"})
libdirs("../extlibs/lib/msvc/x86")
targetdir("../extlibs/lib/msvc/x86")
@ -68,7 +71,7 @@ function NazaraBuild:Execute()
targetsuffix("-s")
configuration("codeblocks or codelite or gmake or xcode3 or xcode4")
buildoptions("-std=c++11")
buildoptions("-std=c++14")
for k, libTable in ipairs(self.OrderedExtLibs) do
project(libTable.Name)
@ -122,7 +125,7 @@ function NazaraBuild:Execute()
defines("NAZARA_STATIC")
configuration("codeblocks or codelite or gmake or xcode3 or xcode4")
buildoptions("-std=c++11")
buildoptions("-std=c++14")
configuration({"linux or bsd or macosx", "gmake"})
buildoptions("-fvisibility=hidden")
@ -131,9 +134,11 @@ function NazaraBuild:Execute()
buildoptions("-fvisibility=hidden")
configuration("vs*")
buildoptions("/MP")
defines("_CRT_SECURE_NO_WARNINGS")
defines("_SCL_SECURE_NO_WARNINGS")
-- Spécification des modules
if (_OPTIONS["united"]) then
project("NazaraEngine")

View File

@ -128,7 +128,7 @@ return {
{
Title = "TaskScheduler",
Description = "Classe permettant de répartir X tâches sur Y workers de façon efficace.",
Portability = Feature.Windows
Portability = Feature.Windows + Feature.POSIX
}
}
},
@ -196,8 +196,7 @@ return {
{
Title = "Récupération d'informations sur le hardware",
Description = "Classe permettant, si la plateforme le supporte, de récupérer des informations utiles sur le matériel: nom et fabricant du processeur, nombre de coeurs, support d'un set d'extension (exemple: SSE), quantité de mémoire vive, exécution de l'instruction CPUID.",
Note = "Il manque de quoi récupérer la quantité de mémoire vive",
Progress = 90,
Progress = 100,
Portability = Feature.Windows + Feature.POSIX
}
}

View File

@ -100,7 +100,7 @@ int main()
std::cout << oss.str() << std::endl;
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.Close();

View File

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

View File

@ -11,8 +11,12 @@
#include <functional>
#include <tuple>
template<typename F, typename Tuple> auto NzApply(F&& fn, Tuple&& t);
template<typename O, typename F, typename Tuple> auto NzApply(O& object, F&& fn, Tuple&& t);
template<typename T> void NzHashCombine(std::size_t& seed, const T& v);
template<typename F, typename... ArgsT> void NzUnpackTuple(F func, const std::tuple<ArgsT...>& t);
template<typename T>
struct NzTypeTag {};
#include <Nazara/Core/Algorithm.inl>

View File

@ -8,28 +8,34 @@
#include <Nazara/Core/Debug.hpp>
///TODO: Améliorer l'implémentation de UnpackTuple
template<unsigned int N>
struct NzImplTupleUnpack
// http://www.cppsamples.com/common-tasks/apply-tuple-to-function.html
template<typename F, typename Tuple, size_t... S>
auto NzApplyImplFunc(F&& fn, Tuple&& t, std::index_sequence<S...>)
{
template <typename F, typename... ArgsT, typename... Args>
void operator()(F func, const std::tuple<ArgsT...>& t, Args&... args)
{
NzImplTupleUnpack<N-1>()(func, t, std::get<N-1>(t), args...);
}
};
return std::forward<F>(fn)(std::get<S>(std::forward<Tuple>(t))...);
}
template<>
struct NzImplTupleUnpack<0>
template<typename F, typename Tuple>
auto NzApply(F&& fn, Tuple&& t)
{
template <typename F, typename... ArgsT, typename... Args>
void operator()(F func, const std::tuple<ArgsT...>&, Args&... args)
{
func(args...);
}
};
constexpr std::size_t tSize = std::tuple_size<typename std::remove_reference<Tuple>::type>::value;
return NzApplyImplFunc(std::forward<F>(fn), std::forward<Tuple>(t), std::make_index_sequence<tSize>());
}
template<typename O, typename F, typename Tuple, size_t... S>
auto NzApplyImplMethod(O& object, F&& fn, Tuple&& t, std::index_sequence<S...>)
{
return (object .* std::forward<F>(fn))(std::get<S>(std::forward<Tuple>(t))...);
}
template<typename O, typename F, typename Tuple>
auto NzApply(O& object, F&& fn, Tuple&& t)
{
constexpr std::size_t tSize = std::tuple_size<typename std::remove_reference<Tuple>::type>::value;
return NzApplyImplMethod(object, std::forward<F>(fn), std::forward<Tuple>(t), std::make_index_sequence<tSize>());
}
// Algorithme venant de CityHash par Google
// http://stackoverflow.com/questions/8513911/how-to-create-a-good-hash-combine-with-64-bit-output-inspired-by-boosthash-co
template<typename T>
@ -47,10 +53,4 @@ void NzHashCombine(std::size_t& seed, const T& v)
seed = static_cast<std::size_t>(b * kMul);
}
template<typename F, typename... ArgsT>
void NzUnpackTuple(F func, const std::tuple<ArgsT...>& t)
{
NzImplTupleUnpack<sizeof...(ArgsT)>()(func, t);
}
#include <Nazara/Core/DebugOff.hpp>

View File

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

View File

@ -0,0 +1,319 @@
// 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
inline NzByteArray::NzByteArray(size_type n) :
m_array()
{
m_array.reserve(n);
}
inline NzByteArray::NzByteArray(const void* buffer, size_type n) :
m_array(static_cast<const_pointer>(buffer), static_cast<const_pointer>(buffer) + n)
{
}
inline NzByteArray::NzByteArray(size_type n, const value_type value) :
m_array(n, value)
{
}
template <class InputIterator>
NzByteArray::NzByteArray(InputIterator first, InputIterator last) :
m_array(first, last)
{
}
inline NzByteArray::iterator NzByteArray::Append(const void* buffer, size_type n)
{
return Insert(end(), static_cast<const_pointer>(buffer), static_cast<const_pointer>(buffer) + n);
}
inline NzByteArray::iterator NzByteArray::Append(const NzByteArray& other)
{
return Insert(end(), other.begin(), other.end());
}
inline void NzByteArray::Assign(size_type n, value_type value)
{
m_array.assign(n, value);
}
template <class InputIterator>
void NzByteArray::Assign(InputIterator first, InputIterator last)
{
m_array.assign(first, last);
}
inline NzByteArray::reference NzByteArray::Back()
{
return m_array.back();
}
inline NzByteArray::const_reference NzByteArray::Back() const
{
return m_array.back();
}
inline NzByteArray::iterator NzByteArray::Erase(const_iterator pos)
{
return m_array.erase(pos);
}
inline NzByteArray::iterator NzByteArray::Erase(const_iterator first, const_iterator last)
{
return m_array.erase(first, last);
}
inline NzByteArray::allocator_type NzByteArray::GetAllocator() const
{
return m_array.get_allocator();
}
inline NzByteArray::pointer NzByteArray::GetBuffer()
{
return m_array.data();
}
inline NzByteArray::size_type NzByteArray::GetCapacity() const noexcept
{
return m_array.capacity();
}
inline NzByteArray::const_pointer NzByteArray::GetConstBuffer() const
{
return m_array.data();
}
inline NzByteArray::size_type NzByteArray::GetMaxSize() const noexcept
{
return m_array.max_size();
}
inline NzByteArray::size_type NzByteArray::GetSize() const noexcept
{
return m_array.size();
}
inline NzByteArray NzByteArray::GetSubArray(const_iterator startPos, const_iterator endPos) const
{
return NzByteArray(startPos, endPos);
}
inline NzByteArray::iterator NzByteArray::Insert(const_iterator pos, const void* buffer, size_type n)
{
return m_array.insert(pos, static_cast<const_pointer>(buffer), static_cast<const_pointer>(buffer) + n);
}
inline NzByteArray::iterator NzByteArray::Insert(const_iterator pos, const NzByteArray& other)
{
return m_array.insert(pos, other.begin(), other.end());
}
inline NzByteArray::iterator NzByteArray::Insert(const_iterator pos, size_type n, value_type byte)
{
return m_array.insert(pos, n, byte);
}
template <class InputIterator>
NzByteArray::iterator NzByteArray::Insert(const_iterator pos, InputIterator first, InputIterator last)
{
return m_array.insert(pos, first, last);
}
inline bool NzByteArray::IsEmpty() const noexcept
{
return m_array.empty();
}
inline void NzByteArray::PopBack()
{
Erase(end() - 1);
}
inline void NzByteArray::PopFront()
{
Erase(begin());
}
inline NzByteArray::iterator NzByteArray::Prepend(const void* buffer, size_type n)
{
return Insert(begin(), buffer, n);
}
inline NzByteArray::iterator NzByteArray::Prepend(const NzByteArray& other)
{
return Insert(begin(), other);
}
inline void NzByteArray::PushBack(const value_type byte)
{
m_array.push_back(byte);
}
inline void NzByteArray::PushFront(const value_type byte)
{
m_array.insert(begin(), 1, byte);
}
inline void NzByteArray::Reserve(size_type bufferSize)
{
m_array.reserve(bufferSize);
}
inline void NzByteArray::Resize(size_type newSize)
{
m_array.resize(newSize);
}
inline void NzByteArray::Resize(size_type newSize, const value_type byte)
{
m_array.resize(newSize, byte);
}
inline void NzByteArray::ShrinkToFit()
{
m_array.shrink_to_fit();
}
inline void NzByteArray::Swap(NzByteArray& other)
{
m_array.swap(other.m_array);
}
inline NzString NzByteArray::ToString() const
{
return NzString(reinterpret_cast<const char*>(GetConstBuffer()), GetSize());
}
inline NzByteArray::iterator NzByteArray::begin() noexcept
{
return m_array.begin();
}
inline NzByteArray::const_iterator NzByteArray::begin() const noexcept
{
return m_array.begin();
}
inline NzByteArray::const_iterator NzByteArray::cbegin() const noexcept
{
return m_array.cbegin();
}
inline NzByteArray::const_iterator NzByteArray::cend() const noexcept
{
return m_array.cend();
}
inline NzByteArray::const_reverse_iterator NzByteArray::crbegin() const noexcept
{
return m_array.crbegin();
}
inline NzByteArray::const_reverse_iterator NzByteArray::crend() const noexcept
{
return m_array.crend();
}
inline bool NzByteArray::empty() const noexcept
{
return m_array.empty();
}
inline NzByteArray::iterator NzByteArray::end() noexcept
{
return m_array.end();
}
inline NzByteArray::const_iterator NzByteArray::end() const noexcept
{
return m_array.end();
}
inline NzByteArray::reverse_iterator NzByteArray::rbegin() noexcept
{
return m_array.rbegin();
}
inline NzByteArray::const_reverse_iterator NzByteArray::rbegin() const noexcept
{
return m_array.rbegin();
}
inline NzByteArray::reverse_iterator NzByteArray::rend() noexcept
{
return m_array.rend();
}
inline NzByteArray::size_type NzByteArray::size() const noexcept
{
return GetSize();
}
inline NzByteArray::reference NzByteArray::operator[](size_type pos)
{
NazaraAssert(pos < GetSize(), "Index out of range");
return m_array[pos];
}
inline NzByteArray::const_reference NzByteArray::operator[](size_type pos) const
{
NazaraAssert(pos < GetSize(), "Index out of range");
return m_array[pos];
}
inline NzByteArray NzByteArray::operator+(const NzByteArray& other) const
{
NzByteArray tmp(*this);
tmp += other;
return tmp;
}
inline NzByteArray& NzByteArray::operator+=(const NzByteArray& other)
{
Append(other);
return *this;
}
inline bool NzByteArray::operator==(const NzByteArray& rhs) const
{
return m_array == rhs.m_array;
}
inline bool NzByteArray::operator!=(const NzByteArray& rhs) const
{
return !operator==(rhs);
}
inline bool NzByteArray::operator<(const NzByteArray& rhs) const
{
return m_array < rhs.m_array;
}
inline bool NzByteArray::operator<=(const NzByteArray& rhs) const
{
return m_array <= rhs.m_array;
}
inline bool NzByteArray::operator>(const NzByteArray& rhs) const
{
return m_array > rhs.m_array;
}
inline bool NzByteArray::operator>=(const NzByteArray& rhs) const
{
return m_array >= rhs.m_array;
}
namespace std
{
inline void swap(NzByteArray& lhs, NzByteArray& rhs)
{
lhs.Swap(rhs);
}
}

View File

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

View File

@ -8,11 +8,12 @@
#define NAZARA_CONDITIONVARIABLE_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/NonCopyable.hpp>
class NzConditionVariableImpl;
class NzMutex;
class NAZARA_CORE_API NzConditionVariable
class NAZARA_CORE_API NzConditionVariable : NzNonCopyable
{
public:
NzConditionVariable();

View File

@ -15,7 +15,7 @@
// On force la valeur de MANAGE_MEMORY en mode debug
#if defined(NAZARA_DEBUG) && !NAZARA_CORE_MANAGE_MEMORY
#undef NAZARA_CORE_MANAGE_MEMORY
#define NAZARA_CORE_MANAGE_MEMORY 1
#define NAZARA_CORE_MANAGE_MEMORY 0
#endif
NazaraCheckTypeAndVal(NAZARA_CORE_DECIMAL_DIGITS, integral, >, 0, " shall be a strictly positive integer");

View File

@ -27,7 +27,7 @@
#include <Nazara/Core/ThreadSafetyOff.hpp>
#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;

View File

@ -15,6 +15,15 @@ enum nzCoordSys
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
{
nzEndianness_Unknown = -1,
@ -57,7 +66,24 @@ enum nzHash
nzHash_SHA256,
nzHash_SHA384,
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

View File

@ -23,34 +23,16 @@
#include <Nazara/Core/ThreadSafetyOff.hpp>
#endif
#include <ctime>
class NzFileImpl;
class NAZARA_CORE_API NzFile : public NzHashable, public NzInputStream, NzNonCopyable
{
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(const NzString& filePath);
NzFile(const NzString& filePath, unsigned long openMode);
NzFile(const NzString& filePath, unsigned int openMode);
NzFile(NzFile&& file) noexcept;
~NzFile();
@ -77,14 +59,14 @@ class NAZARA_CORE_API NzFile : public NzHashable, public NzInputStream, NzNonCop
bool IsOpen() const;
bool Open(unsigned long openMode = Current);
bool Open(const NzString& filePath, unsigned long openMode = Current);
bool Open(unsigned int openMode = nzOpenMode_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 typeSize, unsigned int count);
bool Rename(const NzString& newFilePath);
bool SetCursorPos(CursorPosition pos, nzInt64 offset = 0);
bool SetCursorPos(nzCursorPosition pos, nzInt64 offset = 0);
bool SetCursorPos(nzUInt64 offset);
void SetEndianness(nzEndianness endianness);
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

@ -26,7 +26,7 @@ m_args(std::forward<Args>(args)...)
template<typename F, typename... Args>
void NzFunctorWithArgs<F, Args...>::Run()
{
NzUnpackTuple(m_func, m_args);
NzApply(m_func, m_args);
}

View File

@ -20,6 +20,7 @@ class NAZARA_CORE_API NzHardwareInfo
static unsigned int GetProcessorCount();
static nzProcessorVendor GetProcessorVendor();
static NzString GetProcessorVendorName();
static nzUInt64 GetTotalMemory();
static bool HasCapability(nzProcessorCap capability);

View File

@ -21,7 +21,9 @@ class NAZARA_CORE_API NzMutex : NzNonCopyable
~NzMutex();
void Lock();
bool TryLock();
void Unlock();
private:

View File

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

View File

@ -19,7 +19,9 @@ class NAZARA_CORE_API NzSemaphore : NzNonCopyable
~NzSemaphore();
unsigned int GetCount() const;
void Post();
void Wait();
bool Wait(nzUInt32 timeout);

View File

@ -11,6 +11,7 @@
#include <Nazara/Core/Hashable.hpp>
#include <atomic>
#include <iosfwd>
#include <memory>
#include <string>
#include <vector>
@ -22,15 +23,13 @@ class NAZARA_CORE_API NzString : public NzHashable
public:
enum Flags
{
None = 0x00, // Mode par défaut
CaseInsensitive = 0x01, // Insensible à la casse
HandleUtf8 = 0x02, // Traite les octets comme une suite de caractères UTF-8
None = 0x00, // Mode par défaut
CaseInsensitive = 0x01, // Insensible à la casse
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
TrimOnlyRight = 0x08 // Trim(med), ne coupe que la partie droite de la chaîne
};
struct SharedString;
NzString();
explicit NzString(char character);
NzString(unsigned int rep, char character);
@ -40,10 +39,9 @@ class NAZARA_CORE_API NzString : public NzHashable
NzString(const char* string);
NzString(const char* string, unsigned int length);
NzString(const std::string& string);
NzString(const NzString& string);
NzString(NzString&& string) noexcept;
NzString(SharedString* sharedString);
~NzString();
NzString(const NzString& string) = default;
NzString(NzString&& string) noexcept = default;
~NzString() = default;
NzString& Append(char character);
NzString& Append(const char* string);
@ -137,7 +135,6 @@ class NAZARA_CORE_API NzString : public NzHashable
NzString& Set(const std::string& string);
NzString& Set(const NzString& string);
NzString& Set(NzString&& string) noexcept;
NzString& Set(SharedString* sharedString);
NzString Simplified(nzUInt32 flags = None) const;
NzString& Simplify(nzUInt32 flags = None);
@ -299,37 +296,30 @@ class NAZARA_CORE_API NzString : public NzHashable
NAZARA_CORE_API friend bool operator>=(const char* string, const NzString& nstring);
NAZARA_CORE_API friend bool operator>=(const std::string& string, const NzString& nstring);
struct NAZARA_CORE_API SharedString
{
SharedString() :
refCount(1)
{
}
SharedString(unsigned short referenceCount, unsigned int bufferSize, unsigned int stringSize, char* str) :
capacity(bufferSize),
size(stringSize),
string(str),
refCount(referenceCount)
{
}
unsigned int capacity;
unsigned int size;
char* string;
std::atomic_ushort refCount;
};
static SharedString emptyString;
static const unsigned int npos;
private:
struct SharedString;
NzString(std::shared_ptr<SharedString>&& sharedString);
void EnsureOwnership(bool discardContent = false);
bool FillHash(NzAbstractHash* hash) const;
void ReleaseString();
inline void ReleaseString();
SharedString* m_sharedString;
static std::shared_ptr<SharedString> GetEmptyString();
std::shared_ptr<SharedString> m_sharedString;
struct SharedString
{
inline SharedString();
inline SharedString(unsigned int strSize);
unsigned int capacity;
unsigned int size;
std::unique_ptr<char[]> string;
};
};
namespace std

View File

@ -4,11 +4,36 @@
#include <Nazara/Core/Debug.hpp>
inline NzString::NzString(std::shared_ptr<SharedString>&& sharedString) :
m_sharedString(std::move(sharedString))
{
}
inline void NzString::ReleaseString()
{
m_sharedString = std::move(GetEmptyString());
}
inline NzString::SharedString::SharedString() : // Special case: empty string
capacity(0),
size(0)
{
}
inline NzString::SharedString::SharedString(unsigned int strSize) :
capacity(strSize),
size(strSize),
string(new char[strSize + 1])
{
string[strSize] = '\0';
}
namespace std
{
template<>
struct hash<NzString>
{
template<>
struct hash<NzString>
{
size_t operator()(const NzString& str) const
{
// Algorithme DJB2
@ -26,7 +51,7 @@ namespace std
return h;
}
};
};
}
#include <Nazara/Core/DebugOff.hpp>

View File

@ -108,8 +108,9 @@ class NAZARA_LUA_API NzLuaInstance : NzNonCopyable
void Pop(unsigned int n = 1U);
void PushBoolean(bool value);
void PushCFunction(NzLuaCFunction func, int upvalueCount = 0);
void PushCFunction(NzLuaCFunction func, unsigned int upvalueCount = 0);
void PushFunction(NzLuaFunction func);
template<typename R, typename... Args> void PushFunction(R(*func)(Args...));
void PushInteger(long long value);
void PushLightUserdata(void* value);
void PushMetatable(const char* str);
@ -118,6 +119,7 @@ class NAZARA_LUA_API NzLuaInstance : NzNonCopyable
void PushNumber(double value);
void PushReference(int ref);
void PushString(const char* str);
void PushString(const char* str, unsigned int size);
void PushString(const NzString& str);
void PushTable(unsigned int sequenceElementCount = 0, unsigned int arrayElementCount = 0);
void* PushUserdata(unsigned int size);
@ -165,4 +167,6 @@ class NAZARA_LUA_API NzLuaInstance : NzNonCopyable
unsigned int m_level;
};
#include <Nazara/Lua/LuaInstance.inl>
#endif // NAZARA_LUASTATE_HPP

View File

@ -0,0 +1,167 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Lua scripting module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Algorithm.hpp>
#include <string>
// Functions args
bool NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<bool>)
{
return instance.CheckBoolean(index);
}
double NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<double>)
{
return instance.CheckNumber(index);
}
float NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<float>)
{
return static_cast<float>(instance.CheckNumber(index));
}
int NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<int>)
{
return static_cast<int>(instance.CheckInteger(index));
}
std::string NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<std::string>)
{
std::size_t strLength = 0;
const char* str = instance.CheckString(index, &strLength);
return std::string(str, strLength);
}
NzString NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<NzString>)
{
std::size_t strLength = 0;
const char* str = instance.CheckString(index, &strLength);
return NzString(str, strLength);
}
template<typename T>
T NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<const T&>)
{
return NzLuaImplQueryArg(instance, index, NzTypeTag<T>());
}
template<typename T>
std::enable_if_t<std::is_unsigned<T>::value, T> NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<T>)
{
return static_cast<T>(NzLuaImplQueryArg(instance, index, NzTypeTag<typename std::make_signed<T>::type>()));
}
// Function returns
int NzLuaImplReplyVal(NzLuaInstance& instance, bool&& val, NzTypeTag<bool>)
{
instance.PushBoolean(val);
return 1;
}
int NzLuaImplReplyVal(NzLuaInstance& instance, double&& val, NzTypeTag<double>)
{
instance.PushNumber(val);
return 1;
}
int NzLuaImplReplyVal(NzLuaInstance& instance, float&& val, NzTypeTag<float>)
{
instance.PushNumber(val);
return 1;
}
int NzLuaImplReplyVal(NzLuaInstance& instance, int&& val, NzTypeTag<int>)
{
instance.PushInteger(val);
return 1;
}
int NzLuaImplReplyVal(NzLuaInstance& instance, std::string&& val, NzTypeTag<std::string>)
{
instance.PushString(val.c_str(), val.size());
return 1;
}
int NzLuaImplReplyVal(NzLuaInstance& instance, NzString&& val, NzTypeTag<NzString>)
{
instance.PushString(std::move(val));
return 1;
}
template<typename T1, typename T2>
int NzLuaImplReplyVal(NzLuaInstance& instance, std::pair<T1, T2>&& val, NzTypeTag<std::pair<T1, T2>>)
{
int retVal = 0;
retVal += NzLuaImplReplyVal(instance, std::move(val.first), NzTypeTag<T1>());
retVal += NzLuaImplReplyVal(instance, std::move(val.second), NzTypeTag<T2>());
return retVal;
}
template<typename T>
std::enable_if_t<std::is_unsigned<T>::value, int> NzLuaImplReplyVal(NzLuaInstance& instance, T&& val, NzTypeTag<T>)
{
using SignedT = typename std::make_signed<T>::type;
return NzLuaImplReplyVal(instance, val, NzTypeTag<SignedT>());
}
template<typename... Args>
class NzLuaImplFunctionProxy
{
public:
NzLuaImplFunctionProxy(NzLuaInstance& instance) :
m_instance(instance)
{
}
template<unsigned int N, typename ArgType>
void ProcessArgs()
{
std::get<N>(m_args) = std::move(NzLuaImplQueryArg(m_instance, N+1, NzTypeTag<ArgType>()));
}
template<int N, typename ArgType1, typename ArgType2, typename... Rest>
void ProcessArgs()
{
ProcessArgs<N, ArgType1>();
ProcessArgs<N+1, ArgType2, Rest...>();
}
void ProcessArgs()
{
ProcessArgs<0, Args...>();
}
int Invoke(void (*func)(Args...))
{
NzApply(func, m_args);
return 0;
}
template<typename Ret>
int Invoke(Ret (*func)(Args...))
{
return NzLuaImplReplyVal(m_instance, std::move(NzApply(func, m_args)), NzTypeTag<decltype(NzApply(func, m_args))>());
}
private:
NzLuaInstance& m_instance;
std::tuple<Args...> m_args;
};
template<typename R, typename... Args>
void NzLuaInstance::PushFunction(R(*func)(Args...))
{
PushFunction([func](NzLuaInstance& instance) -> int
{
NzLuaImplFunctionProxy<Args...> handler(instance);
handler.ProcessArgs();
return handler.Invoke(func);
});
}

View File

@ -6,6 +6,7 @@
#include <Nazara/Core/String.hpp>
#include <Nazara/Math/Config.hpp>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <type_traits>
#include <Nazara/Core/Debug.hpp>
@ -336,9 +337,10 @@ bool NzNumberEquals(T a, T b)
template<typename T>
bool NzNumberEquals(T a, T b, T maxDifference)
{
std::pair<const T&, const T&> minmax = std::minmax(a, b);
T diff = minmax.second - minmax.first;
if (b > a)
std::swap(a, b);
T diff = a - b;
return diff <= maxDifference;
}

View File

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

View File

@ -65,7 +65,7 @@ template<typename T>
bool NzBox<T>::Contains(const NzBox<T>& box) const
{
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>
@ -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> 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,
std::fabs(matrix(0,1))*halfSize.x + std::fabs(matrix(1,1))*halfSize.y + std::fabs(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);
halfSize.Set(std::abs(matrix(0,0))*halfSize.x + std::abs(matrix(1,0))*halfSize.y + std::abs(matrix(2,0))*halfSize.z,
std::abs(matrix(0,1))*halfSize.x + std::abs(matrix(1,1))*halfSize.y + std::abs(matrix(2,1))*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);
}
@ -486,7 +486,7 @@ template<typename T>
bool NzBox<T>::operator==(const NzBox& box) const
{
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>

View File

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

View File

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

View File

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

View File

@ -585,6 +585,21 @@ NzMatrix4<T>& NzMatrix4<T>::MakeIdentity()
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>
NzMatrix4<T>& NzMatrix4<T>::MakeOrtho(T left, T right, T top, T bottom, T zNear, T zFar)
{
@ -597,22 +612,6 @@ NzMatrix4<T>& NzMatrix4<T>::MakeOrtho(T left, T right, T top, T bottom, T zNear,
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>
NzMatrix4<T>& NzMatrix4<T>::MakePerspective(T angle, T ratio, T zNear, T zFar)
{
@ -627,8 +626,8 @@ NzMatrix4<T>& NzMatrix4<T>::MakePerspective(T angle, T ratio, T zNear, T zFar)
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), F(0.0), zFar / (zNear-zFar), F(-1.0),
F(0.0), F(0.0), (zNear*zFar) / (zNear-zFar), F(0.0));
F(0.0), F(0.0), - (zFar + zNear) / (zFar - zNear), F(-1.0),
F(0.0), F(0.0), F(-2.0) * (zNear * zFar) / (zFar - zNear), F(0.0));
return *this;
}
@ -703,7 +702,7 @@ NzMatrix4<T>& NzMatrix4<T>::MakeViewMatrix(const NzVector3<T>& translation, cons
// Une matrice de vue doit appliquer une transformation opposée à la matrice "monde"
NzQuaternion<T> invRot = rotation.GetConjugate(); // Inverse de la rotation
return MakeTransform(-(invRot*translation), invRot);
return MakeTransform(-(invRot * translation), invRot);
}
template<typename T>
@ -828,9 +827,9 @@ NzString NzMatrix4<T>::ToString() const
{
NzStringStream ss;
return ss << "Matrix4(" << m11 << ", " << m12 << ", " << m13 << ", " << m14 << ",\n"
<< " " << m21 << ", " << m22 << ", " << m23 << ", " << m24 << ",\n"
<< " " << m31 << ", " << m32 << ", " << m33 << ", " << m34 << ",\n"
<< " " << m41 << ", " << m42 << ", " << m43 << ", " << m44 << ')';
<< " " << m21 << ", " << m22 << ", " << m23 << ", " << m24 << ",\n"
<< " " << m31 << ", " << m32 << ", " << m33 << ", " << m34 << ",\n"
<< " " << m41 << ", " << m42 << ", " << m43 << ", " << m44 << ')';
}
template<typename T>

View File

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

View File

@ -37,6 +37,9 @@ class NzPlane
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 XY();
static NzPlane XZ();

View File

@ -49,7 +49,7 @@ NzPlane<T>::NzPlane(const NzPlane<U>& plane)
template<typename T>
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>
@ -110,7 +110,7 @@ NzPlane<T>& NzPlane<T>::Set(const NzVector3<T>& point1, const NzVector3<T>& poin
normal = edge1.CrossProduct(edge2);
normal.Normalize();
distance = -normal.DotProduct(point3);
distance = normal.DotProduct(point3);
return *this;
}
@ -133,6 +133,18 @@ NzString NzPlane<T>::ToString() const
return ss << "Plane(Normal: " << normal.ToString() << "; Distance: " << distance << ')';
}
template<typename T>
bool NzPlane<T>::operator==(const NzPlane& plane) const
{
return (normal == plane.normal && NzNumberEquals(distance, plane.distance)) || (normal == -plane.normal && NzNumberEquals(distance, -plane.distance));
}
template<typename T>
bool NzPlane<T>::operator!=(const NzPlane& plane) const
{
return !operator==(plane);
}
template<typename T>
NzPlane<T> NzPlane<T>::Lerp(const NzPlane& from, const NzPlane& to, T interpolation)
{
@ -155,19 +167,19 @@ NzPlane<T> NzPlane<T>::Lerp(const NzPlane& from, const NzPlane& to, T interpolat
template<typename T>
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>
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>
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>

View File

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

View File

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

View File

@ -59,18 +59,18 @@ T NzRay<T>::ClosestPoint(const NzVector3<T>& point) const
template<typename T>
NzVector3<T> NzRay<T>::GetPoint(T lambda) const
{
return origin + lambda*direction;
return origin + lambda * direction;
}
/*
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)
{
case nzExtend_Finite:
{
if (Intersect(volume.aabb))
return Intersect(volume.obb, closestHit, farthestHit);
return Intersect(volume.obb, closestHit, furthestHit);
return false;
}
@ -80,8 +80,8 @@ bool NzRay<T>::Intersect(const NzBoundingVolume<T>& volume, T* closestHit, T* fa
if (closestHit)
*closestHit = F(0.0);
if (farthestHit)
*farthestHit = std::numeric_limits<T>::infinity();
if (furthestHit)
*furthestHit = std::numeric_limits<T>::infinity();
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) + ')');
return false;
}
*/
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/
T tfirst = F(0.0);
@ -134,14 +134,14 @@ bool NzRay<T>::Intersect(const NzBox<T>& box, T* closestHit, T* farthestHit) con
if (closestHit)
*closestHit = tfirst;
if (farthestHit)
*farthestHit = tlast;
if (furthestHit)
*furthestHit = tlast;
return true;
}
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/
// 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)
*closestHit = tMin;
if (farthestHit)
*farthestHit = tMax;
if (furthestHit)
*furthestHit = tMax;
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>
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> height = (orientedBox.GetCorner(nzBoxCorner_FarLeftTop) - orientedBox.GetCorner(nzBoxCorner_FarLeftBottom)).Normalize();
NzVector3<T> depth = (orientedBox.GetCorner(nzBoxCorner_FarRightBottom) - orientedBox.GetCorner(nzBoxCorner_FarLeftBottom)).Normalize();
NzVector3<T> corner = orientedBox.GetCorner(nzBoxCorner_FarLeftBottom);
NzVector3<T> oppositeCorner = orientedBox.GetCorner(nzBoxCorner_NearRightTop);
NzVector3<T> width = (orientedBox.GetCorner(nzBoxCorner_NearLeftBottom) - corner);
NzVector3<T> height = (orientedBox.GetCorner(nzBoxCorner_FarLeftTop) - corner);
NzVector3<T> depth = (orientedBox.GetCorner(nzBoxCorner_FarRightBottom) - corner);
// Construction de la matrice de transformation de l'OBB
NzMatrix4<T> matrix(width.x, height.x, depth.x, F(0.0),
width.y, height.y, depth.y, F(0.0),
width.z, height.z, depth.z, F(0.0),
NzMatrix4<T> matrix(width.x, height.x, depth.x, corner.x,
width.y, height.y, depth.y, corner.y,
width.z, height.z, depth.z, corner.z,
F(0.0), F(0.0), F(0.0), F(1.0));
// Test en tant qu'AABB avec une matrice de rotation
return Intersect(orientedBox.localBox, matrix, closestHit, farthestHit);
matrix.InverseAffine();
corner = matrix.Transform(corner);
oppositeCorner = matrix.Transform(oppositeCorner);
NzBox<T> tmpBox(corner, oppositeCorner);
NzRay<T> tmpRay(matrix.Transform(origin), matrix.Transform(direction));
return tmpRay.Intersect(tmpBox, closestHit, furthestHit);
}
*/
template<typename T>
bool NzRay<T>::Intersect(const NzPlane<T>& plane, T* hit) const
{
@ -225,9 +232,9 @@ bool NzRay<T>::Intersect(const NzPlane<T>& plane, T* hit) const
if (NzNumberEquals(divisor, F(0.0)))
return false; // perpendicular
T lambda = -(plane.normal.DotProduct(origin) + plane.distance) / divisor; // The plane is ax+by+cz=d
T lambda = -(plane.normal.DotProduct(origin) - plane.distance) / divisor; // The plane is ax + by + cz = d
if (lambda < F(0.0))
return false; // Le plan est derrière le rayon
return false; // The plane is 'behind' the ray.
if (hit)
*hit = lambda;
@ -236,7 +243,7 @@ bool NzRay<T>::Intersect(const NzPlane<T>& plane, T* hit) const
}
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;
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
// Calcul des points d'intersection si besoin
if (closestHit || farthestHit)
if (closestHit || furthestHit)
{
T deltaLambda = std::sqrt(squaredRadius - squaredDistance);
if (closestHit)
*closestHit = length - deltaLambda;
if (farthestHit)
*farthestHit = length + deltaLambda;
if (furthestHit)
*furthestHit = length + deltaLambda;
}
return true;
@ -380,6 +387,18 @@ NzVector3<T> NzRay<T>::operator*(T lambda) const
return GetPoint(lambda);
}
template<typename T>
bool NzRay<T>::operator==(const NzRay& ray) const
{
return direction == ray.direction && origin == ray.origin;
}
template<typename T>
bool NzRay<T>::operator!=(const NzRay& ray) const
{
return !operator==(ray);
}
template<typename T>
NzRay<T> NzRay<T>::AxisX()
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -64,9 +64,9 @@ template<typename T>
T NzVector3<T>::AngleBetween(const NzVector3& vec) const
{
// 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)))
{
NzString error("Division by zero");
@ -325,7 +325,7 @@ NzVector3<T>& NzVector3<T>::Set(const NzVector4<T>& vec)
template<typename T>
T NzVector3<T>::SquaredDistance(const NzVector3& vec) const
{
return operator-(vec).GetSquaredLength();
return (*this - vec).GetSquaredLength();
}
template<typename T>

View File

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

View File

@ -121,7 +121,7 @@
#define NAZARA_EXPORT __attribute__((visibility ("default")))
#define NAZARA_IMPORT __attribute__((visibility ("default")))
/*#elif defined(__APPLE__) && defined(__MACH__)
#define NAZARA_API
#define NAZARA_CORE_API
#define NAZARA_PLATFORM_MACOSX
#define NAZARA_PLATFORM_POSIX*/
#else
@ -129,7 +129,7 @@
#error This operating system is not fully supported by the Nazara Engine
#define NAZARA_PLATFORM_UNKNOWN
#define NAZARA_API
#define NAZARA_CORE_API
#endif
// Détection 64 bits

View File

@ -29,6 +29,7 @@ class NAZARA_RENDERER_API NzDebugDrawer
static void Draw(const NzOrientedBoxf& orientedBox);
static void Draw(const NzSkeleton* skeleton);
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 DrawCone(const NzVector3f& origin, const NzQuaternionf& rotation, float angle, float length);
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
// (les flux automatiquement ouverts par le ResourceLoader étant fermés après celui-ci)
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());
return false;

View File

@ -4,495 +4,18 @@
#include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Math/Algorithm.hpp>
#include <algorithm>
#include <cstring>
#include <limits>
#include <ostream>
#include <Nazara/Core/Debug.hpp>
// Cet algorithme est inspiré de la documentation de Qt
inline unsigned int nzGetNewSize(unsigned int newSize)
std::ostream& operator<<(std::ostream& out, const NzByteArray& byteArray)
{
if (newSize < 20)
return newSize+4;
else
{
if (newSize < (1 << 12)-12)
return NzGetNearestPowerOfTwo(newSize << 1)-12;
else
return newSize + (1 << 11);
}
}
NzByteArray::NzByteArray() :
m_sharedArray(&emptyArray)
{
}
NzByteArray::NzByteArray(unsigned int size)
{
if (size > 0)
{
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)
{
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) :
m_sharedArray(buffer.m_sharedArray)
{
if (m_sharedArray != &emptyArray)
m_sharedArray->refCount++;
}
NzByteArray::NzByteArray(NzByteArray&& buffer) noexcept :
m_sharedArray(buffer.m_sharedArray)
{
buffer.m_sharedArray = &emptyArray;
}
NzByteArray::NzByteArray(SharedArray* sharedArray) :
m_sharedArray(sharedArray)
{
}
NzByteArray::~NzByteArray()
{
ReleaseArray();
}
NzByteArray& NzByteArray::Append(const void* buffer, unsigned int size)
{
return Insert(m_sharedArray->size, buffer, size);
}
NzByteArray& NzByteArray::Append(const NzByteArray& array)
{
return Insert(m_sharedArray->size, array);
}
void NzByteArray::Clear(bool keepBuffer)
{
if (keepBuffer)
{
EnsureOwnership();
m_sharedArray->size = 0;
}
else
ReleaseArray();
}
nzUInt8* NzByteArray::GetBuffer()
{
EnsureOwnership();
return m_sharedArray->buffer;
}
unsigned int NzByteArray::GetCapacity() const
{
return m_sharedArray->capacity;
}
const nzUInt8* NzByteArray::GetConstBuffer() const
{
return m_sharedArray->buffer;
}
unsigned int NzByteArray::GetSize() const
{
return m_sharedArray->size;
}
NzByteArray& NzByteArray::Insert(int pos, const void* buffer, unsigned int size)
{
if (size == 0)
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)
{
return Insert(pos, array.m_sharedArray->buffer, array.m_sharedArray->size);
}
bool NzByteArray::IsEmpty() const
{
return m_sharedArray->size == 0;
}
NzByteArray& NzByteArray::Prepend(const void* buffer, unsigned int size)
{
return Insert(0, buffer, size);
}
NzByteArray& NzByteArray::Prepend(const NzByteArray& array)
{
return Insert(0, array);
}
void NzByteArray::Reserve(unsigned int bufferSize)
{
if (m_sharedArray->capacity >= bufferSize)
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)
{
if (size == 0)
{
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)
{
if (size == 0)
{
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
{
if (size < 0)
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
{
if (size < 0)
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
{
if (startPos < 0)
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)
{
std::swap(m_sharedArray, array.m_sharedArray);
}
nzUInt8* NzByteArray::begin()
{
return m_sharedArray->buffer;
}
const nzUInt8* NzByteArray::begin() const
{
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 (pos >= m_sharedArray->size)
{
NazaraError("Index out of range (" + NzString::Number(pos) + " >= " + NzString::Number(m_sharedArray->size) + ')');
return 0;
}
#endif
return m_sharedArray->buffer[pos];
}
NzByteArray& NzByteArray::operator=(const NzByteArray& array)
{
if (this != &array)
{
ReleaseArray();
m_sharedArray = array.m_sharedArray;
if (m_sharedArray != &emptyArray)
m_sharedArray->refCount++;
}
return *this;
}
NzByteArray& NzByteArray::operator=(NzByteArray&& array) noexcept
{
std::swap(m_sharedArray, array.m_sharedArray);
return *this;
}
NzByteArray NzByteArray::operator+(const NzByteArray& array) const
{
if (array.m_sharedArray->size == 0)
return *this;
if (m_sharedArray->size == 0)
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)
{
return Append(array);
}
int NzByteArray::Compare(const NzByteArray& first, const NzByteArray& second)
{
return std::memcmp(first.m_sharedArray->buffer, second.m_sharedArray->buffer, std::min(first.m_sharedArray->size, second.m_sharedArray->size));
}
void NzByteArray::EnsureOwnership()
{
if (m_sharedArray == &emptyArray)
return;
if (m_sharedArray->refCount > 1)
{
m_sharedArray->refCount--;
nzUInt8* buffer = new nzUInt8[m_sharedArray->capacity];
std::memcpy(buffer, m_sharedArray->buffer, m_sharedArray->size);
m_sharedArray = new SharedArray(1, m_sharedArray->capacity, m_sharedArray->size, buffer);
}
out << byteArray.ToString();
return out;
}
bool NzByteArray::FillHash(NzAbstractHash* hash) const
{
hash->Append(m_sharedArray->buffer, m_sharedArray->size);
hash->Append(GetConstBuffer(), GetSize());
return true;
}
void NzByteArray::ReleaseArray()
{
if (m_sharedArray == &emptyArray)
return;
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
{
void swap(NzByteArray& lhs, NzByteArray& rhs)
{
lhs.Swap(rhs);
}
}

View File

@ -11,6 +11,7 @@
#include <windows.h>
#elif defined(NAZARA_PLATFORM_POSIX)
#include <cstring>
#include <errno.h>
#endif
#include <Nazara/Core/Debug.hpp>

View File

@ -32,22 +32,22 @@
NzFile::NzFile() :
m_endianness(nzEndianness_Unknown),
m_impl(nullptr),
m_openMode(0)
m_openMode(nzOpenMode_Current)
{
}
NzFile::NzFile(const NzString& filePath) :
m_endianness(nzEndianness_Unknown),
m_impl(nullptr),
m_openMode(0)
m_openMode(nzOpenMode_Current)
{
SetFile(filePath);
}
NzFile::NzFile(const NzString& filePath, unsigned long openMode) :
NzFile::NzFile(const NzString& filePath, unsigned int openMode) :
m_endianness(nzEndianness_Unknown),
m_impl(nullptr),
m_openMode(0)
m_openMode(openMode)
{
Open(filePath, openMode);
}
@ -133,7 +133,7 @@ void NzFile::Flush()
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");
return;
@ -225,7 +225,7 @@ std::size_t NzFile::Read(void* buffer, std::size_t size)
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");
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
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);
}
@ -281,7 +281,7 @@ bool NzFile::Rename(const NzString& newFilePath)
return success;
}
bool NzFile::Open(unsigned long openMode)
bool NzFile::Open(unsigned int openMode)
{
NazaraLock(m_mutex)
@ -306,13 +306,13 @@ bool NzFile::Open(unsigned long openMode)
m_impl = impl.release();
if (m_openMode & Text)
if (m_openMode & nzOpenMode_Text)
m_streamOptions |= nzStreamOption_Text;
return true;
}
bool NzFile::Open(const NzString& filePath, unsigned long openMode)
bool NzFile::Open(const NzString& filePath, unsigned int openMode)
{
NazaraLock(m_mutex)
@ -322,7 +322,7 @@ bool NzFile::Open(const NzString& filePath, unsigned long openMode)
return Open(openMode);
}
bool NzFile::SetCursorPos(CursorPosition pos, nzInt64 offset)
bool NzFile::SetCursorPos(nzCursorPosition pos, nzInt64 offset)
{
NazaraLock(m_mutex)
@ -349,7 +349,7 @@ bool NzFile::SetCursorPos(nzUInt64 offset)
}
#endif
return m_impl->SetCursorPos(AtBegin, offset);
return m_impl->SetCursorPos(nzCursorPosition_AtBegin, offset);
}
void NzFile::SetEndianness(nzEndianness endianness)
@ -389,7 +389,7 @@ bool NzFile::SetOpenMode(unsigned int openMode)
{
NazaraLock(m_mutex)
if (openMode == 0 || openMode == m_openMode)
if (openMode == nzOpenMode_Current || openMode == m_openMode)
return true;
if (IsOpen())
@ -406,7 +406,7 @@ bool NzFile::SetOpenMode(unsigned int openMode)
m_impl = impl.release();
if (m_openMode & Text)
if (m_openMode & nzOpenMode_Text)
m_streamOptions |= nzStreamOption_Text;
}
@ -417,7 +417,7 @@ bool NzFile::SetOpenMode(unsigned int openMode)
bool NzFile::Write(const NzByteArray& byteArray)
{
unsigned int size = byteArray.GetSize();
NzByteArray::size_type size = byteArray.GetSize();
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;
}
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");
return 0;
@ -716,7 +716,7 @@ bool NzFile::Rename(const NzString& sourcePath, const NzString& targetPath)
bool NzFile::FillHash(NzAbstractHash* hash) const
{
NzFile file(m_filePath);
if (!file.Open(NzFile::ReadOnly))
if (!file.Open(nzOpenMode_ReadOnly))
{
NazaraError("Unable to open file");
return false;

View File

@ -116,6 +116,13 @@ NzString NzHardwareInfo::GetProcessorVendorName()
return vendorNames[s_vendorEnum+1];
}
nzUInt64 NzHardwareInfo::GetTotalMemory()
{
///DOC: Ne nécessite pas l'initialisation de HardwareInfo pour fonctionner
static nzUInt64 totalMemory = NzHardwareInfoImpl::GetTotalMemory();
return totalMemory;
}
bool NzHardwareInfo::HasCapability(nzProcessorCap capability)
{
#ifdef NAZARA_DEBUG

View File

@ -82,11 +82,12 @@ NzString NzHashDigest::ToHex() const
return NzString();
unsigned int length = m_digestLength*2;
char* hexOutput = new char[length+1];
for (unsigned int i = 0; i < m_digestLength; ++i)
std::sprintf(hexOutput + i*2, "%02x", m_digest[i]);
return NzString(new NzString::SharedString(1, length, length, hexOutput));
NzString hexOutput(length);
for (unsigned int i = 0; i < m_digestLength; ++i)
std::sprintf(&hexOutput[i*2], "%02x", m_digest[i]);
return hexOutput;
}
nzUInt8 NzHashDigest::operator[](unsigned int pos) const

View File

@ -114,7 +114,7 @@ void NzLog::Write(const NzString& string)
if (m_enabled)
{
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;

View File

@ -6,6 +6,7 @@
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <new>
#include <stdexcept>
#if defined(NAZARA_PLATFORM_WINDOWS)

View File

@ -6,6 +6,9 @@
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Debug.hpp>
#include <errno.h>
#include <sys/param.h>
NzDirectoryImpl::NzDirectoryImpl(const NzDirectory* parent)
{
NazaraUnused(parent);
@ -82,13 +85,10 @@ bool NzDirectoryImpl::Exists(const NzString& dirPath)
NzString NzDirectoryImpl::GetCurrent()
{
NzString currentPath;
char* path = getcwd(nullptr, 0);
if (path)
{
char path[MAXPATHLEN];
if (getcwd(path, MAXPATHLEN))
currentPath = path;
free(path);
}
else
NazaraError("Unable to get current directory: " + NzError::GetLastSystemError()); // Bug: initialisation -> if no path for log !

View File

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

View File

@ -35,7 +35,7 @@ class NzFileImpl : NzNonCopyable
nzUInt64 GetCursorPos() const;
bool Open(const NzString& filePath, unsigned int mode);
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);
static bool Copy(const NzString& sourcePath, const NzString& targetPath);

View File

@ -6,16 +6,16 @@
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Debug.hpp>
void NzHardwareInfoImpl::Cpuid(nzUInt32 code, nzUInt32 result[4])
void NzHardwareInfoImpl::Cpuid(nzUInt32 functionId, nzUInt32 subFunctionId, nzUInt32 registers[4])
{
#if defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
#if defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
// Source: http://stackoverflow.com/questions/1666093/cpuid-implementations-in-c
asm volatile ("cpuid" // Besoin d'être volatile ?
: "=a" (result[0]), "=b" (result[1]), "=c" (result[2]), "=d" (result[3]) // output
: "a" (code), "c" (0)); // input
#else
: "=a" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]) // output
: "a" (functionId), "c" (subFunctionId)); // input
#else
NazaraInternalError("Cpuid has been called although it is not supported");
#endif
#endif
}
unsigned int NzHardwareInfoImpl::GetProcessorCount()
@ -24,32 +24,40 @@ unsigned int NzHardwareInfoImpl::GetProcessorCount()
return sysconf(_SC_NPROCESSORS_CONF);
}
nzUInt64 NzHardwareInfoImpl::GetTotalMemory()
{
nzUInt64 pages = sysconf(_SC_PHYS_PAGES);
nzUInt64 page_size = sysconf(_SC_PAGE_SIZE);
return pages * page_size;
}
bool NzHardwareInfoImpl::IsCpuidSupported()
{
#ifdef NAZARA_PLATFORM_x64
#ifdef NAZARA_PLATFORM_x64
return true; // Toujours supporté sur un processeur 64 bits
#else
#if defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
int supported;
asm volatile (" pushfl\n"
" pop %%eax\n"
" mov %%eax, %%ecx\n"
" xor $0x200000, %%eax\n"
" push %%eax\n"
" popfl\n"
" pushfl\n"
" pop %%eax\n"
" xor %%ecx, %%eax\n"
" mov %%eax, %0\n"
" push %%ecx\n"
" popfl"
: "=m" (supported) // output
: // input
: "eax", "ecx", "memory"); // clobbered register
#else
#if defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
int supported;
asm volatile (" pushfl\n"
" pop %%eax\n"
" mov %%eax, %%ecx\n"
" xor $0x200000, %%eax\n"
" push %%eax\n"
" popfl\n"
" pushfl\n"
" pop %%eax\n"
" xor %%ecx, %%eax\n"
" mov %%eax, %0\n"
" push %%ecx\n"
" popfl"
: "=m" (supported) // output
: // input
: "eax", "ecx", "memory"); // clobbered register
return supported != 0;
#else
return false;
#endif
return supported != 0;
#else
return false;
#endif
#endif
}

View File

@ -13,8 +13,9 @@
class NzHardwareInfoImpl
{
public:
static void Cpuid(nzUInt32 code, nzUInt32 result[4]);
static void Cpuid(nzUInt32 functionId, nzUInt32 subFunctionId, nzUInt32 registers[4]);
static unsigned int GetProcessorCount();
static nzUInt64 GetTotalMemory();
static bool IsCpuidSupported();
};

View File

@ -0,0 +1,192 @@
// 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
#include <Nazara/Core/Posix/TaskSchedulerImpl.hpp>
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Debug.hpp>
bool NzTaskSchedulerImpl::Initialize(unsigned int workerCount)
{
if (IsInitialized())
return true; // Déjà initialisé
#if NAZARA_CORE_SAFE
if (workerCount == 0)
{
NazaraError("Invalid worker count ! (0)");
return false;
}
#endif
s_workerCount = workerCount;
s_isDone = false;
s_isWaiting = false;
s_shouldFinish = false;
s_threads.reset(new pthread_t[workerCount]);
// On initialise les conditions variables, mutex et barrière.
pthread_cond_init(&s_cvEmpty, nullptr);
pthread_cond_init(&s_cvNotEmpty, nullptr);
pthread_mutex_init(&s_mutexQueue, nullptr);
pthread_barrier_init(&s_barrier, nullptr, workerCount + 1);
for (unsigned int i = 0; i < s_workerCount; ++i)
{
// Le thread va se lancer, attendre que tous se créent et attendre d'être réveillé.
pthread_create(&s_threads[i], nullptr, WorkerProc, nullptr);
}
pthread_barrier_wait(&s_barrier); // On attend que les enfants soient bien créés.
return true;
}
bool NzTaskSchedulerImpl::IsInitialized()
{
return s_workerCount > 0;
}
void NzTaskSchedulerImpl::Run(NzFunctor** tasks, unsigned int count)
{
// On s'assure que des tâches ne sont pas déjà en cours
Wait();
pthread_mutex_lock(&s_mutexQueue);
s_isDone = false;
while (count--)
s_tasks.push(*tasks++);
pthread_cond_signal(&s_cvNotEmpty);
pthread_mutex_unlock(&s_mutexQueue);
}
void NzTaskSchedulerImpl::Uninitialize()
{
#ifdef NAZARA_CORE_SAFE
if (s_workerCount == 0)
{
NazaraError("Task scheduler is not initialized");
return;
}
#endif
// On réveille les threads pour qu'ils sortent de la boucle et terminent.
pthread_mutex_lock(&s_mutexQueue);
// On commence par vider la queue et demander qu'ils s'arrêtent.
std::queue<NzFunctor*> emptyQueue;
std::swap(s_tasks, emptyQueue);
s_shouldFinish = true;
pthread_cond_broadcast(&s_cvNotEmpty);
pthread_mutex_unlock(&s_mutexQueue);
// On attend que chaque thread se termine
for (unsigned int i = 0; i < s_workerCount; ++i)
pthread_join(s_threads[i], nullptr);
// Et on libère les ressources
pthread_barrier_destroy(&s_barrier);
pthread_cond_destroy(&s_cvEmpty);
pthread_cond_destroy(&s_cvNotEmpty);
pthread_mutex_destroy(&s_mutexQueue);
s_workerCount = 0;
}
void NzTaskSchedulerImpl::WaitForTasks()
{
#ifdef NAZARA_CORE_SAFE
if (s_workerCount == 0)
{
NazaraError("Task scheduler is not initialized");
return;
}
#endif
Wait();
}
NzFunctor* NzTaskSchedulerImpl::PopQueue()
{
NzFunctor* task = nullptr;
pthread_mutex_lock(&s_mutexQueue);
if (!s_tasks.empty())
{
task = s_tasks.front();
s_tasks.pop();
}
pthread_mutex_unlock(&s_mutexQueue);
return task;
}
void NzTaskSchedulerImpl::Wait()
{
if (s_isDone)
return;
pthread_mutex_lock(&s_mutexQueue);
s_isWaiting = true;
pthread_cond_broadcast(&s_cvNotEmpty);
pthread_cond_wait(&s_cvEmpty, &s_mutexQueue);
pthread_mutex_unlock(&s_mutexQueue);
s_isDone = true;
}
void* NzTaskSchedulerImpl::WorkerProc(void* /*userdata*/)
{
// On s'assure que tous les threads soient correctement lancés.
pthread_barrier_wait(&s_barrier);
// On quitte s'il doit terminer.
while (!s_shouldFinish)
{
NzFunctor* task = PopQueue();
if (task)
{
// On exécute la tâche avant de la supprimer
task->Run();
delete task;
}
else
{
pthread_mutex_lock(&s_mutexQueue);
if (s_tasks.empty())
s_isDone = true;
while (!(!s_tasks.empty() || s_isWaiting || s_shouldFinish))
pthread_cond_wait(&s_cvNotEmpty, &s_mutexQueue);
if (s_tasks.empty() && s_isWaiting)
{
// On prévient le thread qui attend que les tâches soient effectuées.
s_isWaiting = false;
pthread_cond_signal(&s_cvEmpty);
}
pthread_mutex_unlock(&s_mutexQueue);
}
}
return nullptr;
}
std::queue<NzFunctor*> NzTaskSchedulerImpl::s_tasks;
std::unique_ptr<pthread_t[]> NzTaskSchedulerImpl::s_threads;
std::atomic<bool> NzTaskSchedulerImpl::s_isDone;
std::atomic<bool> NzTaskSchedulerImpl::s_isWaiting;
std::atomic<bool> NzTaskSchedulerImpl::s_shouldFinish;
unsigned int NzTaskSchedulerImpl::s_workerCount;
pthread_mutex_t NzTaskSchedulerImpl::s_mutexQueue;
pthread_cond_t NzTaskSchedulerImpl::s_cvEmpty;
pthread_cond_t NzTaskSchedulerImpl::s_cvNotEmpty;
pthread_barrier_t NzTaskSchedulerImpl::s_barrier;

View File

@ -0,0 +1,47 @@
// 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_TASKSCHEDULERIMPL_HPP
#define NAZARA_TASKSCHEDULERIMPL_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Functor.hpp>
#include <atomic>
#include <memory>
#include <pthread.h>
#include <queue>
class NzTaskSchedulerImpl
{
public:
NzTaskSchedulerImpl() = delete;
~NzTaskSchedulerImpl() = delete;
static bool Initialize(unsigned int workerCount);
static bool IsInitialized();
static void Run(NzFunctor** tasks, unsigned int count);
static void Uninitialize();
static void WaitForTasks();
private:
static NzFunctor* PopQueue();
static void Wait();
static void* WorkerProc(void* userdata);
static std::queue<NzFunctor*> s_tasks;
static std::unique_ptr<pthread_t[]> s_threads;
static std::atomic<bool> s_isDone;
static std::atomic<bool> s_isWaiting;
static std::atomic<bool> s_shouldFinish;
static unsigned int s_workerCount;
static pthread_mutex_t s_mutexQueue;
static pthread_cond_t s_cvEmpty;
static pthread_cond_t s_cvNotEmpty;
static pthread_barrier_t s_barrier;
};
#endif // NAZARA_TASKSCHEDULERIMPL_HPP

File diff suppressed because it is too large Load Diff

View File

@ -57,31 +57,31 @@ bool NzFileImpl::Open(const NzString& filePath, unsigned int mode)
DWORD access;
DWORD shareMode = FILE_SHARE_READ;
DWORD openMode;
if (mode & NzFile::ReadOnly)
if (mode & nzOpenMode_ReadOnly)
{
access = GENERIC_READ;
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;
else
access = GENERIC_READ | GENERIC_WRITE;
if (mode & NzFile::Truncate)
if (mode & nzOpenMode_Truncate)
openMode = CREATE_ALWAYS;
else
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;
else
access = GENERIC_WRITE;
if (mode & NzFile::Truncate)
if (mode & nzOpenMode_Truncate)
openMode = CREATE_ALWAYS;
else
openMode = OPEN_ALWAYS;
@ -89,7 +89,7 @@ bool NzFileImpl::Open(const NzString& filePath, unsigned int mode)
else
return false;
if ((mode & NzFile::Lock) == 0)
if ((mode & nzOpenMode_Lock) == 0)
shareMode |= FILE_SHARE_WRITE;
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;
}
bool NzFileImpl::SetCursorPos(NzFile::CursorPosition pos, nzInt64 offset)
bool NzFileImpl::SetCursorPos(nzCursorPosition pos, nzInt64 offset)
{
DWORD moveMethod;
switch (pos)
{
case NzFile::AtBegin:
case nzCursorPosition_AtBegin:
moveMethod = FILE_BEGIN;
break;
case NzFile::AtCurrent:
case nzCursorPosition_AtCurrent:
moveMethod = FILE_CURRENT;
break;
case NzFile::AtEnd:
case nzCursorPosition_AtEnd:
moveMethod = FILE_END;
break;

View File

@ -28,7 +28,7 @@ class NzFileImpl : NzNonCopyable
nzUInt64 GetCursorPos() const;
bool Open(const NzString& filePath, unsigned int mode);
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);
static bool Copy(const NzString& sourcePath, const NzString& targetPath);

View File

@ -33,11 +33,20 @@ unsigned int NzHardwareInfoImpl::GetProcessorCount()
{
// Plus simple (et plus portable) que de passer par le CPUID
SYSTEM_INFO infos;
GetSystemInfo(&infos);
GetNativeSystemInfo(&infos);
return infos.dwNumberOfProcessors;
}
nzUInt64 NzHardwareInfoImpl::GetTotalMemory()
{
MEMORYSTATUSEX memStatus;
memStatus.dwLength = sizeof(memStatus);
GlobalMemoryStatusEx(&memStatus);
return memStatus.ullTotalPhys;
}
bool NzHardwareInfoImpl::IsCpuidSupported()
{
#ifdef NAZARA_PLATFORM_x64

View File

@ -14,6 +14,7 @@ class NzHardwareInfoImpl
public:
static void Cpuid(nzUInt32 functionId, nzUInt32 subFunctionId, nzUInt32 registers[4]);
static unsigned int GetProcessorCount();
static nzUInt64 GetTotalMemory();
static bool IsCpuidSupported();
};

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)
{
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() + ')');
return false;

View File

@ -103,7 +103,8 @@ bool NzSkyboxBackground::Initialize()
"void main()\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"
"}\n";

View File

@ -393,7 +393,7 @@ bool NzLuaInstance::Execute(const NzString& code)
bool NzLuaInstance::ExecuteFromFile(const NzString& filePath)
{
NzFile file(filePath);
if (!file.Open(NzFile::ReadOnly | NzFile::Text))
if (!file.Open(nzOpenMode_ReadOnly | nzOpenMode_Text))
{
NazaraError("Failed to open file");
return false;
@ -624,7 +624,7 @@ void NzLuaInstance::PushBoolean(bool value)
lua_pushboolean(m_state, (value) ? 1 : 0);
}
void NzLuaInstance::PushCFunction(NzLuaCFunction func, int upvalueCount)
void NzLuaInstance::PushCFunction(NzLuaCFunction func, unsigned int upvalueCount)
{
lua_pushcclosure(m_state, func, upvalueCount);
}
@ -677,6 +677,11 @@ void NzLuaInstance::PushString(const char* str)
lua_pushstring(m_state, str);
}
void NzLuaInstance::PushString(const char* str, unsigned int size)
{
lua_pushlstring(m_state, str, size);
}
void NzLuaInstance::PushString(const NzString& str)
{
lua_pushlstring(m_state, str.GetConstBuffer(), str.GetSize());

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));
}
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)
{
if (!Initialize())

View File

@ -2002,7 +2002,8 @@ void NzRenderer::UpdateMatrix(nzMatrixType type)
// Matrices combinées
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;
break;

View File

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

View File

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

View File

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

View File

@ -279,7 +279,7 @@ namespace
bool SetFile(const NzString& filePath)
{
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());
return false;

View File

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