From b51e151930afb722d10103ac60948d3c05dfc716 Mon Sep 17 00:00:00 2001 From: Gawaboumga Date: Fri, 21 Aug 2015 11:09:18 +0200 Subject: [PATCH 01/20] Suppression unused file Former-commit-id: 60221e1d8486e6a17a7e5368fd932628d9c52b85 --- include/Nazara/Core.hpp | 1 - include/Nazara/Core/Format.hpp | 14 -------------- 2 files changed, 15 deletions(-) delete mode 100644 include/Nazara/Core/Format.hpp diff --git a/include/Nazara/Core.hpp b/include/Nazara/Core.hpp index 49a8bf3f1..170a3aab3 100644 --- a/include/Nazara/Core.hpp +++ b/include/Nazara/Core.hpp @@ -45,7 +45,6 @@ #include #include #include -#include #include #include #include diff --git a/include/Nazara/Core/Format.hpp b/include/Nazara/Core/Format.hpp deleted file mode 100644 index d03f05eae..000000000 --- a/include/Nazara/Core/Format.hpp +++ /dev/null @@ -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 - -template NzString NzFormat(const NzString& str, Args... args); - -#endif // NAZARA_FORMAT_HPP From 8cda289b82b8faeb5c6a3587442b507755de94b0 Mon Sep 17 00:00:00 2001 From: Gawaboumga Date: Fri, 21 Aug 2015 11:11:04 +0200 Subject: [PATCH 02/20] Indentation String Former-commit-id: 86848a87089804d5152f80e960308f8b2eb12ff3 --- include/Nazara/Core/String.hpp | 6 +++--- include/Nazara/Core/String.inl | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/Nazara/Core/String.hpp b/include/Nazara/Core/String.hpp index 419f23135..363be3c45 100644 --- a/include/Nazara/Core/String.hpp +++ b/include/Nazara/Core/String.hpp @@ -22,9 +22,9 @@ class NAZARA_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 }; diff --git a/include/Nazara/Core/String.inl b/include/Nazara/Core/String.inl index 1224afa32..36299b485 100644 --- a/include/Nazara/Core/String.inl +++ b/include/Nazara/Core/String.inl @@ -6,9 +6,9 @@ namespace std { - template<> - struct hash - { + template<> + struct hash + { size_t operator()(const NzString& str) const { // Algorithme DJB2 @@ -26,7 +26,7 @@ namespace std return h; } - }; + }; } #include From 3dbcb25384d638d17e464c0a039e088d8fdfc57f Mon Sep 17 00:00:00 2001 From: Gawaboumga Date: Fri, 21 Aug 2015 11:22:35 +0200 Subject: [PATCH 03/20] Transfert enumeration from file to enums Former-commit-id: 0d9e191373affda50d0eb6c2376c7a23720e591b --- examples/HardwareInfo/main.cpp | 2 +- include/Nazara/Core/Enums.hpp | 28 ++++++++++++++- include/Nazara/Core/File.hpp | 28 +++------------ include/Nazara/Core/ResourceLoader.inl | 2 +- src/Nazara/Audio/Loaders/sndfile/Loader.cpp | 2 +- src/Nazara/Core/File.cpp | 34 +++++++++---------- src/Nazara/Core/Log.cpp | 2 +- src/Nazara/Core/Posix/FileImpl.cpp | 24 ++++++------- src/Nazara/Core/Posix/FileImpl.hpp | 2 +- src/Nazara/Core/Win32/FileImpl.cpp | 24 ++++++------- src/Nazara/Core/Win32/FileImpl.hpp | 2 +- src/Nazara/Graphics/Loaders/OBJ/Loader.cpp | 4 ++- src/Nazara/Lua/LuaInstance.cpp | 2 +- src/Nazara/Renderer/ShaderStage.cpp | 2 +- .../Renderer/UberShaderPreprocessor.cpp | 2 +- .../Utility/Loaders/FreeType/Loader.cpp | 2 +- 16 files changed, 85 insertions(+), 77 deletions(-) diff --git a/examples/HardwareInfo/main.cpp b/examples/HardwareInfo/main.cpp index d1a12dade..bcc76c4c3 100644 --- a/examples/HardwareInfo/main.cpp +++ b/examples/HardwareInfo/main.cpp @@ -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(); diff --git a/include/Nazara/Core/Enums.hpp b/include/Nazara/Core/Enums.hpp index 81ccae4e0..94d8584ad 100644 --- a/include/Nazara/Core/Enums.hpp +++ b/include/Nazara/Core/Enums.hpp @@ -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 diff --git a/include/Nazara/Core/File.hpp b/include/Nazara/Core/File.hpp index 556acfb3b..d11ed32ea 100644 --- a/include/Nazara/Core/File.hpp +++ b/include/Nazara/Core/File.hpp @@ -30,29 +30,9 @@ class NzFileImpl; class NAZARA_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(); @@ -79,14 +59,14 @@ class NAZARA_API NzFile : public NzHashable, public NzInputStream, NzNonCopyable 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); diff --git a/include/Nazara/Core/ResourceLoader.inl b/include/Nazara/Core/ResourceLoader.inl index 6622be2f4..11d9a0a63 100644 --- a/include/Nazara/Core/ResourceLoader.inl +++ b/include/Nazara/Core/ResourceLoader.inl @@ -57,7 +57,7 @@ bool NzResourceLoader::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; diff --git a/src/Nazara/Audio/Loaders/sndfile/Loader.cpp b/src/Nazara/Audio/Loaders/sndfile/Loader.cpp index 140798a80..159e9e88b 100644 --- a/src/Nazara/Audio/Loaders/sndfile/Loader.cpp +++ b/src/Nazara/Audio/Loaders/sndfile/Loader.cpp @@ -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 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; diff --git a/src/Nazara/Core/File.cpp b/src/Nazara/Core/File.cpp index 1acee0122..f6c45c6c8 100644 --- a/src/Nazara/Core/File.cpp +++ b/src/Nazara/Core/File.cpp @@ -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(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; @@ -721,7 +721,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; diff --git a/src/Nazara/Core/Log.cpp b/src/Nazara/Core/Log.cpp index 51622d100..a2602228a 100644 --- a/src/Nazara/Core/Log.cpp +++ b/src/Nazara/Core/Log.cpp @@ -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; diff --git a/src/Nazara/Core/Posix/FileImpl.cpp b/src/Nazara/Core/Posix/FileImpl.cpp index 56c3084da..b33dce80b 100644 --- a/src/Nazara/Core/Posix/FileImpl.cpp +++ b/src/Nazara/Core/Posix/FileImpl.cpp @@ -51,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); @@ -98,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; diff --git a/src/Nazara/Core/Posix/FileImpl.hpp b/src/Nazara/Core/Posix/FileImpl.hpp index b6d22aca5..eda3f5400 100644 --- a/src/Nazara/Core/Posix/FileImpl.hpp +++ b/src/Nazara/Core/Posix/FileImpl.hpp @@ -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); diff --git a/src/Nazara/Core/Win32/FileImpl.cpp b/src/Nazara/Core/Win32/FileImpl.cpp index 4ba16d90a..a2e4ef192 100644 --- a/src/Nazara/Core/Win32/FileImpl.cpp +++ b/src/Nazara/Core/Win32/FileImpl.cpp @@ -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; diff --git a/src/Nazara/Core/Win32/FileImpl.hpp b/src/Nazara/Core/Win32/FileImpl.hpp index 15420b8db..b9c667595 100644 --- a/src/Nazara/Core/Win32/FileImpl.hpp +++ b/src/Nazara/Core/Win32/FileImpl.hpp @@ -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); diff --git a/src/Nazara/Graphics/Loaders/OBJ/Loader.cpp b/src/Nazara/Graphics/Loaders/OBJ/Loader.cpp index 190517f72..c2721f74c 100644 --- a/src/Nazara/Graphics/Loaders/OBJ/Loader.cpp +++ b/src/Nazara/Graphics/Loaders/OBJ/Loader.cpp @@ -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; @@ -121,6 +121,8 @@ namespace model->SetMaterial(meshes[i].material, it->second); } + + return true; } bool Load(NzModel* model, NzInputStream& stream, const NzModelParameters& parameters) diff --git a/src/Nazara/Lua/LuaInstance.cpp b/src/Nazara/Lua/LuaInstance.cpp index 3aa8f9a23..efb2a1ee1 100644 --- a/src/Nazara/Lua/LuaInstance.cpp +++ b/src/Nazara/Lua/LuaInstance.cpp @@ -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; diff --git a/src/Nazara/Renderer/ShaderStage.cpp b/src/Nazara/Renderer/ShaderStage.cpp index c45757192..24b8248fb 100644 --- a/src/Nazara/Renderer/ShaderStage.cpp +++ b/src/Nazara/Renderer/ShaderStage.cpp @@ -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; diff --git a/src/Nazara/Renderer/UberShaderPreprocessor.cpp b/src/Nazara/Renderer/UberShaderPreprocessor.cpp index efcc492c5..078fb892f 100644 --- a/src/Nazara/Renderer/UberShaderPreprocessor.cpp +++ b/src/Nazara/Renderer/UberShaderPreprocessor.cpp @@ -151,7 +151,7 @@ void NzUberShaderPreprocessor::SetShader(nzShaderStage stage, const NzString& so bool NzUberShaderPreprocessor::SetShaderFromFile(nzShaderStage stage, const NzString& filePath, const NzString& shaderFlags, const NzString& requiredFlags) { NzFile file(filePath); - if (!file.Open(NzFile::ReadOnly | NzFile::Text)) + if (!file.Open(nzOpenMode_ReadOnly | nzOpenMode_Text)) { NazaraError("Failed to open \"" + filePath + '"'); return false; diff --git a/src/Nazara/Utility/Loaders/FreeType/Loader.cpp b/src/Nazara/Utility/Loaders/FreeType/Loader.cpp index b16c89d02..9d1eac832 100644 --- a/src/Nazara/Utility/Loaders/FreeType/Loader.cpp +++ b/src/Nazara/Utility/Loaders/FreeType/Loader.cpp @@ -280,7 +280,7 @@ namespace bool SetFile(const NzString& filePath) { std::unique_ptr 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; From 0b390e45a1c15a430350dd3c34116a9f5687b774 Mon Sep 17 00:00:00 2001 From: Gawaboumga Date: Fri, 21 Aug 2015 11:28:04 +0200 Subject: [PATCH 04/20] ByteArray rewritten Now works internally with std::vector Former-commit-id: 643f1d88b2959aed324743dbf91f831130a9198e --- include/Nazara/Core/ByteArray.hpp | 194 ++++++---- src/Nazara/Core/ByteArray.cpp | 603 ++++++++++++------------------ src/Nazara/Renderer/Shader.cpp | 2 +- 3 files changed, 365 insertions(+), 434 deletions(-) diff --git a/include/Nazara/Core/ByteArray.hpp b/include/Nazara/Core/ByteArray.hpp index aba0d0158..c0ac542b5 100644 --- a/include/Nazara/Core/ByteArray.hpp +++ b/include/Nazara/Core/ByteArray.hpp @@ -8,120 +8,156 @@ #define NAZARA_BYTEARRAY_HPP #include -#include #include -#include +#include +#include +#include class NzAbstractHash; -class NzHashDigest; class NAZARA_API NzByteArray : public NzHashable { + using Container = std::vector; + public: - struct SharedArray; + // types: + using value_type = typename Container::value_type; + using allocator_type = typename Container::allocator_type; + using size_type = typename Container::size_type; + using difference_type = typename Container::difference_type; + using reference = typename Container::reference; + using const_reference = typename Container::const_reference; + using pointer = typename Container::pointer; + using const_pointer = typename Container::const_pointer; + using iterator = typename Container::iterator; + using const_iterator = typename Container::const_iterator; + using reverse_iterator = typename Container::reverse_iterator; + using const_reverse_iterator = typename Container::const_reverse_iterator; + // iterators: + iterator begin() noexcept; + const_iterator begin() const noexcept; + iterator end() noexcept; + const_iterator end() const noexcept; + reverse_iterator rbegin() noexcept; + const_reverse_iterator rbegin() const noexcept; + reverse_iterator rend() noexcept; + const_reverse_iterator rend() const noexcept; + const_iterator cbegin() const noexcept; + const_iterator cend() const noexcept; + const_reverse_iterator crbegin() const noexcept; + const_reverse_iterator crend() const noexcept; + + // construct/destroy: NzByteArray(); - explicit NzByteArray(unsigned int size); - NzByteArray(const void* buffer, unsigned int size); - NzByteArray(const NzByteArray& buffer); - NzByteArray(NzByteArray&& buffer) noexcept; - NzByteArray(SharedArray* sharedArray); - ~NzByteArray(); + explicit NzByteArray(size_type n); + NzByteArray(const void* buffer, size_type n); + NzByteArray(size_type n, const value_type value); + template + NzByteArray(InputIterator first, InputIterator last); + NzByteArray(const NzByteArray& other); + NzByteArray(NzByteArray&& other); + virtual ~NzByteArray(); - NzByteArray& Append(const void* buffer, unsigned int size); - NzByteArray& Append(const NzByteArray& array); + iterator Append(const void* buffer, size_type size); + iterator Append(const NzByteArray& other); + template + void Assign(InputIterator first, InputIterator last); + void Assign(size_type n, const value_type value); + + reference Back(); + const_reference Back() const; void Clear(bool keepBuffer = false); - nzUInt8* GetBuffer(); - unsigned int GetCapacity() const; - const nzUInt8* GetConstBuffer() const; - unsigned int GetSize() const; + pointer data(); + const_pointer data() const; - NzByteArray& Insert(int pos, const void* buffer, unsigned int size); - NzByteArray& Insert(int pos, const NzByteArray& array); + bool empty() const noexcept; + iterator Erase(const_iterator pos); + iterator Erase(const_iterator first, const_iterator last); - bool IsEmpty() const; + reference Front(); + const_reference Front() const; - NzByteArray& Prepend(const void* buffer, unsigned int size); - NzByteArray& Prepend(const NzByteArray& array); + iterator Insert(const_iterator pos, const void* buffer, size_type n); + iterator Insert(const_iterator pos, const NzByteArray& other); + iterator Insert(const_iterator pos, size_type n, const value_type byte); + template + iterator Insert(const_iterator pos, InputIterator first, InputIterator last); + bool IsEmpty() const noexcept; - void Reserve(unsigned int bufferSize); + allocator_type GetAllocator() const; + pointer GetBuffer(); + size_type GetCapacity() const noexcept; + const_pointer GetConstBuffer() const; + size_type GetSize() const noexcept; - NzByteArray& Resize(int size); - NzByteArray& Resize(int size, nzUInt8 byte); - NzByteArray Resized(int size) const; - NzByteArray Resized(int size, nzUInt8 byte) const; - - NzByteArray SubArray(int startPos, int endPos = -1) const; - - void Swap(NzByteArray& array); - - // Méthodes compatibles STD - nzUInt8* begin(); - const nzUInt8* begin() const; - nzUInt8* end(); - const nzUInt8* end() const; - void push_front(nzUInt8 byte); - void push_back(nzUInt8 byte); - /*nzUInt8* rbegin(); - const nzUInt8* rbegin() const; - nzUInt8* rend(); - const nzUInt8* rend() const;*/ - - typedef const nzUInt8& const_reference; - typedef nzUInt8* iterator; - //typedef nzUInt8* reverse_iterator; - typedef nzUInt8 value_type; - // Méthodes compatibles STD - - nzUInt8& operator[](unsigned int pos); - nzUInt8 operator[](unsigned int pos) const; + size_type MaxSize() const noexcept; + // operators: + reference operator[](size_type pos); + const_reference operator[](size_type pos) const; NzByteArray& operator=(const NzByteArray& array); - NzByteArray& operator=(NzByteArray&& array) noexcept; - + NzByteArray& operator=(NzByteArray&& array); NzByteArray operator+(const NzByteArray& array) const; NzByteArray& operator+=(const NzByteArray& array); - static int Compare(const NzByteArray& first, const NzByteArray& second); + bool operator==(const NzByteArray& rhs) const; + bool operator!=(const NzByteArray& rhs) const; + bool operator<(const NzByteArray& rhs) const; + bool operator<=(const NzByteArray& rhs) const; + bool operator>(const NzByteArray& rhs) const; + bool operator>=(const NzByteArray& rhs) const; - struct NAZARA_API SharedArray - { - SharedArray() : - refCount(1) - { - } + void PopBack(); + void PopFront(); + iterator Prepend(const void* buffer, size_type size); + iterator Prepend(const NzByteArray& other); + void PushBack(const value_type byte); + void PushFront(const value_type byte); - SharedArray(unsigned short referenceCount, unsigned int bufferSize, unsigned int arraySize, nzUInt8* ptr) : - capacity(bufferSize), - size(arraySize), - buffer(ptr), - refCount(referenceCount) - { - } + void Reserve(size_type bufferSize); + void Resize(size_type newSize); + void Resize(size_type newSize, const value_type byte); - unsigned int capacity; - unsigned int size; - nzUInt8* buffer; + size_type size() const noexcept; + void ShrinkToFit(); + NzByteArray SubArray(const_iterator startPos, const_iterator endPos) const; + void Swap(NzByteArray& other); - std::atomic_ushort refCount; - }; - - static SharedArray emptyArray; - static unsigned int npos; + NzString ToString() const; private: - void EnsureOwnership(); - bool FillHash(NzAbstractHash* hash) const; - void ReleaseArray(); - SharedArray* m_sharedArray; + bool FillHash(NzAbstractHash* hash) const; + + Container m_array; }; +NAZARA_API std::ostream& operator<<(std::ostream& out, const NzByteArray& byteArray); + namespace std { NAZARA_API void swap(NzByteArray& lhs, NzByteArray& rhs); } +template +NzByteArray::NzByteArray(InputIterator first, InputIterator last) : +m_array(first, last) +{ +} + +template +void NzByteArray::Assign(InputIterator first, InputIterator last) +{ + m_array.assign(first, last); +} + +template +NzByteArray::iterator NzByteArray::Insert(const_iterator pos, InputIterator first, InputIterator last) +{ + return m_array.insert(pos, first, last); +} + #endif // NAZARA_BYTEARRAY_HPP diff --git a/src/Nazara/Core/ByteArray.cpp b/src/Nazara/Core/ByteArray.cpp index 16a7ed1b2..47bcec7e8 100644 --- a/src/Nazara/Core/ByteArray.cpp +++ b/src/Nazara/Core/ByteArray.cpp @@ -3,492 +3,387 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include + #include -#include -#include -#include -#include +#include +#include #include -// Cet algorithme est inspiré de la documentation de Qt -inline unsigned int nzGetNewSize(unsigned int newSize) + NzByteArray::iterator NzByteArray::begin() noexcept { - if (newSize < 20) - return newSize+4; - else - { - if (newSize < (1 << 12)-12) - return NzGetNearestPowerOfTwo(newSize << 1)-12; - else - return newSize + (1 << 11); - } + return m_array.begin(); +} + +NzByteArray::const_iterator NzByteArray::begin() const noexcept +{ + return m_array.begin(); +} + + NzByteArray::iterator NzByteArray::end() noexcept +{ + return m_array.end(); +} + +NzByteArray::const_iterator NzByteArray::end() const noexcept +{ + return m_array.end(); +} + +NzByteArray::reverse_iterator NzByteArray::rbegin() noexcept +{ + return m_array.rbegin(); +} + +NzByteArray::const_reverse_iterator NzByteArray::rbegin() const noexcept +{ + return m_array.rbegin(); +} + +NzByteArray::reverse_iterator NzByteArray::rend() noexcept +{ + return m_array.rend(); +} + +NzByteArray::const_iterator NzByteArray::cbegin() const noexcept +{ + return m_array.cbegin(); +} + +NzByteArray::const_iterator NzByteArray::cend() const noexcept +{ + return m_array.cend(); +} + +NzByteArray::const_reverse_iterator NzByteArray::crbegin() const noexcept +{ + return m_array.crbegin(); +} + +NzByteArray::const_reverse_iterator NzByteArray::crend() const noexcept +{ + return m_array.crend(); } NzByteArray::NzByteArray() : -m_sharedArray(&emptyArray) +m_array() { } -NzByteArray::NzByteArray(unsigned int size) +NzByteArray::NzByteArray(size_type n) : +m_array() { - 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; + m_array.reserve(n); } -NzByteArray::NzByteArray(const void* buffer, unsigned int size) +NzByteArray::NzByteArray(const void* buffer, size_type n) : +m_array(static_cast(buffer), static_cast(buffer) + n) { - if (size > 0) - { - m_sharedArray = new SharedArray; - m_sharedArray->buffer = new nzUInt8[size]; - m_sharedArray->capacity = size; - m_sharedArray->size = size; - std::memcpy(m_sharedArray->buffer, buffer, size); - } - else - m_sharedArray = &emptyArray; } -NzByteArray::NzByteArray(const NzByteArray& buffer) : -m_sharedArray(buffer.m_sharedArray) +NzByteArray::NzByteArray(size_type n, const value_type value) : +m_array(n, value) { - if (m_sharedArray != &emptyArray) - m_sharedArray->refCount++; } -NzByteArray::NzByteArray(NzByteArray&& buffer) noexcept : -m_sharedArray(buffer.m_sharedArray) +NzByteArray::NzByteArray(const NzByteArray& other) : +m_array(other.m_array) { - buffer.m_sharedArray = &emptyArray; } -NzByteArray::NzByteArray(SharedArray* sharedArray) : -m_sharedArray(sharedArray) +NzByteArray::NzByteArray(NzByteArray&& other) : +m_array(std::move(other.m_array)) { } NzByteArray::~NzByteArray() { - ReleaseArray(); } -NzByteArray& NzByteArray::Append(const void* buffer, unsigned int size) +NzByteArray::iterator NzByteArray::Append(const void* buffer, size_type n) { - return Insert(m_sharedArray->size, buffer, size); + return Insert(end(), static_cast(buffer), static_cast(buffer) + n); } -NzByteArray& NzByteArray::Append(const NzByteArray& array) +NzByteArray::iterator NzByteArray::Append(const NzByteArray& other) { - return Insert(m_sharedArray->size, array); + return Insert(end(), other.begin(), other.end()); +} + +void NzByteArray::Assign(size_type n, const value_type value) +{ + m_array.assign(n, value); +} + +NzByteArray::reference NzByteArray::Back() +{ + return m_array.back(); +} + +NzByteArray::const_reference NzByteArray::Back() const +{ + return m_array.back(); } void NzByteArray::Clear(bool keepBuffer) { - if (keepBuffer) - { - EnsureOwnership(); - m_sharedArray->size = 0; - } - else - ReleaseArray(); + m_array.clear(); + + if (!keepBuffer) + ShrinkToFit(); } -nzUInt8* NzByteArray::GetBuffer() +NzByteArray::pointer NzByteArray::data() { - EnsureOwnership(); - - return m_sharedArray->buffer; + return GetBuffer(); } -unsigned int NzByteArray::GetCapacity() const +NzByteArray::const_pointer NzByteArray::data() const { - return m_sharedArray->capacity; + return GetConstBuffer(); } -const nzUInt8* NzByteArray::GetConstBuffer() const +bool NzByteArray::empty() const noexcept { - return m_sharedArray->buffer; + return IsEmpty(); } -unsigned int NzByteArray::GetSize() const +NzByteArray::iterator NzByteArray::Erase(const_iterator pos) { - return m_sharedArray->size; + return m_array.erase(pos); } -NzByteArray& NzByteArray::Insert(int pos, const void* buffer, unsigned int size) +NzByteArray::iterator NzByteArray::Erase(const_iterator first, const_iterator last) { - if (size == 0) - return *this; - - if (pos < 0) - pos = std::max(static_cast(m_sharedArray->size + pos), 0); - - unsigned int start = std::min(static_cast(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; + return m_array.erase(first, last); } -NzByteArray& NzByteArray::Insert(int pos, const NzByteArray& array) +NzByteArray::reference NzByteArray::Front() { - return Insert(pos, array.m_sharedArray->buffer, array.m_sharedArray->size); + return m_array.front(); } -bool NzByteArray::IsEmpty() const +NzByteArray::const_reference NzByteArray::Front() const { - return m_sharedArray->size == 0; + return m_array.front(); } -NzByteArray& NzByteArray::Prepend(const void* buffer, unsigned int size) +NzByteArray::iterator NzByteArray::Insert(const_iterator pos, const void* buffer, size_type n) { - return Insert(0, buffer, size); + return Insert(pos, static_cast(buffer), static_cast(buffer) + n); } -NzByteArray& NzByteArray::Prepend(const NzByteArray& array) +NzByteArray::iterator NzByteArray::Insert(const_iterator pos, const NzByteArray& other) { - return Insert(0, array); + return Insert(pos, other.begin(), other.end()); } -void NzByteArray::Reserve(unsigned int bufferSize) +NzByteArray::iterator NzByteArray::Insert(const_iterator pos, size_type n, const value_type byte) { - if (m_sharedArray->capacity >= bufferSize) - return; - - 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; + return Insert(pos, n, byte); } -NzByteArray& NzByteArray::Resize(int size) +bool NzByteArray::IsEmpty() const noexcept { - if (size == 0) - { - Clear(true); - return *this; - } - - if (size < 0) - size = std::max(static_cast(m_sharedArray->size + size), 0); - - unsigned int newSize = static_cast(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; + return m_array.empty(); } -NzByteArray& NzByteArray::Resize(int size, nzUInt8 byte) +NzByteArray::allocator_type NzByteArray::GetAllocator() const { - if (size == 0) - { - Clear(true); - return *this; - } - - if (size < 0) - size = std::max(static_cast(m_sharedArray->size + size), 0); - - unsigned int newSize = static_cast(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; + return m_array.get_allocator(); } -NzByteArray NzByteArray::Resized(int size) const +NzByteArray::pointer NzByteArray::GetBuffer() { - if (size < 0) - size = m_sharedArray->size + size; - - if (size <= 0) - return NzByteArray(); - - unsigned int newSize = static_cast(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)); + return m_array.data(); } -NzByteArray NzByteArray::Resized(int size, nzUInt8 byte) const +NzByteArray::size_type NzByteArray::GetCapacity() const noexcept { - if (size < 0) - size = m_sharedArray->size + size; - - if (size <= 0) - return NzByteArray(); - - unsigned int newSize = static_cast(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)); + return m_array.capacity(); } -NzByteArray NzByteArray::SubArray(int startPos, int endPos) const +NzByteArray::const_pointer NzByteArray::GetConstBuffer() const { - if (startPos < 0) - startPos = std::max(m_sharedArray->size+startPos, 0U); - - unsigned int start = static_cast(startPos); - - if (endPos < 0) - { - endPos = m_sharedArray->size + endPos; - if (endPos < 0) - return NzByteArray(); - } - - unsigned int minEnd = std::min(static_cast(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)); + return m_array.data(); } -void NzByteArray::Swap(NzByteArray& array) +NzByteArray::size_type NzByteArray::GetSize() const noexcept { - std::swap(m_sharedArray, array.m_sharedArray); + return m_array.size(); } -nzUInt8* NzByteArray::begin() +NzByteArray::size_type NzByteArray::MaxSize() const noexcept { - return m_sharedArray->buffer; + return m_array.max_size(); } -const nzUInt8* NzByteArray::begin() const -{ - 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 +NzByteArray::reference NzByteArray::operator[](size_type pos) { #if NAZARA_CORE_SAFE - if (pos >= m_sharedArray->size) - { - NazaraError("Index out of range (" + NzString::Number(pos) + " >= " + NzString::Number(m_sharedArray->size) + ')'); - return 0; - } + if (pos >= GetSize()) + NazaraError("Index out of range (" + NzString::Number(pos) + " >= " + NzString::Number(GetSize()) + ')'); #endif - return m_sharedArray->buffer[pos]; + return m_array[pos]; } -NzByteArray& NzByteArray::operator=(const NzByteArray& array) +NzByteArray::const_reference NzByteArray::operator[](size_type pos) const { - if (this != &array) - { - ReleaseArray(); + #if NAZARA_CORE_SAFE + if (pos >= GetSize()) + NazaraError("Index out of range (" + NzString::Number(pos) + " >= " + NzString::Number(GetSize()) + ')'); + #endif - m_sharedArray = array.m_sharedArray; - if (m_sharedArray != &emptyArray) - m_sharedArray->refCount++; - } + return m_array[pos]; +} + +NzByteArray& NzByteArray::operator=(const NzByteArray& other) +{ + m_array = other.m_array; return *this; } -NzByteArray& NzByteArray::operator=(NzByteArray&& array) noexcept +NzByteArray& NzByteArray::operator=(NzByteArray&& other) { - std::swap(m_sharedArray, array.m_sharedArray); + m_array = std::move(other.m_array); return *this; } -NzByteArray NzByteArray::operator+(const NzByteArray& array) const +NzByteArray NzByteArray::operator+(const NzByteArray& other) const { - if (array.m_sharedArray->size == 0) - return *this; + NzByteArray tmp(*this); + tmp += other; - 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)); + return tmp; } -NzByteArray& NzByteArray::operator+=(const NzByteArray& array) +NzByteArray& NzByteArray::operator+=(const NzByteArray& other) { - return Append(array); + Append(other); + + return *this; } -int NzByteArray::Compare(const NzByteArray& first, const NzByteArray& second) +bool NzByteArray::operator==(const NzByteArray& rhs) const { - return std::memcmp(first.m_sharedArray->buffer, second.m_sharedArray->buffer, std::min(first.m_sharedArray->size, second.m_sharedArray->size)); + return m_array == rhs.m_array; } -void NzByteArray::EnsureOwnership() +bool NzByteArray::operator!=(const NzByteArray& rhs) const { - if (m_sharedArray == &emptyArray) - return; + return !operator==(rhs); +} - if (m_sharedArray->refCount > 1) - { - m_sharedArray->refCount--; +bool NzByteArray::operator<(const NzByteArray& rhs) const +{ + return m_array < rhs.m_array; +} - nzUInt8* buffer = new nzUInt8[m_sharedArray->capacity]; - std::memcpy(buffer, m_sharedArray->buffer, m_sharedArray->size); +bool NzByteArray::operator<=(const NzByteArray& rhs) const +{ + return m_array <= rhs.m_array; +} - m_sharedArray = new SharedArray(1, m_sharedArray->capacity, m_sharedArray->size, buffer); - } +bool NzByteArray::operator>(const NzByteArray& rhs) const +{ + return m_array > rhs.m_array; +} + +bool NzByteArray::operator>=(const NzByteArray& rhs) const +{ + return m_array >= rhs.m_array; +} + +void NzByteArray::PopBack() +{ + Erase(end() - 1); +} + +void NzByteArray::PopFront() +{ + Erase(begin()); +} + +NzByteArray::iterator NzByteArray::Prepend(const void* buffer, size_type n) +{ + return Insert(begin(), buffer, n); +} + +NzByteArray::iterator NzByteArray::Prepend(const NzByteArray& other) +{ + return Insert(begin(), other); +} + +void NzByteArray::PushBack(const value_type byte) +{ + m_array.push_back(byte); +} + +void NzByteArray::PushFront(const value_type byte) +{ + m_array.insert(begin(), 1, byte); +} + +void NzByteArray::Reserve(size_type bufferSize) +{ + m_array.reserve(bufferSize); +} + +void NzByteArray::Resize(size_type newSize) +{ + m_array.resize(newSize); +} + +void NzByteArray::Resize(size_type newSize, const value_type byte) +{ + m_array.resize(newSize, byte); +} + +NzByteArray::size_type NzByteArray::size() const noexcept +{ + return GetSize(); +} + +void NzByteArray::ShrinkToFit() +{ + m_array.shrink_to_fit(); +} + +NzByteArray NzByteArray::SubArray(const_iterator startPos, const_iterator endPos) const +{ + return NzByteArray(startPos, endPos); +} + +void NzByteArray::Swap(NzByteArray& other) +{ + m_array.swap(other.m_array); +} + +NzString NzByteArray::ToString() const +{ + NzStringStream ss; + + for (const auto& it : m_array) + ss << it; + + return ss; } bool NzByteArray::FillHash(NzAbstractHash* hash) const { - hash->Append(m_sharedArray->buffer, m_sharedArray->size); + hash->Append(GetConstBuffer(), GetSize()); return true; } -void NzByteArray::ReleaseArray() +std::ostream& operator<<(std::ostream& out, const NzByteArray& byteArray) { - if (m_sharedArray == &emptyArray) - return; - - if (--m_sharedArray->refCount == 0) - { - delete[] m_sharedArray->buffer; - delete m_sharedArray; - } - - m_sharedArray = &emptyArray; + out << byteArray.ToString(); + return out; } -NzByteArray::SharedArray NzByteArray::emptyArray(0, 0, 0, nullptr); -unsigned int NzByteArray::npos(std::numeric_limits::max()); - namespace std { void swap(NzByteArray& lhs, NzByteArray& rhs) diff --git a/src/Nazara/Renderer/Shader.cpp b/src/Nazara/Renderer/Shader.cpp index d01f1eda2..3df361123 100644 --- a/src/Nazara/Renderer/Shader.cpp +++ b/src/Nazara/Renderer/Shader.cpp @@ -192,7 +192,7 @@ NzByteArray NzShader::GetBinary() const if (binaryLength > 0) { - byteArray.Resize(sizeof(nzUInt64) + binaryLength); + byteArray.Reserve(sizeof(nzUInt64) + binaryLength); nzUInt8* buffer = byteArray.GetBuffer(); From 376df6a3b74c74782a4d8e5381a9af65f62a56be Mon Sep 17 00:00:00 2001 From: Gawaboumga Date: Fri, 21 Aug 2015 11:32:29 +0200 Subject: [PATCH 05/20] Indentations Former-commit-id: 0d82a4464cb9369bc4ca5cf2d7780c921eff953d --- include/Nazara/Core/Algorithm.inl | 2 +- include/Nazara/Core/Color.inl | 4 ++-- include/Nazara/Core/DynLib.hpp | 2 +- include/Nazara/Math/Matrix4.hpp | 1 - include/Nazara/Math/Vector3.hpp | 2 -- include/Nazara/Math/Vector3.inl | 6 +++--- include/Nazara/Math/Vector4.inl | 22 +++++++++++----------- src/Nazara/Core/String.cpp | 27 ++++++++++++++------------- src/Nazara/Utility/VertexBuffer.cpp | 2 +- 9 files changed, 33 insertions(+), 35 deletions(-) diff --git a/include/Nazara/Core/Algorithm.inl b/include/Nazara/Core/Algorithm.inl index 1fa2a9032..2b5cffb47 100644 --- a/include/Nazara/Core/Algorithm.inl +++ b/include/Nazara/Core/Algorithm.inl @@ -14,7 +14,7 @@ template struct NzImplTupleUnpack { template - void operator()(F func, const std::tuple& t, Args&... args) + void operator()(F func, const std::tuple& t, Args&... args) { NzImplTupleUnpack()(func, t, std::get(t), args...); } diff --git a/include/Nazara/Core/Color.inl b/include/Nazara/Core/Color.inl index 8e2caa76c..9dfe4e474 100644 --- a/include/Nazara/Core/Color.inl +++ b/include/Nazara/Core/Color.inl @@ -312,8 +312,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 diff --git a/include/Nazara/Core/DynLib.hpp b/include/Nazara/Core/DynLib.hpp index 733b7c962..bce67acf0 100644 --- a/include/Nazara/Core/DynLib.hpp +++ b/include/Nazara/Core/DynLib.hpp @@ -27,7 +27,7 @@ #include #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; diff --git a/include/Nazara/Math/Matrix4.hpp b/include/Nazara/Math/Matrix4.hpp index ac142f4f1..7d011f171 100644 --- a/include/Nazara/Math/Matrix4.hpp +++ b/include/Nazara/Math/Matrix4.hpp @@ -80,7 +80,6 @@ class NzMatrix4 NzMatrix4& Set(const T matrix[16]); //NzMatrix4(const NzMatrix3& matrix); NzMatrix4& Set(const NzMatrix4& matrix); - NzMatrix4& Set(NzMatrix4&& matrix); template NzMatrix4& Set(const NzMatrix4& matrix); NzMatrix4& SetRotation(const NzQuaternion& rotation); NzMatrix4& SetScale(const NzVector3& scale); diff --git a/include/Nazara/Math/Vector3.hpp b/include/Nazara/Math/Vector3.hpp index 14cd41b0a..21f3c30be 100644 --- a/include/Nazara/Math/Vector3.hpp +++ b/include/Nazara/Math/Vector3.hpp @@ -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; diff --git a/include/Nazara/Math/Vector3.inl b/include/Nazara/Math/Vector3.inl index a2f0ed35c..598c8f686 100644 --- a/include/Nazara/Math/Vector3.inl +++ b/include/Nazara/Math/Vector3.inl @@ -64,9 +64,9 @@ template T NzVector3::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& NzVector3::Set(const NzVector4& vec) template T NzVector3::SquaredDistance(const NzVector3& vec) const { - return operator-(vec).GetSquaredLength(); + return (*this - vec).GetSquaredLength(); } template diff --git a/include/Nazara/Math/Vector4.inl b/include/Nazara/Math/Vector4.inl index fdef535a7..6b17b2ced 100644 --- a/include/Nazara/Math/Vector4.inl +++ b/include/Nazara/Math/Vector4.inl @@ -121,11 +121,11 @@ NzVector4& NzVector4::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& NzVector4::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 bool NzVector4::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 diff --git a/src/Nazara/Core/String.cpp b/src/Nazara/Core/String.cpp index d2ba08601..1269c747c 100644 --- a/src/Nazara/Core/String.cpp +++ b/src/Nazara/Core/String.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -50,24 +51,24 @@ inline char nzToUpper(char character) inline int nzStrcasecmp(const char* s1, const char* s2) { - int ret = 0; + int ret = 0; - while (!(ret = static_cast(nzToLower(*s1)) - static_cast(nzToLower(*s2))) && *s2) - ++s1, ++s2; + while (!(ret = static_cast(nzToLower(*s1)) - static_cast(nzToLower(*s2))) && *s2) + ++s1, ++s2; - return ret != 0 ? (ret > 0 ? 1 : -1) : 0; + return ret != 0 ? (ret > 0 ? 1 : -1) : 0; } inline int nzUnicodecasecmp(const char* s1, const char* s2) { - int ret = 0; + int ret = 0; utf8::unchecked::iterator it1(s1); utf8::unchecked::iterator it2(s2); - while (!(ret = NzUnicode::GetLowercase(*it1) - NzUnicode::GetLowercase(*it2)) && *it2) - ++it1, ++it2; + while (!(ret = NzUnicode::GetLowercase(*it1) - NzUnicode::GetLowercase(*it2)) && *it2) + ++it1, ++it2; - return ret != 0 ? (ret > 0 ? 1 : -1) : 0; + return ret != 0 ? (ret > 0 ? 1 : -1) : 0; } NzString::NzString() : @@ -2087,8 +2088,8 @@ bool NzString::Match(const char* pattern) const if (!*++pattern) return true; - mp = pattern; - cp = str+1; + mp = pattern; + cp = str+1; } else if (*pattern == *str || *pattern == '?') { @@ -3977,7 +3978,7 @@ NzString NzString::Unicode(char32_t character) count = 2; else if (character < 0x10000) count = 3; - else + else count = 4; char* str = new char[count+1]; @@ -4028,7 +4029,7 @@ NzString NzString::Unicode(const char32_t* u32String) count += 2; else if (cp < 0x10000) count += 3; - else + else count += 4; } while (*++ptr); @@ -4056,7 +4057,7 @@ NzString NzString::Unicode(const wchar_t* wString) count += 2; else if (cp < 0x10000) count += 3; - else + else count += 4; } while (*++ptr); diff --git a/src/Nazara/Utility/VertexBuffer.cpp b/src/Nazara/Utility/VertexBuffer.cpp index 463917e17..556e5ba92 100644 --- a/src/Nazara/Utility/VertexBuffer.cpp +++ b/src/Nazara/Utility/VertexBuffer.cpp @@ -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) From 2d07922478dac394a61045e6d9b76d89d98b4934 Mon Sep 17 00:00:00 2001 From: Gawaboumga Date: Fri, 21 Aug 2015 11:34:08 +0200 Subject: [PATCH 06/20] Add Unit for vector2 Former-commit-id: 4a143363f24e08d0be12a5ef6bfb46c71b11be4a --- include/Nazara/Math/Vector2.hpp | 4 ++-- include/Nazara/Math/Vector2.inl | 23 +++++++++++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/include/Nazara/Math/Vector2.hpp b/include/Nazara/Math/Vector2.hpp index c42700de5..24eea3806 100644 --- a/include/Nazara/Math/Vector2.hpp +++ b/include/Nazara/Math/Vector2.hpp @@ -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(); diff --git a/include/Nazara/Math/Vector2.inl b/include/Nazara/Math/Vector2.inl index 05a7ae792..c8ec7730f 100644 --- a/include/Nazara/Math/Vector2.inl +++ b/include/Nazara/Math/Vector2.inl @@ -105,6 +105,12 @@ T NzVector2::GetSquaredLength() const return x*x + y*y; } +template +NzVector2& NzVector2::MakeUnit() +{ + return Set(F(1.0), F(1.0)); +} + template NzVector2& NzVector2::MakeUnitX() { @@ -129,7 +135,7 @@ NzVector2& NzVector2::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& NzVector2::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& NzVector2::Set(const NzVector4& vec) template T NzVector2::SquaredDistance(const NzVector2& vec) const { - return operator-(vec).GetSquaredLength(); + return (*this - vec).GetSquaredLength(); } template @@ -398,7 +404,7 @@ template bool NzVector2::operator==(const NzVector2& vec) const { return NzNumberEquals(x, vec.x) && - NzNumberEquals(y, vec.y); + NzNumberEquals(y, vec.y); } template @@ -443,6 +449,15 @@ NzVector2 NzVector2::Lerp(const NzVector2& from, const NzVector2& to, T in return NzLerp(from, to, interpolation); } +template +NzVector2 NzVector2::Unit() +{ + NzVector2 vector; + vector.MakeUnit(); + + return vector; +} + template NzVector2 NzVector2::UnitX() { From f61aa8f36eece4fa07109b174b786d6ebc30ffaa Mon Sep 17 00:00:00 2001 From: Gawaboumga Date: Fri, 21 Aug 2015 11:46:46 +0200 Subject: [PATCH 07/20] Include Catch and tests for Core Catch 1.2.1 Former-commit-id: 4149eaa61b21532d4d204db8a3771c6de8e4672c --- tests/Nazara/Core/ByteArray.cpp | 216 +++++++++++++++++++++++++++++ tests/Nazara/Core/Clock.cpp | 31 +++++ tests/Nazara/Core/Color.cpp | 22 +++ tests/Nazara/Core/Directory.cpp | 34 +++++ tests/Nazara/Core/Error.cpp | 28 ++++ tests/Nazara/Core/File.cpp | 53 +++++++ tests/Nazara/Core/String.cpp | 111 +++++++++++++++ tests/Nazara/Core/StringStream.cpp | 71 ++++++++++ 8 files changed, 566 insertions(+) create mode 100644 tests/Nazara/Core/ByteArray.cpp create mode 100644 tests/Nazara/Core/Clock.cpp create mode 100644 tests/Nazara/Core/Color.cpp create mode 100644 tests/Nazara/Core/Directory.cpp create mode 100644 tests/Nazara/Core/Error.cpp create mode 100644 tests/Nazara/Core/File.cpp create mode 100644 tests/Nazara/Core/String.cpp create mode 100644 tests/Nazara/Core/StringStream.cpp diff --git a/tests/Nazara/Core/ByteArray.cpp b/tests/Nazara/Core/ByteArray.cpp new file mode 100644 index 000000000..b2b97fe08 --- /dev/null +++ b/tests/Nazara/Core/ByteArray.cpp @@ -0,0 +1,216 @@ +#include +#include + +#include + +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()); + } + } + } +} diff --git a/tests/Nazara/Core/Clock.cpp b/tests/Nazara/Core/Clock.cpp new file mode 100644 index 000000000..9f33a002d --- /dev/null +++ b/tests/Nazara/Core/Clock.cpp @@ -0,0 +1,31 @@ +#include +#include + +#include + +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); + } + } + } + } +} diff --git a/tests/Nazara/Core/Color.cpp b/tests/Nazara/Core/Color.cpp new file mode 100644 index 000000000..a07610839 --- /dev/null +++ b/tests/Nazara/Core/Color.cpp @@ -0,0 +1,22 @@ +#include +#include + +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)); + } + } + } +} diff --git a/tests/Nazara/Core/Directory.cpp b/tests/Nazara/Core/Directory.cpp new file mode 100644 index 000000000..203529bb1 --- /dev/null +++ b/tests/Nazara/Core/Directory.cpp @@ -0,0 +1,34 @@ +#include +#include + +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")); + } + } + } +} + diff --git a/tests/Nazara/Core/Error.cpp b/tests/Nazara/Core/Error.cpp new file mode 100644 index 000000000..c05e695be --- /dev/null +++ b/tests/Nazara/Core/Error.cpp @@ -0,0 +1,28 @@ +#include +#include + +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); +} diff --git a/tests/Nazara/Core/File.cpp b/tests/Nazara/Core/File.cpp new file mode 100644 index 000000000..1527632f8 --- /dev/null +++ b/tests/Nazara/Core/File.cpp @@ -0,0 +1,53 @@ +#include +#include + +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")); + } + } + } +} diff --git a/tests/Nazara/Core/String.cpp b/tests/Nazara/Core/String.cpp new file mode 100644 index 000000000..88daf56da --- /dev/null +++ b/tests/Nazara/Core/String.cpp @@ -0,0 +1,111 @@ +#include +#include + +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); + } + } + }*/ +} + diff --git a/tests/Nazara/Core/StringStream.cpp b/tests/Nazara/Core/StringStream.cpp new file mode 100644 index 000000000..62f0b794e --- /dev/null +++ b/tests/Nazara/Core/StringStream.cpp @@ -0,0 +1,71 @@ +#include +#include + +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(nullptr); + + REQUIRE(stringstream.ToString() == (NzString("default3330x") + NzString(sizeof(void*) * 2, "0"))); + } + } +} From c2161f2a8bc60c2404b31b263f3289876df99acc Mon Sep 17 00:00:00 2001 From: Gawaboumga Date: Fri, 21 Aug 2015 11:49:37 +0200 Subject: [PATCH 08/20] Fix NumberEquals with unsigned Former-commit-id: 30b573278e84991a9d76604a359bd3110f13d87c --- include/Nazara/Math/Algorithm.hpp | 4 + include/Nazara/Math/Algorithm.inl | 6 +- tests/Nazara/Math/Algorithm.cpp | 197 ++++++++++++++++++++++++++++++ 3 files changed, 204 insertions(+), 3 deletions(-) create mode 100644 tests/Nazara/Math/Algorithm.cpp diff --git a/include/Nazara/Math/Algorithm.hpp b/include/Nazara/Math/Algorithm.hpp index a842c1df8..f1820e844 100644 --- a/include/Nazara/Math/Algorithm.hpp +++ b/include/Nazara/Math/Algorithm.hpp @@ -16,6 +16,10 @@ #define M_PI 3.141592653589793238462643 #endif +#ifndef M_PI_2 +#define M_PI_2 1.5707963267948966192313217 +#endif + #ifndef M_SQRT2 #define M_SQRT2 1.4142135623730950488016887 #endif diff --git a/include/Nazara/Math/Algorithm.inl b/include/Nazara/Math/Algorithm.inl index 86ed6d9f6..6a7e5b4ed 100644 --- a/include/Nazara/Math/Algorithm.inl +++ b/include/Nazara/Math/Algorithm.inl @@ -223,10 +223,10 @@ T NzNormalizeAngle(T angle) template bool NzNumberEquals(T a, T b, T maxDifference) { - T diff = a - b; - if (diff < F(0.0)) - diff = -diff; + if (b > a) + std::swap(a, b); + T diff = a - b; return diff <= maxDifference; } diff --git a/tests/Nazara/Math/Algorithm.cpp b/tests/Nazara/Math/Algorithm.cpp new file mode 100644 index 000000000..8683a3058 --- /dev/null +++ b/tests/Nazara/Math/Algorithm.cpp @@ -0,0 +1,197 @@ +#include +#include + +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); + } +} From f0660d5da80cb877730ae34c57812c65f5f253aa Mon Sep 17 00:00:00 2001 From: Gawaboumga Date: Fri, 21 Aug 2015 11:52:05 +0200 Subject: [PATCH 09/20] Fix operator== with infinite BoundingVolume Former-commit-id: 47cee9fb8d8d2b8188d3918527aeebab56b03992 --- include/Nazara/Math/BoundingVolume.inl | 5 +- tests/Nazara/Math/BoundingVolume.cpp | 103 +++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 tests/Nazara/Math/BoundingVolume.cpp diff --git a/include/Nazara/Math/BoundingVolume.inl b/include/Nazara/Math/BoundingVolume.inl index ad8fc9415..74d45549e 100644 --- a/include/Nazara/Math/BoundingVolume.inl +++ b/include/Nazara/Math/BoundingVolume.inl @@ -202,7 +202,10 @@ template bool NzBoundingVolume::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; } diff --git a/tests/Nazara/Math/BoundingVolume.cpp b/tests/Nazara/Math/BoundingVolume.cpp new file mode 100644 index 000000000..57c82cfeb --- /dev/null +++ b/tests/Nazara/Math/BoundingVolume.cpp @@ -0,0 +1,103 @@ +#include +#include + +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 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); + } + } + } +} From b4f926d3ca6f9eb0937863eb22cc57035e7a065f Mon Sep 17 00:00:00 2001 From: Gawaboumga Date: Fri, 21 Aug 2015 11:52:44 +0200 Subject: [PATCH 10/20] Test box No problem except indentation Former-commit-id: 58d711b48164363fd672c51c005e16eb5ce55e9e --- include/Nazara/Math/Box.inl | 10 ++-- tests/Nazara/Math/Box.cpp | 113 ++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 tests/Nazara/Math/Box.cpp diff --git a/include/Nazara/Math/Box.inl b/include/Nazara/Math/Box.inl index 58904abc3..19da1ef63 100644 --- a/include/Nazara/Math/Box.inl +++ b/include/Nazara/Math/Box.inl @@ -65,7 +65,7 @@ template bool NzBox::Contains(const NzBox& 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 @@ -399,9 +399,9 @@ NzBox& NzBox::Transform(const NzMatrix4& matrix, bool applyTranslation) NzVector3 center = matrix.Transform(GetCenter(), (applyTranslation) ? F(1.0) : F(0.0)); // Valeur multipliant la translation NzVector3 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 bool NzBox::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 diff --git a/tests/Nazara/Math/Box.cpp b/tests/Nazara/Math/Box.cpp new file mode 100644 index 000000000..724fe1ec5 --- /dev/null +++ b/tests/Nazara/Math/Box.cpp @@ -0,0 +1,113 @@ +#include +#include + +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)); + } + } + } + } +} From 077584ec491b38a099b40c59f52ca88e041d726b Mon Sep 17 00:00:00 2001 From: Gawaboumga Date: Fri, 21 Aug 2015 11:53:16 +0200 Subject: [PATCH 11/20] EulerAngles simplification Former-commit-id: 775b07a51077e6f17b9fe05773dc5c277c49919d --- include/Nazara/Math/EulerAngles.inl | 15 ++++-- tests/Nazara/Math/EulerAngles.cpp | 83 +++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 tests/Nazara/Math/EulerAngles.cpp diff --git a/include/Nazara/Math/EulerAngles.inl b/include/Nazara/Math/EulerAngles.inl index 8e29a40d9..b02e5f6ed 100644 --- a/include/Nazara/Math/EulerAngles.inl +++ b/include/Nazara/Math/EulerAngles.inl @@ -91,11 +91,18 @@ void NzEulerAngles::Set(const NzEulerAngles& angles) template NzQuaternion NzEulerAngles::ToQuaternion() const { - NzQuaternion rotX(pitch, NzVector3::UnitX()); - NzQuaternion rotY(yaw, NzVector3::UnitY()); - NzQuaternion rotZ(roll, NzVector3::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(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 diff --git a/tests/Nazara/Math/EulerAngles.cpp b/tests/Nazara/Math/EulerAngles.cpp new file mode 100644 index 000000000..6a4508179 --- /dev/null +++ b/tests/Nazara/Math/EulerAngles.cpp @@ -0,0 +1,83 @@ +#include +#include + +SCENARIO("EulerAngles", "[MATH][EULERANGLES]") +{ + GIVEN("Two zero euler angles") + { + NzEulerAnglesf firstZero(0.f, 0.f, 0.f); + NzEulerAnglesf secondZero(NzEulerAngles::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)); + } + } + } +} From f2b80bfe64d8334ccc6bde178811daa28c3bd6f1 Mon Sep 17 00:00:00 2001 From: Gawaboumga Date: Fri, 21 Aug 2015 11:57:56 +0200 Subject: [PATCH 12/20] Planes are ax+by+cz=d Planes are changed to ax+by+cz=d, so the plane with normal (0, 1, 0) and distance 1 is y=1. Operators == and !=. Former-commit-id: 5267a183a9e6fb490de099d536ea2f64558f674d --- tests/Nazara/Math/Plane.cpp | 75 ++++++++++++++ tests/Nazara/Math/Plane.hpp | 60 +++++++++++ tests/Nazara/Math/Plane.inl | 193 ++++++++++++++++++++++++++++++++++++ 3 files changed, 328 insertions(+) create mode 100644 tests/Nazara/Math/Plane.cpp create mode 100644 tests/Nazara/Math/Plane.hpp create mode 100644 tests/Nazara/Math/Plane.inl diff --git a/tests/Nazara/Math/Plane.cpp b/tests/Nazara/Math/Plane.cpp new file mode 100644 index 000000000..59db2ef29 --- /dev/null +++ b/tests/Nazara/Math/Plane.cpp @@ -0,0 +1,75 @@ +#include +#include + +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)); + } + } + } +} diff --git a/tests/Nazara/Math/Plane.hpp b/tests/Nazara/Math/Plane.hpp new file mode 100644 index 000000000..f3971acb1 --- /dev/null +++ b/tests/Nazara/Math/Plane.hpp @@ -0,0 +1,60 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Mathematics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_PLANE_HPP +#define NAZARA_PLANE_HPP + +#include +#include + +template +class NzPlane +{ + public: + NzPlane() = default; + NzPlane(T normalX, T normalY, T normalZ, T Distance); + NzPlane(const T plane[4]); + NzPlane(const NzVector3& Normal, T Distance); + NzPlane(const NzVector3& Normal, const NzVector3& point); + NzPlane(const NzVector3& point1, const NzVector3& point2, const NzVector3& point3); + template explicit NzPlane(const NzPlane& plane); + NzPlane(const NzPlane& plane) = default; + ~NzPlane() = default; + + T Distance(const NzVector3& point) const; + T Distance(T x, T y, T z) const; + + NzPlane& Set(T normalX, T normalY, T normalZ, T Distance); + NzPlane& Set(const T plane[4]); + NzPlane& Set(const NzPlane& plane); + NzPlane& Set(const NzVector3& Normal, T Distance); + NzPlane& Set(const NzVector3& Normal, const NzVector3& point); + NzPlane& Set(const NzVector3& point1, const NzVector3& point2, const NzVector3& point3); + template NzPlane& Set(const NzPlane& plane); + + 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(); + static NzPlane YZ(); + + NzVector3 normal; + T distance; +}; + +template +std::ostream& operator<<(std::ostream& out, const NzPlane& plane); + +typedef NzPlane NzPlaned; +typedef NzPlane NzPlanef; + +#include + +#endif // NAZARA_PLANE_HPP diff --git a/tests/Nazara/Math/Plane.inl b/tests/Nazara/Math/Plane.inl new file mode 100644 index 000000000..834435085 --- /dev/null +++ b/tests/Nazara/Math/Plane.inl @@ -0,0 +1,193 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Mathematics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +#define F(a) static_cast(a) + +template +NzPlane::NzPlane(T normalX, T normalY, T normalZ, T D) +{ + Set(normalX, normalY, normalZ, D); +} + +template +NzPlane::NzPlane(const T plane[4]) +{ + Set(plane); +} + +template +NzPlane::NzPlane(const NzVector3& Normal, T D) +{ + Set(Normal, D); +} + +template +NzPlane::NzPlane(const NzVector3& Normal, const NzVector3& point) +{ + Set(Normal, point); +} + +template +NzPlane::NzPlane(const NzVector3& point1, const NzVector3& point2, const NzVector3& point3) +{ + Set(point1, point2, point3); +} + +template +template +NzPlane::NzPlane(const NzPlane& plane) +{ + Set(plane); +} + +template +T NzPlane::Distance(const NzVector3& point) const +{ + return normal.DotProduct(point) - distance; // ax + by + cd - d = 0. +} + +template +T NzPlane::Distance(T x, T y, T z) const +{ + return Distance(NzVector3(x, y, z)); +} + +template +NzPlane& NzPlane::Set(T normalX, T normalY, T normalZ, T D) +{ + distance = D; + normal.Set(normalX, normalY, normalZ); + + return *this; +} + +template +NzPlane& NzPlane::Set(const T plane[4]) +{ + normal.Set(plane[0], plane[1], plane[2]); + distance = plane[3]; + + return *this; +} + +template +NzPlane& NzPlane::Set(const NzPlane& plane) +{ + std::memcpy(this, &plane, sizeof(NzPlane)); + + return *this; +} + +template +NzPlane& NzPlane::Set(const NzVector3& Normal, T D) +{ + distance = D; + normal = Normal; + + return *this; +} + +template +NzPlane& NzPlane::Set(const NzVector3& Normal, const NzVector3& point) +{ + normal = Normal; + distance = -normal.DotProduct(point); + + return *this; +} + +template +NzPlane& NzPlane::Set(const NzVector3& point1, const NzVector3& point2, const NzVector3& point3) +{ + NzVector3 edge1 = point2 - point1; + NzVector3 edge2 = point3 - point1; + normal = edge1.CrossProduct(edge2); + normal.Normalize(); + + distance = normal.DotProduct(point3); + + return *this; +} + +template +template +NzPlane& NzPlane::Set(const NzPlane& plane) +{ + normal.Set(plane.normal); + distance = F(plane.distance); + + return *this; +} + +template +NzString NzPlane::ToString() const +{ + NzStringStream ss; + + return ss << "Plane(Normal: " << normal.ToString() << "; Distance: " << distance << ')'; +} + +template +bool NzPlane::operator==(const NzPlane& plane) const +{ + return (normal == plane.normal && NzNumberEquals(distance, plane.distance)) || (normal == -plane.normal && NzNumberEquals(distance, -plane.distance)); +} + +template +bool NzPlane::operator!=(const NzPlane& plane) const +{ + return !operator==(plane); +} + +template +NzPlane NzPlane::Lerp(const NzPlane& from, const NzPlane& to, T interpolation) +{ + #ifdef NAZARA_DEBUG + if (interpolation < F(0.0) || interpolation > F(1.0)) + { + NazaraError("Interpolation must be in range [0..1] (Got " + NzString::Number(interpolation) + ')'); + return NzPlane(); + } + #endif + + NzPlane plane; + plane.distance = NzLerp(from.distance, to.distance, interpolation); + plane.normal = NzVector3::Lerp(from.normal, to.normal, interpolation); + plane.normal.Normalize(); + + return plane; +} + +template +NzPlane NzPlane::XY() +{ + return NzPlane(F(0.0), F(0.0), F(1.0), F(0.0)); +} + +template +NzPlane NzPlane::XZ() +{ + return NzPlane(F(0.0), F(1.0), F(0.0), F(0.0)); +} + +template +NzPlane NzPlane::YZ() +{ + return NzPlane(F(1.0), F(0.0), F(0.0), F(0.0)); +} + +template +std::ostream& operator<<(std::ostream& out, const NzPlane& plane) +{ + return out << plane.ToString(); +} + +#undef F + +#include From 282bdf98647498bf0f554e819fd22de06b4732f0 Mon Sep 17 00:00:00 2001 From: Gawaboumga Date: Fri, 21 Aug 2015 12:01:52 +0200 Subject: [PATCH 13/20] Consequences of the plane change + change perspective The perspective matrix now as in glm (because the near frustum plane was wrong). So there is a factor "2" on the component w and the skybox must be changed in consequence. Former-commit-id: 09dd049c177532b9ace34a5a60b1b96014652297 --- include/Nazara/Math/Frustum.inl | 17 +- include/Nazara/Math/Matrix4.inl | 45 ++- src/Nazara/Graphics/SkyboxBackground.cpp | 6 +- tests/Nazara/Math/Frustum.cpp | 82 +++++ tests/Nazara/Math/Matrix4.cpp | 134 +++++++ tests/Nazara/Math/Ray.cpp | 95 +++++ tests/Nazara/Math/Ray.hpp | 78 ++++ tests/Nazara/Math/Ray.inl | 443 +++++++++++++++++++++++ 8 files changed, 865 insertions(+), 35 deletions(-) create mode 100644 tests/Nazara/Math/Frustum.cpp create mode 100644 tests/Nazara/Math/Matrix4.cpp create mode 100644 tests/Nazara/Math/Ray.cpp create mode 100644 tests/Nazara/Math/Ray.hpp create mode 100644 tests/Nazara/Math/Ray.inl diff --git a/include/Nazara/Math/Frustum.inl b/include/Nazara/Math/Frustum.inl index fbdbdbdcc..45f8cc98d 100644 --- a/include/Nazara/Math/Frustum.inl +++ b/include/Nazara/Math/Frustum.inl @@ -180,7 +180,7 @@ NzFrustum& NzFrustum::Extract(const NzMatrix4& 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& NzFrustum::Extract(const NzMatrix4& 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& NzFrustum::Extract(const NzMatrix4& 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& NzFrustum::Extract(const NzMatrix4& 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& NzFrustum::Extract(const NzMatrix4& 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& NzFrustum::Extract(const NzMatrix4& 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& NzFrustum::Extract(const NzMatrix4& clipMatrix) template NzFrustum& NzFrustum::Extract(const NzMatrix4& view, const NzMatrix4& projection) { - NzMatrix4 clipMatrix(view); - clipMatrix *= projection; - - return Extract(clipMatrix); + return Extract(NzMatrix4::Concatenate(view, projection)); } template diff --git a/include/Nazara/Math/Matrix4.inl b/include/Nazara/Math/Matrix4.inl index e3d172c32..06f30ae6e 100644 --- a/include/Nazara/Math/Matrix4.inl +++ b/include/Nazara/Math/Matrix4.inl @@ -578,6 +578,21 @@ NzMatrix4& NzMatrix4::MakeIdentity() return *this; } +template +NzMatrix4& NzMatrix4::MakeLookAt(const NzVector3& eye, const NzVector3& target, const NzVector3& up) +{ + NzVector3 f = NzVector3::Normalize(target - eye); + NzVector3 s = NzVector3::Normalize(f.CrossProduct(up)); + NzVector3 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 NzMatrix4& NzMatrix4::MakeOrtho(T left, T right, T top, T bottom, T zNear, T zFar) { @@ -590,22 +605,6 @@ NzMatrix4& NzMatrix4::MakeOrtho(T left, T right, T top, T bottom, T zNear, return *this; } -template -NzMatrix4& NzMatrix4::MakeLookAt(const NzVector3& eye, const NzVector3& target, const NzVector3& up) -{ - NzVector3 f = NzVector3::Normalize(target - eye); - NzVector3 u(up.GetNormal()); - NzVector3 s = NzVector3::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 NzMatrix4& NzMatrix4::MakePerspective(T angle, T ratio, T zNear, T zFar) { @@ -616,12 +615,12 @@ NzMatrix4& NzMatrix4::MakePerspective(T angle, T ratio, T zNear, T zFar) angle = NzDegreeToRadian(angle/F(2.0)); #endif - T yScale = F(1.0) / std::tan(angle); + T yScale = std::tan(M_PI_2 - angle); Set(yScale / ratio, F(0.0), F(0.0), F(0.0), 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; } @@ -696,7 +695,7 @@ NzMatrix4& NzMatrix4::MakeViewMatrix(const NzVector3& translation, cons // Une matrice de vue doit appliquer une transformation opposée à la matrice "monde" NzQuaternion invRot = rotation.GetConjugate(); // Inverse de la rotation - return MakeTransform(-(invRot*translation), invRot); + return MakeTransform(-(invRot * translation), invRot); } template @@ -821,9 +820,9 @@ NzString NzMatrix4::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 diff --git a/src/Nazara/Graphics/SkyboxBackground.cpp b/src/Nazara/Graphics/SkyboxBackground.cpp index ba806d76b..a2345734b 100644 --- a/src/Nazara/Graphics/SkyboxBackground.cpp +++ b/src/Nazara/Graphics/SkyboxBackground.cpp @@ -86,7 +86,8 @@ namespace "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"; @@ -101,7 +102,8 @@ namespace "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"; diff --git a/tests/Nazara/Math/Frustum.cpp b/tests/Nazara/Math/Frustum.cpp new file mode 100644 index 000000000..ae13afe7b --- /dev/null +++ b/tests/Nazara/Math/Frustum.cpp @@ -0,0 +1,82 @@ +#include +#include + +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)); + } + } + } +} diff --git a/tests/Nazara/Math/Matrix4.cpp b/tests/Nazara/Math/Matrix4.cpp new file mode 100644 index 000000000..ea61e4541 --- /dev/null +++ b/tests/Nazara/Math/Matrix4.cpp @@ -0,0 +1,134 @@ +#include +#include + +SCENARIO("Matrix4", "[MATH][MATRIX4]") +{ + GIVEN("Two identity matrix") + { + NzMatrix4f firstIdentity(NzMatrix4::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); + } + } + } +} diff --git a/tests/Nazara/Math/Ray.cpp b/tests/Nazara/Math/Ray.cpp new file mode 100644 index 000000000..3b7c4648c --- /dev/null +++ b/tests/Nazara/Math/Ray.cpp @@ -0,0 +1,95 @@ +#include +#include + +SCENARIO("Ray", "[RAY]") +{ + GIVEN("Two same rays (0, 0, 0) -> (0, 1, 0)") + { + NzRayf firstRay(NzRay(NzPlane::XY(), NzPlane::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)); + } + + } + } +} diff --git a/tests/Nazara/Math/Ray.hpp b/tests/Nazara/Math/Ray.hpp new file mode 100644 index 000000000..24b25e110 --- /dev/null +++ b/tests/Nazara/Math/Ray.hpp @@ -0,0 +1,78 @@ +// Copyright (C) 2015 Gawaboumga (https://github.com/Gawaboumga) - Jérôme Leclercq +// This file is part of the "Nazara Engine - Mathematics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_RAY_HPP +#define NAZARA_RAY_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +template +class NzRay +{ + public: + NzRay() = default; + NzRay(T X, T Y, T Z, T directionX, T directionY, T directionZ); + NzRay(const T origin[3], const T direction[3]); + NzRay(const NzPlane& planeOne, const NzPlane& planeTwo); + NzRay(const NzVector3& origin, const NzVector3& direction); + template explicit NzRay(const NzRay& ray); + template explicit NzRay(const NzVector3& origin, const NzVector3& direction); + NzRay(const NzRay& ray) = default; + ~NzRay() = default; + + T ClosestPoint(const NzVector3& point) const; + + NzVector3 GetPoint(T lambda) const; + + bool Intersect(const NzBoundingVolume& volume, T* closestHit = nullptr, T* furthestHit = nullptr) const; + bool Intersect(const NzBox& box, T* closestHit = nullptr, T* furthestHit = nullptr) const; + bool Intersect(const NzBox& box, const NzMatrix4& transform, T* closestHit = nullptr, T* furthestHit = nullptr) const; + bool Intersect(const NzOrientedBox& orientedBox, T* closestHit = nullptr, T* furthestHit = nullptr) const; + bool Intersect(const NzPlane& plane, T* hit = nullptr) const; + bool Intersect(const NzSphere& sphere, T* closestHit = nullptr, T* furthestHit = nullptr) const; + + NzRay& MakeAxisX(); + NzRay& MakeAxisY(); + NzRay& MakeAxisZ(); + + NzRay& Set(T X, T Y, T Z, T directionX, T directionY, T directionZ); + NzRay& Set(const T origin[3], const T direction[3]); + NzRay& Set(const NzPlane& planeOne, const NzPlane& planeTwo); + NzRay& Set(const NzRay& ray); + NzRay& Set(const NzVector3& origin, const NzVector3& direction); + template NzRay& Set(const NzRay& ray); + template NzRay& Set(const NzVector3& origin, const NzVector3& direction); + + NzString ToString() const; + + NzVector3 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(); + static NzRay Lerp(const NzRay& from, const NzRay& to, T interpolation); + + NzVector3 direction, origin; +}; + +template std::ostream& operator<<(std::ostream& out, const NzRay& vec); + +typedef NzRay NzRayd; +typedef NzRay NzRayf; + +#include + +#endif // NAZARA_RAY_HPP diff --git a/tests/Nazara/Math/Ray.inl b/tests/Nazara/Math/Ray.inl new file mode 100644 index 000000000..d0ee2d76c --- /dev/null +++ b/tests/Nazara/Math/Ray.inl @@ -0,0 +1,443 @@ +// Copyright (C) 2015 Gawaboumga (https://github.com/Gawaboumga) - Jérôme Leclercq +// This file is part of the "Nazara Engine - Mathematics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +#define F(a) static_cast(a) + +template +NzRay::NzRay(T X, T Y, T Z, T DirectionX, T DirectionY, T DirectionZ) +{ + Set(X, Y, Z, DirectionX, DirectionY, DirectionZ); +} + +template +NzRay::NzRay(const T Origin[3], const T Direction[3]) +{ + Set(Origin, Direction); +} + +template +NzRay::NzRay(const NzPlane& planeOne, const NzPlane& planeTwo) +{ + Set(planeOne, planeTwo); +} + +template +NzRay::NzRay(const NzVector3& Origin, const NzVector3& Direction) +{ + Set(Origin, Direction); +} + +template +template +NzRay::NzRay(const NzRay& ray) +{ + Set(ray); +} + +template +template +NzRay::NzRay(const NzVector3& Origin, const NzVector3& Direction) +{ + Set(Origin, Direction); +} + +template +T NzRay::ClosestPoint(const NzVector3& point) const +{ + NzVector3 delta = point - origin; + T vsq = direction.GetSquaredLength(); + T proj = delta.DotProduct(direction); + + return proj/vsq; +} + +template +NzVector3 NzRay::GetPoint(T lambda) const +{ + return origin + lambda * direction; +} + +template +bool NzRay::Intersect(const NzBoundingVolume& volume, T* closestHit, T* furthestHit) const +{ + switch (volume.extend) + { + case nzExtend_Finite: + { + if (Intersect(volume.aabb)) + return Intersect(volume.obb, closestHit, furthestHit); + + return false; + } + + case nzExtend_Infinite: + { + if (closestHit) + *closestHit = F(0.0); + + if (furthestHit) + *furthestHit = std::numeric_limits::infinity(); + + return true; + } + + case nzExtend_Null: + return false; + } + + NazaraError("Invalid extend type (0x" + NzString::Number(volume.extend, 16) + ')'); + return false; +} + +template +bool NzRay::Intersect(const NzBox& box, T* closestHit, T* furthestHit) const +{ + // http://www.gamedev.net/topic/429443-obb-ray-and-obb-plane-intersection/ + T tfirst = F(0.0); + T tlast = std::numeric_limits::infinity(); + + NzVector3 boxMin = box.GetMinimum(); + NzVector3 boxMax = box.GetMaximum(); + + for (unsigned int i = 0; i < 3; ++i) + { + T dir = direction[i]; + T ori = origin[i]; + T max = boxMax[i]; + T min = boxMin[i]; + + if (NzNumberEquals(dir, F(0.0))) + { + if (ori < max && ori > min) + continue; + + return false; + } + + T tmin = (min - ori) / dir; + T tmax = (max - ori) / dir; + if (tmin > tmax) + std::swap(tmin, tmax); + + if (tmax < tfirst || tmin > tlast) + return false; + + tfirst = std::max(tfirst, tmin); + tlast = std::min(tlast, tmax); + } + + if (closestHit) + *closestHit = tfirst; + + if (furthestHit) + *furthestHit = tlast; + + return true; +} + +template +bool NzRay::Intersect(const NzBox& box, const NzMatrix4& transform, T* closestHit, T* furthestHit) const +{ + // http://www.opengl-tutorial.org/miscellaneous/clicking-on-objects/picking-with-custom-ray-obb-function/ + // Intersection method from Real-Time Rendering and Essential Mathematics for Games + T tMin = F(0.0); + T tMax = std::numeric_limits::infinity(); + + NzVector3 boxMin = box.GetMinimum(); + NzVector3 boxMax = box.GetMaximum(); + NzVector3 delta = transform.GetTranslation() - origin; + + // Test intersection with the 2 planes perpendicular to the OBB's X axis + for (unsigned int i = 0; i < 3; ++i) + { + NzVector3 axis(transform(0, i), transform(1, i), transform(2, i)); + T e = axis.DotProduct(delta); + T f = direction.DotProduct(axis); + + if (!NzNumberEquals(f, F(0.0))) + { + T t1 = (e + boxMin[i]) / f; // Intersection with the "left" plane + T t2 = (e + boxMax[i]) / f; // Intersection with the "right" plane + // t1 and t2 now contain distances betwen ray origin and ray-plane intersections + + // We want t1 to represent the nearest intersection, + // so if it's not the case, invert t1 and t2 + if (t1 > t2) + std::swap(t1, t2); + + // tMax is the nearest "far" intersection (amongst the X,Y and Z planes pairs) + if (t2 < tMax) + tMax = t2; + + // tMin is the farthest "near" intersection (amongst the X,Y and Z planes pairs) + if (t1 > tMin) + tMin = t1; + + // And here's the trick : + // If "far" is closer than "near", then there is NO intersection. + if (tMax < tMin) + return false; + } + else + // Rare case : the ray is almost parallel to the planes, so they don't have any "intersection" + if (-e + boxMin[i] > F(0.0) || -e + boxMax[i] < F(0.0)) + return false; + } + + if (closestHit) + *closestHit = tMin; + + if (furthestHit) + *furthestHit = tMax; + + return true; +} + +template +bool NzRay::Intersect(const NzOrientedBox& orientedBox, T* closestHit, T* furthestHit) const +{ + NzVector3 corner = orientedBox.GetCorner(nzBoxCorner_FarLeftBottom); + NzVector3 oppositeCorner = orientedBox.GetCorner(nzBoxCorner_NearRightTop); + + NzVector3 width = (orientedBox.GetCorner(nzBoxCorner_NearLeftBottom) - corner); + NzVector3 height = (orientedBox.GetCorner(nzBoxCorner_FarLeftTop) - corner); + NzVector3 depth = (orientedBox.GetCorner(nzBoxCorner_FarRightBottom) - corner); + + // Construction de la matrice de transformation de l'OBB + NzMatrix4 matrix(width.x, height.x, depth.x, corner.x, + width.y, height.y, depth.y, corner.y, + width.z, height.z, depth.z, corner.z, + F(0.0), F(0.0), F(0.0), F(1.0)); + + matrix.InverseAffine(); + + corner = matrix.Transform(corner); + oppositeCorner = matrix.Transform(oppositeCorner); + + NzBox tmpBox(corner, oppositeCorner); + NzRay tmpRay(matrix.Transform(origin), matrix.Transform(direction)); + + return tmpRay.Intersect(tmpBox, closestHit, furthestHit); +} + +template +bool NzRay::Intersect(const NzPlane& plane, T* hit) const +{ + T divisor = plane.normal.DotProduct(direction); + if (NzNumberEquals(divisor, F(0.0))) + return false; // perpendicular + + T lambda = -(plane.normal.DotProduct(origin) - plane.distance) / divisor; // The plane is ax + by + cz = d + if (lambda < F(0.0)) + return false; // The plane is 'behind' the ray. + + if (hit) + *hit = lambda; + + return true; +} + +template +bool NzRay::Intersect(const NzSphere& sphere, T* closestHit, T* furthestHit) const +{ + NzVector3 sphereRay = sphere.GetPosition() - origin; + T length = sphereRay.DotProduct(direction); + + if (length < F(0.0)) + return false; // ray is perpendicular to the vector origin - center + + T squaredDistance = sphereRay.GetSquaredLength() - length*length; + T squaredRadius = sphere.radius*sphere.radius; + + if (squaredDistance > squaredRadius) + return false; // if the ray is further than the radius + + // Calcul des points d'intersection si besoin + if (closestHit || furthestHit) + { + T deltaLambda = std::sqrt(squaredRadius - squaredDistance); + + if (closestHit) + *closestHit = length - deltaLambda; + + if (furthestHit) + *furthestHit = length + deltaLambda; + } + + return true; +} + +template +NzRay& NzRay::MakeAxisX() +{ + return Set(NzVector3::Zero(), NzVector3::UnitX()); +} + +template +NzRay& NzRay::MakeAxisY() +{ + return Set(NzVector3::Zero(), NzVector3::UnitY()); +} + +template +NzRay& NzRay::MakeAxisZ() +{ + return Set(NzVector3::Zero(), NzVector3::UnitZ()); +} + +template +NzRay& NzRay::Set(T X, T Y, T Z, T directionX, T directionY, T directionZ) +{ + direction.Set(directionX, directionY, directionZ); + origin.Set(X, Y, Z); + + return *this; +} + +template +NzRay& NzRay::Set(const T Origin[3], const T Direction[3]) +{ + direction.Set(Direction); + origin.Set(Origin); + + return *this; +} + +template +NzRay& NzRay::Set(const NzPlane& planeOne, const NzPlane& planeTwo) +{ + T termOne = planeOne.normal.GetLength(); + T termTwo = planeOne.normal.DotProduct(planeTwo.normal); + T termFour = planeTwo.normal.GetLength(); + T det = termOne * termFour - termTwo * termTwo; + + #if NAZARA_MATH_SAFE + if (NzNumberEquals(det, F(0.0))) + { + NzString error("Planes are parallel."); + + NazaraError(error); + throw std::domain_error(error); + } + #endif + + T invdet = F(1.0) / det; + T fc0 = (termFour * -planeOne.distance + termTwo * planeTwo.distance) * invdet; + T fc1 = (termOne * -planeTwo.distance + termTwo * planeOne.distance) * invdet; + + direction = planeOne.normal.CrossProduct(planeTwo.normal); + origin = planeOne.normal * fc0 + planeTwo.normal * fc1; + + return *this; +} + +template +NzRay& NzRay::Set(const NzRay& ray) +{ + std::memcpy(this, &ray, sizeof(NzRay)); + + return *this; +} + +template +NzRay& NzRay::Set(const NzVector3& Origin, const NzVector3& Direction) +{ + direction = Direction; + origin = Origin; + + return *this; +} + +template +template +NzRay& NzRay::Set(const NzRay& ray) +{ + direction.Set(ray.direction); + origin.Set(ray.origin); + + return *this; +} + +template +template +NzRay& NzRay::Set(const NzVector3& Origin, const NzVector3& Direction) +{ + direction.Set(Direction); + origin.Set(Origin); + + return *this; +} + +template +NzString NzRay::ToString() const +{ + NzStringStream ss; + + return ss << "Ray(origin: " << origin.ToString() << ", direction: " << direction.ToString() << ")"; +} + +template +NzVector3 NzRay::operator*(T lambda) const +{ + return GetPoint(lambda); +} + +template +bool NzRay::operator==(const NzRay& ray) const +{ + return direction == ray.direction && origin == ray.origin; +} + +template +bool NzRay::operator!=(const NzRay& ray) const +{ + return !operator==(ray); +} + +template +NzRay NzRay::AxisX() +{ + NzRay axis; + axis.MakeAxisX(); + + return axis; +} + +template +NzRay NzRay::AxisY() +{ + NzRay axis; + axis.MakeAxisY(); + + return axis; +} + +template +NzRay NzRay::AxisZ() +{ + NzRay axis; + axis.MakeAxisZ(); + + return axis; +} + +template +NzRay NzRay::Lerp(const NzRay& from, const NzRay& to, T interpolation) +{ + return NzRay(from.origin.Lerp(to.origin, interpolation), from.direction.Lerp(to.direction, interpolation)); +} + +template +std::ostream& operator<<(std::ostream& out, const NzRay& ray) +{ + return out << ray.ToString(); +} + +#undef F + +#include From 9d7dc63574f638cb05947bc90473b7f48c4ff223 Mon Sep 17 00:00:00 2001 From: Gawaboumga Date: Fri, 21 Aug 2015 12:02:55 +0200 Subject: [PATCH 14/20] Wrong place Former-commit-id: 909750e9bca284c2a0096a51c782c1083b258cef --- include/Nazara/Math/Plane.hpp | 3 + include/Nazara/Math/Plane.inl | 22 +- include/Nazara/Math/Ray.hpp | 13 +- include/Nazara/Math/Ray.inl | 83 ++++--- tests/Nazara/Math/Plane.hpp | 60 ----- tests/Nazara/Math/Plane.inl | 193 --------------- tests/Nazara/Math/Ray.hpp | 78 ------ tests/Nazara/Math/Ray.inl | 443 ---------------------------------- 8 files changed, 79 insertions(+), 816 deletions(-) delete mode 100644 tests/Nazara/Math/Plane.hpp delete mode 100644 tests/Nazara/Math/Plane.inl delete mode 100644 tests/Nazara/Math/Ray.hpp delete mode 100644 tests/Nazara/Math/Ray.inl diff --git a/include/Nazara/Math/Plane.hpp b/include/Nazara/Math/Plane.hpp index f2c428bde..f3971acb1 100644 --- a/include/Nazara/Math/Plane.hpp +++ b/include/Nazara/Math/Plane.hpp @@ -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(); diff --git a/include/Nazara/Math/Plane.inl b/include/Nazara/Math/Plane.inl index 10ece793d..834435085 100644 --- a/include/Nazara/Math/Plane.inl +++ b/include/Nazara/Math/Plane.inl @@ -49,7 +49,7 @@ NzPlane::NzPlane(const NzPlane& plane) template T NzPlane::Distance(const NzVector3& point) const { - return normal.DotProduct(point) + distance; + return normal.DotProduct(point) - distance; // ax + by + cd - d = 0. } template @@ -110,7 +110,7 @@ NzPlane& NzPlane::Set(const NzVector3& point1, const NzVector3& poin normal = edge1.CrossProduct(edge2); normal.Normalize(); - distance = -normal.DotProduct(point3); + distance = normal.DotProduct(point3); return *this; } @@ -133,6 +133,18 @@ NzString NzPlane::ToString() const return ss << "Plane(Normal: " << normal.ToString() << "; Distance: " << distance << ')'; } +template +bool NzPlane::operator==(const NzPlane& plane) const +{ + return (normal == plane.normal && NzNumberEquals(distance, plane.distance)) || (normal == -plane.normal && NzNumberEquals(distance, -plane.distance)); +} + +template +bool NzPlane::operator!=(const NzPlane& plane) const +{ + return !operator==(plane); +} + template NzPlane NzPlane::Lerp(const NzPlane& from, const NzPlane& to, T interpolation) { @@ -155,19 +167,19 @@ NzPlane NzPlane::Lerp(const NzPlane& from, const NzPlane& to, T interpolat template NzPlane NzPlane::XY() { - return NzPlane(F(0.0), F(0.0), F(1.0), F(0.0)); + return NzPlane(F(0.0), F(0.0), F(1.0), F(0.0)); } template NzPlane NzPlane::XZ() { - return NzPlane(F(0.0), F(1.0), F(0.0), F(0.0)); + return NzPlane(F(0.0), F(1.0), F(0.0), F(0.0)); } template NzPlane NzPlane::YZ() { - return NzPlane(F(1.0), F(0.0), F(0.0), F(0.0)); + return NzPlane(F(1.0), F(0.0), F(0.0), F(0.0)); } template diff --git a/include/Nazara/Math/Ray.hpp b/include/Nazara/Math/Ray.hpp index e1cc40829..24b25e110 100644 --- a/include/Nazara/Math/Ray.hpp +++ b/include/Nazara/Math/Ray.hpp @@ -34,12 +34,12 @@ class NzRay NzVector3 GetPoint(T lambda) const; - //bool Intersect(const NzBoundingVolume& volume, T* closestHit = nullptr, T* farthestHit = nullptr) const; - bool Intersect(const NzBox& box, T* closestHit = nullptr, T* farthestHit = nullptr) const; - bool Intersect(const NzBox& box, const NzMatrix4& transform, T* closestHit = nullptr, T* farthestHit = nullptr) const; - //bool Intersect(const NzOrientedBox& orientedBox, T* closestHit = nullptr, T* farthestHit = nullptr) const; + bool Intersect(const NzBoundingVolume& volume, T* closestHit = nullptr, T* furthestHit = nullptr) const; + bool Intersect(const NzBox& box, T* closestHit = nullptr, T* furthestHit = nullptr) const; + bool Intersect(const NzBox& box, const NzMatrix4& transform, T* closestHit = nullptr, T* furthestHit = nullptr) const; + bool Intersect(const NzOrientedBox& orientedBox, T* closestHit = nullptr, T* furthestHit = nullptr) const; bool Intersect(const NzPlane& plane, T* hit = nullptr) const; - bool Intersect(const NzSphere& sphere, T* closestHit = nullptr, T* farthestHit = nullptr) const; + bool Intersect(const NzSphere& sphere, T* closestHit = nullptr, T* furthestHit = nullptr) const; NzRay& MakeAxisX(); NzRay& MakeAxisY(); @@ -57,6 +57,9 @@ class NzRay NzVector3 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(); diff --git a/include/Nazara/Math/Ray.inl b/include/Nazara/Math/Ray.inl index 6ee22ad4e..d0ee2d76c 100644 --- a/include/Nazara/Math/Ray.inl +++ b/include/Nazara/Math/Ray.inl @@ -59,18 +59,18 @@ T NzRay::ClosestPoint(const NzVector3& point) const template NzVector3 NzRay::GetPoint(T lambda) const { - return origin + lambda*direction; + return origin + lambda * direction; } -/* + template -bool NzRay::Intersect(const NzBoundingVolume& volume, T* closestHit, T* farthestHit) const +bool NzRay::Intersect(const NzBoundingVolume& 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::Intersect(const NzBoundingVolume& volume, T* closestHit, T* fa if (closestHit) *closestHit = F(0.0); - if (farthestHit) - *farthestHit = std::numeric_limits::infinity(); + if (furthestHit) + *furthestHit = std::numeric_limits::infinity(); return true; } @@ -93,9 +93,9 @@ bool NzRay::Intersect(const NzBoundingVolume& volume, T* closestHit, T* fa NazaraError("Invalid extend type (0x" + NzString::Number(volume.extend, 16) + ')'); return false; } -*/ + template -bool NzRay::Intersect(const NzBox& box, T* closestHit, T* farthestHit) const +bool NzRay::Intersect(const NzBox& 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::Intersect(const NzBox& box, T* closestHit, T* farthestHit) con if (closestHit) *closestHit = tfirst; - if (farthestHit) - *farthestHit = tlast; + if (furthestHit) + *furthestHit = tlast; return true; } template -bool NzRay::Intersect(const NzBox& box, const NzMatrix4& transform, T* closestHit, T* farthestHit) const +bool NzRay::Intersect(const NzBox& box, const NzMatrix4& 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::Intersect(const NzBox& box, const NzMatrix4& 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 -bool NzRay::Intersect(const NzOrientedBox& orientedBox, T* closestHit, T* farthestHit) const +bool NzRay::Intersect(const NzOrientedBox& orientedBox, T* closestHit, T* furthestHit) const { - NzVector3 width = (orientedBox.GetCorner(nzBoxCorner_NearLeftBottom) - orientedBox.GetCorner(nzBoxCorner_FarLeftBottom)).Normalize(); - NzVector3 height = (orientedBox.GetCorner(nzBoxCorner_FarLeftTop) - orientedBox.GetCorner(nzBoxCorner_FarLeftBottom)).Normalize(); - NzVector3 depth = (orientedBox.GetCorner(nzBoxCorner_FarRightBottom) - orientedBox.GetCorner(nzBoxCorner_FarLeftBottom)).Normalize(); + NzVector3 corner = orientedBox.GetCorner(nzBoxCorner_FarLeftBottom); + NzVector3 oppositeCorner = orientedBox.GetCorner(nzBoxCorner_NearRightTop); + + NzVector3 width = (orientedBox.GetCorner(nzBoxCorner_NearLeftBottom) - corner); + NzVector3 height = (orientedBox.GetCorner(nzBoxCorner_FarLeftTop) - corner); + NzVector3 depth = (orientedBox.GetCorner(nzBoxCorner_FarRightBottom) - corner); // Construction de la matrice de transformation de l'OBB - NzMatrix4 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 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 tmpBox(corner, oppositeCorner); + NzRay tmpRay(matrix.Transform(origin), matrix.Transform(direction)); + + return tmpRay.Intersect(tmpBox, closestHit, furthestHit); } -*/ + template bool NzRay::Intersect(const NzPlane& plane, T* hit) const { @@ -225,9 +232,9 @@ bool NzRay::Intersect(const NzPlane& 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::Intersect(const NzPlane& plane, T* hit) const } template -bool NzRay::Intersect(const NzSphere& sphere, T* closestHit, T* farthestHit) const +bool NzRay::Intersect(const NzSphere& sphere, T* closestHit, T* furthestHit) const { NzVector3 sphereRay = sphere.GetPosition() - origin; T length = sphereRay.DotProduct(direction); @@ -251,15 +258,15 @@ bool NzRay::Intersect(const NzSphere& 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 NzRay::operator*(T lambda) const return GetPoint(lambda); } +template +bool NzRay::operator==(const NzRay& ray) const +{ + return direction == ray.direction && origin == ray.origin; +} + +template +bool NzRay::operator!=(const NzRay& ray) const +{ + return !operator==(ray); +} + template NzRay NzRay::AxisX() { diff --git a/tests/Nazara/Math/Plane.hpp b/tests/Nazara/Math/Plane.hpp deleted file mode 100644 index f3971acb1..000000000 --- a/tests/Nazara/Math/Plane.hpp +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Mathematics module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_PLANE_HPP -#define NAZARA_PLANE_HPP - -#include -#include - -template -class NzPlane -{ - public: - NzPlane() = default; - NzPlane(T normalX, T normalY, T normalZ, T Distance); - NzPlane(const T plane[4]); - NzPlane(const NzVector3& Normal, T Distance); - NzPlane(const NzVector3& Normal, const NzVector3& point); - NzPlane(const NzVector3& point1, const NzVector3& point2, const NzVector3& point3); - template explicit NzPlane(const NzPlane& plane); - NzPlane(const NzPlane& plane) = default; - ~NzPlane() = default; - - T Distance(const NzVector3& point) const; - T Distance(T x, T y, T z) const; - - NzPlane& Set(T normalX, T normalY, T normalZ, T Distance); - NzPlane& Set(const T plane[4]); - NzPlane& Set(const NzPlane& plane); - NzPlane& Set(const NzVector3& Normal, T Distance); - NzPlane& Set(const NzVector3& Normal, const NzVector3& point); - NzPlane& Set(const NzVector3& point1, const NzVector3& point2, const NzVector3& point3); - template NzPlane& Set(const NzPlane& plane); - - 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(); - static NzPlane YZ(); - - NzVector3 normal; - T distance; -}; - -template -std::ostream& operator<<(std::ostream& out, const NzPlane& plane); - -typedef NzPlane NzPlaned; -typedef NzPlane NzPlanef; - -#include - -#endif // NAZARA_PLANE_HPP diff --git a/tests/Nazara/Math/Plane.inl b/tests/Nazara/Math/Plane.inl deleted file mode 100644 index 834435085..000000000 --- a/tests/Nazara/Math/Plane.inl +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Mathematics module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include - -#define F(a) static_cast(a) - -template -NzPlane::NzPlane(T normalX, T normalY, T normalZ, T D) -{ - Set(normalX, normalY, normalZ, D); -} - -template -NzPlane::NzPlane(const T plane[4]) -{ - Set(plane); -} - -template -NzPlane::NzPlane(const NzVector3& Normal, T D) -{ - Set(Normal, D); -} - -template -NzPlane::NzPlane(const NzVector3& Normal, const NzVector3& point) -{ - Set(Normal, point); -} - -template -NzPlane::NzPlane(const NzVector3& point1, const NzVector3& point2, const NzVector3& point3) -{ - Set(point1, point2, point3); -} - -template -template -NzPlane::NzPlane(const NzPlane& plane) -{ - Set(plane); -} - -template -T NzPlane::Distance(const NzVector3& point) const -{ - return normal.DotProduct(point) - distance; // ax + by + cd - d = 0. -} - -template -T NzPlane::Distance(T x, T y, T z) const -{ - return Distance(NzVector3(x, y, z)); -} - -template -NzPlane& NzPlane::Set(T normalX, T normalY, T normalZ, T D) -{ - distance = D; - normal.Set(normalX, normalY, normalZ); - - return *this; -} - -template -NzPlane& NzPlane::Set(const T plane[4]) -{ - normal.Set(plane[0], plane[1], plane[2]); - distance = plane[3]; - - return *this; -} - -template -NzPlane& NzPlane::Set(const NzPlane& plane) -{ - std::memcpy(this, &plane, sizeof(NzPlane)); - - return *this; -} - -template -NzPlane& NzPlane::Set(const NzVector3& Normal, T D) -{ - distance = D; - normal = Normal; - - return *this; -} - -template -NzPlane& NzPlane::Set(const NzVector3& Normal, const NzVector3& point) -{ - normal = Normal; - distance = -normal.DotProduct(point); - - return *this; -} - -template -NzPlane& NzPlane::Set(const NzVector3& point1, const NzVector3& point2, const NzVector3& point3) -{ - NzVector3 edge1 = point2 - point1; - NzVector3 edge2 = point3 - point1; - normal = edge1.CrossProduct(edge2); - normal.Normalize(); - - distance = normal.DotProduct(point3); - - return *this; -} - -template -template -NzPlane& NzPlane::Set(const NzPlane& plane) -{ - normal.Set(plane.normal); - distance = F(plane.distance); - - return *this; -} - -template -NzString NzPlane::ToString() const -{ - NzStringStream ss; - - return ss << "Plane(Normal: " << normal.ToString() << "; Distance: " << distance << ')'; -} - -template -bool NzPlane::operator==(const NzPlane& plane) const -{ - return (normal == plane.normal && NzNumberEquals(distance, plane.distance)) || (normal == -plane.normal && NzNumberEquals(distance, -plane.distance)); -} - -template -bool NzPlane::operator!=(const NzPlane& plane) const -{ - return !operator==(plane); -} - -template -NzPlane NzPlane::Lerp(const NzPlane& from, const NzPlane& to, T interpolation) -{ - #ifdef NAZARA_DEBUG - if (interpolation < F(0.0) || interpolation > F(1.0)) - { - NazaraError("Interpolation must be in range [0..1] (Got " + NzString::Number(interpolation) + ')'); - return NzPlane(); - } - #endif - - NzPlane plane; - plane.distance = NzLerp(from.distance, to.distance, interpolation); - plane.normal = NzVector3::Lerp(from.normal, to.normal, interpolation); - plane.normal.Normalize(); - - return plane; -} - -template -NzPlane NzPlane::XY() -{ - return NzPlane(F(0.0), F(0.0), F(1.0), F(0.0)); -} - -template -NzPlane NzPlane::XZ() -{ - return NzPlane(F(0.0), F(1.0), F(0.0), F(0.0)); -} - -template -NzPlane NzPlane::YZ() -{ - return NzPlane(F(1.0), F(0.0), F(0.0), F(0.0)); -} - -template -std::ostream& operator<<(std::ostream& out, const NzPlane& plane) -{ - return out << plane.ToString(); -} - -#undef F - -#include diff --git a/tests/Nazara/Math/Ray.hpp b/tests/Nazara/Math/Ray.hpp deleted file mode 100644 index 24b25e110..000000000 --- a/tests/Nazara/Math/Ray.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (C) 2015 Gawaboumga (https://github.com/Gawaboumga) - Jérôme Leclercq -// This file is part of the "Nazara Engine - Mathematics module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_RAY_HPP -#define NAZARA_RAY_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -template -class NzRay -{ - public: - NzRay() = default; - NzRay(T X, T Y, T Z, T directionX, T directionY, T directionZ); - NzRay(const T origin[3], const T direction[3]); - NzRay(const NzPlane& planeOne, const NzPlane& planeTwo); - NzRay(const NzVector3& origin, const NzVector3& direction); - template explicit NzRay(const NzRay& ray); - template explicit NzRay(const NzVector3& origin, const NzVector3& direction); - NzRay(const NzRay& ray) = default; - ~NzRay() = default; - - T ClosestPoint(const NzVector3& point) const; - - NzVector3 GetPoint(T lambda) const; - - bool Intersect(const NzBoundingVolume& volume, T* closestHit = nullptr, T* furthestHit = nullptr) const; - bool Intersect(const NzBox& box, T* closestHit = nullptr, T* furthestHit = nullptr) const; - bool Intersect(const NzBox& box, const NzMatrix4& transform, T* closestHit = nullptr, T* furthestHit = nullptr) const; - bool Intersect(const NzOrientedBox& orientedBox, T* closestHit = nullptr, T* furthestHit = nullptr) const; - bool Intersect(const NzPlane& plane, T* hit = nullptr) const; - bool Intersect(const NzSphere& sphere, T* closestHit = nullptr, T* furthestHit = nullptr) const; - - NzRay& MakeAxisX(); - NzRay& MakeAxisY(); - NzRay& MakeAxisZ(); - - NzRay& Set(T X, T Y, T Z, T directionX, T directionY, T directionZ); - NzRay& Set(const T origin[3], const T direction[3]); - NzRay& Set(const NzPlane& planeOne, const NzPlane& planeTwo); - NzRay& Set(const NzRay& ray); - NzRay& Set(const NzVector3& origin, const NzVector3& direction); - template NzRay& Set(const NzRay& ray); - template NzRay& Set(const NzVector3& origin, const NzVector3& direction); - - NzString ToString() const; - - NzVector3 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(); - static NzRay Lerp(const NzRay& from, const NzRay& to, T interpolation); - - NzVector3 direction, origin; -}; - -template std::ostream& operator<<(std::ostream& out, const NzRay& vec); - -typedef NzRay NzRayd; -typedef NzRay NzRayf; - -#include - -#endif // NAZARA_RAY_HPP diff --git a/tests/Nazara/Math/Ray.inl b/tests/Nazara/Math/Ray.inl deleted file mode 100644 index d0ee2d76c..000000000 --- a/tests/Nazara/Math/Ray.inl +++ /dev/null @@ -1,443 +0,0 @@ -// Copyright (C) 2015 Gawaboumga (https://github.com/Gawaboumga) - Jérôme Leclercq -// This file is part of the "Nazara Engine - Mathematics module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include - -#define F(a) static_cast(a) - -template -NzRay::NzRay(T X, T Y, T Z, T DirectionX, T DirectionY, T DirectionZ) -{ - Set(X, Y, Z, DirectionX, DirectionY, DirectionZ); -} - -template -NzRay::NzRay(const T Origin[3], const T Direction[3]) -{ - Set(Origin, Direction); -} - -template -NzRay::NzRay(const NzPlane& planeOne, const NzPlane& planeTwo) -{ - Set(planeOne, planeTwo); -} - -template -NzRay::NzRay(const NzVector3& Origin, const NzVector3& Direction) -{ - Set(Origin, Direction); -} - -template -template -NzRay::NzRay(const NzRay& ray) -{ - Set(ray); -} - -template -template -NzRay::NzRay(const NzVector3& Origin, const NzVector3& Direction) -{ - Set(Origin, Direction); -} - -template -T NzRay::ClosestPoint(const NzVector3& point) const -{ - NzVector3 delta = point - origin; - T vsq = direction.GetSquaredLength(); - T proj = delta.DotProduct(direction); - - return proj/vsq; -} - -template -NzVector3 NzRay::GetPoint(T lambda) const -{ - return origin + lambda * direction; -} - -template -bool NzRay::Intersect(const NzBoundingVolume& volume, T* closestHit, T* furthestHit) const -{ - switch (volume.extend) - { - case nzExtend_Finite: - { - if (Intersect(volume.aabb)) - return Intersect(volume.obb, closestHit, furthestHit); - - return false; - } - - case nzExtend_Infinite: - { - if (closestHit) - *closestHit = F(0.0); - - if (furthestHit) - *furthestHit = std::numeric_limits::infinity(); - - return true; - } - - case nzExtend_Null: - return false; - } - - NazaraError("Invalid extend type (0x" + NzString::Number(volume.extend, 16) + ')'); - return false; -} - -template -bool NzRay::Intersect(const NzBox& box, T* closestHit, T* furthestHit) const -{ - // http://www.gamedev.net/topic/429443-obb-ray-and-obb-plane-intersection/ - T tfirst = F(0.0); - T tlast = std::numeric_limits::infinity(); - - NzVector3 boxMin = box.GetMinimum(); - NzVector3 boxMax = box.GetMaximum(); - - for (unsigned int i = 0; i < 3; ++i) - { - T dir = direction[i]; - T ori = origin[i]; - T max = boxMax[i]; - T min = boxMin[i]; - - if (NzNumberEquals(dir, F(0.0))) - { - if (ori < max && ori > min) - continue; - - return false; - } - - T tmin = (min - ori) / dir; - T tmax = (max - ori) / dir; - if (tmin > tmax) - std::swap(tmin, tmax); - - if (tmax < tfirst || tmin > tlast) - return false; - - tfirst = std::max(tfirst, tmin); - tlast = std::min(tlast, tmax); - } - - if (closestHit) - *closestHit = tfirst; - - if (furthestHit) - *furthestHit = tlast; - - return true; -} - -template -bool NzRay::Intersect(const NzBox& box, const NzMatrix4& transform, T* closestHit, T* furthestHit) const -{ - // http://www.opengl-tutorial.org/miscellaneous/clicking-on-objects/picking-with-custom-ray-obb-function/ - // Intersection method from Real-Time Rendering and Essential Mathematics for Games - T tMin = F(0.0); - T tMax = std::numeric_limits::infinity(); - - NzVector3 boxMin = box.GetMinimum(); - NzVector3 boxMax = box.GetMaximum(); - NzVector3 delta = transform.GetTranslation() - origin; - - // Test intersection with the 2 planes perpendicular to the OBB's X axis - for (unsigned int i = 0; i < 3; ++i) - { - NzVector3 axis(transform(0, i), transform(1, i), transform(2, i)); - T e = axis.DotProduct(delta); - T f = direction.DotProduct(axis); - - if (!NzNumberEquals(f, F(0.0))) - { - T t1 = (e + boxMin[i]) / f; // Intersection with the "left" plane - T t2 = (e + boxMax[i]) / f; // Intersection with the "right" plane - // t1 and t2 now contain distances betwen ray origin and ray-plane intersections - - // We want t1 to represent the nearest intersection, - // so if it's not the case, invert t1 and t2 - if (t1 > t2) - std::swap(t1, t2); - - // tMax is the nearest "far" intersection (amongst the X,Y and Z planes pairs) - if (t2 < tMax) - tMax = t2; - - // tMin is the farthest "near" intersection (amongst the X,Y and Z planes pairs) - if (t1 > tMin) - tMin = t1; - - // And here's the trick : - // If "far" is closer than "near", then there is NO intersection. - if (tMax < tMin) - return false; - } - else - // Rare case : the ray is almost parallel to the planes, so they don't have any "intersection" - if (-e + boxMin[i] > F(0.0) || -e + boxMax[i] < F(0.0)) - return false; - } - - if (closestHit) - *closestHit = tMin; - - if (furthestHit) - *furthestHit = tMax; - - return true; -} - -template -bool NzRay::Intersect(const NzOrientedBox& orientedBox, T* closestHit, T* furthestHit) const -{ - NzVector3 corner = orientedBox.GetCorner(nzBoxCorner_FarLeftBottom); - NzVector3 oppositeCorner = orientedBox.GetCorner(nzBoxCorner_NearRightTop); - - NzVector3 width = (orientedBox.GetCorner(nzBoxCorner_NearLeftBottom) - corner); - NzVector3 height = (orientedBox.GetCorner(nzBoxCorner_FarLeftTop) - corner); - NzVector3 depth = (orientedBox.GetCorner(nzBoxCorner_FarRightBottom) - corner); - - // Construction de la matrice de transformation de l'OBB - NzMatrix4 matrix(width.x, height.x, depth.x, corner.x, - width.y, height.y, depth.y, corner.y, - width.z, height.z, depth.z, corner.z, - F(0.0), F(0.0), F(0.0), F(1.0)); - - matrix.InverseAffine(); - - corner = matrix.Transform(corner); - oppositeCorner = matrix.Transform(oppositeCorner); - - NzBox tmpBox(corner, oppositeCorner); - NzRay tmpRay(matrix.Transform(origin), matrix.Transform(direction)); - - return tmpRay.Intersect(tmpBox, closestHit, furthestHit); -} - -template -bool NzRay::Intersect(const NzPlane& plane, T* hit) const -{ - T divisor = plane.normal.DotProduct(direction); - if (NzNumberEquals(divisor, F(0.0))) - return false; // perpendicular - - T lambda = -(plane.normal.DotProduct(origin) - plane.distance) / divisor; // The plane is ax + by + cz = d - if (lambda < F(0.0)) - return false; // The plane is 'behind' the ray. - - if (hit) - *hit = lambda; - - return true; -} - -template -bool NzRay::Intersect(const NzSphere& sphere, T* closestHit, T* furthestHit) const -{ - NzVector3 sphereRay = sphere.GetPosition() - origin; - T length = sphereRay.DotProduct(direction); - - if (length < F(0.0)) - return false; // ray is perpendicular to the vector origin - center - - T squaredDistance = sphereRay.GetSquaredLength() - length*length; - T squaredRadius = sphere.radius*sphere.radius; - - if (squaredDistance > squaredRadius) - return false; // if the ray is further than the radius - - // Calcul des points d'intersection si besoin - if (closestHit || furthestHit) - { - T deltaLambda = std::sqrt(squaredRadius - squaredDistance); - - if (closestHit) - *closestHit = length - deltaLambda; - - if (furthestHit) - *furthestHit = length + deltaLambda; - } - - return true; -} - -template -NzRay& NzRay::MakeAxisX() -{ - return Set(NzVector3::Zero(), NzVector3::UnitX()); -} - -template -NzRay& NzRay::MakeAxisY() -{ - return Set(NzVector3::Zero(), NzVector3::UnitY()); -} - -template -NzRay& NzRay::MakeAxisZ() -{ - return Set(NzVector3::Zero(), NzVector3::UnitZ()); -} - -template -NzRay& NzRay::Set(T X, T Y, T Z, T directionX, T directionY, T directionZ) -{ - direction.Set(directionX, directionY, directionZ); - origin.Set(X, Y, Z); - - return *this; -} - -template -NzRay& NzRay::Set(const T Origin[3], const T Direction[3]) -{ - direction.Set(Direction); - origin.Set(Origin); - - return *this; -} - -template -NzRay& NzRay::Set(const NzPlane& planeOne, const NzPlane& planeTwo) -{ - T termOne = planeOne.normal.GetLength(); - T termTwo = planeOne.normal.DotProduct(planeTwo.normal); - T termFour = planeTwo.normal.GetLength(); - T det = termOne * termFour - termTwo * termTwo; - - #if NAZARA_MATH_SAFE - if (NzNumberEquals(det, F(0.0))) - { - NzString error("Planes are parallel."); - - NazaraError(error); - throw std::domain_error(error); - } - #endif - - T invdet = F(1.0) / det; - T fc0 = (termFour * -planeOne.distance + termTwo * planeTwo.distance) * invdet; - T fc1 = (termOne * -planeTwo.distance + termTwo * planeOne.distance) * invdet; - - direction = planeOne.normal.CrossProduct(planeTwo.normal); - origin = planeOne.normal * fc0 + planeTwo.normal * fc1; - - return *this; -} - -template -NzRay& NzRay::Set(const NzRay& ray) -{ - std::memcpy(this, &ray, sizeof(NzRay)); - - return *this; -} - -template -NzRay& NzRay::Set(const NzVector3& Origin, const NzVector3& Direction) -{ - direction = Direction; - origin = Origin; - - return *this; -} - -template -template -NzRay& NzRay::Set(const NzRay& ray) -{ - direction.Set(ray.direction); - origin.Set(ray.origin); - - return *this; -} - -template -template -NzRay& NzRay::Set(const NzVector3& Origin, const NzVector3& Direction) -{ - direction.Set(Direction); - origin.Set(Origin); - - return *this; -} - -template -NzString NzRay::ToString() const -{ - NzStringStream ss; - - return ss << "Ray(origin: " << origin.ToString() << ", direction: " << direction.ToString() << ")"; -} - -template -NzVector3 NzRay::operator*(T lambda) const -{ - return GetPoint(lambda); -} - -template -bool NzRay::operator==(const NzRay& ray) const -{ - return direction == ray.direction && origin == ray.origin; -} - -template -bool NzRay::operator!=(const NzRay& ray) const -{ - return !operator==(ray); -} - -template -NzRay NzRay::AxisX() -{ - NzRay axis; - axis.MakeAxisX(); - - return axis; -} - -template -NzRay NzRay::AxisY() -{ - NzRay axis; - axis.MakeAxisY(); - - return axis; -} - -template -NzRay NzRay::AxisZ() -{ - NzRay axis; - axis.MakeAxisZ(); - - return axis; -} - -template -NzRay NzRay::Lerp(const NzRay& from, const NzRay& to, T interpolation) -{ - return NzRay(from.origin.Lerp(to.origin, interpolation), from.direction.Lerp(to.direction, interpolation)); -} - -template -std::ostream& operator<<(std::ostream& out, const NzRay& ray) -{ - return out << ray.ToString(); -} - -#undef F - -#include From 19e1cb05bb0f31599f16650769253ad5bf4690f3 Mon Sep 17 00:00:00 2001 From: Gawaboumga Date: Fri, 21 Aug 2015 12:03:37 +0200 Subject: [PATCH 15/20] OrientedBox no problem Former-commit-id: ad1256baf4bf6d832cb376fe62b1b52f25479e67 --- include/Nazara/Math/OrientedBox.inl | 8 ++--- tests/Nazara/Math/OrientedBox.cpp | 46 +++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 tests/Nazara/Math/OrientedBox.cpp diff --git a/include/Nazara/Math/OrientedBox.inl b/include/Nazara/Math/OrientedBox.inl index c83aee440..8855eae38 100644 --- a/include/Nazara/Math/OrientedBox.inl +++ b/include/Nazara/Math/OrientedBox.inl @@ -103,9 +103,9 @@ template NzOrientedBox& NzOrientedBox::Set(const NzOrientedBox& 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; } @@ -151,7 +151,7 @@ NzVector3& NzOrientedBox::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()); @@ -168,7 +168,7 @@ NzVector3 NzOrientedBox::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()); diff --git a/tests/Nazara/Math/OrientedBox.cpp b/tests/Nazara/Math/OrientedBox.cpp new file mode 100644 index 000000000..c5b650c7d --- /dev/null +++ b/tests/Nazara/Math/OrientedBox.cpp @@ -0,0 +1,46 @@ +#include +#include + +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(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)); + } + } + } + } +} From cb8ab90300408cf897e9ef77bba3e66a38146374 Mon Sep 17 00:00:00 2001 From: Gawaboumga Date: Fri, 21 Aug 2015 12:04:46 +0200 Subject: [PATCH 16/20] Quaternion bug fix: missing 'x' And indentation Former-commit-id: 87e7cc0f69604f3c4593395b15068b9ded59ba1a --- include/Nazara/Math/Quaternion.inl | 50 +++++----- tests/Nazara/Math/Quaternion.cpp | 154 +++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+), 25 deletions(-) create mode 100644 tests/Nazara/Math/Quaternion.cpp diff --git a/include/Nazara/Math/Quaternion.inl b/include/Nazara/Math/Quaternion.inl index 9d498b5c6..a83fb9296 100644 --- a/include/Nazara/Math/Quaternion.inl +++ b/include/Nazara/Math/Quaternion.inl @@ -237,10 +237,10 @@ template template NzQuaternion& NzQuaternion::Set(const NzQuaternion& quat) { - w = static_cast(quat.w); - x = static_cast(quat.x); - y = static_cast(quat.y); - z = static_cast(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 NzQuaternion::ToEulerAngles() const if (test < F(-0.499)) return NzEulerAngles(NzFromDegrees(F(-90.0)), NzFromRadians(F(-2.0) * std::atan2(x, w)), F(0.0)); - return NzEulerAngles(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(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 @@ -329,9 +329,9 @@ template NzQuaternion NzQuaternion::operator*(T scale) const { return NzQuaternion(w * scale, - x * scale, - y * scale, - z * scale); + x * scale, + y * scale, + z * scale); } template @@ -368,9 +368,9 @@ template bool NzQuaternion::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 @@ -450,23 +450,23 @@ NzQuaternion NzQuaternion::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 diff --git a/tests/Nazara/Math/Quaternion.cpp b/tests/Nazara/Math/Quaternion.cpp new file mode 100644 index 000000000..7ce748cbf --- /dev/null +++ b/tests/Nazara/Math/Quaternion.cpp @@ -0,0 +1,154 @@ +#include +#include + +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())); + } + } + } +} From 89e0f631d6dcc4f893faca37f8e210c1b32dbd8f Mon Sep 17 00:00:00 2001 From: Gawaboumga Date: Fri, 21 Aug 2015 12:05:46 +0200 Subject: [PATCH 17/20] No problems No problems found in Rect, Sphere, Vector2, Vector3 and Vector4 Former-commit-id: 6688608a2beaa9cf5328daf7e5108b6cfebd843d --- include/Nazara/Math/Rect.inl | 4 +-- include/Nazara/Math/Sphere.inl | 14 ++++---- tests/Nazara/Math/Rect.cpp | 56 ++++++++++++++++++++++++++++++ tests/Nazara/Math/Sphere.cpp | 63 ++++++++++++++++++++++++++++++++++ tests/Nazara/Math/Vector2.cpp | 49 ++++++++++++++++++++++++++ tests/Nazara/Math/Vector3.cpp | 56 ++++++++++++++++++++++++++++++ tests/Nazara/Math/Vector4.cpp | 43 +++++++++++++++++++++++ 7 files changed, 276 insertions(+), 9 deletions(-) create mode 100644 tests/Nazara/Math/Rect.cpp create mode 100644 tests/Nazara/Math/Sphere.cpp create mode 100644 tests/Nazara/Math/Vector2.cpp create mode 100644 tests/Nazara/Math/Vector3.cpp create mode 100644 tests/Nazara/Math/Vector4.cpp diff --git a/include/Nazara/Math/Rect.inl b/include/Nazara/Math/Rect.inl index 9fba791c0..9dc595708 100644 --- a/include/Nazara/Math/Rect.inl +++ b/include/Nazara/Math/Rect.inl @@ -64,7 +64,7 @@ template bool NzRect::Contains(const NzRect& 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 @@ -410,7 +410,7 @@ template bool NzRect::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 diff --git a/include/Nazara/Math/Sphere.inl b/include/Nazara/Math/Sphere.inl index f8ece724c..340e1319d 100644 --- a/include/Nazara/Math/Sphere.inl +++ b/include/Nazara/Math/Sphere.inl @@ -51,13 +51,13 @@ bool NzSphere::Contains(T X, T Y, T Z) const template bool NzSphere::Contains(const NzBox& 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 bool NzSphere::Contains(const NzVector3& point) const @@ -156,7 +156,7 @@ bool NzSphere::Intersect(const NzBox& box) const squaredDistance += diff*diff; } - return squaredDistance <= radius * radius; + return squaredDistance <= radius * radius; } template diff --git a/tests/Nazara/Math/Rect.cpp b/tests/Nazara/Math/Rect.cpp new file mode 100644 index 000000000..a09eb747c --- /dev/null +++ b/tests/Nazara/Math/Rect.cpp @@ -0,0 +1,56 @@ +#include +#include + +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()); + + } + } + } +} diff --git a/tests/Nazara/Math/Sphere.cpp b/tests/Nazara/Math/Sphere.cpp new file mode 100644 index 000000000..cb668999a --- /dev/null +++ b/tests/Nazara/Math/Sphere.cpp @@ -0,0 +1,63 @@ +#include +#include + +SCENARIO("Sphere", "[MATH][SPHERE]") +{ + GIVEN("Two same sphere center and unit") + { + NzSpheref firstCenterAndUnit(0.f, 0.f, 0.f, 1.f); + NzSpheref secondCenterAndUnit(NzSphere(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)); + } + } + } +} diff --git a/tests/Nazara/Math/Vector2.cpp b/tests/Nazara/Math/Vector2.cpp new file mode 100644 index 000000000..533a6bf35 --- /dev/null +++ b/tests/Nazara/Math/Vector2.cpp @@ -0,0 +1,49 @@ +#include +#include + +#include + +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))); + } + } + } +} diff --git a/tests/Nazara/Math/Vector3.cpp b/tests/Nazara/Math/Vector3.cpp new file mode 100644 index 000000000..de8290a64 --- /dev/null +++ b/tests/Nazara/Math/Vector3.cpp @@ -0,0 +1,56 @@ +#include +#include + +#include + +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))); + } + } + } +} diff --git a/tests/Nazara/Math/Vector4.cpp b/tests/Nazara/Math/Vector4.cpp new file mode 100644 index 000000000..ba60c2232 --- /dev/null +++ b/tests/Nazara/Math/Vector4.cpp @@ -0,0 +1,43 @@ +#include +#include + +#include + +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)); + } + } + } +} From 8716daf73c668ede38068f5504b98d70526086c8 Mon Sep 17 00:00:00 2001 From: Gawaboumga Date: Fri, 21 Aug 2015 12:14:35 +0200 Subject: [PATCH 18/20] Debug axes Former-commit-id: e7d93df67679d1e29014120aef5cc0c3421fd9c2 --- include/Nazara/Renderer/DebugDrawer.hpp | 1 + src/Nazara/Renderer/DebugDrawer.cpp | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/include/Nazara/Renderer/DebugDrawer.hpp b/include/Nazara/Renderer/DebugDrawer.hpp index cb1ae2953..f8faf0337 100644 --- a/include/Nazara/Renderer/DebugDrawer.hpp +++ b/include/Nazara/Renderer/DebugDrawer.hpp @@ -28,6 +28,7 @@ class NAZARA_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); diff --git a/src/Nazara/Renderer/DebugDrawer.cpp b/src/Nazara/Renderer/DebugDrawer.cpp index c13bcfce1..9d3559540 100644 --- a/src/Nazara/Renderer/DebugDrawer.cpp +++ b/src/Nazara/Renderer/DebugDrawer.cpp @@ -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()) From 853ff0e7012e9d8248611c821ef81101a362e28e Mon Sep 17 00:00:00 2001 From: Gawaboumga Date: Fri, 21 Aug 2015 12:16:09 +0200 Subject: [PATCH 19/20] Consistency Former-commit-id: 379ae9d0f63c08a2de6f573bdb52068ed84c19ef --- src/Nazara/Renderer/Renderer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index d536c85ba..44618a4d9 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -2027,7 +2027,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; From 2c3eb992cead1b616c2094593d0eafcbc067188e Mon Sep 17 00:00:00 2001 From: Gawaboumga Date: Fri, 21 Aug 2015 12:17:05 +0200 Subject: [PATCH 20/20] Main for tests Former-commit-id: 34ac8d991d59372a772aad7ffd29d6222cbb7004 --- tests/main.cpp | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tests/main.cpp diff --git a/tests/main.cpp b/tests/main.cpp new file mode 100644 index 000000000..b3143fbb1 --- /dev/null +++ b/tests/main.cpp @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#include