From 06eda4eba962dfe8bb3a5cc36f61c2fc3873fc1c Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 13 Jul 2012 15:22:14 +0200 Subject: [PATCH] Added Meshes and Animations (And many more) Added NzTexture::IsMipmappingSupported Color::(FromTo)HSV now takes hue and saturation in degrees Fixed Context::EnsureContext Fixed COW thread-safety (String, Image, Matrix4) Fixed Quatenion::operator*(const Vector3&) Fixed ResourceLoader Fixed String::Resize with a size of 0 Fixed Texture mipmapping crash Fixed per-class thread-safety IndexBuffer and VertexBuffer are now resources It is now possible to use more than 8 texcoords per shader Moved all enumerations into separate files (Core/Enums.hpp, Utility/Enums.hpp, ..) Removed NzContextParameters::defaultWindow VertexDeclaration has been rewritten (New interface/COW) --- include/Nazara/Core/ByteArray.hpp | 8 +- include/Nazara/Core/Clock.hpp | 7 +- include/Nazara/Core/Color.hpp | 4 +- include/Nazara/Core/Color.inl | 22 +- include/Nazara/Core/Directory.hpp | 7 +- include/Nazara/Core/DynLib.hpp | 7 +- include/Nazara/Core/Endianness.hpp | 8 +- include/Nazara/Core/Enums.hpp | 25 + include/Nazara/Core/Error.hpp | 9 +- include/Nazara/Core/File.hpp | 7 +- include/Nazara/Core/Log.hpp | 7 +- include/Nazara/Core/String.hpp | 11 +- include/Nazara/Core/StringStream.hpp | 7 +- include/Nazara/Core/ThreadSafety.hpp | 36 +- include/Nazara/Core/ThreadSafetyOff.hpp | 21 + include/Nazara/Core/Unicode.hpp | 167 ++--- include/Nazara/Math/Config.hpp | 2 +- include/Nazara/Math/Matrix4.hpp | 21 +- include/Nazara/Math/Matrix4.inl | 67 +- include/Nazara/Math/Quaternion.inl | 2 +- include/Nazara/Math/ThreadSafety.hpp | 37 -- include/Nazara/Renderer/Config.hpp | 2 +- include/Nazara/Renderer/ContextParameters.hpp | 3 +- include/Nazara/Renderer/Enums.hpp | 132 ++++ include/Nazara/Renderer/Renderer.hpp | 96 +-- include/Nazara/Renderer/Shader.hpp | 18 +- include/Nazara/Renderer/Texture.hpp | 17 +- include/Nazara/Utility/Animation.hpp | 81 +++ include/Nazara/Utility/Buffer.hpp | 29 +- include/Nazara/Utility/Config.hpp | 8 + include/Nazara/Utility/Enums.hpp | 191 ++++++ include/Nazara/Utility/Image.hpp | 51 +- include/Nazara/Utility/IndexBuffer.hpp | 3 +- include/Nazara/Utility/KeyframeMesh.hpp | 23 + include/Nazara/Utility/Mesh.hpp | 93 +++ include/Nazara/Utility/PixelFormat.hpp | 48 +- include/Nazara/Utility/ResourceLoader.hpp | 40 +- include/Nazara/Utility/ResourceLoader.inl | 42 +- include/Nazara/Utility/StaticMesh.hpp | 44 ++ include/Nazara/Utility/SubMesh.hpp | 42 ++ include/Nazara/Utility/VertexBuffer.hpp | 3 +- include/Nazara/Utility/VertexDeclaration.hpp | 74 +-- include/Nazara/Utility/Window.hpp | 41 +- src/Nazara/Core/Clock.cpp | 2 - src/Nazara/Core/Directory.cpp | 2 - src/Nazara/Core/DynLib.cpp | 2 - src/Nazara/Core/File.cpp | 3 +- src/Nazara/Core/Log.cpp | 2 - src/Nazara/Core/String.cpp | 21 +- src/Nazara/Core/Unicode.cpp | 77 ++- src/Nazara/Core/Win32/ThreadConditionImpl.hpp | 4 +- src/Nazara/Renderer/Context.cpp | 3 +- src/Nazara/Renderer/ContextParameters.cpp | 18 +- src/Nazara/Renderer/GLSLShader.cpp | 7 +- src/Nazara/Renderer/OpenGL.cpp | 23 +- src/Nazara/Renderer/Renderer.cpp | 39 +- src/Nazara/Renderer/Texture.cpp | 50 +- src/Nazara/Utility/Animation.cpp | 318 ++++++++++ src/Nazara/Utility/Image.cpp | 49 +- src/Nazara/Utility/IndexBuffer.cpp | 1 + src/Nazara/Utility/KeyframeMesh.cpp | 13 + src/Nazara/Utility/Loaders/MD2.hpp | 15 + src/Nazara/Utility/Loaders/MD2/Constants.cpp | 173 ++++++ src/Nazara/Utility/Loaders/MD2/Constants.hpp | 65 ++ src/Nazara/Utility/Loaders/MD2/Loader.cpp | 266 ++++++++ src/Nazara/Utility/Loaders/MD2/Mesh.cpp | 275 +++++++++ src/Nazara/Utility/Loaders/MD2/Mesh.hpp | 64 ++ .../Loaders/{PCX.cpp => PCX/Loader.cpp} | 39 +- .../Loaders/{STB.cpp => STB/Loader.cpp} | 36 +- src/Nazara/Utility/Mesh.cpp | 575 ++++++++++++++++++ src/Nazara/Utility/StaticMesh.cpp | 141 +++++ src/Nazara/Utility/SubMesh.cpp | 68 +++ src/Nazara/Utility/Utility.cpp | 9 +- src/Nazara/Utility/VertexBuffer.cpp | 6 +- src/Nazara/Utility/VertexDeclaration.cpp | 317 ++++++++-- 75 files changed, 3385 insertions(+), 861 deletions(-) create mode 100644 include/Nazara/Core/Enums.hpp create mode 100644 include/Nazara/Core/ThreadSafetyOff.hpp delete mode 100644 include/Nazara/Math/ThreadSafety.hpp create mode 100644 include/Nazara/Renderer/Enums.hpp create mode 100644 include/Nazara/Utility/Animation.hpp create mode 100644 include/Nazara/Utility/Enums.hpp create mode 100644 include/Nazara/Utility/KeyframeMesh.hpp create mode 100644 include/Nazara/Utility/Mesh.hpp create mode 100644 include/Nazara/Utility/StaticMesh.hpp create mode 100644 include/Nazara/Utility/SubMesh.hpp create mode 100644 src/Nazara/Utility/Animation.cpp create mode 100644 src/Nazara/Utility/KeyframeMesh.cpp create mode 100644 src/Nazara/Utility/Loaders/MD2.hpp create mode 100644 src/Nazara/Utility/Loaders/MD2/Constants.cpp create mode 100644 src/Nazara/Utility/Loaders/MD2/Constants.hpp create mode 100644 src/Nazara/Utility/Loaders/MD2/Loader.cpp create mode 100644 src/Nazara/Utility/Loaders/MD2/Mesh.cpp create mode 100644 src/Nazara/Utility/Loaders/MD2/Mesh.hpp rename src/Nazara/Utility/Loaders/{PCX.cpp => PCX/Loader.cpp} (83%) rename src/Nazara/Utility/Loaders/{STB.cpp => STB/Loader.cpp} (65%) create mode 100644 src/Nazara/Utility/Mesh.cpp create mode 100644 src/Nazara/Utility/StaticMesh.cpp create mode 100644 src/Nazara/Utility/SubMesh.cpp diff --git a/include/Nazara/Core/ByteArray.hpp b/include/Nazara/Core/ByteArray.hpp index 46d26b60b..aaef8e65a 100644 --- a/include/Nazara/Core/ByteArray.hpp +++ b/include/Nazara/Core/ByteArray.hpp @@ -8,10 +8,14 @@ #define NAZARA_BYTEARRAY_HPP #include +#include #include -#define NAZARA_CLASS_BYTEARRAY +#if NAZARA_THREADSAFETY_BYTEARRAY #include +#else +#include +#endif class NzAbstractHash; class NzHashDigest; @@ -122,6 +126,4 @@ namespace std NAZARA_API void swap(NzByteArray& lhs, NzByteArray& rhs); } -#undef NAZARA_CLASS_BYTEARRAY - #endif // NAZARA_BYTEARRAY_HPP diff --git a/include/Nazara/Core/Clock.hpp b/include/Nazara/Core/Clock.hpp index 426b848e9..d6e221702 100644 --- a/include/Nazara/Core/Clock.hpp +++ b/include/Nazara/Core/Clock.hpp @@ -9,8 +9,11 @@ #include -#define NAZARA_CLASS_CLOCK +#if NAZARA_THREADSAFETY_CLOCK #include +#else +#include +#endif class NAZARA_API NzClock { @@ -40,6 +43,4 @@ typedef nzUInt64 (*NzClockFunction)(); extern NAZARA_API NzClockFunction NzGetMicroseconds; extern NAZARA_API NzClockFunction NzGetMilliseconds; -#undef NAZARA_CLASS_CLOCK - #endif // NAZARA_CLOCK_HPP diff --git a/include/Nazara/Core/Color.hpp b/include/Nazara/Core/Color.hpp index 609fae5ae..96bebca0d 100644 --- a/include/Nazara/Core/Color.hpp +++ b/include/Nazara/Core/Color.hpp @@ -35,13 +35,13 @@ class NzColor static NzColor FromCMY(float cyan, float magenta, float yellow); static NzColor FromCMYK(float cyan, float magenta, float yellow, float black); static NzColor FromHSL(nzUInt8 hue, nzUInt8 saturation, nzUInt8 lightness); - static NzColor FromHSV(nzUInt8 hue, nzUInt8 saturation, float value); + static NzColor FromHSV(float hue, float saturation, float value); static NzColor FromXYZ(const NzVector3f& vec); static NzColor FromXYZ(float x, float y, float z); static void ToCMY(const NzColor& color, float* cyan, float* magenta, float* yellow); static void ToCMYK(const NzColor& color, float* cyan, float* magenta, float* yellow, float* black); static void ToHSL(const NzColor& color, nzUInt8* hue, nzUInt8* saturation, nzUInt8* lightness); - static void ToHSV(const NzColor& color, nzUInt8* hue, nzUInt8* saturation, float* value); + static void ToHSV(const NzColor& color, float* hue, float* saturation, float* value); static void ToXYZ(const NzColor& color, NzVector3f* vec); static void ToXYZ(const NzColor& color, float* x, float* y, float* z); diff --git a/include/Nazara/Core/Color.inl b/include/Nazara/Core/Color.inl index ec5491dd8..6c9cdd758 100644 --- a/include/Nazara/Core/Color.inl +++ b/include/Nazara/Core/Color.inl @@ -2,6 +2,8 @@ // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp +// http://www.easyrgb.com/index.php?X=MATH + #include #include #include @@ -130,14 +132,14 @@ inline NzColor NzColor::FromHSL(nzUInt8 hue, nzUInt8 saturation, nzUInt8 lightne } } -inline NzColor NzColor::FromHSV(nzUInt8 hue, nzUInt8 saturation, float value) +inline NzColor NzColor::FromHSV(float hue, float saturation, float value) { - if (saturation == 0) + if (NzNumberEquals(saturation, 0.f)) return NzColor(static_cast(value * 255.f)); else { - float h = hue/240.f * 6.f; - float s = saturation/240.f; + float h = hue/360.f * 6.f; + float s = saturation/360.f; if (NzNumberEquals(h, 6.f)) h = 0; // hue must be < 1 @@ -200,17 +202,17 @@ inline NzColor NzColor::FromXYZ(float x, float y, float z) double g = x * -0.9689 + y * 1.8758 + z * 0.0415; double b = x * 0.0557 + y * -0.2040 + z * 1.0570; - if (r > 0.0031308) + if (r > 0.0031308f) r = 1.055 * (std::pow(r, 1.0/2.4)) - 0.055; else r *= 12.92; - if (g > 0.0031308) + if (g > 0.0031308f) g = 1.055 * (std::pow(g, 1.0/2.4)) - 0.055; else g *= 12.92; - if (b > 0.0031308) + if (b > 0.0031308f) b = 1.055 * (std::pow(b, 1.0/2.4)) - 0.055; else b *= 12.92; @@ -300,7 +302,7 @@ inline void NzColor::ToHSL(const NzColor& color, nzUInt8* hue, nzUInt8* saturati } } -inline void NzColor::ToHSV(const NzColor& color, nzUInt8* hue, nzUInt8* saturation, float* value) +inline void NzColor::ToHSV(const NzColor& color, float* hue, float* saturation, float* value) { float r = color.r / 255.f; float g = color.g / 255.f; @@ -322,7 +324,7 @@ inline void NzColor::ToHSV(const NzColor& color, nzUInt8* hue, nzUInt8* saturati else { //Chromatic data... - *saturation = deltaMax/max*240.f; + *saturation = deltaMax/max*360.f; float deltaR = ((max - r)/6.f + deltaMax/2.f)/deltaMax; float deltaG = ((max - g)/6.f + deltaMax/2.f)/deltaMax; @@ -342,7 +344,7 @@ inline void NzColor::ToHSV(const NzColor& color, nzUInt8* hue, nzUInt8* saturati else if (h > 1.f) h -= 1.f; - *hue = h*240.f; + *hue = h*360.f; } } diff --git a/include/Nazara/Core/Directory.hpp b/include/Nazara/Core/Directory.hpp index 93b0d1328..c4b0109dc 100644 --- a/include/Nazara/Core/Directory.hpp +++ b/include/Nazara/Core/Directory.hpp @@ -19,8 +19,11 @@ #define NAZARA_DIRECTORY_SEPARATOR '/' #endif -#define NAZARA_CLASS_DIRECTORY +#if NAZARA_THREADSAFETY_DIRECTORY #include +#else +#include +#endif class NzDirectoryImpl; @@ -59,6 +62,4 @@ class NAZARA_API NzDirectory NzDirectoryImpl* m_impl; }; -#undef NAZARA_CLASS_DIRECTORY - #endif // NAZARA_DIRECTORY_HPP diff --git a/include/Nazara/Core/DynLib.hpp b/include/Nazara/Core/DynLib.hpp index a7da89da8..3035e08a4 100644 --- a/include/Nazara/Core/DynLib.hpp +++ b/include/Nazara/Core/DynLib.hpp @@ -11,8 +11,11 @@ #include #include -#define NAZARA_CLASS_DYNLIB +#if NAZARA_THREADSAFETY_DYNLIB #include +#else +#include +#endif class NzDynLibImpl; typedef int (*NzDynLibFunc)(); // Type "générique" de pointeur sur fonction @@ -40,6 +43,4 @@ class NzDynLib : NzNonCopyable NzDynLibImpl* m_impl; }; -#undef NAZARA_CLASS_DYNLIB - #endif // NAZARA_DYNLIB_HPP diff --git a/include/Nazara/Core/Endianness.hpp b/include/Nazara/Core/Endianness.hpp index d5af604c9..1f079a70f 100644 --- a/include/Nazara/Core/Endianness.hpp +++ b/include/Nazara/Core/Endianness.hpp @@ -8,6 +8,7 @@ #define NAZARA_ENDIANNESS_HPP #include +#include #if !defined(NAZARA_BIG_ENDIAN) && !defined(NAZARA_LITTLE_ENDIAN) // Détection automatique selon les macros du compilateur @@ -23,13 +24,6 @@ #error You cannot define both NAZARA_BIG_ENDIAN and NAZARA_LITTLE_ENDIAN #endif -enum nzEndianness -{ - nzEndianness_BigEndian, - nzEndianness_LittleEndian, - nzEndianness_Unknown -}; - inline void NzByteSwap(void* buffer, unsigned int size); inline nzEndianness NzGetPlatformEndianness(); diff --git a/include/Nazara/Core/Enums.hpp b/include/Nazara/Core/Enums.hpp new file mode 100644 index 000000000..79d7e09ad --- /dev/null +++ b/include/Nazara/Core/Enums.hpp @@ -0,0 +1,25 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine". +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_ENUMS_CORE_HPP +#define NAZARA_ENUMS_CORE_HPP + +enum nzEndianness +{ + nzEndianness_BigEndian, + nzEndianness_LittleEndian, + nzEndianness_Unknown +}; + +enum nzErrorType +{ + nzErrorType_AssertFailed, + nzErrorType_Internal, + nzErrorType_Normal, + nzErrorType_Warning +}; + +#endif // NAZARA_ENUMS_CORE_HPP diff --git a/include/Nazara/Core/Error.hpp b/include/Nazara/Core/Error.hpp index 056fae28a..9c95ade9b 100644 --- a/include/Nazara/Core/Error.hpp +++ b/include/Nazara/Core/Error.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #if NAZARA_CORE_ENABLE_ASSERTS || defined(NAZARA_DEBUG) @@ -21,14 +22,6 @@ #define NazaraInternalError(err) NzError(nzErrorType_Internal, err, __LINE__, __FILE__, NAZARA_FUNCTION) #define NazaraWarning(err) NzError(nzErrorType_Warning, err, __LINE__, __FILE__, NAZARA_FUNCTION) -enum nzErrorType -{ - nzErrorType_AssertFailed, - nzErrorType_Internal, - nzErrorType_Normal, - nzErrorType_Warning -}; - NAZARA_API void NzError(nzErrorType type, const NzString& error, unsigned int line, const char* file, const char* function); NAZARA_API unsigned int NzGetLastSystemErrorCode(); NAZARA_API NzString NzGetLastSystemError(unsigned int code = NzGetLastSystemErrorCode()); diff --git a/include/Nazara/Core/File.hpp b/include/Nazara/Core/File.hpp index b253d30b9..9a43c84b6 100644 --- a/include/Nazara/Core/File.hpp +++ b/include/Nazara/Core/File.hpp @@ -16,8 +16,11 @@ #include #include -#define NAZARA_CLASS_FILE +#if NAZARA_THREADSAFETY_FILE #include +#else +#include +#endif class NzFileImpl; @@ -117,6 +120,4 @@ class NAZARA_API NzFile : public NzHashable, public NzInputStream, NzNonCopyable unsigned int m_openMode; }; -#undef NAZARA_CLASS_FILE - #endif // NAZARA_FILE_HPP diff --git a/include/Nazara/Core/Log.hpp b/include/Nazara/Core/Log.hpp index 857a375b1..b9696c96d 100644 --- a/include/Nazara/Core/Log.hpp +++ b/include/Nazara/Core/Log.hpp @@ -12,8 +12,11 @@ #include #include -#define NAZARA_CLASS_LOG +#if NAZARA_THREADSAFETY_LOG #include +#else +#include +#endif #define NazaraLog NzLog::Instance() #define NazaraNotice(txt) NazaraLog->Write(txt) @@ -51,6 +54,4 @@ class NAZARA_API NzLog : NzNonCopyable bool m_writeTime; }; -#undef NAZARA_CLASS_LOG - #endif // NAZARA_LOGGER_HPP diff --git a/include/Nazara/Core/String.hpp b/include/Nazara/Core/String.hpp index 8707dacb3..7c3deae91 100644 --- a/include/Nazara/Core/String.hpp +++ b/include/Nazara/Core/String.hpp @@ -13,8 +13,11 @@ #include #include -#define NAZARA_CLASS_STRING +#if NAZARA_THREADSAFETY_STRING #include +#else +#include +#endif class NzAbstractHash; class NzHashDigest; @@ -154,7 +157,7 @@ class NAZARA_API NzString : public NzHashable NzString Trimmed(nzUInt32 flags = None) const; NzString Trimmed(char character, nzUInt32 flags = None) const; - // Méthodes compatibles STD + // Méthodes STD char* begin(); const char* begin() const; char* end(); @@ -170,7 +173,7 @@ class NAZARA_API NzString : public NzHashable typedef char* iterator; //typedef char* reverse_iterator; typedef char value_type; - // Méthodes compatibles STD + // Méthodes STD operator std::string() const; @@ -318,6 +321,4 @@ namespace std NAZARA_API void swap(NzString& lhs, NzString& rhs); } -#undef NAZARA_CLASS_STRING - #endif // NAZARA_STRING_HPP diff --git a/include/Nazara/Core/StringStream.hpp b/include/Nazara/Core/StringStream.hpp index d07dc7ce8..996c06eec 100644 --- a/include/Nazara/Core/StringStream.hpp +++ b/include/Nazara/Core/StringStream.hpp @@ -12,8 +12,11 @@ #include #include -#define NAZARA_CLASS_STRINGSTREAM +#if NAZARA_THREADSAFETY_STRINGSTREAM #include +#else +#include +#endif class NAZARA_API NzStringStream { @@ -51,6 +54,4 @@ class NAZARA_API NzStringStream unsigned int m_bufferSize; }; -#undef NAZARA_CLASS_STRINGSTREAM - #endif // NAZARA_STRINGSTREAM_HPP diff --git a/include/Nazara/Core/ThreadSafety.hpp b/include/Nazara/Core/ThreadSafety.hpp index dcbc4a515..ff6ee4907 100644 --- a/include/Nazara/Core/ThreadSafety.hpp +++ b/include/Nazara/Core/ThreadSafety.hpp @@ -4,7 +4,8 @@ // Pas de header guard -#include +#include +#include // Ces macros peuvent changer pour n'importe quel fichier qui l'utilise dans une même unité de compilation #undef NazaraLock @@ -14,30 +15,9 @@ #undef NazaraMutexUnlock #undef NazaraNamedLock -#if NAZARA_CORE_THREADSAFE && (\ - (NAZARA_THREADSAFETY_BYTEARRAY && defined(NAZARA_CLASS_BYTEARRAY)) || \ - (NAZARA_THREADSAFETY_CLOCK && defined(NAZARA_CLASS_CLOCK)) || \ - (NAZARA_THREADSAFETY_DIRECTORY && defined(NAZARA_CLASS_DIRECTORY)) || \ - (NAZARA_THREADSAFETY_DYNLIB && defined(NAZARA_CLASS_DYNLIB)) || \ - (NAZARA_THREADSAFETY_FILE && defined(NAZARA_CLASS_FILE)) || \ - (NAZARA_THREADSAFETY_LOG && defined(NAZARA_CLASS_LOG)) || \ - (NAZARA_THREADSAFETY_STRING && defined(NAZARA_CLASS_STRING)) || \ - (NAZARA_THREADSAFETY_STRINGSTREAM && defined(NAZARA_CLASS_STRINGSTREAM))) - - #include - #include - - #define NazaraLock(mutex) NzLockGuard lock_mutex(mutex); - #define NazaraMutex(name) NzMutex name; - #define NazaraMutexAttrib(name, attribute) attribute NzMutex name; - #define NazaraMutexLock(mutex) mutex.Lock(); - #define NazaraMutexUnlock(mutex) mutex.Unlock(); - #define NazaraNamedLock(mutex, name) NzLock lock_##name(mutex); -#else - #define NazaraLock(mutex) - #define NazaraMutex(name) - #define NazaraMutexAttrib(name, attribute) - #define NazaraMutexLock(mutex) - #define NazaraMutexUnlock(mutex) - #define NazaraNamedLock(mutex, name) -#endif +#define NazaraLock(mutex) NzLockGuard lock_mutex(mutex); +#define NazaraMutex(name) NzMutex name; +#define NazaraMutexAttrib(name, attribute) attribute NzMutex name; +#define NazaraMutexLock(mutex) mutex.Lock(); +#define NazaraMutexUnlock(mutex) mutex.Unlock(); +#define NazaraNamedLock(mutex, name) NzLockGuard lock_##name(mutex); diff --git a/include/Nazara/Core/ThreadSafetyOff.hpp b/include/Nazara/Core/ThreadSafetyOff.hpp new file mode 100644 index 000000000..86c84e938 --- /dev/null +++ b/include/Nazara/Core/ThreadSafetyOff.hpp @@ -0,0 +1,21 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine". +// For conditions of distribution and use, see copyright notice in Config.hpp + +// Pas de header guard + +// Ces macros peuvent changer pour n'importe quel fichier qui l'utilise dans une même unité de compilation +#undef NazaraLock +#undef NazaraMutex +#undef NazaraMutexAttrib +#undef NazaraMutexLock +#undef NazaraMutexUnlock +#undef NazaraNamedLock + +#define NazaraLock(mutex) +#define NazaraMutex(name) +#define NazaraMutexAttrib(name, attribute) +#define NazaraMutexLock(mutex) +#define NazaraMutexUnlock(mutex) +#define NazaraNamedLock(mutex, name) + diff --git a/include/Nazara/Core/Unicode.hpp b/include/Nazara/Core/Unicode.hpp index 7f9fd0940..f9b05d6fd 100644 --- a/include/Nazara/Core/Unicode.hpp +++ b/include/Nazara/Core/Unicode.hpp @@ -9,98 +9,99 @@ #include -namespace NzUnicode +class NzUnicode { - /* - Catégorie Unicode: - -Les valeurs de 0x01 à 0x80 indiquent la catégorie. - -Les valeurs de 0x100 à 0x10000 indiquent la sous-catégorie. - */ - enum Category : nzUInt16 - { - // Catégorie non-reconnue par Nazara - Category_NoCategory = 0, + public: + /* + Catégorie Unicode: + -Les valeurs de 0x01 à 0x80 indiquent la catégorie. + -Les valeurs de 0x100 à 0x10000 indiquent la sous-catégorie. + */ + enum Category : nzUInt16 + { + // Catégorie non-reconnue par Nazara + Category_NoCategory = 0, - // Lettres - Category_Letter = 0x01, // L - Category_Letter_Lowercase = Category_Letter | 0x0100, // Ll - Category_Letter_Modifier = Category_Letter | 0x0200, // Lm - Category_Letter_Other = Category_Letter | 0x0400, // Lo - Category_Letter_Titlecase = Category_Letter | 0x0800, // Lt - Category_Letter_Uppercase = Category_Letter | 0x1000, // Lu + // Lettres + Category_Letter = 0x01, // L + Category_Letter_Lowercase = Category_Letter | 0x0100, // Ll + Category_Letter_Modifier = Category_Letter | 0x0200, // Lm + Category_Letter_Other = Category_Letter | 0x0400, // Lo + Category_Letter_Titlecase = Category_Letter | 0x0800, // Lt + Category_Letter_Uppercase = Category_Letter | 0x1000, // Lu - // Marques - Category_Mark = 0x02, // M - Category_Mark_Enclosing = Category_Mark | 0x100, // Me - Category_Mark_NonSpacing = Category_Mark | 0x200, // Mn - Category_Mark_SpacingCombining = Category_Mark | 0x400, // Mc + // Marques + Category_Mark = 0x02, // M + Category_Mark_Enclosing = Category_Mark | 0x100, // Me + Category_Mark_NonSpacing = Category_Mark | 0x200, // Mn + Category_Mark_SpacingCombining = Category_Mark | 0x400, // Mc - // Nombres - Category_Number = 0x04, // N - Category_Number_DecimalDigit = Category_Number | 0x100, // Nd - Category_Number_Letter = Category_Number | 0x200, // Nl - Category_Number_Other = Category_Number | 0x400, // No + // Nombres + Category_Number = 0x04, // N + Category_Number_DecimalDigit = Category_Number | 0x100, // Nd + Category_Number_Letter = Category_Number | 0x200, // Nl + Category_Number_Other = Category_Number | 0x400, // No - // Autres - Category_Other = 0x08, // C - Category_Other_Control = Category_Other | 0x0100, // Cc - Category_Other_Format = Category_Other | 0x0200, // Cf - Category_Other_NotAssigned = Category_Other | 0x0400, // Cn - Category_Other_PrivateUse = Category_Other | 0x0800, // Co - Category_Other_Surrogate = Category_Other | 0x1000, // Cs + // Autres + Category_Other = 0x08, // C + Category_Other_Control = Category_Other | 0x0100, // Cc + Category_Other_Format = Category_Other | 0x0200, // Cf + Category_Other_NotAssigned = Category_Other | 0x0400, // Cn + Category_Other_PrivateUse = Category_Other | 0x0800, // Co + Category_Other_Surrogate = Category_Other | 0x1000, // Cs - // Ponctuations - Category_Punctuation = 0x10, // P - Category_Punctuation_Close = Category_Punctuation | 0x0100, // Pe - Category_Punctuation_Connector = Category_Punctuation | 0x0200, // Pc - Category_Punctuation_Dash = Category_Punctuation | 0x0400, // Pd - Category_Punctuation_FinalQuote = Category_Punctuation | 0x0800, // Pf - Category_Punctuation_InitialQuote = Category_Punctuation | 0x1000, // Pi - Category_Punctuation_Open = Category_Punctuation | 0x2000, // Ps - Category_Punctuation_Other = Category_Punctuation | 0x4000, // Po + // Ponctuations + Category_Punctuation = 0x10, // P + Category_Punctuation_Close = Category_Punctuation | 0x0100, // Pe + Category_Punctuation_Connector = Category_Punctuation | 0x0200, // Pc + Category_Punctuation_Dash = Category_Punctuation | 0x0400, // Pd + Category_Punctuation_FinalQuote = Category_Punctuation | 0x0800, // Pf + Category_Punctuation_InitialQuote = Category_Punctuation | 0x1000, // Pi + Category_Punctuation_Open = Category_Punctuation | 0x2000, // Ps + Category_Punctuation_Other = Category_Punctuation | 0x4000, // Po - // Espacements - Category_Separator = 0x20, // Z - Category_Separator_Line = Category_Separator | 0x0100, // Zl - Category_Separator_Paragraph = Category_Separator | 0x0200, // Zp - Category_Separator_Space = Category_Separator | 0x0400, // Zs + // Espacements + Category_Separator = 0x20, // Z + Category_Separator_Line = Category_Separator | 0x0100, // Zl + Category_Separator_Paragraph = Category_Separator | 0x0200, // Zp + Category_Separator_Space = Category_Separator | 0x0400, // Zs - // Symboles - Category_Symbol = 0x40, // S - Category_Symbol_Currency = Category_Symbol | 0x0100, // Sc - Category_Symbol_Math = Category_Symbol | 0x0200, // Sm - Category_Symbol_Modifier = Category_Symbol | 0x0400, // Sk - Category_Symbol_Other = Category_Symbol | 0x0800 // So - }; + // Symboles + Category_Symbol = 0x40, // S + Category_Symbol_Currency = Category_Symbol | 0x0100, // Sc + Category_Symbol_Math = Category_Symbol | 0x0200, // Sm + Category_Symbol_Modifier = Category_Symbol | 0x0400, // Sk + Category_Symbol_Other = Category_Symbol | 0x0800 // So + }; - enum Direction : nzUInt8 - { - Direction_Arabic_Letter, // AL - Direction_Arabic_Number, // AN - Direction_Boundary_Neutral, // BN - Direction_Common_Separator, // CS - Direction_European_Number, // EN - Direction_European_Separator, // ES - Direction_European_Terminator, // ET - Direction_Left_To_Right, // L - Direction_Left_To_Right_Embedding, // LRE - Direction_Left_To_Right_Override, // LRO - Direction_Nonspacing_Mark, // NSM - Direction_Other_Neutral, // ON - Direction_Paragraph_Separator, // B - Direction_Pop_Directional_Format, // PDF - Direction_Right_To_Left, // R - Direction_Right_To_Left_Embedding, // RLE - Direction_Right_To_Left_Override, // RLO - Direction_Segment_Separator, // S - Direction_White_Space // WS - }; + enum Direction : nzUInt8 + { + Direction_Arabic_Letter, // AL + Direction_Arabic_Number, // AN + Direction_Boundary_Neutral, // BN + Direction_Common_Separator, // CS + Direction_European_Number, // EN + Direction_European_Separator, // ES + Direction_European_Terminator, // ET + Direction_Left_To_Right, // L + Direction_Left_To_Right_Embedding, // LRE + Direction_Left_To_Right_Override, // LRO + Direction_Nonspacing_Mark, // NSM + Direction_Other_Neutral, // ON + Direction_Paragraph_Separator, // B + Direction_Pop_Directional_Format, // PDF + Direction_Right_To_Left, // R + Direction_Right_To_Left_Embedding, // RLE + Direction_Right_To_Left_Override, // RLO + Direction_Segment_Separator, // S + Direction_White_Space // WS + }; - Category GetCategory(char32_t character); - Direction GetDirection(char32_t character); - char32_t GetLowercase(char32_t character); - char32_t GetTitlecase(char32_t character); - char32_t GetUppercase(char32_t character); -} + static Category GetCategory(char32_t character); + static Direction GetDirection(char32_t character); + static char32_t GetLowercase(char32_t character); + static char32_t GetTitlecase(char32_t character); + static char32_t GetUppercase(char32_t character); +}; #endif // NAZARA_UNICODE_HPP diff --git a/include/Nazara/Math/Config.hpp b/include/Nazara/Math/Config.hpp index 7bfbeba1d..e0f53a715 100644 --- a/include/Nazara/Math/Config.hpp +++ b/include/Nazara/Math/Config.hpp @@ -33,7 +33,7 @@ // Définit le radian comme l'unité utilisée pour les angles #define NAZARA_MATH_ANGLE_RADIAN 0 -// Définit la disposition des matrices en colonnes +// Définit la disposition des matrices en colonnes (Façon OpenGL) #define NAZARA_MATH_MATRIX_COLUMN_MAJOR 1 // Active les tests de sécurité basés sur le code (Conseillé pour le développement) diff --git a/include/Nazara/Math/Matrix4.hpp b/include/Nazara/Math/Matrix4.hpp index 5b6e5878c..80d30b25f 100644 --- a/include/Nazara/Math/Matrix4.hpp +++ b/include/Nazara/Math/Matrix4.hpp @@ -9,8 +9,11 @@ #include -#define NAZARA_CLASS_MATRIX4 -#include +#if NAZARA_THREADSAFETY_MATRIX4 +#include +#else +#include +#endif template class NzEulerAngles; template class NzQuaternion; @@ -26,7 +29,7 @@ template class NzMatrix4 T r21, T r22, T r23, T r24, T r31, T r32, T r33, T r34, T r41, T r42, T r43, T r44); - NzMatrix4(T matrix[16]); + NzMatrix4(const T matrix[16]); //NzMatrix4(const NzMatrix3& matrix); template explicit NzMatrix4(const NzMatrix4& matrix); NzMatrix4(const NzMatrix4& matrix); @@ -47,7 +50,7 @@ template class NzMatrix4 T r21, T r22, T r23, T r24, T r31, T r32, T r33, T r34, T r41, T r42, T r43, T r44); - void Set(T matrix[16]); + void Set(const T matrix[16]); //NzMatrix4(const NzMatrix3& matrix); void Set(const NzMatrix4& matrix); void Set(NzMatrix4&& matrix); @@ -96,10 +99,10 @@ template class NzMatrix4 struct SharedMatrix { - T m11, m12, m13, m14; - T m21, m22, m23, m24; - T m31, m32, m33, m34; - T m41, m42, m43, m44; + T m11, m12, m13, m14, + m21, m22, m23, m24, + m31, m32, m33, m34, + m41, m42, m43, m44; unsigned short refCount = 1; NazaraMutex(mutex) @@ -117,8 +120,6 @@ template std::ostream& operator<<(std::ostream& out, const NzMatrix4 typedef NzMatrix4 NzMatrix4d; typedef NzMatrix4 NzMatrix4f; -#undef NAZARA_CLASS_MATRIX4 - #include #endif // NAZARA_MATRIX4_HPP diff --git a/include/Nazara/Math/Matrix4.inl b/include/Nazara/Math/Matrix4.inl index 708190ad8..184648cbe 100644 --- a/include/Nazara/Math/Matrix4.inl +++ b/include/Nazara/Math/Matrix4.inl @@ -15,9 +15,6 @@ #include #include #include - -#define NAZARA_CLASS_MATRIX4 -#include #include template @@ -40,7 +37,7 @@ m_sharedMatrix(nullptr) } template -NzMatrix4::NzMatrix4(T matrix[16]) : +NzMatrix4::NzMatrix4(const T matrix[16]) : m_sharedMatrix(nullptr) { Set(matrix); @@ -243,12 +240,12 @@ void NzMatrix4::Set(T r11, T r12, T r13, T r14, } template -void NzMatrix4::Set(T matrix[16]) +void NzMatrix4::Set(const T matrix[16]) { EnsureOwnership(); // Ici nous sommes certains de la continuité des éléments en mémoire - std::memcpy(&m_sharedMatrix->m41, matrix, 16*sizeof(T)); + std::memcpy(&m_sharedMatrix->m11, matrix, 16*sizeof(T)); } template @@ -309,6 +306,7 @@ void NzMatrix4::SetOrtho(T left, T top, T width, T height, T zNear, T zFar) template void NzMatrix4::SetLookAt(const NzVector3& eye, const NzVector3& center, const NzVector3& up) { + // http://www.opengl.org/sdk/docs/man/xhtml/gluLookAt.xml NzVector3 f = center - eye; f.Normalize(); @@ -316,14 +314,19 @@ void NzMatrix4::SetLookAt(const NzVector3& eye, const NzVector3& center u.Normalize(); NzVector3 s = f.CrossProduct(u); - s.Normalize(); - u = s.CrossProduct(f); + #if NAZARA_MATH_MATRIX_COLUMN_MAJOR + Set(s.x, s.y, s.z, 0.0, + u.x, u.y, u.z, 0.0, + -f.x, -f.y, -f.z, 0.0, + 0.0, 0.0, 0.0, 1.0); + #else Set(s.x, u.x, -f.x, 0.0, s.y, u.y, -f.y, 0.0, s.z, u.z, -f.z, 0.0, 0.0, 0.0, 0.0, 1.0); + #endif operator*=(Translate(-eye)); } @@ -587,34 +590,22 @@ NzMatrix4 NzMatrix4::operator*(const NzMatrix4& matrix) const } #endif - NzMatrix4 mat; - for(int k = 0; k < 4; k++) - { - for(int j = 0; j < 4; j++) - { - for(int i = 0; i < 4; i++) - mat(j, k) += (*this)(j, i) * matrix(i, k); - } - } - - return mat; - /*return NzMatrix4(m11 * matrix.m11 + m21 * matrix.m12 + m31 * matrix.m13 + m41 * matrix.m14, - m12 * matrix.m11 + m22 * matrix.m12 + m32 * matrix.m13 + m42 * matrix.m14, - m13 * matrix.m11 + m23 * matrix.m12 + m33 * matrix.m13 + m43 * matrix.m14, - m14 * matrix.m11 + m24 * matrix.m12 + m34 * matrix.m13 + m44 * matrix.m14, - m11 * matrix.m21 + m21 * matrix.m22 + m31 * matrix.m23 + m41 * matrix.m24, - m12 * matrix.m21 + m22 * matrix.m22 + m32 * matrix.m23 + m42 * matrix.m24, - m13 * matrix.m21 + m23 * matrix.m22 + m33 * matrix.m23 + m43 * matrix.m24, - m14 * matrix.m21 + m24 * matrix.m22 + m34 * matrix.m23 + m44 * matrix.m24, - m11 * matrix.m31 + m21 * matrix.m32 + m31 * matrix.m33 + m41 * matrix.m34, - m12 * matrix.m31 + m22 * matrix.m32 + m32 * matrix.m33 + m42 * matrix.m34, - m13 * matrix.m31 + m23 * matrix.m32 + m33 * matrix.m33 + m43 * matrix.m34, - m14 * matrix.m31 + m24 * matrix.m32 + m34 * matrix.m33 + m44 * matrix.m34, - m11 * matrix.m41 + m21 * matrix.m42 + m31 * matrix.m43 + m41 * matrix.m44, - m12 * matrix.m41 + m22 * matrix.m42 + m32 * matrix.m43 + m42 * matrix.m44, - m13 * matrix.m41 + m23 * matrix.m42 + m33 * matrix.m43 + m43 * matrix.m44, - m14 * matrix.m41 + m24 * matrix.m42 + m34 * matrix.m43 + m44 * matrix.m44);*/ - + return NzMatrix4(m_sharedMatrix->m11 * matrix.m_sharedMatrix->m11 + m_sharedMatrix->m21 * matrix.m_sharedMatrix->m12 + m_sharedMatrix->m31 * matrix.m_sharedMatrix->m13 + m_sharedMatrix->m41 * matrix.m_sharedMatrix->m14, + m_sharedMatrix->m12 * matrix.m_sharedMatrix->m11 + m_sharedMatrix->m22 * matrix.m_sharedMatrix->m12 + m_sharedMatrix->m32 * matrix.m_sharedMatrix->m13 + m_sharedMatrix->m42 * matrix.m_sharedMatrix->m14, + m_sharedMatrix->m13 * matrix.m_sharedMatrix->m11 + m_sharedMatrix->m23 * matrix.m_sharedMatrix->m12 + m_sharedMatrix->m33 * matrix.m_sharedMatrix->m13 + m_sharedMatrix->m43 * matrix.m_sharedMatrix->m14, + m_sharedMatrix->m14 * matrix.m_sharedMatrix->m11 + m_sharedMatrix->m24 * matrix.m_sharedMatrix->m12 + m_sharedMatrix->m34 * matrix.m_sharedMatrix->m13 + m_sharedMatrix->m44 * matrix.m_sharedMatrix->m14, + m_sharedMatrix->m11 * matrix.m_sharedMatrix->m21 + m_sharedMatrix->m21 * matrix.m_sharedMatrix->m22 + m_sharedMatrix->m31 * matrix.m_sharedMatrix->m23 + m_sharedMatrix->m41 * matrix.m_sharedMatrix->m24, + m_sharedMatrix->m12 * matrix.m_sharedMatrix->m21 + m_sharedMatrix->m22 * matrix.m_sharedMatrix->m22 + m_sharedMatrix->m32 * matrix.m_sharedMatrix->m23 + m_sharedMatrix->m42 * matrix.m_sharedMatrix->m24, + m_sharedMatrix->m13 * matrix.m_sharedMatrix->m21 + m_sharedMatrix->m23 * matrix.m_sharedMatrix->m22 + m_sharedMatrix->m33 * matrix.m_sharedMatrix->m23 + m_sharedMatrix->m43 * matrix.m_sharedMatrix->m24, + m_sharedMatrix->m14 * matrix.m_sharedMatrix->m21 + m_sharedMatrix->m24 * matrix.m_sharedMatrix->m22 + m_sharedMatrix->m34 * matrix.m_sharedMatrix->m23 + m_sharedMatrix->m44 * matrix.m_sharedMatrix->m24, + m_sharedMatrix->m11 * matrix.m_sharedMatrix->m31 + m_sharedMatrix->m21 * matrix.m_sharedMatrix->m32 + m_sharedMatrix->m31 * matrix.m_sharedMatrix->m33 + m_sharedMatrix->m41 * matrix.m_sharedMatrix->m34, + m_sharedMatrix->m12 * matrix.m_sharedMatrix->m31 + m_sharedMatrix->m22 * matrix.m_sharedMatrix->m32 + m_sharedMatrix->m32 * matrix.m_sharedMatrix->m33 + m_sharedMatrix->m42 * matrix.m_sharedMatrix->m34, + m_sharedMatrix->m13 * matrix.m_sharedMatrix->m31 + m_sharedMatrix->m23 * matrix.m_sharedMatrix->m32 + m_sharedMatrix->m33 * matrix.m_sharedMatrix->m33 + m_sharedMatrix->m43 * matrix.m_sharedMatrix->m34, + m_sharedMatrix->m14 * matrix.m_sharedMatrix->m31 + m_sharedMatrix->m24 * matrix.m_sharedMatrix->m32 + m_sharedMatrix->m34 * matrix.m_sharedMatrix->m33 + m_sharedMatrix->m44 * matrix.m_sharedMatrix->m34, + m_sharedMatrix->m11 * matrix.m_sharedMatrix->m41 + m_sharedMatrix->m21 * matrix.m_sharedMatrix->m42 + m_sharedMatrix->m31 * matrix.m_sharedMatrix->m43 + m_sharedMatrix->m41 * matrix.m_sharedMatrix->m44, + m_sharedMatrix->m12 * matrix.m_sharedMatrix->m41 + m_sharedMatrix->m22 * matrix.m_sharedMatrix->m42 + m_sharedMatrix->m32 * matrix.m_sharedMatrix->m43 + m_sharedMatrix->m42 * matrix.m_sharedMatrix->m44, + m_sharedMatrix->m13 * matrix.m_sharedMatrix->m41 + m_sharedMatrix->m23 * matrix.m_sharedMatrix->m42 + m_sharedMatrix->m33 * matrix.m_sharedMatrix->m43 + m_sharedMatrix->m43 * matrix.m_sharedMatrix->m44, + m_sharedMatrix->m14 * matrix.m_sharedMatrix->m41 + m_sharedMatrix->m24 * matrix.m_sharedMatrix->m42 + m_sharedMatrix->m34 * matrix.m_sharedMatrix->m43 + m_sharedMatrix->m44 * matrix.m_sharedMatrix->m44); } template @@ -806,10 +797,10 @@ void NzMatrix4::ReleaseMatrix() return; NazaraMutexLock(m_sharedMatrix->mutex); - m_sharedMatrix->refCount--; + bool freeSharedMatrix = (--m_sharedMatrix->refCount == 0); NazaraMutexUnlock(m_sharedMatrix->mutex); - if (m_sharedMatrix->refCount == 0) + if (freeSharedMatrix) delete m_sharedMatrix; m_sharedMatrix = nullptr; diff --git a/include/Nazara/Math/Quaternion.inl b/include/Nazara/Math/Quaternion.inl index afba1dd72..b4a459d3d 100644 --- a/include/Nazara/Math/Quaternion.inl +++ b/include/Nazara/Math/Quaternion.inl @@ -273,7 +273,7 @@ template NzVector3 NzQuaternion::operator*(const NzVector3& vec) const { NzVector3 normal(vec); - normal.Normalise(); + normal.Normalize(); NzQuaternion qvec(0.0, normal.x, normal.y, normal.z); NzQuaternion result = operator*(qvec * GetConjugate()); diff --git a/include/Nazara/Math/ThreadSafety.hpp b/include/Nazara/Math/ThreadSafety.hpp deleted file mode 100644 index cf55bae44..000000000 --- a/include/Nazara/Math/ThreadSafety.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (C) 2012 Jérôme Leclercq -// This file is part of the "Nazara Engine". -// For conditions of distribution and use, see copyright notice in Config.hpp - -// Pas de header guard - -#include - -// Ces macros peuvent changer pour n'importe quel fichier qui l'utilise dans une même unité de compilation -#undef NazaraLock -#undef NazaraMutex -#undef NazaraMutexAttrib -#undef NazaraMutexLock -#undef NazaraMutexUnlock -#undef NazaraNamedLock - -#if NAZARA_MATH_THREADSAFE && (\ - (NAZARA_THREADSAFETY_MATRIX3 && (defined(NAZARA_MATRIX3) || defined(NAZARA_MATRIX3_INL))) || \ - (NAZARA_THREADSAFETY_MATRIX4 && (defined(NAZARA_MATRIX4) || defined(NAZARA_MATRIX4_INL)))) - - #include - #include - - #define NazaraLock(mutex) NzLock lock_mutex(mutex); - #define NazaraMutex(name) NzMutex name; - #define NazaraMutexAttrib(name, attribute) attribute NzMutex name; - #define NazaraMutexLock(mutex) mutex.Lock(); - #define NazaraMutexUnlock(mutex) mutex.Unlock(); - #define NazaraNamedLock(mutex, name) NzLock lock_##name(mutex); -#else - #define NazaraLock(mutex) - #define NazaraMutex(name) - #define NazaraMutexAttrib(name, attribute) - #define NazaraMutexLock(mutex) - #define NazaraMutexUnlock(mutex) - #define NazaraNamedLock(mutex, name) -#endif diff --git a/include/Nazara/Renderer/Config.hpp b/include/Nazara/Renderer/Config.hpp index 4c256125a..9d5cbe613 100644 --- a/include/Nazara/Renderer/Config.hpp +++ b/include/Nazara/Renderer/Config.hpp @@ -32,7 +32,7 @@ // Active une fenêtre de rendu (NzRenderWindow) lors de sa création #define NAZARA_RENDERER_ACTIVATE_RENDERWINDOW_ON_CREATION 1 -// Force les buffers à posséder un stride multiple de 32 bytes (Gain de performances sur certaines cartes) +// Force les buffers à posséder un stride multiple de 32 bytes (Gain de performances sur certaines cartes/plus de consommation mémoire) #define NAZARA_RENDERER_FORCE_DECLARATION_STRIDE_MULTIPLE_OF_32 0 // Utilise un tracker pour repérer les éventuels leaks (Ralentit l'exécution) diff --git a/include/Nazara/Renderer/ContextParameters.hpp b/include/Nazara/Renderer/ContextParameters.hpp index aad31d304..93b731e04 100644 --- a/include/Nazara/Renderer/ContextParameters.hpp +++ b/include/Nazara/Renderer/ContextParameters.hpp @@ -23,7 +23,7 @@ struct NAZARA_API NzContextParameters minorVersion(defaultMinorVersion), stencilBits(parameters.stencilBits), shareContext(defaultShareContext), - window(defaultWindow), + window(0), compatibilityProfile(defaultCompatibilityProfile), debugMode(defaultDebugMode), doubleBuffered(defaultDoubleBuffered), @@ -47,7 +47,6 @@ struct NAZARA_API NzContextParameters static nzUInt8 defaultMajorVersion; static nzUInt8 defaultMinorVersion; static const NzContext* defaultShareContext; - static NzWindowHandle defaultWindow; static bool defaultCompatibilityProfile; static bool defaultDebugMode; static bool defaultDoubleBuffered; diff --git a/include/Nazara/Renderer/Enums.hpp b/include/Nazara/Renderer/Enums.hpp new file mode 100644 index 000000000..2497b0df8 --- /dev/null +++ b/include/Nazara/Renderer/Enums.hpp @@ -0,0 +1,132 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine". +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_ENUMS_RENDERER_HPP +#define NAZARA_ENUMS_RENDERER_HPP + +enum nzBlendFunc +{ + nzBlendFunc_DestAlpha, + nzBlendFunc_DestColor, + nzBlendFunc_SrcAlpha, + nzBlendFunc_SrcColor, + nzBlendFunc_InvDestAlpha, + nzBlendFunc_InvDestColor, + nzBlendFunc_InvSrcAlpha, + nzBlendFunc_InvSrcColor, + nzBlendFunc_One, + nzBlendFunc_Zero +}; + +enum nzFaceCulling +{ + nzFaceCulling_Back, + nzFaceCulling_Front, + nzFaceCulling_FrontAndBack +}; + +enum nzFaceFilling +{ + nzFaceFilling_Point, + nzFaceFilling_Line, + nzFaceFilling_Fill +}; + +enum nzPixelBufferType +{ + nzPixelBufferType_Pack, + nzPixelBufferType_Unpack +}; + +enum nzRendererCap +{ + nzRendererCap_AnisotropicFilter, + nzRendererCap_FP64, + nzRendererCap_HardwareBuffer, + nzRendererCap_MultipleRenderTargets, + nzRendererCap_OcclusionQuery, + nzRendererCap_PixelBufferObject, + nzRendererCap_Texture3D, + nzRendererCap_TextureCubemap, + nzRendererCap_TextureMulti, + nzRendererCap_TextureNPOT, + + nzRendererCap_Max = nzRendererCap_TextureNPOT +}; + +enum nzRendererClear +{ + nzRendererClear_Color = 0x01, + nzRendererClear_Depth = 0x02, + nzRendererClear_Stencil = 0x04 +}; + +enum nzRendererComparison +{ + nzRendererComparison_Always, + nzRendererComparison_Equal, + nzRendererComparison_Greater, + nzRendererComparison_GreaterOrEqual, + nzRendererComparison_Less, + nzRendererComparison_LessOrEqual, + nzRendererComparison_Never +}; + +enum nzRendererParameter +{ + nzRendererParameter_Blend, + nzRendererParameter_ColorWrite, + nzRendererParameter_DepthTest, + nzRendererParameter_DepthWrite, + nzRendererParameter_FaceCulling, + nzRendererParameter_Stencil +}; + +enum nzShaderLanguage +{ + nzShaderLanguage_Unknown, + + nzShaderLanguage_Cg, + nzShaderLanguage_GLSL +}; + +enum nzShaderType +{ + nzShaderType_Fragment, + nzShaderType_Geometry, + nzShaderType_Vertex, + + nzShaderType_Max = nzShaderType_Vertex +}; + +enum nzStencilOperation +{ + nzStencilOperation_Decrement, + nzStencilOperation_DecrementToSaturation, + nzStencilOperation_Increment, + nzStencilOperation_IncrementToSaturation, + nzStencilOperation_Invert, + nzStencilOperation_Keep, + nzStencilOperation_Replace, + nzStencilOperation_Zero +}; + +enum nzTextureFilter +{ + nzTextureFilter_Bilinear, + nzTextureFilter_Nearest, + nzTextureFilter_Trilinear, + nzTextureFilter_Unknown +}; + +enum nzTextureWrap +{ + nzTextureWrap_Clamp, + nzTextureWrap_Repeat, + nzTextureWrap_Unknown +}; + +#endif // NAZARA_ENUMS_RENDERER_HPP diff --git a/include/Nazara/Renderer/Renderer.hpp b/include/Nazara/Renderer/Renderer.hpp index 4a0f80492..74484ff36 100644 --- a/include/Nazara/Renderer/Renderer.hpp +++ b/include/Nazara/Renderer/Renderer.hpp @@ -9,105 +9,13 @@ #include #include +#include +#include #include #include #define NazaraRenderer NzRenderer::Instance() -enum nzBlendFunc -{ - nzBlendFunc_DestAlpha, - nzBlendFunc_DestColor, - nzBlendFunc_SrcAlpha, - nzBlendFunc_SrcColor, - nzBlendFunc_InvDestAlpha, - nzBlendFunc_InvDestColor, - nzBlendFunc_InvSrcAlpha, - nzBlendFunc_InvSrcColor, - nzBlendFunc_One, - nzBlendFunc_Zero -}; - -enum nzFaceCulling -{ - nzFaceCulling_Back, - nzFaceCulling_Front, - nzFaceCulling_FrontAndBack -}; - -enum nzFaceFilling -{ - nzFaceFilling_Point, - nzFaceFilling_Line, - nzFaceFilling_Fill -}; - -enum nzPrimitiveType -{ - nzPrimitiveType_LineList, - nzPrimitiveType_LineStrip, - nzPrimitiveType_PointList, - nzPrimitiveType_TriangleList, - nzPrimitiveType_TriangleStrip, - nzPrimitiveType_TriangleFan -}; - -enum nzRendererCap -{ - nzRendererCap_AnisotropicFilter, - nzRendererCap_FP64, - nzRendererCap_HardwareBuffer, - nzRendererCap_MultipleRenderTargets, - nzRendererCap_OcclusionQuery, - nzRendererCap_PixelBufferObject, - nzRendererCap_Texture3D, - nzRendererCap_TextureCubemap, - nzRendererCap_TextureMulti, - nzRendererCap_TextureNPOT, - - nzRendererCap_Max = nzRendererCap_TextureNPOT -}; - -enum nzRendererClear -{ - nzRendererClear_Color = 0x01, - nzRendererClear_Depth = 0x02, - nzRendererClear_Stencil = 0x04 -}; - -enum nzRendererComparison -{ - nzRendererComparison_Always, - nzRendererComparison_Equal, - nzRendererComparison_Greater, - nzRendererComparison_GreaterOrEqual, - nzRendererComparison_Less, - nzRendererComparison_LessOrEqual, - nzRendererComparison_Never -}; - -enum nzRendererParameter -{ - nzRendererParameter_Blend, - nzRendererParameter_ColorWrite, - nzRendererParameter_DepthTest, - nzRendererParameter_DepthWrite, - nzRendererParameter_FaceCulling, - nzRendererParameter_Stencil -}; - -enum nzStencilOperation -{ - nzStencilOperation_Decrement, - nzStencilOperation_DecrementToSaturation, - nzStencilOperation_Increment, - nzStencilOperation_IncrementToSaturation, - nzStencilOperation_Invert, - nzStencilOperation_Keep, - nzStencilOperation_Replace, - nzStencilOperation_Zero -}; - class NzColor; class NzContext; class NzIndexBuffer; diff --git a/include/Nazara/Renderer/Shader.hpp b/include/Nazara/Renderer/Shader.hpp index 2ef694110..c100cef13 100644 --- a/include/Nazara/Renderer/Shader.hpp +++ b/include/Nazara/Renderer/Shader.hpp @@ -14,25 +14,9 @@ #include #include #include +#include #include -enum nzShaderLanguage -{ - nzShaderLanguage_Unknown, - - nzShaderLanguage_Cg, - nzShaderLanguage_GLSL -}; - -enum nzShaderType -{ - nzShaderType_Fragment, - nzShaderType_Geometry, - nzShaderType_Vertex, - - nzShaderType_Max = nzShaderType_Vertex -}; - class NzRenderer; class NzShaderImpl; class NzTexture; diff --git a/include/Nazara/Renderer/Texture.hpp b/include/Nazara/Renderer/Texture.hpp index 98df54f38..af056c0db 100644 --- a/include/Nazara/Renderer/Texture.hpp +++ b/include/Nazara/Renderer/Texture.hpp @@ -9,24 +9,10 @@ #include #include +#include #include #include -enum nzTextureFilter -{ - nzTextureFilter_Bilinear, - nzTextureFilter_Nearest, - nzTextureFilter_Trilinear, - nzTextureFilter_Unknown -}; - -enum nzTextureWrap -{ - nzTextureWrap_Clamp, - nzTextureWrap_Repeat, - nzTextureWrap_Unknown -}; - class NzShader; struct NzTextureImpl; @@ -92,6 +78,7 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable static unsigned int GetValidSize(unsigned int size); static bool IsFormatSupported(nzPixelFormat format); + static bool IsMipmappingSupported(); static bool IsTypeSupported(nzImageType type); private: diff --git a/include/Nazara/Utility/Animation.hpp b/include/Nazara/Utility/Animation.hpp new file mode 100644 index 000000000..b8b8d251e --- /dev/null +++ b/include/Nazara/Utility/Animation.hpp @@ -0,0 +1,81 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine". +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_ANIMATION_HPP +#define NAZARA_ANIMATION_HPP + +#include +#include +#include +#include +#include +#include +#include + +struct NzAnimationParams +{ + unsigned int endFrame = static_cast(-1); + unsigned int startFrame = 0; + + bool IsValid() const; +}; + +struct NzSequence +{ + NzString name; + unsigned int firstFrame; + unsigned int lastFrame; + unsigned int framePerSecond; +}; + +class NzAnimation; + +typedef NzResourceLoader NzAnimationLoader; + +struct NzAnimationImpl; + +class NAZARA_API NzAnimation : public NzResource +{ + friend class NzResourceLoader; + + public: + NzAnimation() = default; + ~NzAnimation(); + + unsigned int AddSequence(const NzSequence& sequence); + + bool Create(nzAnimationType type, unsigned int frameCount); + void Destroy(); + + unsigned int GetFrameCount() const; + NzSequence* GetSequence(const NzString& sequenceName); + NzSequence* GetSequence(unsigned int index); + const NzSequence* GetSequence(const NzString& sequenceName) const; + const NzSequence* GetSequence(unsigned int index) const; + unsigned int GetSequenceCount() const; + nzAnimationType GetType() const; + + bool HasSequence(const NzString& sequenceName) const; + bool HasSequence(unsigned int index = 0) const; + + bool IsValid() const; + + bool LoadFromFile(const NzString& filePath, const NzAnimationParams& params = NzAnimationParams()); + bool LoadFromMemory(const void* data, std::size_t size, const NzAnimationParams& params = NzAnimationParams()); + bool LoadFromStream(NzInputStream& stream, const NzAnimationParams& params = NzAnimationParams()); + + void RemoveSequence(const NzString& sequenceName); + void RemoveSequence(unsigned int index); + + private: + NzAnimationImpl* m_impl = nullptr; + + static std::list s_memoryLoaders; + static std::list s_streamLoaders; + static std::multimap s_fileLoaders; +}; + +#endif // NAZARA_ANIMATION_HPP diff --git a/include/Nazara/Utility/Buffer.hpp b/include/Nazara/Utility/Buffer.hpp index 8cdc0b5ac..7fcad2221 100644 --- a/include/Nazara/Utility/Buffer.hpp +++ b/include/Nazara/Utility/Buffer.hpp @@ -9,36 +9,9 @@ #include #include +#include #include -enum nzBufferAccess -{ - nzBufferAccess_DiscardAndWrite, - nzBufferAccess_ReadOnly, - nzBufferAccess_ReadWrite, - nzBufferAccess_WriteOnly -}; - -enum nzBufferStorage -{ - nzBufferStorage_Hardware, - nzBufferStorage_Software, - - nzBufferStorage_Max = nzBufferStorage_Software -}; - -enum nzBufferType -{ - nzBufferType_Index, - nzBufferType_Vertex -}; - -enum nzBufferUsage -{ - nzBufferUsage_Dynamic, - nzBufferUsage_Static -}; - class NzBufferImpl; class NzRenderer; class NzUtility; diff --git a/include/Nazara/Utility/Config.hpp b/include/Nazara/Utility/Config.hpp index a7d025626..a9f059da4 100644 --- a/include/Nazara/Utility/Config.hpp +++ b/include/Nazara/Utility/Config.hpp @@ -38,4 +38,12 @@ // Fait tourner chaque fenêtre dans un thread séparé si le système le supporte #define NAZARA_UTILITY_THREADED_WINDOW 0 ///FIXME: Buggé depuis GCC 4.7 +// Protège le module des accès concurrentiels +#define NAZARA_UTILITY_THREADSAFE 1 + +#if NAZARA_UTILITY_THREADSAFE + #define NAZARA_THREADSAFETY_IMAGE 1 // NzImage (COW) + #define NAZARA_THREADSAFETY_VERTEXDECLARATION 1 // NzVertexDeclaration (COW) +#endif + #endif // NAZARA_CONFIG_UTILITY_HPP diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp new file mode 100644 index 000000000..b2da366e7 --- /dev/null +++ b/include/Nazara/Utility/Enums.hpp @@ -0,0 +1,191 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine". +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_ENUMS_UTILITY_HPP +#define NAZARA_ENUMS_UTILITY_HPP + +enum nzAnimationType +{ + nzAnimationType_Keyframe, + nzAnimationType_Skeletal, + nzAnimationType_Static +}; + +enum nzBufferAccess +{ + nzBufferAccess_DiscardAndWrite, + nzBufferAccess_ReadOnly, + nzBufferAccess_ReadWrite, + nzBufferAccess_WriteOnly +}; + +enum nzBufferStorage +{ + nzBufferStorage_Hardware, + nzBufferStorage_Software, + + nzBufferStorage_Max = nzBufferStorage_Software +}; + +enum nzBufferType +{ + nzBufferType_Index, + nzBufferType_Vertex +}; + +enum nzBufferUsage +{ + nzBufferUsage_Dynamic, + nzBufferUsage_Static +}; + +enum nzCubemapFace +{ + // L'ordre est X, -X, Y, -Y, Z, -Z + // Cette énumération est prévue pour remplacer l'argument "z" des méthodes de NzImage contenant un cubemap + nzCubemapFace_PositiveX = 0, + nzCubemapFace_PositiveY = 2, + nzCubemapFace_PositiveZ = 4, + nzCubemapFace_NegativeX = 1, + nzCubemapFace_NegativeY = 3, + nzCubemapFace_NegativeZ = 5 +}; + +enum nzElementStream +{ + nzElementStream_VertexData, + nzElementStream_InstancedData, + + nzElementStream_Max = nzElementStream_InstancedData +}; + +enum nzElementType +{ + nzElementType_Color, + nzElementType_Double1, + nzElementType_Double2, + nzElementType_Double3, + nzElementType_Double4, + nzElementType_Float1, + nzElementType_Float2, + nzElementType_Float3, + nzElementType_Float4 +}; + +enum nzElementUsage +{ + nzElementUsage_Diffuse, + nzElementUsage_Normal, + nzElementUsage_Position, + nzElementUsage_Tangent, + nzElementUsage_TexCoord, + + nzElementUsage_Max = nzElementUsage_TexCoord +}; + +enum nzImageType +{ + nzImageType_1D, + nzImageType_2D, + nzImageType_3D, + nzImageType_Cubemap, + + nzImageType_Max = nzImageType_Cubemap +}; + +enum nzPixelFormat +{ + nzPixelFormat_Undefined, + + nzPixelFormat_BGR8, // 3*nzUInt8 + nzPixelFormat_BGRA8, // 4*nzUInt8 + nzPixelFormat_DXT1, + nzPixelFormat_DXT3, + nzPixelFormat_DXT5, + nzPixelFormat_L8, // 1*nzUInt8 + nzPixelFormat_LA8, // 2*nzUInt8 + /* + nzPixelFormat_RGB16F, + nzPixelFormat_RGB16I, // 4*nzUInt16 + nzPixelFormat_RGB32F, + nzPixelFormat_RGB32I, // 4*nzUInt32 + nzPixelFormat_RGBA16F, + nzPixelFormat_RGBA16I, // 4*nzUInt16 + nzPixelFormat_RGBA32F, + nzPixelFormat_RGBA32I, // 4*nzUInt32 + */ + nzPixelFormat_RGBA4, // 1*nzUInt16 + nzPixelFormat_RGB5A1, // 1*nzUInt16 + nzPixelFormat_RGB8, // 3*nzUInt8 + nzPixelFormat_RGBA8, // 4*nzUInt8 + /* + nzPixelFormat_Depth16, + nzPixelFormat_Depth24, + nzPixelFormat_Depth24Stencil8, + nzPixelFormat_Depth32, + nzPixelFormat_Stencil1, + nzPixelFormat_Stencil4, + nzPixelFormat_Stencil8, + nzPixelFormat_Stencil16, + */ + + nzPixelFormat_Max = nzPixelFormat_RGBA8 +}; + +enum nzPixelFlipping +{ + nzPixelFlipping_Horizontally, + nzPixelFlipping_Vertically, + + nzPixelFlipping_Max = nzPixelFlipping_Vertically +}; + +enum nzPrimitiveType +{ + nzPrimitiveType_LineList, + nzPrimitiveType_LineStrip, + nzPrimitiveType_PointList, + nzPrimitiveType_TriangleList, + nzPrimitiveType_TriangleStrip, + nzPrimitiveType_TriangleFan +}; + +enum nzWindowCursor +{ + nzWindowCursor_None, + nzWindowCursor_Default, + + nzWindowCursor_Crosshair, + nzWindowCursor_Hand, + nzWindowCursor_Help, + nzWindowCursor_Move, + nzWindowCursor_Pointer, + nzWindowCursor_Progress, + nzWindowCursor_ResizeE, + nzWindowCursor_ResizeN, + nzWindowCursor_ResizeNE, + nzWindowCursor_ResizeNW, + nzWindowCursor_ResizeS, + nzWindowCursor_ResizeSE, + nzWindowCursor_ResizeSW, + nzWindowCursor_ResizeW, + nzWindowCursor_Text, + nzWindowCursor_Wait +}; + +enum nzWindowStyle +{ + nzWindowStyle_None = 0x0, + nzWindowStyle_Fullscreen = 0x1, + + nzWindowStyle_Closable = 0x2, + nzWindowStyle_Resizable = 0x4, + nzWindowStyle_Titlebar = 0x4, + + nzWindowStyle_Default = nzWindowStyle_Closable | nzWindowStyle_Resizable | nzWindowStyle_Titlebar +}; + +#endif // NAZARA_ENUMS_UTILITY_HPP diff --git a/include/Nazara/Utility/Image.hpp b/include/Nazara/Utility/Image.hpp index a85055c45..8882aa73f 100644 --- a/include/Nazara/Utility/Image.hpp +++ b/include/Nazara/Utility/Image.hpp @@ -13,46 +13,37 @@ #include #include #include +#include #include #include #include -//#include +#include +#include -enum nzCubemapFace -{ - nzCubemapFace_PositiveX = 0, - nzCubemapFace_NegativeX = 1, - nzCubemapFace_PositiveY = 2, - nzCubemapFace_NegativeY = 3, - nzCubemapFace_PositiveZ = 4, - nzCubemapFace_NegativeZ = 5 -}; - -enum nzImageType -{ - nzImageType_1D, - nzImageType_2D, - nzImageType_3D, - nzImageType_Cubemap, - - nzImageType_Max = nzImageType_Cubemap -}; +#if NAZARA_THREADSAFETY_IMAGE +#include +#else +#include +#endif struct NzImageParams { nzPixelFormat loadFormat = nzPixelFormat_Undefined; nzUInt8 levelCount = 0; - bool IsValid() const - { - return loadFormat == nzPixelFormat_Undefined || NzPixelFormat::IsValid(loadFormat); - } + bool IsValid() const; }; ///TODO: Filtres -class NAZARA_API NzImage : public NzResource, public NzResourceLoader +class NzImage; + +typedef NzResourceLoader NzImageLoader; + +class NAZARA_API NzImage : public NzResource { + friend class NzResourceLoader; + public: struct SharedImage; @@ -109,12 +100,6 @@ class NAZARA_API NzImage : public NzResource, public NzResourceLoader s_memoryLoaders; + static std::list s_streamLoaders; + static std::multimap s_fileLoaders; }; #endif // NAZARA_IMAGE_HPP diff --git a/include/Nazara/Utility/IndexBuffer.hpp b/include/Nazara/Utility/IndexBuffer.hpp index 80d6eeb23..22c22104b 100644 --- a/include/Nazara/Utility/IndexBuffer.hpp +++ b/include/Nazara/Utility/IndexBuffer.hpp @@ -9,8 +9,9 @@ #include #include +#include -class NAZARA_API NzIndexBuffer +class NAZARA_API NzIndexBuffer : public NzResource { public: NzIndexBuffer(NzBuffer* buffer, unsigned int startIndex, unsigned int indexCount); diff --git a/include/Nazara/Utility/KeyframeMesh.hpp b/include/Nazara/Utility/KeyframeMesh.hpp new file mode 100644 index 000000000..d2e894c51 --- /dev/null +++ b/include/Nazara/Utility/KeyframeMesh.hpp @@ -0,0 +1,23 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine". +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_KEYFRAMEMESH_HPP +#define NAZARA_KEYFRAMEMESH_HPP + +#include +#include + +class NzMesh; +struct NzAnimation; + +class NAZARA_API NzKeyframeMesh : public NzSubMesh +{ + public: + NzKeyframeMesh(const NzMesh* parent); + virtual ~NzKeyframeMesh(); +}; + +#endif // NAZARA_KEYFRAMEMESH_HPP diff --git a/include/Nazara/Utility/Mesh.hpp b/include/Nazara/Utility/Mesh.hpp new file mode 100644 index 000000000..b7dbc71f1 --- /dev/null +++ b/include/Nazara/Utility/Mesh.hpp @@ -0,0 +1,93 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine". +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_MESH_HPP +#define NAZARA_MESH_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +class NzSubMesh; +class NzVertexDeclaration; + +struct NzMeshParams +{ + NzAnimationParams animation; + //const NzVertexDeclaration* declaration = nullptr; + bool forceSoftware = false; + bool loadAnimations = true; + + bool IsValid() const; +}; + +class NzMesh; + +typedef NzResourceLoader NzMeshLoader; + +struct NzMeshImpl; + +class NAZARA_API NzMesh : public NzResource +{ + friend class NzResourceLoader; + + public: + NzMesh() = default; + ~NzMesh(); + + unsigned int AddSkin(const NzString& skin, bool setDefault = false); + nzUInt8 AddSubMesh(NzSubMesh* subMesh); + nzUInt8 AddSubMesh(const NzString& identifier, NzSubMesh* subMesh); + + void Animate(unsigned int frameA, unsigned int frameB, float interpolation); + + bool Create(nzAnimationType type); + void Destroy(); + + const NzAnimation* GetAnimation() const; + nzAnimationType GetAnimationType() const; + unsigned int GetFrameCount() const; + NzString GetSkin(unsigned int index = 0) const; + unsigned int GetSkinCount() const; + NzSubMesh* GetSubMesh(const NzString& identifier); + NzSubMesh* GetSubMesh(nzUInt8 index); + const NzSubMesh* GetSubMesh(const NzString& identifier) const; + const NzSubMesh* GetSubMesh(nzUInt8 index) const; + nzUInt8 GetSubMeshCount() const; + unsigned int GetVertexCount() const; + + bool HasAnimation() const; + bool HasSkin(unsigned int index = 0) const; + bool HasSubMesh(const NzString& identifier) const; + bool HasSubMesh(nzUInt8 index = 0) const; + + bool IsAnimable() const; + bool IsValid() const; + + bool LoadFromFile(const NzString& filePath, const NzMeshParams& params = NzMeshParams()); + bool LoadFromMemory(const void* data, std::size_t size, const NzMeshParams& params = NzMeshParams()); + bool LoadFromStream(NzInputStream& stream, const NzMeshParams& params = NzMeshParams()); + + void RemoveSkin(unsigned int index = 0); + void RemoveSubMesh(const NzString& identifier); + void RemoveSubMesh(nzUInt8 index = 0); + + bool SetAnimation(const NzAnimation* animation); + + private: + NzMeshImpl* m_impl = nullptr; + + static std::list s_memoryLoaders; + static std::list s_streamLoaders; + static std::multimap s_fileLoaders; +}; + +#endif // NAZARA_MESH_HPP diff --git a/include/Nazara/Utility/PixelFormat.hpp b/include/Nazara/Utility/PixelFormat.hpp index a69ad0092..2f71927b7 100644 --- a/include/Nazara/Utility/PixelFormat.hpp +++ b/include/Nazara/Utility/PixelFormat.hpp @@ -9,55 +9,9 @@ #include #include +#include #include -enum nzPixelFormat -{ - nzPixelFormat_Undefined, - - nzPixelFormat_BGR8, // 3*nzUInt8 - nzPixelFormat_BGRA8, // 4*nzUInt8 - nzPixelFormat_DXT1, - nzPixelFormat_DXT3, - nzPixelFormat_DXT5, - nzPixelFormat_L8, // 1*nzUInt8 - nzPixelFormat_LA8, // 2*nzUInt8 - /* - nzPixelFormat_RGB16F, - nzPixelFormat_RGB16I, // 4*nzUInt16 - nzPixelFormat_RGB32F, - nzPixelFormat_RGB32I, // 4*nzUInt32 - nzPixelFormat_RGBA16F, - nzPixelFormat_RGBA16I, // 4*nzUInt16 - nzPixelFormat_RGBA32F, - nzPixelFormat_RGBA32I, // 4*nzUInt32 - */ - nzPixelFormat_RGBA4, // 1*nzUInt16 - nzPixelFormat_RGB5A1, // 1*nzUInt16 - nzPixelFormat_RGB8, // 3*nzUInt8 - nzPixelFormat_RGBA8, // 4*nzUInt8 - /* - nzPixelFormat_Depth16, - nzPixelFormat_Depth24, - nzPixelFormat_Depth24Stencil8, - nzPixelFormat_Depth32, - nzPixelFormat_Stencil1, - nzPixelFormat_Stencil4, - nzPixelFormat_Stencil8, - nzPixelFormat_Stencil16, - */ - - nzPixelFormat_Max = nzPixelFormat_RGBA8 -}; - -enum nzPixelFlipping -{ - nzPixelFlipping_Horizontally, - nzPixelFlipping_Vertically, - - nzPixelFlipping_Max = nzPixelFlipping_Vertically -}; - class NzUtility; class NzPixelFormat diff --git a/include/Nazara/Utility/ResourceLoader.hpp b/include/Nazara/Utility/ResourceLoader.hpp index bb5053459..732d6de98 100644 --- a/include/Nazara/Utility/ResourceLoader.hpp +++ b/include/Nazara/Utility/ResourceLoader.hpp @@ -8,8 +8,6 @@ #define NAZARA_RESOURCELOADER_HPP #include -#include -#include #include class NzInputStream; @@ -18,30 +16,26 @@ template class NzResourceLoader { public: - typedef bool (*IsMemoryLoadingSupportedFunction)(const void* data, unsigned int size, const Parameters& parameters); - typedef bool (*IsStreamLoadingSupportedFunction)(NzInputStream& stream, const Parameters& parameters); - typedef bool (*LoadFileFunction)(Type* resource, const NzString& filePath, const Parameters& parameters); - typedef bool (*LoadMemoryFunction)(Type* resource, const void* data, unsigned int size, const Parameters& parameters); - typedef bool (*LoadStreamFunction)(Type* resource, NzInputStream& stream, const Parameters& parameters); + using IdentifyMemoryFunction = bool (*)(const void* data, unsigned int size, const Parameters& parameters); + using IdentifyStreamFunction = bool (*)(NzInputStream& stream, const Parameters& parameters); + using LoadFileFunction = bool (*)(Type* resource, const NzString& filePath, const Parameters& parameters); + using LoadMemoryFunction = bool (*)(Type* resource, const void* data, unsigned int size, const Parameters& parameters); + using LoadStreamFunction = bool (*)(Type* resource, NzInputStream& stream, const Parameters& parameters); - protected: - static bool LoadResourceFromFile(Type* resource, const NzString& filePath, const Parameters& parameters); - static bool LoadResourceFromMemory(Type* resource, const void* data, unsigned int size, const Parameters& parameters); - static bool LoadResourceFromStream(Type* resource, NzInputStream& stream, const Parameters& parameters); - static void RegisterResourceFileLoader(const NzString& extensions, LoadFileFunction loadFile); - static void RegisterResourceMemoryLoader(IsMemoryLoadingSupportedFunction isLoadingSupported, LoadMemoryFunction loadMemory); - static void RegisterResourceStreamLoader(IsStreamLoadingSupportedFunction isLoadingSupported, LoadStreamFunction loadStream); - static void UnregisterResourceFileLoader(const NzString& extensions, LoadFileFunction loadFile); - static void UnregisterResourceMemoryLoader(IsMemoryLoadingSupportedFunction isLoadingSupported, LoadMemoryFunction loadMemory); - static void UnregisterResourceStreamLoader(IsStreamLoadingSupportedFunction isLoadingSupported, LoadStreamFunction loadStream); + static bool LoadFromFile(Type* resource, const NzString& filePath, const Parameters& parameters = Parameters()); + static bool LoadFromMemory(Type* resource, const void* data, unsigned int size, const Parameters& parameters = Parameters()); + static bool LoadFromStream(Type* resource, NzInputStream& stream, const Parameters& parameters = Parameters()); - private: - typedef std::pair MemoryLoader; - typedef std::pair StreamLoader; + static void RegisterFileLoader(const NzString& extensions, LoadFileFunction loadFile); + static void RegisterMemoryLoader(IdentifyMemoryFunction identifyMemory, LoadMemoryFunction loadMemory); + static void RegisterStreamLoader(IdentifyStreamFunction identifyStream, LoadStreamFunction loadStream); - static std::list s_memoryLoaders; - static std::list s_streamLoaders; - static std::multimap s_fileLoaders; + static void UnregisterFileLoader(const NzString& extensions, LoadFileFunction loadFile); + static void UnregisterMemoryLoader(IdentifyMemoryFunction identifyMemory, LoadMemoryFunction loadMemory); + static void UnregisterStreamLoader(IdentifyStreamFunction identifyStream, LoadStreamFunction loadStream); + + typedef std::pair MemoryLoader; + typedef std::pair StreamLoader; }; #include diff --git a/include/Nazara/Utility/ResourceLoader.inl b/include/Nazara/Utility/ResourceLoader.inl index ccc3cae0e..9833cf40b 100644 --- a/include/Nazara/Utility/ResourceLoader.inl +++ b/include/Nazara/Utility/ResourceLoader.inl @@ -9,7 +9,7 @@ #include template -bool NzResourceLoader::LoadResourceFromFile(Type* resource, const NzString& filePath, const Parameters& parameters) +bool NzResourceLoader::LoadFromFile(Type* resource, const NzString& filePath, const Parameters& parameters) { #if NAZARA_UTILITY_SAFE if (!parameters.IsValid()) @@ -28,7 +28,7 @@ bool NzResourceLoader::LoadResourceFromFile(Type* resource, co } // Récupération de tous les loaders de cette extension - auto range = s_fileLoaders.equal_range(ext); + auto range = Type::s_fileLoaders.equal_range(ext); if (range.first == range.second) { NazaraError("No loader found for extension \"" + ext + '"'); @@ -56,7 +56,7 @@ bool NzResourceLoader::LoadResourceFromFile(Type* resource, co } template -bool NzResourceLoader::LoadResourceFromMemory(Type* resource, const void* data, unsigned int size, const Parameters& parameters) +bool NzResourceLoader::LoadFromMemory(Type* resource, const void* data, unsigned int size, const Parameters& parameters) { #if NAZARA_UTILITY_SAFE if (!parameters.IsValid()) @@ -72,7 +72,7 @@ bool NzResourceLoader::LoadResourceFromMemory(Type* resource, } #endif - for (auto loader = s_memoryLoaders.rbegin(); loader != s_memoryLoaders.rend(); ++loader) + for (auto loader = Type::s_memoryLoaders.rbegin(); loader != Type::s_memoryLoaders.rend(); ++loader) { // Le loader supporte-t-il les données ? if (!loader->first(data, size, parameters)) @@ -90,7 +90,7 @@ bool NzResourceLoader::LoadResourceFromMemory(Type* resource, } template -bool NzResourceLoader::LoadResourceFromStream(Type* resource, NzInputStream& stream, const Parameters& parameters) +bool NzResourceLoader::LoadFromStream(Type* resource, NzInputStream& stream, const Parameters& parameters) { #if NAZARA_UTILITY_SAFE if (!parameters.IsValid()) @@ -107,7 +107,7 @@ bool NzResourceLoader::LoadResourceFromStream(Type* resource, #endif nzUInt64 streamPos = stream.GetCursorPos(); - for (auto loader = s_streamLoaders.rbegin(); loader != s_streamLoaders.rend(); ++loader) + for (auto loader = Type::s_streamLoaders.rbegin(); loader != Type::s_streamLoaders.rend(); ++loader) { stream.SetCursorPos(streamPos); @@ -129,29 +129,29 @@ bool NzResourceLoader::LoadResourceFromStream(Type* resource, } template -void NzResourceLoader::RegisterResourceFileLoader(const NzString& extensions, LoadFileFunction loadFile) +void NzResourceLoader::RegisterFileLoader(const NzString& extensions, LoadFileFunction loadFile) { std::vector exts; extensions.SplitAny(exts, " /\\*.,;|-_"); for (const NzString& ext : exts) - s_fileLoaders.insert(std::make_pair(ext, loadFile)); + Type::s_fileLoaders.insert(std::make_pair(ext, loadFile)); } template -void NzResourceLoader::RegisterResourceMemoryLoader(IsMemoryLoadingSupportedFunction isLoadingSupported, LoadMemoryFunction loadMemory) +void NzResourceLoader::RegisterMemoryLoader(IdentifyMemoryFunction identifyMemory, LoadMemoryFunction loadMemory) { - s_memoryLoaders.push_back(std::make_pair(isLoadingSupported, loadMemory)); + Type::s_memoryLoaders.push_back(std::make_pair(identifyMemory, loadMemory)); } template -void NzResourceLoader::RegisterResourceStreamLoader(IsStreamLoadingSupportedFunction isLoadingSupported, LoadStreamFunction loadStream) +void NzResourceLoader::RegisterStreamLoader(IdentifyStreamFunction identifyStream, LoadStreamFunction loadStream) { - s_streamLoaders.push_back(std::make_pair(isLoadingSupported, loadStream)); + Type::s_streamLoaders.push_back(std::make_pair(identifyStream, loadStream)); } template -void NzResourceLoader::UnregisterResourceFileLoader(const NzString& extensions, LoadFileFunction loadFile) +void NzResourceLoader::UnregisterFileLoader(const NzString& extensions, LoadFileFunction loadFile) { std::vector exts; extensions.SplitAny(exts, " /\\*.,;|-_"); @@ -159,13 +159,13 @@ void NzResourceLoader::UnregisterResourceFileLoader(const NzSt for (const NzString& ext : exts) { // Récupération de tous les loaders de cette extension - auto range = s_fileLoaders.equal_range(ext); + auto range = Type::s_fileLoaders.equal_range(ext); for (auto it = range.first; it != range.second; ++it) { if (it->second == loadFile) { - s_fileLoaders.erase(it); + Type::s_fileLoaders.erase(it); break; } } @@ -173,19 +173,15 @@ void NzResourceLoader::UnregisterResourceFileLoader(const NzSt } template -void NzResourceLoader::UnregisterResourceMemoryLoader(IsMemoryLoadingSupportedFunction isLoadingSupported, LoadMemoryFunction loadMemory) +void NzResourceLoader::UnregisterMemoryLoader(IdentifyMemoryFunction identifyMemory, LoadMemoryFunction loadMemory) { - s_memoryLoaders.remove(std::make_pair(isLoadingSupported, loadMemory)); + Type::s_memoryLoaders.remove(std::make_pair(identifyMemory, loadMemory)); } template -void NzResourceLoader::UnregisterResourceStreamLoader(IsStreamLoadingSupportedFunction isLoadingSupported, LoadStreamFunction loadStream) +void NzResourceLoader::UnregisterStreamLoader(IdentifyStreamFunction identifyStream, LoadStreamFunction loadStream) { - s_streamLoaders.remove(std::make_pair(isLoadingSupported, loadStream)); + Type::s_streamLoaders.remove(std::make_pair(identifyStream, loadStream)); } -template std::list::MemoryLoader> NzResourceLoader::s_memoryLoaders; -template std::list::StreamLoader> NzResourceLoader::s_streamLoaders; -template std::multimap::LoadFileFunction> NzResourceLoader::s_fileLoaders; - #include diff --git a/include/Nazara/Utility/StaticMesh.hpp b/include/Nazara/Utility/StaticMesh.hpp new file mode 100644 index 000000000..2e1c5684a --- /dev/null +++ b/include/Nazara/Utility/StaticMesh.hpp @@ -0,0 +1,44 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine". +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_STATICMESH_HPP +#define NAZARA_STATICMESH_HPP + +#include +#include + +class NAZARA_API NzStaticMesh final : public NzSubMesh +{ + public: + NzStaticMesh(const NzMesh* parent); + NzStaticMesh(const NzMesh* parent, const NzVertexBuffer* vertexBuffer, const NzVertexDeclaration* vertexDeclaration, const NzIndexBuffer* indexBuffer = nullptr); + virtual ~NzStaticMesh(); + + bool Create(const NzVertexBuffer* vertexBuffer, const NzVertexDeclaration* vertexDeclaration, const NzIndexBuffer* indexBuffer = nullptr); + void Destroy(); + + nzAnimationType GetAnimationType() const; + unsigned int GetFrameCount() const; + const NzIndexBuffer* GetIndexBuffer() const; + nzPrimitiveType GetPrimitiveType() const; + const NzVertexBuffer* GetVertexBuffer() const; + const NzVertexDeclaration* GetVertexDeclaration() const; + + bool IsAnimated() const; + bool IsValid() const; + + void SetPrimitiveType(nzPrimitiveType primitiveType); + + private: + void AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation); + + nzPrimitiveType m_primitiveType = nzPrimitiveType_TriangleList; + const NzIndexBuffer* m_indexBuffer = nullptr; + const NzVertexBuffer* m_vertexBuffer = nullptr; + const NzVertexDeclaration* m_vertexDeclaration = nullptr; +}; + +#endif // NAZARA_STATICMESH_HPP diff --git a/include/Nazara/Utility/SubMesh.hpp b/include/Nazara/Utility/SubMesh.hpp new file mode 100644 index 000000000..070563218 --- /dev/null +++ b/include/Nazara/Utility/SubMesh.hpp @@ -0,0 +1,42 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine". +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_SUBMESH_HPP +#define NAZARA_SUBMESH_HPP + +#include +#include +#include +#include +#include +#include + +class NzMesh; + +class NAZARA_API NzSubMesh : public NzResource +{ + friend class NzMesh; + + public: + NzSubMesh(const NzMesh* parent); + virtual ~NzSubMesh(); + + void Animate(unsigned int frameA, unsigned int frameB, float interpolation); + + virtual const NzIndexBuffer* GetIndexBuffer() const = 0; + const NzMesh* GetParent() const; + virtual nzPrimitiveType GetPrimitiveType() const = 0; + virtual const NzVertexBuffer* GetVertexBuffer() const = 0; + virtual const NzVertexDeclaration* GetVertexDeclaration() const = 0; + unsigned int GetVertexCount() const; + + protected: + virtual void AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation) = 0; + + const NzMesh* m_parent; +}; + +#endif // NAZARA_SUBMESH_HPP diff --git a/include/Nazara/Utility/VertexBuffer.hpp b/include/Nazara/Utility/VertexBuffer.hpp index d5f1acc68..49cee5012 100644 --- a/include/Nazara/Utility/VertexBuffer.hpp +++ b/include/Nazara/Utility/VertexBuffer.hpp @@ -9,8 +9,9 @@ #include #include +#include -class NAZARA_API NzVertexBuffer +class NAZARA_API NzVertexBuffer : public NzResource { public: NzVertexBuffer(NzBuffer* buffer, unsigned int startVertex, unsigned int vertexCount); diff --git a/include/Nazara/Utility/VertexDeclaration.hpp b/include/Nazara/Utility/VertexDeclaration.hpp index 1a4fa6267..78e284b97 100644 --- a/include/Nazara/Utility/VertexDeclaration.hpp +++ b/include/Nazara/Utility/VertexDeclaration.hpp @@ -6,70 +6,48 @@ #define NAZARA_VERTEXDECLARATION_HPP #include -#include - -enum nzElementType -{ - nzElementType_Color, - nzElementType_Double1, - nzElementType_Double2, - nzElementType_Double3, - nzElementType_Double4, - nzElementType_Float1, - nzElementType_Float2, - nzElementType_Float3, - nzElementType_Float4 -}; - -enum nzElementUsage -{ - nzElementUsage_Diffuse, - nzElementUsage_Normal, - nzElementUsage_Position, - nzElementUsage_Tangent, - nzElementUsage_TexCoord -}; +#include +#include struct NzVertexElement { - NzVertexElement() : stream(0), usageIndex(0) {} - unsigned int offset; - unsigned int stream; - unsigned int usageIndex; + unsigned int usageIndex = 0; + nzElementStream stream = nzElementStream_VertexData; nzElementType type; nzElementUsage usage; }; -class NAZARA_API NzVertexDeclaration +struct NzVertexDeclarationImpl; + +class NAZARA_API NzVertexDeclaration : public NzResource { public: - struct Element - { - unsigned int offset; - unsigned int usageIndex; - nzElementType type; - nzElementUsage usage; - }; - NzVertexDeclaration() = default; - ~NzVertexDeclaration() = default; + NzVertexDeclaration(const NzVertexElement* elements, unsigned int elementCount); + NzVertexDeclaration(const NzVertexDeclaration& declaration); + NzVertexDeclaration(NzVertexDeclaration&& declaration); + ~NzVertexDeclaration(); bool Create(const NzVertexElement* elements, unsigned int elementCount); + void Destroy(); - const Element* GetElement(unsigned int i, unsigned int stream = 0) const; - unsigned int GetElementCount(unsigned int stream = 0) const; - unsigned int GetStreamCount() const; - unsigned int GetStride(unsigned int stream = 0) const; + const NzVertexElement* GetElement(unsigned int i) const; + const NzVertexElement* GetElement(nzElementStream stream, unsigned int i) const; + const NzVertexElement* GetElement(nzElementStream stream, nzElementUsage usage, unsigned int usageIndex = 0) const; + unsigned int GetElementCount() const; + unsigned int GetElementCount(nzElementStream stream) const; + unsigned int GetStride(nzElementStream stream) const; + + bool HasStream(nzElementStream stream) const; + + bool IsValid() const; + + NzVertexDeclaration& operator=(const NzVertexDeclaration& declaration); + NzVertexDeclaration& operator=(NzVertexDeclaration&& declaration); private: - struct Stream - { - std::vector elements; - unsigned int stride; - }; - - std::vector m_streams; + NzVertexDeclarationImpl* m_sharedImpl = nullptr; }; #endif // NAZARA_VERTEXDECLARATION_HPP diff --git a/include/Nazara/Utility/Window.hpp b/include/Nazara/Utility/Window.hpp index 16c258739..be45ed6b9 100644 --- a/include/Nazara/Utility/Window.hpp +++ b/include/Nazara/Utility/Window.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -24,48 +25,12 @@ #include #endif +class NzCursor; class NzImage; +class NzIcon; class NzUtility; class NzWindowImpl; -enum nzWindowCursor -{ - nzWindowCursor_None, - nzWindowCursor_Default, - - nzWindowCursor_Crosshair, - nzWindowCursor_Hand, - nzWindowCursor_Help, - nzWindowCursor_Move, - nzWindowCursor_Pointer, - nzWindowCursor_Progress, - nzWindowCursor_ResizeE, - nzWindowCursor_ResizeN, - nzWindowCursor_ResizeNE, - nzWindowCursor_ResizeNW, - nzWindowCursor_ResizeS, - nzWindowCursor_ResizeSE, - nzWindowCursor_ResizeSW, - nzWindowCursor_ResizeW, - nzWindowCursor_Text, - nzWindowCursor_Wait -}; - -enum nzWindowStyle -{ - nzWindowStyle_None = 0x0, - nzWindowStyle_Fullscreen = 0x1, - - nzWindowStyle_Closable = 0x2, - nzWindowStyle_Resizable = 0x4, - nzWindowStyle_Titlebar = 0x4, - - nzWindowStyle_Default = nzWindowStyle_Closable | nzWindowStyle_Resizable | nzWindowStyle_Titlebar -}; - -class NzCursor; -class NzIcon; - class NAZARA_API NzWindow : NzNonCopyable { friend class NzUtility; diff --git a/src/Nazara/Core/Clock.cpp b/src/Nazara/Core/Clock.cpp index 816b5d69d..0963cf4af 100644 --- a/src/Nazara/Core/Clock.cpp +++ b/src/Nazara/Core/Clock.cpp @@ -13,8 +13,6 @@ #error OS not handled #endif -#define NAZARA_CLASS_CLOCK -#include #include NzClock::NzClock() : diff --git a/src/Nazara/Core/Directory.cpp b/src/Nazara/Core/Directory.cpp index 654f3bdec..c5aa37c51 100644 --- a/src/Nazara/Core/Directory.cpp +++ b/src/Nazara/Core/Directory.cpp @@ -16,8 +16,6 @@ #error OS not handled #endif -#define NAZARA_CLASS_DIRECTORY -#include #include namespace diff --git a/src/Nazara/Core/DynLib.cpp b/src/Nazara/Core/DynLib.cpp index ab88a0602..4877698df 100644 --- a/src/Nazara/Core/DynLib.cpp +++ b/src/Nazara/Core/DynLib.cpp @@ -14,8 +14,6 @@ #error No implementation for this platform #endif -#define NAZARA_CLASS_DYNLIB -#include #include NzDynLib::NzDynLib(const NzString& libraryPath) : diff --git a/src/Nazara/Core/File.cpp b/src/Nazara/Core/File.cpp index c7b21bab7..4b88e957f 100644 --- a/src/Nazara/Core/File.cpp +++ b/src/Nazara/Core/File.cpp @@ -19,8 +19,6 @@ #error OS not handled #endif -#define NAZARA_CLASS_FILE -#include #include NzFile::NzFile() : @@ -295,6 +293,7 @@ std::size_t NzFile::Read(void* buffer, std::size_t size) return m_impl->Read(buffer, size); else { + // Si nous ne devons rien lire, nous avançons simplement nzUInt64 currentPos = m_impl->GetCursorPos(); m_impl->SetCursorPos(NzFile::AtCurrent, size); diff --git a/src/Nazara/Core/Log.cpp b/src/Nazara/Core/Log.cpp index 1b338c60f..6c7ea1cf8 100644 --- a/src/Nazara/Core/Log.cpp +++ b/src/Nazara/Core/Log.cpp @@ -13,8 +13,6 @@ #include #endif -#define NAZARA_CLASS_LOG -#include #include namespace diff --git a/src/Nazara/Core/String.cpp b/src/Nazara/Core/String.cpp index c81388fe2..b983ed9e7 100644 --- a/src/Nazara/Core/String.cpp +++ b/src/Nazara/Core/String.cpp @@ -13,9 +13,6 @@ #include #include #include - -#define NAZARA_CLASS_STRING -#include #include inline unsigned int nzPow2(unsigned int n) @@ -2850,7 +2847,7 @@ unsigned int NzString::Replace(const char* oldString, const char* replaceString, else ///TODO: Algorithme de remplacement sans changement de buffer (si rSize < oSize) { unsigned int newSize = m_sharedString->size + Count(oldString)*(rSize - oSize); - if (newSize == m_sharedString->size) // Count(oldString) == 0 + if (newSize == m_sharedString->size) // Alors c'est que Count(oldString) == 0 return 0; char* newString = new char[newSize+1]; @@ -2920,7 +2917,7 @@ unsigned int NzString::Replace(const NzString& oldString, const NzString& replac else { unsigned int newSize = m_sharedString->size + Count(oldString)*(replaceString.m_sharedString->size - oldString.m_sharedString->size); - if (newSize == m_sharedString->size) // Count(oldString) == 0 + if (newSize == m_sharedString->size) // Alors c'est que Count(oldString) == 0 return 0; char* newString = new char[newSize+1]; @@ -3205,6 +3202,9 @@ void NzString::Reserve(unsigned int bufferSize) NzString& NzString::Resize(int size, char character) { + if (size == 0) + Clear(true); + if (size < 0) size = std::max(static_cast(m_sharedString->size + size), 0); @@ -3249,6 +3249,9 @@ NzString& NzString::Resize(int size, char character) NzString NzString::Resized(int size, char character) const { + if (size == 0) + return NzString(); + if (size < 0) size = m_sharedString->size + size; @@ -3499,8 +3502,9 @@ unsigned int NzString::SplitAny(std::vector& result, const char* separ if (m_sharedString->size == 0) return 0; - unsigned int lastSep = FindAny(separations, start, flags); unsigned int oldSize = result.size(); + + unsigned int lastSep = FindAny(separations, start, flags); if (lastSep == npos) { result.push_back(*this); @@ -5098,11 +5102,12 @@ void NzString::ReleaseString() return; NazaraMutexLock(m_sharedString->mutex); - m_sharedString->refCount--; + bool freeSharedString = (--m_sharedString->refCount == 0); NazaraMutexUnlock(m_sharedString->mutex); - if (m_sharedString->refCount == 0) + if (freeSharedString) { + NazaraMutexUnlock(m_sharedString->mutex); delete[] m_sharedString->string; delete m_sharedString; } diff --git a/src/Nazara/Core/Unicode.cpp b/src/Nazara/Core/Unicode.cpp index da7d59f5d..95828049b 100644 --- a/src/Nazara/Core/Unicode.cpp +++ b/src/Nazara/Core/Unicode.cpp @@ -6,49 +6,46 @@ #include #include -namespace NzUnicode +#if NAZARA_CORE_INCLUDE_UNICODEDATA +struct Character { - #if NAZARA_CORE_INCLUDE_UNICODEDATA - struct Character - { - nzUInt16 category; // Le type du caractère - nzUInt8 direction; // Le sens de lecure du caractère - nzUInt32 lowerCase; // Le caractère correspondant en minuscule - nzUInt32 titleCase; // Le caractère correspondant en titre - nzUInt32 upperCase; // Le caractère correspondant en majuscule - }; + nzUInt16 category; // Le type du caractère + nzUInt8 direction; // Le sens de lecure du caractère + nzUInt32 lowerCase; // Le caractère correspondant en minuscule + nzUInt32 titleCase; // Le caractère correspondant en titre + nzUInt32 upperCase; // Le caractère correspondant en majuscule +}; - #include +#include - #else // Implémentation bidon +#else // Implémentation bidon - Category GetCategory(char32_t character) - { - NazaraUnused(character); +NzUnicode::Category NzUnicode::GetCategory(char32_t character) +{ + NazaraUnused(character); - return Category_NoCategory; - } - - Direction GetDirection(char32_t character) - { - NazaraUnused(character); - - return Direction_Boundary_Neutral; - } - - char32_t GetLowercase(char32_t character) - { - return character; - } - - char32_t GetTitlecase(char32_t character) - { - return character; - } - - char32_t GetUppercase(char32_t character) - { - return character; - } - #endif + return Category_NoCategory; } + +NzUnicode::Direction NzUnicode::GetDirection(char32_t character) +{ + NazaraUnused(character); + + return Direction_Boundary_Neutral; +} + +char32_t NzUnicode::GetLowercase(char32_t character) +{ + return character; +} + +char32_t NzUnicode::GetTitlecase(char32_t character) +{ + return character; +} + +char32_t NzUnicode::GetUppercase(char32_t character) +{ + return character; +} +#endif diff --git a/src/Nazara/Core/Win32/ThreadConditionImpl.hpp b/src/Nazara/Core/Win32/ThreadConditionImpl.hpp index dd7260b40..cf2fb3b8f 100644 --- a/src/Nazara/Core/Win32/ThreadConditionImpl.hpp +++ b/src/Nazara/Core/Win32/ThreadConditionImpl.hpp @@ -2,13 +2,13 @@ // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp +// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html + #pragma once #ifndef NAZARA_THREADCONDITIONIMPL_HPP #define NAZARA_THREADCONDITIONIMPL_HPP -// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html - #include #include diff --git a/src/Nazara/Renderer/Context.cpp b/src/Nazara/Renderer/Context.cpp index 520586671..29d69ce0e 100644 --- a/src/Nazara/Renderer/Context.cpp +++ b/src/Nazara/Renderer/Context.cpp @@ -290,7 +290,8 @@ bool NzContext::EnsureContext() threadContext = context; } - else if (!threadContext->SetActive(true)) + + if (!threadContext->SetActive(true)) { NazaraError("Failed to active thread context"); return false; diff --git a/src/Nazara/Renderer/ContextParameters.cpp b/src/Nazara/Renderer/ContextParameters.cpp index 55bf0794e..04ecffee8 100644 --- a/src/Nazara/Renderer/ContextParameters.cpp +++ b/src/Nazara/Renderer/ContextParameters.cpp @@ -6,15 +6,27 @@ #include #include -nzUInt8 NzContextParameters::defaultMajorVersion; // Initialisé par NzOpenGL -nzUInt8 NzContextParameters::defaultMinorVersion; // Initialisé par NzOpenGL +// Version majeure d'OpenGL, initialisé par NzOpenGL::Initialize() +nzUInt8 NzContextParameters::defaultMajorVersion; + + // Version majeure d'OpenGL, initialisé par NzOpenGL::Initialize() +nzUInt8 NzContextParameters::defaultMinorVersion; + +// Contexte de partage par défaut, initialisé par NzOpenGL::Initialize() const NzContext* NzContextParameters::defaultShareContext = nullptr; -NzWindowHandle NzContextParameters::defaultWindow = 0; + +// Si possible, garder la compatibilité avec les fonctionnalités dépréciées bool NzContextParameters::defaultCompatibilityProfile = false; + +// Mode debug d'OpenGL par défaut #if NAZARA_RENDERER_OPENGL_DEBUG || defined(NAZARA_DEBUG) bool NzContextParameters::defaultDebugMode = true; #else bool NzContextParameters::defaultDebugMode = false; #endif + +// Active le double-buffering sur les contextes bool NzContextParameters::defaultDoubleBuffered = false; + +// Active le partage des ressources entre contextes (Via le defaultShareContext) bool NzContextParameters::defaultShared = true; diff --git a/src/Nazara/Renderer/GLSLShader.cpp b/src/Nazara/Renderer/GLSLShader.cpp index 9c3569fa2..b5d37d905 100644 --- a/src/Nazara/Renderer/GLSLShader.cpp +++ b/src/Nazara/Renderer/GLSLShader.cpp @@ -130,10 +130,11 @@ bool NzGLSLShader::Create() glBindAttribLocation(m_program, attribIndex[nzElementUsage_Diffuse], "Diffuse"); glBindAttribLocation(m_program, attribIndex[nzElementUsage_Tangent], "Tangent"); - NzString uniformName = "TexCoord*"; - for (unsigned int i = 0; i < 8; ++i) + NzString uniform = "TexCoord"; + unsigned int maxTexCoords = NazaraRenderer->GetMaxTextureUnits(); + for (unsigned int i = 0; i < maxTexCoords; ++i) { - uniformName[8] = '0'+i; + NzString uniformName = uniform + NzString::Number(i); glBindAttribLocation(m_program, attribIndex[nzElementUsage_TexCoord]+i, uniformName.GetConstBuffer()); } diff --git a/src/Nazara/Renderer/OpenGL.cpp b/src/Nazara/Renderer/OpenGL.cpp index d119ada59..0c775fef5 100644 --- a/src/Nazara/Renderer/OpenGL.cpp +++ b/src/Nazara/Renderer/OpenGL.cpp @@ -298,7 +298,8 @@ bool NzOpenGL::Initialize() return false; } - // Fonctions optionnelles + /****************************************Extensions****************************************/ + glGetStringi = reinterpret_cast(LoadEntry("glGetStringi", false)); glMapBufferRange = reinterpret_cast(LoadEntry("glMapBufferRange", false)); @@ -310,8 +311,6 @@ bool NzOpenGL::Initialize() glXSwapInterval = reinterpret_cast(LoadEntry("glXSwapIntervalSGI", false)); #endif - /****************************************Extensions****************************************/ - if (!glGetStringi || !LoadExtensions3()) { if (openGLversion >= 300) // Dans le cas contraire c'est normal @@ -353,7 +352,7 @@ bool NzOpenGL::Initialize() } catch (const std::exception& e) { - NazaraError("Failed to load GL_ARB_debug_output: " + NzString(e.what())); + NazaraWarning("Failed to load GL_ARB_debug_output: " + NzString(e.what())); } } @@ -371,7 +370,7 @@ bool NzOpenGL::Initialize() } catch (const std::exception& e) { - NazaraError("Failed to load ARB_gpu_shader_fp64: " + NzString(e.what())); + NazaraWarning("Failed to load ARB_gpu_shader_fp64: " + NzString(e.what())); } } @@ -396,7 +395,7 @@ bool NzOpenGL::Initialize() } catch (const std::exception& e) { - NazaraError("Failed to load ARB_framebuffer_object: (" + NzString(e.what()) + ")"); + NazaraWarning("Failed to load ARB_framebuffer_object: (" + NzString(e.what()) + ")"); } } @@ -452,7 +451,7 @@ bool NzOpenGL::Initialize() } catch (const std::exception& e) { - NazaraError("Failed to load EXT_texture3D: " + NzString(e.what())); + NazaraWarning("Failed to load EXT_texture3D: " + NzString(e.what())); } } } @@ -473,7 +472,7 @@ bool NzOpenGL::Initialize() } catch (const std::exception& e) { - NazaraError("Failed to load ARB_texture_storage: " + NzString(e.what())); + NazaraWarning("Failed to load ARB_texture_storage: " + NzString(e.what())); } } @@ -490,10 +489,14 @@ bool NzOpenGL::Initialize() } catch (const std::exception& e) { - NazaraError("Failed to load ARB_vertex_array_object: " + NzString(e.what())); + NazaraWarning("Failed to load ARB_vertex_array_object: " + NzString(e.what())); } } + // Fonctions de substitut + if (!glGenerateMipmap) + glGenerateMipmap = reinterpret_cast(LoadEntry("glGenerateMipmapEXT", false)); + /****************************************Contexte de référence****************************************/ ///FIXME: Utiliser le contexte de chargement comme référence ? (Vérifier mode debug) @@ -505,6 +508,8 @@ bool NzOpenGL::Initialize() return false; } + NzContextParameters::defaultShareContext = NzContext::GetReference(); + return true; } diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index 6f764ed1e..d5865277f 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -28,7 +28,8 @@ namespace 1, // nzElementUsage_Normal 0, // nzElementUsage_Position 3, // nzElementUsage_Tangent - 4 // nzElementUsage_TexCoord + + 4 // nzElementUsage_TexCoord (Doit être le dernier de la liste car extensible) }; @@ -403,7 +404,11 @@ bool NzRenderer::Initialize() GLint maxTextureUnits; glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits); - m_maxTextureUnit = static_cast(maxTextureUnits); + GLint maxVertexAttribs; + glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs); + + // Impossible de binder plus de texcoords que d'attributes (en sachant qu'un certain nombre est déjà pris par les autres attributs) + m_maxTextureUnit = static_cast(std::min(maxTextureUnits, maxVertexAttribs-attribIndex[nzElementUsage_TexCoord])); } else m_maxTextureUnit = 1; @@ -836,23 +841,23 @@ bool NzRenderer::EnsureStateUpdate() const nzUInt8* buffer = reinterpret_cast(m_vertexBuffer->GetPointer()); - ///FIXME: Améliorer les déclarations pour permettre de faire ça plus simplement - for (int i = 0; i < 12; ++i) // Solution temporaire, à virer - glDisableVertexAttribArray(i); // Chaque itération tue un chaton :( - - unsigned int stride = m_vertexDeclaration->GetStride(); - unsigned int elementCount = m_vertexDeclaration->GetElementCount(); - for (unsigned int i = 0; i < elementCount; ++i) + unsigned int stride = m_vertexDeclaration->GetStride(nzElementStream_VertexData); + for (unsigned int i = 0; i <= nzElementUsage_Max; ++i) { - const NzVertexDeclaration::Element* element = m_vertexDeclaration->GetElement(i); + const NzVertexElement* element = m_vertexDeclaration->GetElement(nzElementStream_VertexData, static_cast(i)); - glEnableVertexAttribArray(attribIndex[element->usage]+element->usageIndex); - glVertexAttribPointer(attribIndex[element->usage]+element->usageIndex, - openglSize[element->type], - openglType[element->type], - (element->type == nzElementType_Color) ? GL_TRUE : GL_FALSE, - stride, - &buffer[element->offset]); + if (element) + { + glEnableVertexAttribArray(attribIndex[i]); + glVertexAttribPointer(attribIndex[i], + openglSize[element->type], + openglType[element->type], + (element->type == nzElementType_Color) ? GL_TRUE : GL_FALSE, + stride, + &buffer[element->offset]); + } + else + glDisableVertexAttribArray(attribIndex[i]); } if (m_indexBuffer) diff --git a/src/Nazara/Renderer/Texture.cpp b/src/Nazara/Renderer/Texture.cpp index 44706f6c5..abd54b992 100644 --- a/src/Nazara/Renderer/Texture.cpp +++ b/src/Nazara/Renderer/Texture.cpp @@ -341,7 +341,7 @@ bool NzTexture::Bind() const glBindTexture(openglTarget[m_impl->type], m_impl->id); - if (!m_impl->mipmapsUpdated) + if (m_impl->mipmapping && !m_impl->mipmapsUpdated) { glGenerateMipmap(openglTarget[m_impl->type]); m_impl->mipmapsUpdated = true; @@ -433,7 +433,13 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt NzContext::EnsureContext(); - levelCount = std::min(levelCount, NzImage::GetMaxLevel(width, height, depth)); + if (IsMipmappingSupported()) + levelCount = std::min(levelCount, NzImage::GetMaxLevel(width, height, depth)); + else if (levelCount > 1) + { + NazaraWarning("Mipmapping not supported, reducing level count to 1"); + levelCount = 1; + } NzTextureImpl* impl = new NzTextureImpl; glGenTextures(1, &impl->id); @@ -477,10 +483,7 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt SetWrapMode(nzTextureWrap_Repeat); if (m_impl->levelCount > 1U) - { - m_impl->mipmapping = true; - m_impl->mipmapsUpdated = false; - } + EnableMipmapping(true); if (!lock) UnlockTexture(impl); @@ -577,25 +580,17 @@ bool NzTexture::EnableMipmapping(bool enable) } #endif - if (!glGenerateMipmap) + if (m_impl->levelCount == 1) + return true; + + if (!IsMipmappingSupported()) { NazaraError("Mipmapping not supported"); return false; } if (!m_impl->mipmapping && enable) - { - GLint tex; - glGetIntegerv(openglTargetBinding[m_impl->type], &tex); - - if (m_impl->id == static_cast(tex)) - { - glGenerateMipmap(openglTarget[m_impl->type]); - m_impl->mipmapsUpdated = true; - } - else - m_impl->mipmapsUpdated = false; - } + m_impl->mipmapsUpdated = false; m_impl->mipmapping = enable; @@ -848,7 +843,6 @@ bool NzTexture::LoadFromImage(const NzImage& image) if (!IsFormatSupported(format)) { nzPixelFormat newFormat = (NzPixelFormat::HasAlpha(format)) ? nzPixelFormat_BGRA8 : nzPixelFormat_BGR8; - NazaraWarning("Format not supported, trying to convert it to " + NzPixelFormat::ToString(newFormat) + "..."); if (NzPixelFormat::IsConversionSupported(format, newFormat)) @@ -872,14 +866,13 @@ bool NzTexture::LoadFromImage(const NzImage& image) } nzImageType type = newImage.GetType(); - nzUInt8 levelCount = newImage.GetLevelCount(); - if (!Create(type, format, newImage.GetWidth(), newImage.GetHeight(), newImage.GetDepth(), levelCount, true)) + if (!Create(type, format, newImage.GetWidth(), newImage.GetHeight(), newImage.GetDepth(), newImage.GetLevelCount(), true)) { NazaraError("Failed to create texture"); return false; } - for (nzUInt8 level = 0; level < levelCount; ++level) + for (nzUInt8 level = 0; level < m_impl->levelCount; ++level) { if (!Update(newImage.GetConstPixels(level), level)) { @@ -942,13 +935,13 @@ bool NzTexture::SetAnisotropyLevel(unsigned int anistropyLevel) NazaraError("Texture must be valid"); return false; } + #endif if (!NzOpenGL::IsSupported(NzOpenGL::AnisotropicFilter)) { NazaraError("Anisotropic filter not supported"); return false; } - #endif LockTexture(m_impl); @@ -981,7 +974,7 @@ bool NzTexture::SetFilterMode(nzTextureFilter filter) switch (filter) { case nzTextureFilter_Bilinear: - if (m_impl->levelCount > 1) + if (m_impl->mipmapping > 1) glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); else glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -990,7 +983,7 @@ bool NzTexture::SetFilterMode(nzTextureFilter filter) break; case nzTextureFilter_Nearest: - if (m_impl->levelCount > 1) + if (m_impl->mipmapping > 1) glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); else glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -1588,6 +1581,11 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format) return false; } +bool NzTexture::IsMipmappingSupported() +{ + return glGenerateMipmap != nullptr; +} + bool NzTexture::IsTypeSupported(nzImageType type) { switch (type) diff --git a/src/Nazara/Utility/Animation.cpp b/src/Nazara/Utility/Animation.cpp new file mode 100644 index 000000000..92e815f9c --- /dev/null +++ b/src/Nazara/Utility/Animation.cpp @@ -0,0 +1,318 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine". +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include + +struct NzAnimationImpl +{ + std::map sequenceMap; + std::vector sequences; + nzAnimationType type; + unsigned int frameCount; +}; + +bool NzAnimationParams::IsValid() const +{ + if (startFrame > endFrame) + { + NazaraError("Start frame must be lower than end frame"); + return false; + } + + return true; +} + +NzAnimation::~NzAnimation() +{ + Destroy(); +} + +unsigned int NzAnimation::AddSequence(const NzSequence& sequence) +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Animation not created"); + return 0; + } + #endif + + unsigned int index = m_impl->sequences.size(); + + if (!sequence.name.IsEmpty()) + { + #if NAZARA_UTILITY_SAFE + auto it = m_impl->sequenceMap.find(sequence.name); + if (it != m_impl->sequenceMap.end()) + { + NazaraError("Sequence name \"" + sequence.name + "\" is already used"); + return 0; + } + #endif + + m_impl->sequenceMap[sequence.name] = index; + } + + m_impl->sequences.push_back(sequence); + + return index; +} + +bool NzAnimation::Create(nzAnimationType type, unsigned int frameCount) +{ + Destroy(); + + #if NAZARA_UTILITY_SAFE + if (type == nzAnimationType_Static) + { + NazaraError("Invalid type"); + return false; + } + + if (frameCount == 0) + { + NazaraError("Frame count must be over zero"); + return false; + } + #endif + + m_impl = new NzAnimationImpl; + m_impl->frameCount = frameCount; + m_impl->type = type; + + return true; +} + +void NzAnimation::Destroy() +{ + if (m_impl) + { + delete m_impl; + m_impl = nullptr; + } +} + +unsigned int NzAnimation::GetFrameCount() const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Animation not created"); + return false; + } + #endif + + return m_impl->frameCount; +} + +NzSequence* NzAnimation::GetSequence(const NzString& sequenceName) +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Animation not created"); + return nullptr; + } + + auto it = m_impl->sequenceMap.find(sequenceName); + if (it == m_impl->sequenceMap.end()) + { + NazaraError("Sequence not found"); + return nullptr; + } + + return &m_impl->sequences[it->second]; + #else + return &m_impl->sequences[m_impl->sequenceMap[sequenceName]]; + #endif +} + +NzSequence* NzAnimation::GetSequence(unsigned int index) +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Animation not created"); + return nullptr; + } + + if (index >= m_impl->sequences.size()) + { + NazaraError("Sequence index out of range (" + NzString::Number(index) + " >= " + NzString::Number(m_impl->sequences.size()) + ')'); + return nullptr; + } + #endif + + return &m_impl->sequences[index]; +} + +const NzSequence* NzAnimation::GetSequence(const NzString& sequenceName) const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Animation not created"); + return nullptr; + } + + auto it = m_impl->sequenceMap.find(sequenceName); + if (it == m_impl->sequenceMap.end()) + { + NazaraError("Sequence not found"); + return nullptr; + } + + return &m_impl->sequences[it->second]; + #else + return &m_impl->sequences[m_impl->sequenceMap[sequenceName]]; + #endif +} + +const NzSequence* NzAnimation::GetSequence(unsigned int index) const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Animation not created"); + return nullptr; + } + + if (index >= m_impl->sequences.size()) + { + NazaraError("Sequence index out of range (" + NzString::Number(index) + " >= " + NzString::Number(m_impl->sequences.size()) + ')'); + return nullptr; + } + #endif + + return &m_impl->sequences[index]; +} + +unsigned int NzAnimation::GetSequenceCount() const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Animation not created"); + return 0; + } + #endif + + return m_impl->sequences.size(); +} + +nzAnimationType NzAnimation::GetType() const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Animation not created"); + return nzAnimationType_Static; // Ce qui est une valeur invalide pour NzAnimation + } + #endif + + return m_impl->type; +} + +bool NzAnimation::HasSequence(const NzString& sequenceName) const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Animation not created"); + return false; + } + #endif + + return m_impl->sequenceMap.find(sequenceName) != m_impl->sequenceMap.end(); +} + +bool NzAnimation::HasSequence(unsigned int index) const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Animation not created"); + return false; + } + #endif + + return index >= m_impl->sequences.size(); +} + +bool NzAnimation::IsValid() const +{ + return m_impl != nullptr; +} + +bool NzAnimation::LoadFromFile(const NzString& filePath, const NzAnimationParams& params) +{ + return NzAnimationLoader::LoadFromFile(this, filePath, params); +} + +bool NzAnimation::LoadFromMemory(const void* data, std::size_t size, const NzAnimationParams& params) +{ + return NzAnimationLoader::LoadFromMemory(this, data, size, params); +} + +bool NzAnimation::LoadFromStream(NzInputStream& stream, const NzAnimationParams& params) +{ + return NzAnimationLoader::LoadFromStream(this, stream, params); +} + +void NzAnimation::RemoveSequence(const NzString& identifier) +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Animation not created"); + return; + } + + auto it = m_impl->sequenceMap.find(identifier); + if (it == m_impl->sequenceMap.end()) + { + NazaraError("SubMesh not found"); + return; + } + + unsigned int index = it->second; + #else + unsigned int index = m_impl->sequenceMap[identifier]; + #endif + + auto it2 = m_impl->sequences.begin(); + std::advance(it2, index); + + m_impl->sequences.erase(it2); +} + +void NzAnimation::RemoveSequence(unsigned int index) +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Animation not created"); + return; + } + + if (index >= m_impl->sequences.size()) + { + NazaraError("Sequence index out of range (" + NzString::Number(index) + " >= " + NzString::Number(m_impl->sequences.size()) + ')'); + return; + } + #endif + + auto it = m_impl->sequences.begin(); + std::advance(it, index); + + m_impl->sequences.erase(it); +} + +std::list NzAnimation::s_memoryLoaders; +std::list NzAnimation::s_streamLoaders; +std::multimap NzAnimation::s_fileLoaders; diff --git a/src/Nazara/Utility/Image.cpp b/src/Nazara/Utility/Image.cpp index 1f7211514..662d59238 100644 --- a/src/Nazara/Utility/Image.cpp +++ b/src/Nazara/Utility/Image.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include @@ -22,6 +21,11 @@ namespace } } +bool NzImageParams::IsValid() const +{ + return true; +} + NzImage::NzImage() : m_sharedImage(&emptyImage) { @@ -799,17 +803,17 @@ bool NzImage::IsValid() const bool NzImage::LoadFromFile(const NzString& filePath, const NzImageParams& params) { - return NzResourceLoader::LoadResourceFromFile(this, filePath, params); + return NzImageLoader::LoadFromFile(this, filePath, params); } bool NzImage::LoadFromMemory(const void* data, std::size_t size, const NzImageParams& params) { - return NzResourceLoader::LoadResourceFromMemory(this, data, size, params); + return NzImageLoader::LoadFromMemory(this, data, size, params); } bool NzImage::LoadFromStream(NzInputStream& stream, const NzImageParams& params) { - return NzResourceLoader::LoadResourceFromStream(this, stream, params); + return NzImageLoader::LoadFromStream(this, stream, params); } bool NzImage::SetLevelCount(nzUInt8 levelCount) @@ -1091,36 +1095,6 @@ nzUInt8 NzImage::GetMaxLevel(unsigned int width, unsigned int height, unsigned i return std::max(std::max(std::max(widthLevel, heightLevel), depthLevel), 1U); } -void NzImage::RegisterFileLoader(const NzString& extensions, LoadFileFunction loadFile) -{ - return RegisterResourceFileLoader(extensions, loadFile); -} - -void NzImage::RegisterMemoryLoader(IsMemoryLoadingSupportedFunction isLoadingSupported, LoadMemoryFunction loadMemory) -{ - return RegisterResourceMemoryLoader(isLoadingSupported, loadMemory); -} - -void NzImage::RegisterStreamLoader(IsStreamLoadingSupportedFunction isLoadingSupported, LoadStreamFunction loadStream) -{ - return RegisterResourceStreamLoader(isLoadingSupported, loadStream); -} - -void NzImage::UnregisterFileLoader(const NzString& extensions, LoadFileFunction loadFile) -{ - UnregisterResourceFileLoader(extensions, loadFile); -} - -void NzImage::UnregisterMemoryLoader(IsMemoryLoadingSupportedFunction isLoadingSupported, LoadMemoryFunction loadMemory) -{ - UnregisterResourceMemoryLoader(isLoadingSupported, loadMemory); -} - -void NzImage::UnregisterStreamLoader(IsStreamLoadingSupportedFunction isLoadingSupported, LoadStreamFunction loadStream) -{ - UnregisterResourceStreamLoader(isLoadingSupported, loadStream); -} - void NzImage::EnsureOwnership() { if (m_sharedImage == &emptyImage) @@ -1149,10 +1123,10 @@ void NzImage::ReleaseImage() return; NazaraMutexLock(m_sharedImage->mutex); - m_sharedImage->refCount--; + bool freeSharedImage = (--m_sharedImage->refCount == 0); NazaraMutexUnlock(m_sharedImage->mutex); - if (m_sharedImage->refCount == 0) + if (freeSharedImage) { for (unsigned int i = 0; i < m_sharedImage->levelCount; ++i) delete[] m_sharedImage->pixels[i]; @@ -1165,3 +1139,6 @@ void NzImage::ReleaseImage() } NzImage::SharedImage NzImage::emptyImage(0, nzImageType_2D, nzPixelFormat_Undefined, 1, nullptr, 0, 0, 0); +std::list NzImage::s_memoryLoaders; +std::list NzImage::s_streamLoaders; +std::multimap NzImage::s_fileLoaders; diff --git a/src/Nazara/Utility/IndexBuffer.cpp b/src/Nazara/Utility/IndexBuffer.cpp index b4792b096..e14f30424 100644 --- a/src/Nazara/Utility/IndexBuffer.cpp +++ b/src/Nazara/Utility/IndexBuffer.cpp @@ -52,6 +52,7 @@ m_startIndex(0) } NzIndexBuffer::NzIndexBuffer(const NzIndexBuffer& indexBuffer) : +NzResource(true), m_buffer(indexBuffer.m_buffer), m_ownsBuffer(indexBuffer.m_ownsBuffer), m_indexCount(indexBuffer.m_indexCount), diff --git a/src/Nazara/Utility/KeyframeMesh.cpp b/src/Nazara/Utility/KeyframeMesh.cpp new file mode 100644 index 000000000..c9d5fe0ff --- /dev/null +++ b/src/Nazara/Utility/KeyframeMesh.cpp @@ -0,0 +1,13 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine". +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +NzKeyframeMesh::NzKeyframeMesh(const NzMesh* parent) : +NzSubMesh(parent) +{ +} + +NzKeyframeMesh::~NzKeyframeMesh() = default; diff --git a/src/Nazara/Utility/Loaders/MD2.hpp b/src/Nazara/Utility/Loaders/MD2.hpp new file mode 100644 index 000000000..a0be386e6 --- /dev/null +++ b/src/Nazara/Utility/Loaders/MD2.hpp @@ -0,0 +1,15 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine". +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_LOADERS_MD2_HPP +#define NAZARA_LOADERS_MD2_HPP + +#include + +void NzLoaders_MD2_Register(); +void NzLoaders_MD2_Unregister(); + +#endif // NAZARA_LOADERS_MD2_HPP diff --git a/src/Nazara/Utility/Loaders/MD2/Constants.cpp b/src/Nazara/Utility/Loaders/MD2/Constants.cpp new file mode 100644 index 000000000..872e5c7dd --- /dev/null +++ b/src/Nazara/Utility/Loaders/MD2/Constants.cpp @@ -0,0 +1,173 @@ +// Copyright (C) 2011 Jérôme Leclercq +// This file is part of the "Ungine". +// For conditions of distribution and use, see copyright notice in Core.h + +#include + +const nzUInt32 md2Ident = 'I' + ('D'<<8) + ('P'<<16) + ('2'<<24); + +const NzVector3f md2Normals[162] = +{ + NzVector3f(-0.525731f, 0.000000f, 0.850651f), + NzVector3f(-0.442863f, 0.238856f, 0.864188f), + NzVector3f(-0.295242f, 0.000000f, 0.955423f), + NzVector3f(-0.309017f, 0.500000f, 0.809017f), + NzVector3f(-0.162460f, 0.262866f, 0.951056f), + NzVector3f(0.000000f, 0.000000f, 1.000000f), + NzVector3f(0.000000f, 0.850651f, 0.525731f), + NzVector3f(-0.147621f, 0.716567f, 0.681718f), + NzVector3f(0.147621f, 0.716567f, 0.681718f), + NzVector3f(0.000000f, 0.525731f, 0.850651f), + NzVector3f(0.309017f, 0.500000f, 0.809017f), + NzVector3f(0.525731f, 0.000000f, 0.850651f), + NzVector3f(0.295242f, 0.000000f, 0.955423f), + NzVector3f(0.442863f, 0.238856f, 0.864188f), + NzVector3f(0.162460f, 0.262866f, 0.951056f), + NzVector3f(-0.681718f, 0.147621f, 0.716567f), + NzVector3f(-0.809017f, 0.309017f, 0.500000f), + NzVector3f(-0.587785f, 0.425325f, 0.688191f), + NzVector3f(-0.850651f, 0.525731f, 0.000000f), + NzVector3f(-0.864188f, 0.442863f, 0.238856f), + NzVector3f(-0.716567f, 0.681718f, 0.147621f), + NzVector3f(-0.688191f, 0.587785f, 0.425325f), + NzVector3f(-0.500000f, 0.809017f, 0.309017f), + NzVector3f(-0.238856f, 0.864188f, 0.442863f), + NzVector3f(-0.425325f, 0.688191f, 0.587785f), + NzVector3f(-0.716567f, 0.681718f, -0.147621f), + NzVector3f(-0.500000f, 0.809017f, -0.309017f), + NzVector3f(-0.525731f, 0.850651f, 0.000000f), + NzVector3f(0.000000f, 0.850651f, -0.525731f), + NzVector3f(-0.238856f, 0.864188f, -0.442863f), + NzVector3f(0.000000f, 0.955423f, -0.295242f), + NzVector3f(-0.262866f, 0.951056f, -0.162460f), + NzVector3f(0.000000f, 1.000000f, 0.000000f), + NzVector3f(0.000000f, 0.955423f, 0.295242f), + NzVector3f(-0.262866f, 0.951056f, 0.162460f), + NzVector3f(0.238856f, 0.864188f, 0.442863f), + NzVector3f(0.262866f, 0.951056f, 0.162460f), + NzVector3f(0.500000f, 0.809017f, 0.309017f), + NzVector3f(0.238856f, 0.864188f, -0.442863f), + NzVector3f(0.262866f, 0.951056f, -0.162460f), + NzVector3f(0.500000f, 0.809017f, -0.309017f), + NzVector3f(0.850651f, 0.525731f, 0.000000f), + NzVector3f(0.716567f, 0.681718f, 0.147621f), + NzVector3f(0.716567f, 0.681718f, -0.147621f), + NzVector3f(0.525731f, 0.850651f, 0.000000f), + NzVector3f(0.425325f, 0.688191f, 0.587785f), + NzVector3f(0.864188f, 0.442863f, 0.238856f), + NzVector3f(0.688191f, 0.587785f, 0.425325f), + NzVector3f(0.809017f, 0.309017f, 0.500000f), + NzVector3f(0.681718f, 0.147621f, 0.716567f), + NzVector3f(0.587785f, 0.425325f, 0.688191f), + NzVector3f(0.955423f, 0.295242f, 0.000000f), + NzVector3f(1.000000f, 0.000000f, 0.000000f), + NzVector3f(0.951056f, 0.162460f, 0.262866f), + NzVector3f(0.850651f, -0.525731f, 0.000000f), + NzVector3f(0.955423f, -0.295242f, 0.000000f), + NzVector3f(0.864188f, -0.442863f, 0.238856f), + NzVector3f(0.951056f, -0.162460f, 0.262866f), + NzVector3f(0.809017f, -0.309017f, 0.500000f), + NzVector3f(0.681718f, -0.147621f, 0.716567f), + NzVector3f(0.850651f, 0.000000f, 0.525731f), + NzVector3f(0.864188f, 0.442863f, -0.238856f), + NzVector3f(0.809017f, 0.309017f, -0.500000f), + NzVector3f(0.951056f, 0.162460f, -0.262866f), + NzVector3f(0.525731f, 0.000000f, -0.850651f), + NzVector3f(0.681718f, 0.147621f, -0.716567f), + NzVector3f(0.681718f, -0.147621f, -0.716567f), + NzVector3f(0.850651f, 0.000000f, -0.525731f), + NzVector3f(0.809017f, -0.309017f, -0.500000f), + NzVector3f(0.864188f, -0.442863f, -0.238856f), + NzVector3f(0.951056f, -0.162460f, -0.262866f), + NzVector3f(0.147621f, 0.716567f, -0.681718f), + NzVector3f(0.309017f, 0.500000f, -0.809017f), + NzVector3f(0.425325f, 0.688191f, -0.587785f), + NzVector3f(0.442863f, 0.238856f, -0.864188f), + NzVector3f(0.587785f, 0.425325f, -0.688191f), + NzVector3f(0.688191f, 0.587785f, -0.425325f), + NzVector3f(-0.147621f, 0.716567f, -0.681718f), + NzVector3f(-0.309017f, 0.500000f, -0.809017f), + NzVector3f(0.000000f, 0.525731f, -0.850651f), + NzVector3f(-0.525731f, 0.000000f, -0.850651f), + NzVector3f(-0.442863f, 0.238856f, -0.864188f), + NzVector3f(-0.295242f, 0.000000f, -0.955423f), + NzVector3f(-0.162460f, 0.262866f, -0.951056f), + NzVector3f(0.000000f, 0.000000f, -1.000000f), + NzVector3f(0.295242f, 0.000000f, -0.955423f), + NzVector3f(0.162460f, 0.262866f, -0.951056f), + NzVector3f(-0.442863f, -0.238856f, -0.864188f), + NzVector3f(-0.309017f, -0.500000f, -0.809017f), + NzVector3f(-0.162460f, -0.262866f, -0.951056f), + NzVector3f(0.000000f, -0.850651f, -0.525731f), + NzVector3f(-0.147621f, -0.716567f, -0.681718f), + NzVector3f(0.147621f, -0.716567f, -0.681718f), + NzVector3f(0.000000f, -0.525731f, -0.850651f), + NzVector3f(0.309017f, -0.500000f, -0.809017f), + NzVector3f(0.442863f, -0.238856f, -0.864188f), + NzVector3f(0.162460f, -0.262866f, -0.951056f), + NzVector3f(0.238856f, -0.864188f, -0.442863f), + NzVector3f(0.500000f, -0.809017f, -0.309017f), + NzVector3f(0.425325f, -0.688191f, -0.587785f), + NzVector3f(0.716567f, -0.681718f, -0.147621f), + NzVector3f(0.688191f, -0.587785f, -0.425325f), + NzVector3f(0.587785f, -0.425325f, -0.688191f), + NzVector3f(0.000000f, -0.955423f, -0.295242f), + NzVector3f(0.000000f, -1.000000f, 0.000000f), + NzVector3f(0.262866f, -0.951056f, -0.162460f), + NzVector3f(0.000000f, -0.850651f, 0.525731f), + NzVector3f(0.000000f, -0.955423f, 0.295242f), + NzVector3f(0.238856f, -0.864188f, 0.442863f), + NzVector3f(0.262866f, -0.951056f, 0.162460f), + NzVector3f(0.500000f, -0.809017f, 0.309017f), + NzVector3f(0.716567f, -0.681718f, 0.147621f), + NzVector3f(0.525731f, -0.850651f, 0.000000f), + NzVector3f(-0.238856f, -0.864188f, -0.442863f), + NzVector3f(-0.500000f, -0.809017f, -0.309017f), + NzVector3f(-0.262866f, -0.951056f, -0.162460f), + NzVector3f(-0.850651f, -0.525731f, 0.000000f), + NzVector3f(-0.716567f, -0.681718f, -0.147621f), + NzVector3f(-0.716567f, -0.681718f, 0.147621f), + NzVector3f(-0.525731f, -0.850651f, 0.000000f), + NzVector3f(-0.500000f, -0.809017f, 0.309017f), + NzVector3f(-0.238856f, -0.864188f, 0.442863f), + NzVector3f(-0.262866f, -0.951056f, 0.162460f), + NzVector3f(-0.864188f, -0.442863f, 0.238856f), + NzVector3f(-0.809017f, -0.309017f, 0.500000f), + NzVector3f(-0.688191f, -0.587785f, 0.425325f), + NzVector3f(-0.681718f, -0.147621f, 0.716567f), + NzVector3f(-0.442863f, -0.238856f, 0.864188f), + NzVector3f(-0.587785f, -0.425325f, 0.688191f), + NzVector3f(-0.309017f, -0.500000f, 0.809017f), + NzVector3f(-0.147621f, -0.716567f, 0.681718f), + NzVector3f(-0.425325f, -0.688191f, 0.587785f), + NzVector3f(-0.162460f, -0.262866f, 0.951056f), + NzVector3f(0.442863f, -0.238856f, 0.864188f), + NzVector3f(0.162460f, -0.262866f, 0.951056f), + NzVector3f(0.309017f, -0.500000f, 0.809017f), + NzVector3f(0.147621f, -0.716567f, 0.681718f), + NzVector3f(0.000000f, -0.525731f, 0.850651f), + NzVector3f(0.425325f, -0.688191f, 0.587785f), + NzVector3f(0.587785f, -0.425325f, 0.688191f), + NzVector3f(0.688191f, -0.587785f, 0.425325f), + NzVector3f(-0.955423f, 0.295242f, 0.000000f), + NzVector3f(-0.951056f, 0.162460f, 0.262866f), + NzVector3f(-1.000000f, 0.000000f, 0.000000f), + NzVector3f(-0.850651f, 0.000000f, 0.525731f), + NzVector3f(-0.955423f, -0.295242f, 0.000000f), + NzVector3f(-0.951056f, -0.162460f, 0.262866f), + NzVector3f(-0.864188f, 0.442863f, -0.238856f), + NzVector3f(-0.951056f, 0.162460f, -0.262866f), + NzVector3f(-0.809017f, 0.309017f, -0.500000f), + NzVector3f(-0.864188f, -0.442863f, -0.238856f), + NzVector3f(-0.951056f, -0.162460f, -0.262866f), + NzVector3f(-0.809017f, -0.309017f, -0.500000f), + NzVector3f(-0.681718f, 0.147621f, -0.716567f), + NzVector3f(-0.681718f, -0.147621f, -0.716567f), + NzVector3f(-0.850651f, 0.000000f, -0.525731f), + NzVector3f(-0.688191f, 0.587785f, -0.425325f), + NzVector3f(-0.587785f, 0.425325f, -0.688191f), + NzVector3f(-0.425325f, 0.688191f, -0.587785f), + NzVector3f(-0.425325f, -0.688191f, -0.587785f), + NzVector3f(-0.587785f, -0.425325f, -0.688191f), + NzVector3f(-0.688191f, -0.587785f, -0.425325f) +}; diff --git a/src/Nazara/Utility/Loaders/MD2/Constants.hpp b/src/Nazara/Utility/Loaders/MD2/Constants.hpp new file mode 100644 index 000000000..ae4263a98 --- /dev/null +++ b/src/Nazara/Utility/Loaders/MD2/Constants.hpp @@ -0,0 +1,65 @@ +// Copyright (C) 2011 Jérôme Leclercq +// This file is part of the "Ungine". +// For conditions of distribution and use, see copyright notice in Core.h + +#ifndef NAZARA_LOADERS_MD2_CONSTANTS_HPP +#define NAZARA_LOADERS_MD2_CONSTANTS_HPP + +#include +#include +#include + +struct md2_header +{ + nzUInt32 ident; // nombre magique : "IDP2" + nzUInt32 version; // version du format : 8 + + nzUInt32 skinwidth; // largeur texture + nzUInt32 skinheight; // hauteur texture + + nzUInt32 framesize; // taille d'une frame en octets + + nzUInt32 num_skins; // nombre de skins + nzUInt32 num_vertices; // nombre de vertices par frame + nzUInt32 num_st; // nombre de coordonnées de texture + nzUInt32 num_tris; // nombre de triangles + nzUInt32 num_glcmds; // nombre de commandes opengl + nzUInt32 num_frames; // nombre de frames + + nzUInt32 offset_skins; // offset données skins + nzUInt32 offset_st; // offset données coordonnées de texture + nzUInt32 offset_tris; // offset données triangles + nzUInt32 offset_frames; // offset données frames + nzUInt32 offset_glcmds; // offset données commandes OpenGL + nzUInt32 offset_end; // offset fin de fichier +}; + +struct md2_vertex +{ + nzUInt8 x, y, z; + nzUInt8 n; +}; + +struct md2_texCoord +{ + nzInt16 u, v; +}; + +struct md2_triangle +{ + nzUInt16 vertices[3]; + nzUInt16 texCoords[3]; +}; + +struct md2_frame +{ + NzVector3f scale; + NzVector3f translate; + char name[16]; + std::vector vertices; +}; + +extern const nzUInt32 md2Ident; +extern const NzVector3f md2Normals[162]; + +#endif // NAZARA_LOADERS_MD2_CONSTANTS_HPP diff --git a/src/Nazara/Utility/Loaders/MD2/Loader.cpp b/src/Nazara/Utility/Loaders/MD2/Loader.cpp new file mode 100644 index 000000000..b625ede27 --- /dev/null +++ b/src/Nazara/Utility/Loaders/MD2/Loader.cpp @@ -0,0 +1,266 @@ +// Copyright (C) 2011 Jérôme Leclercq +// This file is part of the "Ungine". +// For conditions of distribution and use, see copyright notice in Core.h + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + bool NzLoader_MD2_LoadStream(NzMesh* mesh, NzInputStream& stream, const NzMeshParams& parameters); + + bool NzLoader_MD2_LoadFile(NzMesh* mesh, const NzString& filePath, const NzMeshParams& parameters) + { + NzFile file(filePath); + if (!file.Open(NzFile::ReadOnly)) + { + NazaraError("Failed to open file"); + return false; + } + + return NzLoader_MD2_LoadStream(mesh, file, parameters); + } + + bool NzLoader_MD2_LoadMemory(NzMesh* mesh, const void* data, unsigned int size, const NzMeshParams& parameters) + { + NzMemoryStream stream(data, size); + return NzLoader_MD2_LoadStream(mesh, stream, parameters); + } + + bool NzLoader_MD2_LoadStream(NzMesh* mesh, NzInputStream& stream, const NzMeshParams& parameters) + { + md2_header header; + if (stream.Read(&header, sizeof(md2_header)) != sizeof(md2_header)) + { + NazaraError("Failed to read header"); + return false; + } + + // Les fichiers MD2 sont en little endian + #if NAZARA_BIG_ENDIAN + NzByteSwap(&header.ident, sizeof(nzUInt32)); + #endif + + if (header.ident != md2Ident) + { + NazaraError("Invalid MD2 file"); + return false; + } + + #if NAZARA_BIG_ENDIAN + NzByteSwap(&header.version, sizeof(nzUInt32)); + #endif + + if (header.version != 8) + { + NazaraError("Bad version number (" + NzString::Number(header.version) + ')'); + return false; + } + + #if NAZARA_BIG_ENDIAN + NzByteSwap(&header.skinwidth, sizeof(nzUInt32)); + NzByteSwap(&header.skinheight, sizeof(nzUInt32)); + NzByteSwap(&header.framesize, sizeof(nzUInt32)); + NzByteSwap(&header.num_skins, sizeof(nzUInt32)); + NzByteSwap(&header.num_vertices, sizeof(nzUInt32)); + NzByteSwap(&header.num_st, sizeof(nzUInt32)); + NzByteSwap(&header.num_tris, sizeof(nzUInt32)); + NzByteSwap(&header.num_glcmds, sizeof(nzUInt32)); + NzByteSwap(&header.num_frames, sizeof(nzUInt32)); + NzByteSwap(&header.offset_skins, sizeof(nzUInt32)); + NzByteSwap(&header.offset_st, sizeof(nzUInt32)); + NzByteSwap(&header.offset_tris, sizeof(nzUInt32)); + NzByteSwap(&header.offset_frames, sizeof(nzUInt32)); + NzByteSwap(&header.offset_glcmds, sizeof(nzUInt32)); + NzByteSwap(&header.offset_end, sizeof(nzUInt32)); + #endif + + if (stream.GetSize() < header.offset_end) + { + NazaraError("Incomplete MD2 file"); + return false; + } + + /// Création du mesh + // Animé ou statique, c'est la question + bool animated; + unsigned int startFrame = NzClamp(parameters.animation.startFrame, 0U, static_cast(header.num_frames-1)); + unsigned int endFrame = NzClamp(parameters.animation.endFrame, 0U, static_cast(header.num_frames-1)); + + if (parameters.loadAnimations && startFrame != endFrame) + animated = true; + else + animated = false; + + if (!mesh->Create((animated) ? nzAnimationType_Keyframe : nzAnimationType_Static)) // Ne devrait pas échouer + { + NazaraInternalError("Failed to create mesh"); + return false; + } + + /// Chargement des skins + if (header.num_skins > 0) + { + stream.SetCursorPos(header.offset_skins); + { + char skin[68]; + for (unsigned int i = 0; i < header.num_skins; ++i) + { + stream.Read(skin, 68*sizeof(char)); + mesh->AddSkin(skin); + } + } + } + + /// Chargement des animmations + if (animated) + { + NzAnimation* animation = new NzAnimation; + if (animation->Create(nzAnimationType_Keyframe, endFrame-startFrame+1)) + { + NzString frameName; + + NzSequence sequence; + sequence.framePerSecond = 10; // Par défaut pour les animations MD2 + + char name[16], last[16]; + stream.SetCursorPos(header.offset_frames + startFrame*header.framesize + offsetof(md2_frame, name)); + stream.Read(last, 16*sizeof(char)); + + int pos = std::strlen(last)-1; + for (unsigned int j = 0; j < 2; ++j) + { + if (!std::isdigit(last[pos])) + break; + + pos--; + } + last[pos+1] = '\0'; + + unsigned int numFrames = 0; + for (unsigned int i = startFrame; i <= endFrame; ++i) + { + stream.SetCursorPos(header.offset_frames + i*header.framesize + offsetof(md2_frame, name)); + stream.Read(name, 16*sizeof(char)); + + int pos = std::strlen(name)-1; + for (unsigned int j = 0; j < 2; ++j) + { + if (!std::isdigit(name[pos])) + break; + + pos--; + } + name[pos+1] = '\0'; + + if (std::strcmp(name, last) != 0) // Si les deux frames n'ont pas le même nom + { + // Alors on enregistre la séquence + sequence.firstFrame = i-numFrames; + sequence.lastFrame = i-1; + sequence.name = last; + animation->AddSequence(sequence); + + std::strcpy(last, name); + + numFrames = 0; + } + + numFrames++; + } + + // On ajoute la dernière frame (Qui n'a pas été traitée par la boucle) + sequence.firstFrame = endFrame-numFrames; + sequence.lastFrame = endFrame; + sequence.name = last; + animation->AddSequence(sequence); + + mesh->SetAnimation(animation); + animation->SetPersistent(false); + } + else + NazaraInternalError("Failed to create animaton"); + } + + /// Chargement des submesh + // Actuellement le loader ne charge qu'un submesh + // TODO: Utiliser les commandes OpenGL pour accélérer le rendu + NzMD2Mesh* subMesh = new NzMD2Mesh(mesh); + if (!subMesh->Create(header, stream, parameters)) + { + NazaraError("Failed to create MD2 mesh"); + return false; + } + + mesh->AddSubMesh(subMesh); + + return true; + } + + bool NzLoader_MD2_IdentifyMemory(const void* data, unsigned int size, const NzMeshParams& parameters) + { + NazaraUnused(parameters); + + if (size < sizeof(md2_header)) + return false; + + const md2_header* header = reinterpret_cast(data); + + #if NAZARA_BIG_ENDIAN + nzUInt32 ident = header->ident; + nzUInt32 version = header->version; + + NzByteSwap(&ident, sizeof(nzUInt32)); + NzByteSwap(&version, sizeof(nzUInt32)); + + return ident == md2Ident && version == 8; + #else + return header->ident == md2Ident && header->version == 8; + #endif + } + + bool NzLoader_MD2_IdentifyStream(NzInputStream& stream, const NzMeshParams& parameters) + { + NazaraUnused(parameters); + + nzUInt32 magic[2]; + if (stream.Read(&magic[0], 2*sizeof(nzUInt32)) != 2*sizeof(nzUInt32)) + return false; + + #if NAZARA_BIG_ENDIAN + NzByteSwap(&magic[0], sizeof(nzUInt32)); + NzByteSwap(&magic[1], sizeof(nzUInt32)); + #endif + + return magic[0] == md2Ident && magic[1] == 8; + } +} + +void NzLoaders_MD2_Register() +{ + NzMD2Mesh::Initialize(); + + NzMeshLoader::RegisterFileLoader("md2", NzLoader_MD2_LoadFile); + NzMeshLoader::RegisterMemoryLoader(NzLoader_MD2_IdentifyMemory, NzLoader_MD2_LoadMemory); + NzMeshLoader::RegisterStreamLoader(NzLoader_MD2_IdentifyStream, NzLoader_MD2_LoadStream); +} + +void NzLoaders_MD2_Unregister() +{ + NzMeshLoader::UnregisterStreamLoader(NzLoader_MD2_IdentifyStream, NzLoader_MD2_LoadStream); + NzMeshLoader::UnregisterMemoryLoader(NzLoader_MD2_IdentifyMemory, NzLoader_MD2_LoadMemory); + NzMeshLoader::UnregisterFileLoader("md2", NzLoader_MD2_LoadFile); + + NzMD2Mesh::Uninitialize(); +} diff --git a/src/Nazara/Utility/Loaders/MD2/Mesh.cpp b/src/Nazara/Utility/Loaders/MD2/Mesh.cpp new file mode 100644 index 000000000..184bb868f --- /dev/null +++ b/src/Nazara/Utility/Loaders/MD2/Mesh.cpp @@ -0,0 +1,275 @@ +// Copyright (C) 2011 Jérôme Leclercq +// This file is part of the "Ungine". +// For conditions of distribution and use, see copyright notice in Core.h + +#include +#include +#include +#include +#include +#include +#include + +NzMD2Mesh::NzMD2Mesh(const NzMesh* parent) : +NzKeyframeMesh(parent), +m_frames(nullptr), +m_indexBuffer(nullptr), +m_vertexBuffer(nullptr) +{ +} + +NzMD2Mesh::~NzMD2Mesh() +{ + Destroy(); +} + +bool NzMD2Mesh::Create(const md2_header& header, NzInputStream& stream, const NzMeshParams& parameters) +{ + Destroy(); + + unsigned int startFrame = NzClamp(parameters.animation.startFrame, 0U, static_cast(header.num_frames-1)); + unsigned int endFrame = NzClamp(parameters.animation.endFrame, 0U, static_cast(header.num_frames-1)); + + m_frameCount = endFrame - startFrame + 1; + m_vertexCount = header.num_tris*3; + + /// Chargement des vertices + std::vector texCoords(header.num_st); + std::vector triangles(header.num_tris); + + // Lecture des coordonnées de texture + stream.SetCursorPos(header.offset_st); + stream.Read(&texCoords[0], header.num_st*sizeof(md2_texCoord)); + + #if NAZARA_BIG_ENDIAN + for (unsigned int i = 0; i < header.num_st; ++i) + { + NzByteSwap(&texCoords[i].u, sizeof(nzInt16)); + NzByteSwap(&texCoords[i].v, sizeof(nzInt16)); + } + #endif + + stream.SetCursorPos(header.offset_tris); + stream.Read(&triangles[0], header.num_tris*sizeof(md2_triangle)); + + #if NAZARA_BIG_ENDIAN + for (unsigned int i = 0; i < header.num_tris; ++i) + { + NzByteSwap(&triangles[i].vertices[0], sizeof(nzUInt16)); + NzByteSwap(&texCoords[i].texCoords[0], sizeof(nzUInt16)); + + NzByteSwap(&triangles[i].vertices[1], sizeof(nzUInt16)); + NzByteSwap(&texCoords[i].texCoords[1], sizeof(nzUInt16)); + + NzByteSwap(&triangles[i].vertices[2], sizeof(nzUInt16)); + NzByteSwap(&texCoords[i].texCoords[2], sizeof(nzUInt16)); + } + #endif + + stream.SetCursorPos(header.offset_frames + header.framesize*startFrame); + + md2_frame frame; + frame.vertices.resize(header.num_vertices); + + // Pour que le modèle soit correctement aligné, on génère une matrice de rotation que nous appliquerons à chacune des vertices + NzMatrix4f rotationMatrix = NzMatrix4f::Rotate(NzEulerAnglesf(-90.f, 0.f, -90.f)); + //NzMatrix4f rotationMatrix; + //rotationMatrix.SetIdentity(); + + unsigned int stride = s_declaration.GetStride(nzElementStream_VertexData); + + m_frames = new Frame[m_frameCount]; + for (unsigned int i = 0; i < m_frameCount; ++i) + { + stream.Read(&frame.scale, sizeof(NzVector3f)); + stream.Read(&frame.translate, sizeof(NzVector3f)); + stream.Read(&frame.name, 16*sizeof(char)); + stream.Read(&frame.vertices[0], header.num_vertices*sizeof(md2_vertex)); + + #if NAZARA_BIG_ENDIAN + NzByteSwap(&frame.scale.x, sizeof(float)); + NzByteSwap(&frame.scale.y, sizeof(float)); + NzByteSwap(&frame.scale.z, sizeof(float)); + + NzByteSwap(&frame.translate.x, sizeof(float)); + NzByteSwap(&frame.translate.y, sizeof(float)); + NzByteSwap(&frame.translate.z, sizeof(float)); + #endif + + m_frames[i].normal = new nzUInt8[m_vertexCount]; // Nous stockons l'indice de la normale plutôt que la normale (gain d'espace) + m_frames[i].vertices = new NzVector3f[m_vertexCount]; + for (unsigned int t = 0; t < header.num_tris; ++t) + { + for (unsigned int v = 0; v < 3; ++v) + { + const md2_vertex& vert = frame.vertices[triangles[t].vertices[v]]; + + NzVector3f vertex = rotationMatrix * NzVector3f(vert.x * frame.scale.x + frame.translate.x, vert.y * frame.scale.y + frame.translate.y, vert.z * frame.scale.z + frame.translate.z); + + m_frames[i].normal[t*3+v] = vert.n; + m_frames[i].vertices[t*3+v] = vertex; + } + } + } + + nzBufferStorage storage = (NzBuffer::IsSupported(nzBufferStorage_Hardware) && !parameters.forceSoftware) ? nzBufferStorage_Hardware : nzBufferStorage_Software; + + m_indexBuffer = nullptr; // Pas d'indexbuffer pour l'instant + m_vertexBuffer = new NzVertexBuffer(m_vertexCount, (3+3+2)*sizeof(float), storage, nzBufferUsage_Dynamic); + + nzUInt8* ptr = reinterpret_cast(m_vertexBuffer->Map(nzBufferAccess_WriteOnly)); + if (!ptr) + { + NazaraError("Failed to map vertex buffer"); + Destroy(); + + return false; + } + + // On avance jusqu'aux premières coordonnées de texture + ptr += s_declaration.GetElement(nzElementStream_VertexData, nzElementUsage_TexCoord)->offset; + for (unsigned int t = 0; t < header.num_tris; ++t) + { + for (unsigned int v = 0; v < 3; ++v) + { + const md2_texCoord& texC = texCoords[triangles[t].texCoords[v]]; + + NzVector2f* coords = reinterpret_cast(ptr); + coords->x = texC.u / static_cast(header.skinwidth); + coords->y = 1.f - texC.v / static_cast(header.skinheight); + + ptr += stride; + } + } + + if (!m_vertexBuffer->Unmap()) + { + NazaraError("Failed to unmap buffer"); + Destroy(); + + return false; + } + + m_vertexBuffer->AddResourceReference(); + m_vertexBuffer->SetPersistent(false); + + AnimateImpl(0, 0, 0.f); + + return true; +} + +void NzMD2Mesh::Destroy() +{ + if (m_frames) + { + for (unsigned int i = 0; i < m_frameCount; ++i) + { + delete[] m_frames[i].normal; + delete[] m_frames[i].vertices; + } + + delete[] m_frames; + m_frames = nullptr; + } + + if (m_indexBuffer) + { + m_indexBuffer->RemoveResourceReference(); + m_indexBuffer = nullptr; + } + + if (m_vertexBuffer) + { + m_vertexBuffer->RemoveResourceReference(); + m_vertexBuffer = nullptr; + } +} + +nzAnimationType NzMD2Mesh::GetAnimationType() const +{ + if (m_frameCount > 1) + return nzAnimationType_Keyframe; + else + return nzAnimationType_Static; +} + +unsigned int NzMD2Mesh::GetFrameCount() const +{ + return m_frameCount; +} + +const NzIndexBuffer* NzMD2Mesh::GetIndexBuffer() const +{ + return nullptr; + //return m_indexBuffer; +} + +nzPrimitiveType NzMD2Mesh::GetPrimitiveType() const +{ + return nzPrimitiveType_TriangleList; +} + +const NzVertexBuffer* NzMD2Mesh::GetVertexBuffer() const +{ + return m_vertexBuffer; +} + +const NzVertexDeclaration* NzMD2Mesh::GetVertexDeclaration() const +{ + return &s_declaration; +} + +void NzMD2Mesh::Initialize() +{ + NzVertexElement elements[3]; + elements[0].offset = 0; + elements[0].type = nzElementType_Float3; + elements[0].usage = nzElementUsage_Position; + + elements[1].offset = 3*sizeof(float); + elements[1].type = nzElementType_Float3; + elements[1].usage = nzElementUsage_Normal; + + elements[2].offset = 3*sizeof(float) + 3*sizeof(float); + elements[2].type = nzElementType_Float2; + elements[2].usage = nzElementUsage_TexCoord; + + s_declaration.Create(elements, 3); +} + +void NzMD2Mesh::Uninitialize() +{ + s_declaration.Destroy(); +} + +void NzMD2Mesh::AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation) +{ + nzUInt8* ptr = reinterpret_cast(m_vertexBuffer->Map(nzBufferAccess_WriteOnly)); + if (!ptr) + { + NazaraError("Failed to map vertex buffer"); + return; + } + + unsigned int stride = s_declaration.GetStride(nzElementStream_VertexData); + unsigned int positionOffset = s_declaration.GetElement(nzElementStream_VertexData, nzElementUsage_Position)->offset; + unsigned int normalOffset = s_declaration.GetElement(nzElementStream_VertexData, nzElementUsage_Normal)->offset; + + Frame* fA = &m_frames[frameA]; + Frame* fB = &m_frames[frameB]; + for (unsigned int i = 0; i < m_vertexCount; ++i) + { + NzVector3f* position = reinterpret_cast(ptr + positionOffset); + NzVector3f* normal = reinterpret_cast(ptr + normalOffset); + + *position = fA->vertices[i] + interpolation * (fB->vertices[i] - fA->vertices[i]); + *normal = md2Normals[fA->normal[i]] + interpolation * (md2Normals[fB->normal[i]] - md2Normals[fA->normal[i]]); + + ptr += stride; + } + + if (!m_vertexBuffer->Unmap()) + NazaraWarning("Failed to unmap vertex buffer, expect mesh corruption"); +} + +NzVertexDeclaration NzMD2Mesh::s_declaration; diff --git a/src/Nazara/Utility/Loaders/MD2/Mesh.hpp b/src/Nazara/Utility/Loaders/MD2/Mesh.hpp new file mode 100644 index 000000000..5b0b47efd --- /dev/null +++ b/src/Nazara/Utility/Loaders/MD2/Mesh.hpp @@ -0,0 +1,64 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine". +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_LOADERS_MD2_MESH_HPP +#define NAZARA_LOADERS_MD2_MESH_HPP + +#include +#include +#include +#include +#include + +class NzIndexBuffer; +class NzInputStream; +class NzVertexBuffer; +struct NzMeshParams; + +class NAZARA_API NzMD2Mesh : public NzKeyframeMesh +{ + public: + NzMD2Mesh(const NzMesh* parent); + ~NzMD2Mesh(); + + bool Create(const md2_header& header, NzInputStream& stream, const NzMeshParams& parameters); + void Destroy(); + + nzAnimationType GetAnimationType() const; + unsigned int GetFrameCount() const; + const NzIndexBuffer* GetIndexBuffer() const; + nzPrimitiveType GetPrimitiveType() const; + const NzVertexBuffer* GetVertexBuffer() const; + const NzVertexDeclaration* GetVertexDeclaration() const; + + bool IsAnimated() const; + + static void Initialize(); + static void Uninitialize(); + + private: + void AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation); + + struct Frame + { + //AxisAlignedBox aabb; + nzUInt8* normal; + NzVector3f* tangents; + NzVector3f* vertices; + char name[16]; + }; + + //AxisAlignedBox m_aabb; + Frame* m_frames; + NzIndexBuffer* m_indexBuffer; + NzVertexBuffer* m_vertexBuffer; + unsigned int m_frameCount; + unsigned int m_vertexCount; + + static NzVertexDeclaration s_declaration; +}; + +#endif // NAZARA_LOADERS_MD2_MESH_HPP diff --git a/src/Nazara/Utility/Loaders/PCX.cpp b/src/Nazara/Utility/Loaders/PCX/Loader.cpp similarity index 83% rename from src/Nazara/Utility/Loaders/PCX.cpp rename to src/Nazara/Utility/Loaders/PCX/Loader.cpp index 9460ef396..fd30498cd 100644 --- a/src/Nazara/Utility/Loaders/PCX.cpp +++ b/src/Nazara/Utility/Loaders/PCX/Loader.cpp @@ -37,9 +37,9 @@ namespace nzUInt8 padding[54]; }; - bool NzLoader_PCX_LoadStream(NzImage* resource, NzInputStream& stream, const NzImageParams& parameters); + bool NzLoader_PCX_LoadStream(NzImage* image, NzInputStream& stream, const NzImageParams& parameters); - bool NzLoader_PCX_LoadFile(NzImage* resource, const NzString& filePath, const NzImageParams& parameters) + bool NzLoader_PCX_LoadFile(NzImage* image, const NzString& filePath, const NzImageParams& parameters) { NzFile file(filePath); if (!file.Open(NzFile::ReadOnly)) @@ -48,16 +48,16 @@ namespace return false; } - return NzLoader_PCX_LoadStream(resource, file, parameters); + return NzLoader_PCX_LoadStream(image, file, parameters); } - bool NzLoader_PCX_LoadMemory(NzImage* resource, const void* data, unsigned int size, const NzImageParams& parameters) + bool NzLoader_PCX_LoadMemory(NzImage* image, const void* data, unsigned int size, const NzImageParams& parameters) { NzMemoryStream stream(data, size); - return NzLoader_PCX_LoadStream(resource, stream, parameters); + return NzLoader_PCX_LoadStream(image, stream, parameters); } - bool NzLoader_PCX_LoadStream(NzImage* resource, NzInputStream& stream, const NzImageParams& parameters) + bool NzLoader_PCX_LoadStream(NzImage* image, NzInputStream& stream, const NzImageParams& parameters) { NazaraUnused(parameters); @@ -93,13 +93,13 @@ namespace unsigned int width = header.xmax - header.xmin+1; unsigned int height = header.ymax - header.ymin+1; - if (!resource->Create(nzImageType_2D, nzPixelFormat_RGB8, width, height, 1, (parameters.levelCount > 0) ? parameters.levelCount : 1)) + if (!image->Create(nzImageType_2D, nzPixelFormat_RGB8, width, height, 1, (parameters.levelCount > 0) ? parameters.levelCount : 1)) { NazaraError("Failed to create image"); return false; } - nzUInt8* pixels = resource->GetPixels(); + nzUInt8* pixels = image->GetPixels(); int rle_value = 0; unsigned int rle_count = 0; @@ -339,17 +339,17 @@ namespace } default: - NazaraError("Unknown " + NzString::Number(bitCount) + " bitcount pcx files"); + NazaraError("Unable to load " + NzString::Number(bitCount) + " bitcount pcx files"); return false; } if (parameters.loadFormat != nzPixelFormat_Undefined) - resource->Convert(parameters.loadFormat); + image->Convert(parameters.loadFormat); return true; } - bool NzLoader_PCX_IsMemoryLoadingSupported(const void* data, unsigned int size, const NzImageParams& parameters) + bool NzLoader_PCX_IdentifyMemory(const void* data, unsigned int size, const NzImageParams& parameters) { NazaraUnused(parameters); @@ -359,12 +359,13 @@ namespace return *reinterpret_cast(data) == 0x0a; } - bool NzLoader_PCX_IsStreamLoadingSupported(NzInputStream& stream, const NzImageParams& parameters) + bool NzLoader_PCX_IdentifyStream(NzInputStream& stream, const NzImageParams& parameters) { NazaraUnused(parameters); nzUInt8 manufacturer; - stream.Read(&manufacturer, 1); + if (stream.Read(&manufacturer, 1) != 1) + return false; return manufacturer == 0x0a; } @@ -372,14 +373,14 @@ namespace void NzLoaders_PCX_Register() { - NzImage::RegisterFileLoader("pcx", NzLoader_PCX_LoadFile); - NzImage::RegisterMemoryLoader(NzLoader_PCX_IsMemoryLoadingSupported, NzLoader_PCX_LoadMemory); - NzImage::RegisterStreamLoader(NzLoader_PCX_IsStreamLoadingSupported, NzLoader_PCX_LoadStream); + NzImageLoader::RegisterFileLoader("pcx", NzLoader_PCX_LoadFile); + NzImageLoader::RegisterMemoryLoader(NzLoader_PCX_IdentifyMemory, NzLoader_PCX_LoadMemory); + NzImageLoader::RegisterStreamLoader(NzLoader_PCX_IdentifyStream, NzLoader_PCX_LoadStream); } void NzLoaders_PCX_Unregister() { - NzImage::UnregisterStreamLoader(NzLoader_PCX_IsStreamLoadingSupported, NzLoader_PCX_LoadStream); - NzImage::UnregisterMemoryLoader(NzLoader_PCX_IsMemoryLoadingSupported, NzLoader_PCX_LoadMemory); - NzImage::UnregisterFileLoader("pcx", NzLoader_PCX_LoadFile); + NzImageLoader::UnregisterStreamLoader(NzLoader_PCX_IdentifyStream, NzLoader_PCX_LoadStream); + NzImageLoader::UnregisterMemoryLoader(NzLoader_PCX_IdentifyMemory, NzLoader_PCX_LoadMemory); + NzImageLoader::UnregisterFileLoader("pcx", NzLoader_PCX_LoadFile); } diff --git a/src/Nazara/Utility/Loaders/STB.cpp b/src/Nazara/Utility/Loaders/STB/Loader.cpp similarity index 65% rename from src/Nazara/Utility/Loaders/STB.cpp rename to src/Nazara/Utility/Loaders/STB/Loader.cpp index e031fa4b1..d5b260de0 100644 --- a/src/Nazara/Utility/Loaders/STB.cpp +++ b/src/Nazara/Utility/Loaders/STB/Loader.cpp @@ -15,8 +15,6 @@ #include -// Auteur du loader original : David Henry - namespace { int Read(void* userdata, char* data, int size) @@ -39,9 +37,9 @@ namespace static stbi_io_callbacks callbacks = {Read, Skip, Eof}; - bool NzLoader_STB_LoadStream(NzImage* resource, NzInputStream& stream, const NzImageParams& parameters); + bool NzLoader_STB_LoadStream(NzImage* image, NzInputStream& stream, const NzImageParams& parameters); - bool NzLoader_STB_LoadFile(NzImage* resource, const NzString& filePath, const NzImageParams& parameters) + bool NzLoader_STB_LoadFile(NzImage* image, const NzString& filePath, const NzImageParams& parameters) { NzFile file(filePath); if (!file.Open(NzFile::ReadOnly)) @@ -50,16 +48,16 @@ namespace return false; } - return NzLoader_STB_LoadStream(resource, file, parameters); + return NzLoader_STB_LoadStream(image, file, parameters); } - bool NzLoader_STB_LoadMemory(NzImage* resource, const void* data, unsigned int size, const NzImageParams& parameters) + bool NzLoader_STB_LoadMemory(NzImage* image, const void* data, unsigned int size, const NzImageParams& parameters) { NzMemoryStream stream(data, size); - return NzLoader_STB_LoadStream(resource, stream, parameters); + return NzLoader_STB_LoadStream(image, stream, parameters); } - bool NzLoader_STB_LoadStream(NzImage* resource, NzInputStream& stream, const NzImageParams& parameters) + bool NzLoader_STB_LoadStream(NzImage* image, NzInputStream& stream, const NzImageParams& parameters) { NazaraUnused(parameters); @@ -112,7 +110,7 @@ namespace if (format == nzPixelFormat_Undefined) format = formats[bpp-1]; - if (!resource->Create(nzImageType_2D, format, width, height, 1, (parameters.levelCount > 0) ? parameters.levelCount : 1)) + if (!image->Create(nzImageType_2D, format, width, height, 1, (parameters.levelCount > 0) ? parameters.levelCount : 1)) { NazaraError("Failed to create image"); stbi_image_free(ptr); @@ -120,17 +118,17 @@ namespace return false; } - resource->Update(ptr); + image->Update(ptr); stbi_image_free(ptr); if (stbiFormat == STBI_default && parameters.loadFormat != nzPixelFormat_Undefined) - resource->Convert(parameters.loadFormat); + image->Convert(parameters.loadFormat); return true; } - bool NzLoader_STB_IsMemoryLoadingSupported(const void* data, unsigned int size, const NzImageParams& parameters) + bool NzLoader_STB_IdentifyMemory(const void* data, unsigned int size, const NzImageParams& parameters) { NazaraUnused(parameters); @@ -138,7 +136,7 @@ namespace return stbi_info_from_memory(reinterpret_cast(data), size, &width, &height, &bpp); } - bool NzLoader_STB_IsStreamLoadingSupported(NzInputStream& stream, const NzImageParams& parameters) + bool NzLoader_STB_IdentifyStream(NzInputStream& stream, const NzImageParams& parameters) { NazaraUnused(parameters); @@ -149,14 +147,14 @@ namespace void NzLoaders_STB_Register() { - NzImage::RegisterFileLoader("bmp, gif, hdr, jpg, jpeg, pic, png, psd, tga", NzLoader_STB_LoadFile); - NzImage::RegisterMemoryLoader(NzLoader_STB_IsMemoryLoadingSupported, NzLoader_STB_LoadMemory); - NzImage::RegisterStreamLoader(NzLoader_STB_IsStreamLoadingSupported, NzLoader_STB_LoadStream); + NzImageLoader::RegisterFileLoader("bmp, gif, hdr, jpg, jpeg, pic, png, psd, tga", NzLoader_STB_LoadFile); + NzImageLoader::RegisterMemoryLoader(NzLoader_STB_IdentifyMemory, NzLoader_STB_LoadMemory); + NzImageLoader::RegisterStreamLoader(NzLoader_STB_IdentifyStream, NzLoader_STB_LoadStream); } void NzLoaders_STB_Unregister() { - NzImage::UnregisterStreamLoader(NzLoader_STB_IsStreamLoadingSupported, NzLoader_STB_LoadStream); - NzImage::UnregisterMemoryLoader(NzLoader_STB_IsMemoryLoadingSupported, NzLoader_STB_LoadMemory); - NzImage::UnregisterFileLoader("bmp, gif, hdr, jpg, jpeg, pic, png, psd, tga", NzLoader_STB_LoadFile); + NzImageLoader::UnregisterStreamLoader(NzLoader_STB_IdentifyStream, NzLoader_STB_LoadStream); + NzImageLoader::UnregisterMemoryLoader(NzLoader_STB_IdentifyMemory, NzLoader_STB_LoadMemory); + NzImageLoader::UnregisterFileLoader("bmp, gif, hdr, jpg, jpeg, pic, png, psd, tga", NzLoader_STB_LoadFile); } diff --git a/src/Nazara/Utility/Mesh.cpp b/src/Nazara/Utility/Mesh.cpp new file mode 100644 index 000000000..7214e8bd3 --- /dev/null +++ b/src/Nazara/Utility/Mesh.cpp @@ -0,0 +1,575 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine". +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include +#include + +bool NzMeshParams::IsValid() const +{ + if (!animation.IsValid()) + { + NazaraError("Invalid animation parameters"); + return false; + } + + return true; +} + +struct NzMeshImpl +{ + std::map subMeshMap; + std::deque skins; + std::vector subMeshes; + nzAnimationType animationType; + const NzAnimation* animation = nullptr; +}; + +NzMesh::~NzMesh() +{ + Destroy(); +} + +unsigned int NzMesh::AddSkin(const NzString& skin, bool setDefault) +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return 0; + } + + if (skin.IsEmpty()) + { + NazaraError("Skin is empty"); + return 0; + } + #endif + + if (setDefault) + m_impl->skins.push_front(skin); + else + m_impl->skins.push_back(skin); + + return m_impl->skins.size()-1; +} + +nzUInt8 NzMesh::AddSubMesh(NzSubMesh* subMesh) +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return 0; + } + + if (!subMesh) + { + NazaraError("Invalid submesh"); + return 0; + } + #endif + + subMesh->AddResourceReference(); + m_impl->subMeshes.push_back(subMesh); + + return m_impl->subMeshes.size()-1; +} + +nzUInt8 NzMesh::AddSubMesh(const NzString& identifier, NzSubMesh* subMesh) +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return 0; + } + + if (identifier.IsEmpty()) + { + NazaraError("Identifier is empty"); + return 0; + } + + auto it = m_impl->subMeshMap.find(identifier); + if (it != m_impl->subMeshMap.end()) + { + NazaraError("SubMesh identifier \"" + identifier + "\" is already used"); + return it->second; + } + + if (!subMesh) + { + NazaraError("Invalid submesh"); + return 0; + } + #endif + + nzUInt8 index = m_impl->subMeshes.size(); + + subMesh->AddResourceReference(); + + m_impl->subMeshes.push_back(subMesh); + m_impl->subMeshMap[identifier] = index; + + return index; +} + +void NzMesh::Animate(unsigned int frameA, unsigned int frameB, float interpolation) +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return; + } + + if (!m_impl->animation) + { + NazaraError("Mesh has no animation"); + return; + } + + unsigned int frameCount = m_impl->animation->GetFrameCount(); + if (frameA >= frameCount) + { + NazaraError("Frame A is out of range (" + NzString::Number(frameA) + " >= " + NzString::Number(frameCount) + ')'); + return; + } + + if (frameB >= frameCount) + { + NazaraError("Frame B is out of range (" + NzString::Number(frameB) + " >= " + NzString::Number(frameCount) + ')'); + return; + } + + if (interpolation < 0.f || interpolation > 1.f) + { + NazaraError("Interpolation must be in range [0..1] (Got " + NzString::Number(interpolation) + ')'); + return; + } + #endif + + for (NzSubMesh* subMesh : m_impl->subMeshes) + subMesh->AnimateImpl(frameA, frameB, interpolation); +} + +bool NzMesh::Create(nzAnimationType type) +{ + Destroy(); + + m_impl = new NzMeshImpl; + m_impl->animationType = type; + + return true; +} + +void NzMesh::Destroy() +{ + if (m_impl) + { + if (m_impl->animation) + m_impl->animation->RemoveResourceReference(); + + for (NzSubMesh* subMesh : m_impl->subMeshes) + subMesh->RemoveResourceReference(); + + delete m_impl; + m_impl = nullptr; + } +} + +const NzAnimation* NzMesh::GetAnimation() const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return nullptr; + } + #endif + + return m_impl->animation; +} + +nzAnimationType NzMesh::GetAnimationType() const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return nzAnimationType_Static; + } + #endif + + return m_impl->animationType; +} + +unsigned int NzMesh::GetFrameCount() const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return 0; + } + + if (!m_impl->animation) + { + NazaraError("Mesh has no animation"); + return 0; + } + #endif + + return m_impl->animation->GetFrameCount(); +} + +NzString NzMesh::GetSkin(unsigned int index) const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return NzString(); + } + + if (index >= m_impl->skins.size()) + { + NazaraError("Skin index out of range (" + NzString::Number(index) + " >= " + NzString::Number(m_impl->skins.size()) + ')'); + return NzString(); + } + #endif + + return m_impl->skins[index]; +} + +unsigned int NzMesh::GetSkinCount() const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return 0; + } + #endif + + return m_impl->skins.size(); +} + +NzSubMesh* NzMesh::GetSubMesh(const NzString& identifier) +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return nullptr; + } + + auto it = m_impl->subMeshMap.find(identifier); + if (it == m_impl->subMeshMap.end()) + { + NazaraError("SubMesh not found"); + return nullptr; + } + + return m_impl->subMeshes[it->second]; + #else + return m_impl->subMeshes[m_impl->subMeshMap[identifier]]; + #endif +} + +NzSubMesh* NzMesh::GetSubMesh(nzUInt8 index) +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return nullptr; + } + + if (index >= m_impl->subMeshes.size()) + { + NazaraError("SubMesh index out of range (" + NzString::Number(index) + " >= " + NzString::Number(m_impl->subMeshes.size()) + ')'); + return nullptr; + } + #endif + + return m_impl->subMeshes[index]; +} + +const NzSubMesh* NzMesh::GetSubMesh(const NzString& identifier) const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return nullptr; + } + + auto it = m_impl->subMeshMap.find(identifier); + if (it == m_impl->subMeshMap.end()) + { + NazaraError("SubMesh not found"); + return nullptr; + } + + return m_impl->subMeshes[it->second]; + #else + return m_impl->subMeshes[m_impl->subMeshMap[identifier]]; + #endif +} + +const NzSubMesh* NzMesh::GetSubMesh(nzUInt8 index) const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return nullptr; + } + + if (index >= m_impl->subMeshes.size()) + { + NazaraError("SubMesh index out of range (" + NzString::Number(index) + " >= " + NzString::Number(m_impl->subMeshes.size()) + ')'); + return nullptr; + } + #endif + + return m_impl->subMeshes[index]; +} + +nzUInt8 NzMesh::GetSubMeshCount() const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return 0; + } + #endif + + return m_impl->subMeshes.size(); +} + +unsigned int NzMesh::GetVertexCount() const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return 0; + } + #endif + + unsigned int vertexCount = 0; + for (NzSubMesh* subMesh : m_impl->subMeshes) + vertexCount += subMesh->GetVertexCount(); + + return vertexCount; +} + +bool NzMesh::HasAnimation() const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return false; + } + #endif + + return m_impl->animation != nullptr; +} + +bool NzMesh::HasSkin(unsigned int index) const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return false; + } + #endif + + return m_impl->skins.size() > index; +} + +bool NzMesh::HasSubMesh(const NzString& identifier) const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return false; + } + #endif + + return m_impl->subMeshMap.find(identifier) != m_impl->subMeshMap.end(); +} + +bool NzMesh::HasSubMesh(nzUInt8 index) const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return false; + } + #endif + + return index < m_impl->subMeshes.size(); +} + +bool NzMesh::IsAnimable() const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return false; + } + #endif + + return m_impl->animationType != nzAnimationType_Static; +} + +bool NzMesh::IsValid() const +{ + return m_impl != nullptr; +} + +bool NzMesh::LoadFromFile(const NzString& filePath, const NzMeshParams& params) +{ + return NzMeshLoader::LoadFromFile(this, filePath, params); +} + +bool NzMesh::LoadFromMemory(const void* data, std::size_t size, const NzMeshParams& params) +{ + return NzMeshLoader::LoadFromMemory(this, data, size, params); +} + +bool NzMesh::LoadFromStream(NzInputStream& stream, const NzMeshParams& params) +{ + return NzMeshLoader::LoadFromStream(this, stream, params); +} + +void NzMesh::RemoveSkin(unsigned int index) +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return; + } + + if (m_impl->skins.size() <= index) + { + NazaraError("Skin index out of range (" + NzString::Number(index) + " >= " + NzString::Number(m_impl->skins.size()) + ')'); + return; + } + #endif + + auto it = m_impl->skins.begin(); + std::advance(it, index); + + m_impl->skins.erase(it); +} + +void NzMesh::RemoveSubMesh(const NzString& identifier) +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return; + } + + auto it = m_impl->subMeshMap.find(identifier); + if (it == m_impl->subMeshMap.end()) + { + NazaraError("SubMesh not found"); + return; + } + + unsigned int index = it->second; + #else + unsigned int index = m_impl->subMeshMap[identifier]; + #endif + + auto it2 = m_impl->subMeshes.begin(); + std::advance(it2, index); + + m_impl->subMeshes.erase(it2); +} + +void NzMesh::RemoveSubMesh(nzUInt8 index) +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return; + } + + if (index >= m_impl->subMeshes.size()) + { + NazaraError("SubMesh index out of range (" + NzString::Number(index) + " >= " + NzString::Number(m_impl->subMeshes.size()) + ')'); + return; + } + #endif + + auto it = m_impl->subMeshes.begin(); + std::advance(it, index); + + m_impl->subMeshes.erase(it); +} + +bool NzMesh::SetAnimation(const NzAnimation* animation) +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Mesh not created"); + return false; + } + + if (m_impl->animationType == nzAnimationType_Static) + { + NazaraError("Static meshes cannot have animation"); + return false; + } + #endif + + if (animation == m_impl->animation) + return true; + + if (m_impl->animation) + m_impl->animation->RemoveResourceReference(); + + if (animation) + { + #if NAZARA_UTILITY_SAFE + if (animation->GetType() != m_impl->animationType) + { + NazaraError("Animation's type must match mesh animation type"); + return false; + } + #endif + + m_impl->animation = animation; + m_impl->animation->AddResourceReference(); + } + else + m_impl->animation = nullptr; + + return true; +} + +std::list NzMesh::s_memoryLoaders; +std::list NzMesh::s_streamLoaders; +std::multimap NzMesh::s_fileLoaders; diff --git a/src/Nazara/Utility/StaticMesh.cpp b/src/Nazara/Utility/StaticMesh.cpp new file mode 100644 index 000000000..42171bb25 --- /dev/null +++ b/src/Nazara/Utility/StaticMesh.cpp @@ -0,0 +1,141 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine". +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +NzStaticMesh::NzStaticMesh(const NzMesh* parent) : +NzSubMesh(parent) +{ +} + +NzStaticMesh::NzStaticMesh(const NzMesh* parent, const NzVertexBuffer* vertexBuffer, const NzVertexDeclaration* vertexDeclaration, const NzIndexBuffer* indexBuffer) : +NzSubMesh(parent) +{ + #ifdef NAZARA_DEBUG + if (!Create(vertexBuffer, vertexDeclaration, indexBuffer)) + { + NazaraError("Failed to create mesh"); + throw std::runtime_error("Constructor failed"); + } + #else + Create(vertexBuffer, vertexDeclaration, indexBuffer); + #endif +} + +NzStaticMesh::~NzStaticMesh() +{ + Destroy(); +} + +bool NzStaticMesh::Create(const NzVertexBuffer* vertexBuffer, const NzVertexDeclaration* vertexDeclaration, const NzIndexBuffer* indexBuffer) +{ + Destroy(); + + #if NAZARA_UTILITY_SAFE + if (!vertexBuffer) + { + NazaraError("Vertex buffer is null"); + return false; + } + + if (!vertexDeclaration) + { + NazaraError("Vertex declaration is null"); + return false; + } + #endif + + if (indexBuffer) + { + m_indexBuffer = indexBuffer; + m_indexBuffer->AddResourceReference(); + } + + m_vertexBuffer = vertexBuffer; + m_vertexBuffer->AddResourceReference(); + + m_vertexDeclaration = vertexDeclaration; + m_vertexDeclaration->AddResourceReference(); + + return true; +} + +void NzStaticMesh::Destroy() +{ + if (m_indexBuffer) + { + m_indexBuffer->RemoveResourceReference(); + m_indexBuffer = nullptr; + } + + if (m_vertexBuffer) + { + m_vertexBuffer->RemoveResourceReference(); + m_vertexBuffer = nullptr; + } + + if (m_vertexDeclaration) + { + m_vertexDeclaration->RemoveResourceReference(); + m_vertexDeclaration = nullptr; + } +} + +nzAnimationType NzStaticMesh::GetAnimationType() const +{ + return nzAnimationType_Static; +} + +unsigned int NzStaticMesh::GetFrameCount() const +{ + return 1; +} + +const NzIndexBuffer* NzStaticMesh::GetIndexBuffer() const +{ + return m_indexBuffer; +} + +nzPrimitiveType NzStaticMesh::GetPrimitiveType() const +{ + return m_primitiveType; +} + +const NzVertexBuffer* NzStaticMesh::GetVertexBuffer() const +{ + return m_vertexBuffer; +} + +const NzVertexDeclaration* NzStaticMesh::GetVertexDeclaration() const +{ + return m_vertexDeclaration; +} + +bool NzStaticMesh::IsAnimated() const +{ + return false; +} + +bool NzStaticMesh::IsValid() const +{ + return m_vertexBuffer != nullptr && m_vertexDeclaration != nullptr; +} + +void NzStaticMesh::SetPrimitiveType(nzPrimitiveType primitiveType) +{ + m_primitiveType = primitiveType; +} + +void NzStaticMesh::AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation) +{ + NazaraUnused(frameA); + NazaraUnused(frameB); + NazaraUnused(interpolation); + + // Le safe mode est censé nous protéger de cet appel + NazaraError("Static mesh have no animation, please enable safe mode"); +} diff --git a/src/Nazara/Utility/SubMesh.cpp b/src/Nazara/Utility/SubMesh.cpp new file mode 100644 index 000000000..40a6bd661 --- /dev/null +++ b/src/Nazara/Utility/SubMesh.cpp @@ -0,0 +1,68 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine". +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include +#include + +NzSubMesh::NzSubMesh(const NzMesh* parent) : +NzResource(false), // Un SubMesh n'est pas persistant par défaut +m_parent(parent) +{ + #if NAZARA_DEBUG + if (!m_parent) + { + NazaraError("Parent mesh is null"); + throw std::invalid_argument("Parent mesh must be valid"); + } + #endif +} + +NzSubMesh::~NzSubMesh() = default; + +void NzSubMesh::Animate(unsigned int frameA, unsigned int frameB, float interpolation) +{ + #if NAZARA_UTILITY_SAFE + if (!m_parent->HasAnimation()) + { + NazaraError("SubMesh is not animated"); + return; + } + + unsigned int frameCount = m_parent->GetFrameCount(); + if (frameA >= frameCount) + { + NazaraError("Frame A is out of range (" + NzString::Number(frameA) + " >= " + NzString::Number(frameCount) + ')'); + return; + } + + if (frameB >= frameCount) + { + NazaraError("Frame B is out of range (" + NzString::Number(frameB) + " >= " + NzString::Number(frameCount) + ')'); + return; + } + + if (interpolation < 0.f || interpolation > 1.f) + { + NazaraError("Interpolation must be in range [0..1] (Got " + NzString::Number(interpolation) + ')'); + return; + } + #endif + + AnimateImpl(frameA, frameB, interpolation); +} + +const NzMesh* NzSubMesh::GetParent() const +{ + return m_parent; +} + +unsigned int NzSubMesh::GetVertexCount() const +{ + return GetVertexBuffer()->GetVertexCount(); +} diff --git a/src/Nazara/Utility/Utility.cpp b/src/Nazara/Utility/Utility.cpp index a7c7ede20..0d5b541cb 100644 --- a/src/Nazara/Utility/Utility.cpp +++ b/src/Nazara/Utility/Utility.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -53,9 +54,14 @@ bool NzUtility::Initialize() } /// Loaders spécialisés + // Mesh + NzLoaders_MD2_Register(); // Loader de fichiers .MD2 (v8) + + // Image NzLoaders_PCX_Register(); // Loader de fichiers .PCX (1, 4, 8, 24) /// Loaders génériques (En dernier pour donner la priorité aux loaders spécialisés) + // Image NzLoaders_STB_Register(); // Loader générique (STB) s_initialized = true; @@ -73,8 +79,9 @@ void NzUtility::Uninitialize() } #endif - NzLoaders_STB_Unregister(); + NzLoaders_MD2_Unregister(); NzLoaders_PCX_Unregister(); + NzLoaders_STB_Unregister(); NzWindow::Uninitialize(); NzPixelFormat::Uninitialize(); diff --git a/src/Nazara/Utility/VertexBuffer.cpp b/src/Nazara/Utility/VertexBuffer.cpp index 5242afe14..639355e49 100644 --- a/src/Nazara/Utility/VertexBuffer.cpp +++ b/src/Nazara/Utility/VertexBuffer.cpp @@ -4,6 +4,7 @@ #include #include +#include #include NzVertexBuffer::NzVertexBuffer(NzBuffer* buffer, unsigned int startVertex, unsigned int vertexCount) : @@ -15,8 +16,8 @@ m_vertexCount(vertexCount) #ifdef NAZARA_DEBUG if (!m_buffer) { - NazaraError("Passed buffer is null"); - return; + NazaraError("Buffer is null"); + throw std::invalid_argument("Buffer must be valid"); } #endif @@ -34,6 +35,7 @@ m_vertexCount(length) } NzVertexBuffer::NzVertexBuffer(const NzVertexBuffer& vertexBuffer) : +NzResource(true), m_ownsBuffer(vertexBuffer.m_ownsBuffer), m_startVertex(vertexBuffer.m_startVertex), m_vertexCount(vertexBuffer.m_vertexCount) diff --git a/src/Nazara/Utility/VertexDeclaration.cpp b/src/Nazara/Utility/VertexDeclaration.cpp index 7288cd3cc..8db74ddd2 100644 --- a/src/Nazara/Utility/VertexDeclaration.cpp +++ b/src/Nazara/Utility/VertexDeclaration.cpp @@ -5,6 +5,17 @@ #include #include #include +#include +#include +#include +#include + +#if NAZARA_THREADSAFETY_VERTEXDECLARATION +#include +#else +#include +#endif + #include namespace @@ -21,99 +32,315 @@ namespace 12, // nzElementType_Float3 16 // nzElementType_Float4 }; + + bool VertexElementCompare(const NzVertexElement& elementA, const NzVertexElement& elementB) + { + // Nous classons d'abord par stream + if (elementA.stream == elementB.stream) + { + // Ensuite par usage + if (elementA.usage == elementB.usage) + // Et finalement par usageIndex + return elementA.usageIndex < elementB.usageIndex; + else + return elementA.usage < elementB.usage; + } + else + return elementA.stream < elementB.stream; + } +} + +struct NzVertexDeclarationImpl +{ + std::vector elements; + int elementPos[nzElementStream_Max+1][nzElementUsage_Max+1]; + int streamPos[nzElementStream_Max+1]; + unsigned int stride[nzElementStream_Max+1] = {0}; + + unsigned short refCount; + NazaraMutex(mutex) +}; + +NzVertexDeclaration::NzVertexDeclaration(const NzVertexElement* elements, unsigned int elementCount) +{ + #ifdef NAZARA_DEBUG + if (!Create(elements, elementCount)) + { + NazaraError("Failed to create declaration"); + throw std::runtime_error("Constructor failed"); + } + #else + Create(elements, elementCount); + #endif +} + +NzVertexDeclaration::NzVertexDeclaration(const NzVertexDeclaration& declaration) : +NzResource(), +m_sharedImpl(declaration.m_sharedImpl) +{ + if (m_sharedImpl) + { + NazaraMutexLock(m_sharedImpl->mutex); + m_sharedImpl->refCount++; + NazaraMutexUnlock(m_sharedImpl->mutex); + } +} + +NzVertexDeclaration::NzVertexDeclaration(NzVertexDeclaration&& declaration) : +m_sharedImpl(declaration.m_sharedImpl) +{ + declaration.m_sharedImpl = nullptr; +} + +NzVertexDeclaration::~NzVertexDeclaration() +{ + Destroy(); } bool NzVertexDeclaration::Create(const NzVertexElement* elements, unsigned int elementCount) { + Destroy(); + + #if NAZARA_UTILITY_SAFE + if (!elements || elementCount == 0) + { + NazaraError("No element"); + return false; + } + #endif + + NzVertexDeclarationImpl* impl = new NzVertexDeclarationImpl; + std::memset(&impl->elementPos, -1, (nzElementStream_Max+1)*(nzElementUsage_Max+1)*sizeof(int)); + std::memset(&impl->streamPos, -1, (nzElementStream_Max+1)*sizeof(int)); + + // On copie et trie les éléments + impl->elements.resize(elementCount); + std::memcpy(&impl->elements[0], elements, elementCount*sizeof(NzVertexElement)); + std::sort(impl->elements.begin(), impl->elements.end(), VertexElementCompare); + for (unsigned int i = 0; i < elementCount; ++i) { - unsigned int stream = elements[i].stream; - - if (stream >= m_streams.size()) - m_streams.resize(stream+1); + NzVertexElement& current = impl->elements[i]; #if NAZARA_UTILITY_SAFE - else // Seulement si le stream ne vient pas d'être créé (Autrement c'est inutile) + // Notre tableau étant trié, s'il y a collision, les deux éléments identiques se suivent... + if (i > 0) { - for (unsigned int j = 0; j < i; ++j) + NzVertexElement& previous = impl->elements[i-1]; // On accède à l'élément précédent + if (previous.usage == current.usage && previous.usageIndex == current.usageIndex && previous.stream == current.stream) { - if (elements[j].stream == stream && elements[j].usage == elements[i].usage && elements[j].usageIndex == elements[i].usageIndex) - { - NazaraError("Element usage (" + NzString::Number(elements[j].usage, 16) + ") collision on stream " + NzString::Number(stream) + " with usage index " + NzString::Number(elements[j].usageIndex)); - return false; - } + // Les deux éléments sont identiques là où ils ne devraient pas, nous avons une collision... + NazaraError("Element usage 0x" + NzString::Number(current.usage, 16) + " collision with usage index " + NzString::Number(current.usageIndex) + " on stream 0x" + NzString::Number(current.stream, 16)); + delete impl; + + return false; } } #endif - Element element; - element.offset = elements[i].offset; - element.type = elements[i].type; - element.usage = elements[i].usage; - element.usageIndex = elements[i].usageIndex; + if (current.usageIndex == 0) + impl->elementPos[current.stream][current.usage] = i; - m_streams[stream].elements.push_back(element); + if (impl->streamPos[current.stream] == -1) + impl->streamPos[current.stream] = i; // Premier élément du stream (via le triage) + + impl->stride[current.stream] += size[current.type]; } - for (Stream& stream : m_streams) - { - stream.stride = 0; - for (const Element& element : stream.elements) - stream.stride += size[element.type]; + #if NAZARA_RENDERER_FORCE_DECLARATION_STRIDE_MULTIPLE_OF_32 + for (unsigned int& stride : impl->stride) + stride = ((static_cast(stride)-1)/32+1)*32; + #endif - #if NAZARA_RENDERER_FORCE_DECLARATION_STRIDE_MULTIPLE_OF_32 - stream.stride = ((static_cast(stream.stride)-1)/32+1)*32; - #endif - } + m_sharedImpl = impl; return true; } -const NzVertexDeclaration::Element* NzVertexDeclaration::GetElement(unsigned int i, unsigned int stream) const +void NzVertexDeclaration::Destroy() +{ + if (!m_sharedImpl) + return; + + NazaraMutexLock(m_sharedImpl->mutex); + bool freeSharedImpl = (--m_sharedImpl->refCount == 0); + NazaraMutexUnlock(m_sharedImpl->mutex); + + if (freeSharedImpl) + delete m_sharedImpl; + + m_sharedImpl = nullptr; +} + +const NzVertexElement* NzVertexDeclaration::GetElement(unsigned int i) const { #if NAZARA_UTILITY_SAFE - if (stream >= m_streams.size()) + if (!m_sharedImpl) { - NazaraError("Stream out of range"); + NazaraError("Declaration not created"); return nullptr; } - if (i >= m_streams[stream].elements.size()) + if (i >= m_sharedImpl->elements.size()) { - NazaraError("Index out of range"); + NazaraError("Element index out of range (" + NzString::Number(i) + " >= " + NzString::Number(m_sharedImpl->elements.size()) + ')'); return nullptr; } #endif - return &m_streams[stream].elements[i]; + return &m_sharedImpl->elements[i]; } -unsigned int NzVertexDeclaration::GetElementCount(unsigned int stream) const +const NzVertexElement* NzVertexDeclaration::GetElement(nzElementStream stream, unsigned int i) const { #if NAZARA_UTILITY_SAFE - if (stream >= m_streams.size()) + if (!m_sharedImpl) { - NazaraError("Stream out of range"); + NazaraError("Declaration not created"); + return nullptr; + } + + int streamPos = m_sharedImpl->streamPos[stream]; + if (streamPos == -1) + { + NazaraError("Declaration has no stream 0x" + NzString::Number(stream, 16)); + return nullptr; + } + + unsigned int upperLimit = GetElementCount(stream); + if (i >= upperLimit) + { + NazaraError("Element index out of range (" + NzString::Number(i) + " >= " + NzString::Number(upperLimit) + ')'); + return nullptr; + } + #endif + + return &m_sharedImpl->elements[m_sharedImpl->streamPos[stream]+i]; +} + +const NzVertexElement* NzVertexDeclaration::GetElement(nzElementStream stream, nzElementUsage usage, unsigned int usageIndex) const +{ + #if NAZARA_UTILITY_SAFE + if (!m_sharedImpl) + { + NazaraError("Declaration not created"); + return nullptr; + } + #endif + + int elementPos = m_sharedImpl->elementPos[stream][usage]; + if (elementPos == -1) + return nullptr; + + elementPos += usageIndex; + if (static_cast(elementPos) >= m_sharedImpl->elements.size()) + return nullptr; + + NzVertexElement& element = m_sharedImpl->elements[elementPos]; + if (element.stream != stream || element.usage != usage || element.usageIndex != usageIndex) + return nullptr; + + return &element; +} + +unsigned int NzVertexDeclaration::GetElementCount() const +{ + #if NAZARA_UTILITY_SAFE + if (!m_sharedImpl) + { + NazaraError("Declaration not created"); return 0; } #endif - return m_streams[stream].elements.size(); + return m_sharedImpl->elements.size(); } -unsigned int NzVertexDeclaration::GetStreamCount() const -{ - return m_streams.size(); -} - -unsigned int NzVertexDeclaration::GetStride(unsigned int stream) const +unsigned int NzVertexDeclaration::GetElementCount(nzElementStream stream) const { #if NAZARA_UTILITY_SAFE - if (stream >= m_streams.size()) + if (!m_sharedImpl) { - NazaraError("Stream out of range"); + NazaraError("Declaration not created"); return 0; } #endif - return m_streams[stream].stride; + int streamPos = m_sharedImpl->streamPos[stream]; + if (streamPos == -1) + return 0; + + unsigned int upperLimit = 0; + if (stream == nzElementStream_Max) + upperLimit = m_sharedImpl->elements.size(); + else + { + for (unsigned int upperStream = stream+1; upperStream <= nzElementStream_Max; ++upperStream) + { + if (m_sharedImpl->streamPos[upperStream] != -1) + { + upperLimit = m_sharedImpl->streamPos[upperStream]; + break; + } + else if (upperStream == nzElementStream_Max) // Dernier stream, toujours pas de limite + upperLimit = m_sharedImpl->elements.size(); + } + } + + return upperLimit-streamPos; +} + +unsigned int NzVertexDeclaration::GetStride(nzElementStream stream) const +{ + #if NAZARA_UTILITY_SAFE + if (!m_sharedImpl) + { + NazaraError("Declaration not created"); + return 0; + } + #endif + + return m_sharedImpl->stride[stream]; +} + +bool NzVertexDeclaration::HasStream(nzElementStream stream) const +{ + #if NAZARA_UTILITY_SAFE + if (!m_sharedImpl) + { + NazaraError("Declaration not created"); + return false; + } + #endif + + return m_sharedImpl->streamPos[stream] != -1; +} + +bool NzVertexDeclaration::IsValid() const +{ + return m_sharedImpl != nullptr; +} + +NzVertexDeclaration& NzVertexDeclaration::operator=(const NzVertexDeclaration& declaration) +{ + Destroy(); + + m_sharedImpl = declaration.m_sharedImpl; + if (m_sharedImpl) + { + NazaraMutexLock(m_sharedImpl->mutex); + m_sharedImpl->refCount++; + NazaraMutexUnlock(m_sharedImpl->mutex); + } + + return *this; +} + +NzVertexDeclaration& NzVertexDeclaration::operator=(NzVertexDeclaration&& declaration) +{ + Destroy(); + + m_sharedImpl = declaration.m_sharedImpl; + declaration.m_sharedImpl = nullptr; + + return *this; }