diff --git a/.gitignore b/.gitignore index fd6451f19..a4daea85f 100644 --- a/.gitignore +++ b/.gitignore @@ -54,9 +54,6 @@ $RECYCLE.BIN/ [Dd]ebug*/ [Rr]elease/ -build/ - - [Tt]est[Rr]esult [Bb]uild[Ll]og.* diff --git a/NazaraModuleTemplate/include/Nazara/ModuleName/ClassName.hpp b/NazaraModuleTemplate/include/Nazara/ModuleName/ClassName.hpp new file mode 100644 index 000000000..5f7d10f41 --- /dev/null +++ b/NazaraModuleTemplate/include/Nazara/ModuleName/ClassName.hpp @@ -0,0 +1,25 @@ +// Copyright (C) 2012 AUTHORS +// This file is part of the "Nazara Engine". +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_CLASSNAME_HPP +#define NAZARA_CLASSNAME_HPP + +#include + +class NAZARA_API NzClassName +{ + public: + NzClassName(); + + int GetAttribute() const; + + void SetAttribute(int attribute); + + private: + int m_attribute; +}; + +#endif // NAZARA_CLASSNAME_HPP diff --git a/NazaraModuleTemplate/src/Nazara/ModuleName/ClassName.cpp b/NazaraModuleTemplate/src/Nazara/ModuleName/ClassName.cpp new file mode 100644 index 000000000..f57baac14 --- /dev/null +++ b/NazaraModuleTemplate/src/Nazara/ModuleName/ClassName.cpp @@ -0,0 +1,21 @@ +// Copyright (C) 2012 AUTHORS +// This file is part of the "Nazara Engine". +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +NzClassName::NzClassName() : +m_attribute(42) +{ +} + +int NzClassName::GetAttribute() const +{ + return m_attribute; +} + +void NzClassName::SetAttribute(int attribute) +{ + m_attribute = attribute; +} diff --git a/build/scripts/module/renderer.lua b/build/scripts/module/renderer.lua index 4945e717e..9529919f7 100644 --- a/build/scripts/module/renderer.lua +++ b/build/scripts/module/renderer.lua @@ -1,9 +1,5 @@ project "NazaraRenderer" -links "gdi32" -links "opengl32" -links "winmm" - files { "../include/Nazara/Renderer/**.hpp", @@ -14,6 +10,9 @@ files if (os.is("windows")) then excludes { "../src/Nazara/Renderer/Posix/*.hpp", "../src/Nazara/Renderer/Posix/*.cpp" } + links "gdi32" + links "opengl32" + links "winmm" else excludes { "../src/Nazara/Renderer/Win32/*.hpp", "../src/Nazara/Renderer/Win32/*.cpp" } end diff --git a/build/scripts/module/utility.lua b/build/scripts/module/utility.lua index 8cadea0b3..183abe974 100644 --- a/build/scripts/module/utility.lua +++ b/build/scripts/module/utility.lua @@ -13,6 +13,7 @@ files if (os.is("windows")) then excludes { "../src/Nazara/Utility/Posix/*.hpp", "../src/Nazara/Utility/Posix/*.cpp" } + links "gdi32" else excludes { "../src/Nazara/Utility/Win32/*.hpp", "../src/Nazara/Utility/Win32/*.cpp" } end diff --git a/include/GL3/gl3.h b/include/GL3/gl3.h index a6d803bd6..9c17d418c 100644 --- a/include/GL3/gl3.h +++ b/include/GL3/gl3.h @@ -36,9 +36,9 @@ extern "C" { * will probably change slightly as we make sure exactly the right set * of interfaces is included. * - * gl3.h last updated on $Date: 2012-04-26 00:59:42 -0700 (Thu, 26 Apr 2012) $ + * gl3.h last updated on $Date: 2012-06-18 11:26:35 -0700 (Mon, 18 Jun 2012) $ * - * RELEASE NOTES - 2012/04/25 + * RELEASE NOTES - 2012/06/18 * * gl3.h should be placed under a directory 'GL3' and included as * ''. diff --git a/include/GL3/glext.h b/include/GL3/glext.h index 8fce0f6f0..90e013421 100644 --- a/include/GL3/glext.h +++ b/include/GL3/glext.h @@ -29,9 +29,9 @@ extern "C" { */ /* Header file version number, required by OpenGL ABI for Linux */ -/* glext.h last updated $Date: 2012-04-26 00:59:42 -0700 (Thu, 26 Apr 2012) $ */ +/* glext.h last updated $Date: 2012-06-18 11:26:35 -0700 (Mon, 18 Jun 2012) $ */ /* Current version at http://www.opengl.org/registry/ */ -#define GL_GLEXT_VERSION 81 +#define GL_GLEXT_VERSION 82 /* Function declaration macros - to move into glplatform.h */ #if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) @@ -5478,6 +5478,12 @@ extern "C" { #ifndef GL_NV_shader_atomic_float #endif +#ifndef GL_AMD_query_buffer_object +#define GL_QUERY_BUFFER_AMD 0x9192 +#define GL_QUERY_BUFFER_BINDING_AMD 0x9193 +#define GL_QUERY_RESULT_NO_WAIT_AMD 0x9194 +#endif + /*************************************************************/ @@ -11805,6 +11811,10 @@ typedef GLboolean (APIENTRYP PFNGLISIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle) #define GL_NV_shader_atomic_float 1 #endif +#ifndef GL_AMD_query_buffer_object +#define GL_AMD_query_buffer_object 1 +#endif + #ifdef __cplusplus } 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 43d3d9680..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; @@ -46,7 +49,7 @@ class NAZARA_API NzString : public NzHashable NzString& Append(const char* string); NzString& Append(const NzString& string); - void Clear(); + void Clear(bool keepBuffer = false); bool Contains(char character, int start = 0, nzUInt32 flags = None) const; bool Contains(const char* string, int start = 0, nzUInt32 flags = None) const; @@ -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/Basic.hpp b/include/Nazara/Math/Basic.hpp index 1049f2837..ec374efe2 100644 --- a/include/Nazara/Math/Basic.hpp +++ b/include/Nazara/Math/Basic.hpp @@ -40,7 +40,7 @@ template bool NzNumberEquals(T a, T b); inline NzString NzNumberToString(long long number, nzUInt8 radix = 10); template T NzRadians(T radians); template T NzRadianToDegree(T radians); -inline long long NzStringToNumber(NzString str, nzUInt8 radix = 10); +inline long long NzStringToNumber(NzString str, nzUInt8 radix = 10, bool* ok = nullptr); #include diff --git a/include/Nazara/Math/Basic.inl b/include/Nazara/Math/Basic.inl index d86a7c84e..8655680f5 100644 --- a/include/Nazara/Math/Basic.inl +++ b/include/Nazara/Math/Basic.inl @@ -195,7 +195,7 @@ NzString NzNumberToString(long long number, nzUInt8 radix) if (number == 0) return '0'; - static const char* symbols("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + static const char* symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; bool negative; if (number < 0) @@ -238,12 +238,16 @@ T NzRadianToDegree(T radians) return radians * (180.0/M_PI); } -long long NzStringToNumber(NzString str, nzUInt8 radix) +long long NzStringToNumber(NzString str, nzUInt8 radix, bool* ok) { #if NAZARA_MATH_SAFE if (radix < 2 || radix > 36) { NazaraError("Radix must be between 2 and 36"); + + if (ok) + *ok = false; + return 0; } #endif @@ -269,11 +273,18 @@ long long NzStringToNumber(NzString str, nzUInt8 radix) else { NazaraError("str is not a valid number"); + + if (ok) + *ok = false; + return 0; } } while (*++digit); + if (ok) + *ok = true; + return (negative) ? -static_cast(total) : total; } 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/Math/Vector3.hpp b/include/Nazara/Math/Vector3.hpp index 04e3834c2..af4a2b934 100644 --- a/include/Nazara/Math/Vector3.hpp +++ b/include/Nazara/Math/Vector3.hpp @@ -17,7 +17,7 @@ template class NzVector3 NzVector3(T X, T Y, T Z); explicit NzVector3(T scale); NzVector3(T vec[3]); - NzVector3(const NzVector2& vec); + NzVector3(const NzVector2& vec, T Z = 0.0); template explicit NzVector3(const NzVector3& vec); NzVector3(const NzVector3& vec) = default; ~NzVector3() = default; diff --git a/include/Nazara/Math/Vector3.inl b/include/Nazara/Math/Vector3.inl index 9a40aac0f..53ff29c90 100644 --- a/include/Nazara/Math/Vector3.inl +++ b/include/Nazara/Math/Vector3.inl @@ -39,10 +39,10 @@ z(vec[2]) } template -NzVector3::NzVector3(const NzVector2& vec) : +NzVector3::NzVector3(const NzVector2& vec, T Z) : x(vec.x), y(vec.y), -z(0) +z(Z) { } 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/OpenGL.hpp b/include/Nazara/Renderer/OpenGL.hpp index 8f5e92d85..adb36a520 100644 --- a/include/Nazara/Renderer/OpenGL.hpp +++ b/include/Nazara/Renderer/OpenGL.hpp @@ -37,6 +37,7 @@ class NAZARA_API NzOpenGL DebugOutput, FP64, FrameBufferObject, + PixelBufferObject, SeparateShaderObjects, Texture3D, TextureCompression_s3tc, diff --git a/include/Nazara/Renderer/RenderWindow.hpp b/include/Nazara/Renderer/RenderWindow.hpp index fabd16265..8772a8c9e 100644 --- a/include/Nazara/Renderer/RenderWindow.hpp +++ b/include/Nazara/Renderer/RenderWindow.hpp @@ -24,14 +24,14 @@ class NAZARA_API NzRenderWindow : public NzRenderTarget, public NzWindow { public: NzRenderWindow(); - NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style = NzWindow::Default, const NzContextParameters& parameters = NzContextParameters()); + NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style = nzWindowStyle_Default, const NzContextParameters& parameters = NzContextParameters()); NzRenderWindow(NzWindowHandle handle, const NzContextParameters& parameters = NzContextParameters()); virtual ~NzRenderWindow(); bool CopyToImage(NzImage* image); ///TODO: Const bool CopyToTexture(NzTexture* texture); ///TODO: Const - bool Create(NzVideoMode mode, const NzString& title, nzUInt32 style = NzWindow::Default, const NzContextParameters& parameters = NzContextParameters()); + bool Create(NzVideoMode mode, const NzString& title, nzUInt32 style = nzWindowStyle_Default, const NzContextParameters& parameters = NzContextParameters()); bool Create(NzWindowHandle handle, const NzContextParameters& parameters = NzContextParameters()); void Display(); diff --git a/include/Nazara/Renderer/Renderer.hpp b/include/Nazara/Renderer/Renderer.hpp index 6296f22f5..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_SoftwareBuffer, - nzRendererCap_Texture3D, - nzRendererCap_TextureCubemap, - nzRendererCap_TextureMulti, - nzRendererCap_TextureNPOT, - - nzRendererCap_Count -}; - -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; @@ -183,7 +91,7 @@ class NAZARA_API NzRenderer const NzVertexBuffer* m_vertexBuffer; const NzVertexDeclaration* m_vertexDeclaration; bool m_vaoUpdated; - bool m_capabilities[nzRendererCap_Count]; + bool m_capabilities[nzRendererCap_Max+1]; bool m_stencilFuncUpdated; bool m_stencilOpUpdated; unsigned int m_maxAnisotropyLevel; diff --git a/include/Nazara/Renderer/Shader.hpp b/include/Nazara/Renderer/Shader.hpp index b060c9bde..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_Count -}; - 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/Renderer/VertexDeclaration.hpp b/include/Nazara/Renderer/VertexDeclaration.hpp deleted file mode 100644 index 1a4fa6267..000000000 --- a/include/Nazara/Renderer/VertexDeclaration.hpp +++ /dev/null @@ -1,75 +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 - -#ifndef NAZARA_VERTEXDECLARATION_HPP -#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 -}; - -struct NzVertexElement -{ - NzVertexElement() : stream(0), usageIndex(0) {} - - unsigned int offset; - unsigned int stream; - unsigned int usageIndex; - nzElementType type; - nzElementUsage usage; -}; - -class NAZARA_API NzVertexDeclaration -{ - public: - struct Element - { - unsigned int offset; - unsigned int usageIndex; - nzElementType type; - nzElementUsage usage; - }; - - NzVertexDeclaration() = default; - ~NzVertexDeclaration() = default; - - bool Create(const NzVertexElement* elements, unsigned int elementCount); - - 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; - - private: - struct Stream - { - std::vector elements; - unsigned int stride; - }; - - std::vector m_streams; -}; - -#endif // NAZARA_VERTEXDECLARATION_HPP 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/Renderer/Buffer.hpp b/include/Nazara/Utility/Buffer.hpp similarity index 64% rename from include/Nazara/Renderer/Buffer.hpp rename to include/Nazara/Utility/Buffer.hpp index c023ade1c..7fcad2221 100644 --- a/include/Nazara/Renderer/Buffer.hpp +++ b/include/Nazara/Utility/Buffer.hpp @@ -9,57 +9,36 @@ #include #include +#include #include -enum nzBufferAccess -{ - nzBufferAccess_DiscardAndWrite, - nzBufferAccess_ReadOnly, - nzBufferAccess_ReadWrite, - nzBufferAccess_WriteOnly -}; - -enum nzBufferStorage -{ - nzBufferStorage_Hardware, - nzBufferStorage_Software -}; - -enum nzBufferType -{ - nzBufferType_Index, - nzBufferType_Vertex -}; - -enum nzBufferUsage -{ - nzBufferUsage_Dynamic, - nzBufferUsage_Static -}; - class NzBufferImpl; class NzRenderer; +class NzUtility; class NAZARA_API NzBuffer : public NzResource, NzNonCopyable { friend class NzRenderer; + friend class NzUtility; public: + typedef NzBufferImpl* (*BufferFunction)(NzBuffer* parent, nzBufferType type); + NzBuffer(nzBufferType type); - NzBuffer(nzBufferType type, unsigned int length, nzUInt8 typeSize, nzBufferUsage usage = nzBufferUsage_Static); + NzBuffer(nzBufferType type, unsigned int length, nzUInt8 typeSize, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); ~NzBuffer(); bool CopyContent(NzBuffer& buffer); - bool Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage = nzBufferUsage_Static); + bool Create(unsigned int length, nzUInt8 typeSize, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); void Destroy(); bool Fill(const void* data, unsigned int offset, unsigned int length); - void* GetBufferPtr(); - const void* GetBufferPtr() const; NzBufferImpl* GetImpl() const; unsigned int GetLength() const; + void* GetPointer(); + const void* GetPointer() const; unsigned int GetSize() const; nzBufferStorage GetStorage() const; nzBufferType GetType() const; @@ -67,13 +46,21 @@ class NAZARA_API NzBuffer : public NzResource, NzNonCopyable nzBufferUsage GetUsage() const; bool IsHardware() const; + bool IsValid() const; void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0); + + bool SetStorage(nzBufferStorage storage); + bool Unmap(); static bool IsSupported(nzBufferStorage storage); + static void SetBufferFunction(nzBufferStorage storage, BufferFunction func); private: + static bool Initialize(); + static void Uninitialize(); + nzBufferStorage m_storage; nzBufferType m_type; nzBufferUsage m_usage; @@ -81,6 +68,7 @@ class NAZARA_API NzBuffer : public NzResource, NzNonCopyable NzBufferImpl* m_impl; unsigned int m_length; + static BufferFunction s_bufferFunctions[nzBufferStorage_Max+1]; }; #endif // NAZARA_BUFFER_HPP diff --git a/src/Nazara/Renderer/BufferImpl.hpp b/include/Nazara/Utility/BufferImpl.hpp similarity index 85% rename from src/Nazara/Renderer/BufferImpl.hpp rename to include/Nazara/Utility/BufferImpl.hpp index 74795abe9..7821c3c76 100644 --- a/src/Nazara/Renderer/BufferImpl.hpp +++ b/include/Nazara/Utility/BufferImpl.hpp @@ -7,22 +7,20 @@ #ifndef NAZARA_BUFFERIMPL_HPP #define NAZARA_BUFFERIMPL_HPP -#include +#include -class NzBufferImpl +class NAZARA_API NzBufferImpl { public: NzBufferImpl() = default; virtual ~NzBufferImpl(); - virtual void Bind() = 0; - virtual bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static) = 0; virtual void Destroy() = 0; virtual bool Fill(const void* data, unsigned int offset, unsigned int size) = 0; - virtual void* GetBufferPtr() = 0; + virtual void* GetPointer() = 0; virtual bool IsHardware() const = 0; 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/Cursor.hpp b/include/Nazara/Utility/Cursor.hpp new file mode 100644 index 000000000..56156346f --- /dev/null +++ b/include/Nazara/Utility/Cursor.hpp @@ -0,0 +1,35 @@ +// 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_CURSOR_HPP +#define NAZARA_CURSOR_HPP + +#include +#include + +class NzCursorImpl; +class NzImage; +class NzWindowImpl; + +class NAZARA_API NzCursor +{ + friend class NzWindowImpl; + + public: + NzCursor(); + ~NzCursor(); + + bool Create(const NzImage& cursor, int hotSpotX = 0, int hotSpotY = 0); + bool Create(const NzImage& cursor, const NzVector2i& hotSpot); + void Destroy(); + + bool IsValid() const; + + private: + NzCursorImpl* m_impl; +}; + +#endif // NAZARA_CURSOR_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/Icon.hpp b/include/Nazara/Utility/Icon.hpp new file mode 100644 index 000000000..fa724a62c --- /dev/null +++ b/include/Nazara/Utility/Icon.hpp @@ -0,0 +1,34 @@ +// 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_ICON_HPP +#define NAZARA_ICON_HPP + +#include +#include + +class NzImage; +class NzIconImpl; +class NzWindowImpl; + +class NAZARA_API NzIcon +{ + friend class NzWindowImpl; + + public: + NzIcon(); + ~NzIcon(); + + bool Create(const NzImage& icon); + void Destroy(); + + bool IsValid() const; + + private: + NzIconImpl* m_impl; +}; + +#endif // NAZARA_ICON_HPP diff --git a/include/Nazara/Utility/Image.hpp b/include/Nazara/Utility/Image.hpp index 71cddbaa3..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_Count -}; +#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/Renderer/IndexBuffer.hpp b/include/Nazara/Utility/IndexBuffer.hpp similarity index 76% rename from include/Nazara/Renderer/IndexBuffer.hpp rename to include/Nazara/Utility/IndexBuffer.hpp index b3a50b1d0..22c22104b 100644 --- a/include/Nazara/Renderer/IndexBuffer.hpp +++ b/include/Nazara/Utility/IndexBuffer.hpp @@ -8,29 +8,33 @@ #define NAZARA_INDEXBUFFER_HPP #include -#include +#include +#include -class NAZARA_API NzIndexBuffer +class NAZARA_API NzIndexBuffer : public NzResource { public: NzIndexBuffer(NzBuffer* buffer, unsigned int startIndex, unsigned int indexCount); - NzIndexBuffer(unsigned int length, nzUInt8 indexSize, nzBufferUsage usage = nzBufferUsage_Static); + NzIndexBuffer(unsigned int length, nzUInt8 indexSize, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); NzIndexBuffer(const NzIndexBuffer& indexBuffer); ~NzIndexBuffer(); bool Fill(const void* data, unsigned int offset, unsigned int length); NzBuffer* GetBuffer() const; - void* GetBufferPtr(); - const void* GetBufferPtr() const; nzUInt8 GetIndexSize() const; unsigned int GetIndexCount() const; + void* GetPointer(); + const void* GetPointer() const; unsigned int GetStartIndex() const; bool IsHardware() const; bool IsSequential() const; void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0); + + bool SetStorage(nzBufferStorage storage); + bool Unmap(); private: 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 3736c2efe..2f71927b7 100644 --- a/include/Nazara/Utility/PixelFormat.hpp +++ b/include/Nazara/Utility/PixelFormat.hpp @@ -9,45 +9,8 @@ #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_Count -}; +#include +#include class NzUtility; @@ -57,10 +20,13 @@ class NzPixelFormat public: typedef nzUInt8* (*ConvertFunction)(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst); + typedef void (*FlipFunction)(unsigned int width, unsigned int height, unsigned int depth, const nzUInt8* src, nzUInt8* dst); static bool Convert(nzPixelFormat srcFormat, nzPixelFormat dstFormat, const void* src, void* dst); static bool Convert(nzPixelFormat srcFormat, nzPixelFormat dstFormat, const void* start, const void* end, void* dst); + static bool Flip(nzPixelFlipping flipping, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, const void* src, void* dst); + static nzUInt8 GetBPP(nzPixelFormat format); static bool HasAlpha(nzPixelFormat format); @@ -69,7 +35,8 @@ class NzPixelFormat static bool IsConversionSupported(nzPixelFormat srcFormat, nzPixelFormat dstFormat); static bool IsValid(nzPixelFormat format); - static void SetConvertFunction(nzPixelFormat srcFormat, nzPixelFormat dstFormat, ConvertFunction); + static void SetConvertFunction(nzPixelFormat srcFormat, nzPixelFormat dstFormat, ConvertFunction func); + static void SetFlipFunction(nzPixelFlipping flipping, nzPixelFormat format, FlipFunction func); static NzString ToString(nzPixelFormat format); @@ -77,7 +44,8 @@ class NzPixelFormat static bool Initialize(); static void Uninitialize(); - static NAZARA_API ConvertFunction s_convertFunctions[nzPixelFormat_Count][nzPixelFormat_Count]; + static NAZARA_API ConvertFunction s_convertFunctions[nzPixelFormat_Max+1][nzPixelFormat_Max+1]; + static NAZARA_API std::map s_flipFunctions[nzPixelFlipping_Max+1]; }; #include diff --git a/include/Nazara/Utility/PixelFormat.inl b/include/Nazara/Utility/PixelFormat.inl index 2ea636d04..917450700 100644 --- a/include/Nazara/Utility/PixelFormat.inl +++ b/include/Nazara/Utility/PixelFormat.inl @@ -68,6 +68,102 @@ inline bool NzPixelFormat::Convert(nzPixelFormat srcFormat, nzPixelFormat dstFor return true; } +inline bool NzPixelFormat::Flip(nzPixelFlipping flipping, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, const void* src, void* dst) +{ + #if NAZARA_UTILITY_SAFE + if (!IsValid(format)) + { + NazaraError("Invalid pixel format"); + return false; + } + #endif + + auto it = s_flipFunctions[flipping].find(format); + if (it != s_flipFunctions[flipping].end()) + it->second(width, height, depth, reinterpret_cast(src), reinterpret_cast(dst)); + else + { + // Flipping générique + + #if NAZARA_UTILITY_SAFE + if (IsCompressed(format)) + { + NazaraError("No function to flip compressed format"); + return false; + } + #endif + + nzUInt8 bpp = GetBPP(format); + unsigned int lineStride = width*bpp; + switch (flipping) + { + case nzPixelFlipping_Horizontally: + { + if (src == dst) + { + for (unsigned int z = 0; z < depth; ++z) + { + nzUInt8* ptr = reinterpret_cast(dst) + width*height*z; + for (unsigned int y = 0; y < height; ++y) + { + for (unsigned int x = 0; x < width/2; ++x) + std::swap_ranges(&ptr[x*bpp], &ptr[(x+1)*bpp], &ptr[(width-x)*bpp]); + + ptr += lineStride; + } + } + } + else + { + for (unsigned int z = 0; z < depth; ++z) + { + nzUInt8* ptr = reinterpret_cast(dst) + width*height*z; + for (unsigned int y = 0; y < height; ++y) + { + for (unsigned int x = 0; x < width; ++x) + std::memcpy(&ptr[x*bpp], &ptr[(width-x)*bpp], bpp); + + ptr += lineStride; + } + } + } + break; + } + + case nzPixelFlipping_Vertically: + { + if (src == dst) + { + for (unsigned int z = 0; z < depth; ++z) + { + nzUInt8* ptr = reinterpret_cast(dst) + width*height*z; + for (unsigned int y = 0; y < height/2; ++y) + std::swap_ranges(&ptr[y*lineStride], &ptr[(y+1)*lineStride-1], &ptr[(height-y-1)*lineStride]); + } + } + else + { + for (unsigned int z = 0; z < depth; ++z) + { + const nzUInt8* srcPtr = reinterpret_cast(src); + nzUInt8* dstPtr = reinterpret_cast(dst) + (width-1)*height*depth*bpp; + for (unsigned int y = 0; y < height; ++y) + { + std::memcpy(dstPtr, srcPtr, lineStride); + + srcPtr += lineStride; + dstPtr -= lineStride; + } + } + } + break; + } + } + } + + return true; +} + inline nzUInt8 NzPixelFormat::GetBPP(nzPixelFormat format) { switch (format) @@ -129,7 +225,6 @@ inline nzUInt8 NzPixelFormat::GetBPP(nzPixelFormat format) case nzPixelFormat_RGBA8: return 4; - case nzPixelFormat_Count: case nzPixelFormat_Undefined: NazaraError("Invalid pixel format"); return 0; @@ -159,7 +254,6 @@ inline bool NzPixelFormat::HasAlpha(nzPixelFormat format) case nzPixelFormat_RGB8: return false; - case nzPixelFormat_Count: case nzPixelFormat_Undefined: break; } @@ -192,15 +286,7 @@ inline bool NzPixelFormat::IsConversionSupported(nzPixelFormat srcFormat, nzPixe inline bool NzPixelFormat::IsValid(nzPixelFormat format) { - switch (format) - { - case nzPixelFormat_Count: - case nzPixelFormat_Undefined: - return false; - - default: - return true; - } + return format != nzPixelFormat_Undefined; } inline void NzPixelFormat::SetConvertFunction(nzPixelFormat srcFormat, nzPixelFormat dstFormat, ConvertFunction func) @@ -208,6 +294,11 @@ inline void NzPixelFormat::SetConvertFunction(nzPixelFormat srcFormat, nzPixelFo s_convertFunctions[srcFormat][dstFormat] = func; } +inline void NzPixelFormat::SetFlipFunction(nzPixelFlipping flipping, nzPixelFormat format, FlipFunction func) +{ + s_flipFunctions[flipping][format] = func; +} + inline NzString NzPixelFormat::ToString(nzPixelFormat format) { switch (format) @@ -269,7 +360,6 @@ inline NzString NzPixelFormat::ToString(nzPixelFormat format) case nzPixelFormat_RGBA8: return "RGBA8"; - case nzPixelFormat_Count: case nzPixelFormat_Undefined: break; } 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/Renderer/VertexBuffer.hpp b/include/Nazara/Utility/VertexBuffer.hpp similarity index 76% rename from include/Nazara/Renderer/VertexBuffer.hpp rename to include/Nazara/Utility/VertexBuffer.hpp index a4634d78a..49cee5012 100644 --- a/include/Nazara/Renderer/VertexBuffer.hpp +++ b/include/Nazara/Utility/VertexBuffer.hpp @@ -8,21 +8,22 @@ #define NAZARA_VERTEXBUFFER_HPP #include -#include +#include +#include -class NAZARA_API NzVertexBuffer +class NAZARA_API NzVertexBuffer : public NzResource { public: NzVertexBuffer(NzBuffer* buffer, unsigned int startVertex, unsigned int vertexCount); - NzVertexBuffer(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage = nzBufferUsage_Static); + NzVertexBuffer(unsigned int length, nzUInt8 typeSize, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); NzVertexBuffer(const NzVertexBuffer& vertexBuffer); ~NzVertexBuffer(); bool Fill(const void* data, unsigned int offset, unsigned int length); NzBuffer* GetBuffer() const; - void* GetBufferPtr(); - const void* GetBufferPtr() const; + void* GetPointer(); + const void* GetPointer() const; unsigned int GetStartVertex() const; nzUInt8 GetTypeSize() const; unsigned int GetVertexCount() const; @@ -30,6 +31,9 @@ class NAZARA_API NzVertexBuffer bool IsHardware() const; void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0); + + bool SetStorage(nzBufferStorage storage); + bool Unmap(); private: diff --git a/include/Nazara/Utility/VertexDeclaration.hpp b/include/Nazara/Utility/VertexDeclaration.hpp new file mode 100644 index 000000000..78e284b97 --- /dev/null +++ b/include/Nazara/Utility/VertexDeclaration.hpp @@ -0,0 +1,53 @@ +// 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 + +#ifndef NAZARA_VERTEXDECLARATION_HPP +#define NAZARA_VERTEXDECLARATION_HPP + +#include +#include +#include + +struct NzVertexElement +{ + unsigned int offset; + unsigned int usageIndex = 0; + nzElementStream stream = nzElementStream_VertexData; + nzElementType type; + nzElementUsage usage; +}; + +struct NzVertexDeclarationImpl; + +class NAZARA_API NzVertexDeclaration : public NzResource +{ + public: + 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 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: + NzVertexDeclarationImpl* m_sharedImpl = nullptr; +}; + +#endif // NAZARA_VERTEXDECLARATION_HPP diff --git a/include/Nazara/Utility/Window.hpp b/include/Nazara/Utility/Window.hpp index acd694f50..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,6 +25,9 @@ #include #endif +class NzCursor; +class NzImage; +class NzIcon; class NzUtility; class NzWindowImpl; @@ -33,26 +37,14 @@ class NAZARA_API NzWindow : NzNonCopyable friend class NzWindowImpl; public: - enum Style - { - None = 0x0, - Fullscreen = 0x1, - - Closable = 0x2, - Resizable = 0x4, - Titlebar = 0x8, - - Default = Closable | Resizable | Titlebar - }; - NzWindow(); - NzWindow(NzVideoMode mode, const NzString& title, nzUInt32 style = Default); + NzWindow(NzVideoMode mode, const NzString& title, nzUInt32 style = nzWindowStyle_Default); NzWindow(NzWindowHandle handle); virtual ~NzWindow(); void Close(); - bool Create(NzVideoMode mode, const NzString& title, nzUInt32 style = Default); + bool Create(NzVideoMode mode, const NzString& title, nzUInt32 style = nzWindowStyle_Default); bool Create(NzWindowHandle handle); void EnableKeyRepeat(bool enable); @@ -73,8 +65,11 @@ class NAZARA_API NzWindow : NzNonCopyable bool PollEvent(NzEvent* event); + void SetCursor(nzWindowCursor cursor); + void SetCursor(const NzCursor& cursor); void SetEventListener(bool listener); void SetFocus(); + void SetIcon(const NzIcon& icon); void SetMaximumSize(const NzVector2i& maxSize); void SetMaximumSize(int width, int height); void SetMinimumSize(const NzVector2i& minSize); @@ -86,8 +81,6 @@ class NAZARA_API NzWindow : NzNonCopyable void SetTitle(const NzString& title); void SetVisible(bool visible); - void ShowMouseCursor(bool show); - void StayOnTop(bool stayOnTop); bool WaitEvent(NzEvent* event); 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 53395d609..b983ed9e7 100644 --- a/src/Nazara/Core/String.cpp +++ b/src/Nazara/Core/String.cpp @@ -13,15 +13,13 @@ #include #include #include - -#define NAZARA_CLASS_STRING -#include #include inline unsigned int nzPow2(unsigned int n) { unsigned int x = 1; + // Tant que x est plus petit que n, on décale ses bits vers la gauche, ce qui revient à multiplier par deux while(x <= n) x <<= 1; @@ -265,9 +263,15 @@ NzString& NzString::Append(const NzString& string) return *this; } -void NzString::Clear() +void NzString::Clear(bool keepBuffer) { - ReleaseString(); + if (keepBuffer) + { + EnsureOwnership(); + m_sharedString->size = 0; + } + else + ReleaseString(); } bool NzString::Contains(char character, int start, nzUInt32 flags) const @@ -2843,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]; @@ -2913,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]; @@ -3198,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); @@ -3242,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; @@ -3492,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); @@ -3842,7 +3853,7 @@ bool NzString::ToBool(bool* value, nzUInt32 flags) const bool NzString::ToDouble(double* value) const { - if (m_sharedString->size) + if (m_sharedString->size == 0) return false; if (value) @@ -3853,13 +3864,15 @@ bool NzString::ToDouble(double* value) const bool NzString::ToInteger(long long* value, nzUInt8 base) const { - if (!IsNumber(base)) - return false; - if (value) - *value = NzStringToNumber(*this, base); + { + bool ok; + *value = NzStringToNumber(*this, base, &ok); - return true; + return ok; + } + else + return IsNumber(base); } NzString NzString::ToLower(nzUInt32 flags) const @@ -5089,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/Buffer.cpp b/src/Nazara/Renderer/Buffer.cpp deleted file mode 100644 index d5fa5b961..000000000 --- a/src/Nazara/Renderer/Buffer.cpp +++ /dev/null @@ -1,243 +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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace -{ - nzRendererCap storageToCapability[] = { - nzRendererCap_HardwareBuffer, // nzBufferStorage_Hardware - nzRendererCap_SoftwareBuffer, // nzBufferStorage_Software - }; -} - -NzBuffer::NzBuffer(nzBufferType type) : -m_type(type), -m_typeSize(0), -m_impl(nullptr), -m_length(0) -{ -} - -NzBuffer::NzBuffer(nzBufferType type, unsigned int length, nzUInt8 typeSize, nzBufferUsage usage) : -m_type(type), -m_impl(nullptr) -{ - Create(length, typeSize, usage); - - #ifdef NAZARA_DEBUG - if (!m_impl) - { - NazaraError("Failed to create buffer"); - throw std::runtime_error("Constructor failed"); - } - #endif -} - -NzBuffer::~NzBuffer() -{ - Destroy(); -} - -bool NzBuffer::CopyContent(NzBuffer& buffer) -{ - void* ptr = buffer.Map(nzBufferAccess_ReadOnly); - if (!ptr) - { - NazaraError("Failed to map source buffer"); - return false; - } - - bool r = Fill(ptr, 0, m_length); - - if (!buffer.Unmap()) - NazaraWarning("Failed to unmap source buffer"); - - return r; -} - -bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage) -{ - Destroy(); - - // On tente d'abord de faire un buffer hardware, si supporté - if (NazaraRenderer->HasCapability(nzRendererCap_HardwareBuffer)) - { - m_impl = new NzHardwareBuffer(this, m_type); - if (!m_impl->Create(length*typeSize, usage)) - { - NazaraWarning("Failed to create hardware buffer, trying to create software buffer..."); - - delete m_impl; - m_impl = nullptr; - } - } - - if (!m_impl) - { - if (!NazaraRenderer->HasCapability(nzRendererCap_SoftwareBuffer)) - { - // Ne devrait jamais arriver - NazaraError("Software buffer not supported"); - return false; - } - - m_impl = new NzSoftwareBuffer(this, m_type); - if (!m_impl->Create(length*typeSize, usage)) - { - NazaraError("Failed to create software buffer"); - delete m_impl; - m_impl = nullptr; - - return false; - } - } - - m_length = length; - m_typeSize = typeSize; - m_usage = usage; - - // Si on arrive ici c'est que tout s'est bien passé. - return true; -} - -void NzBuffer::Destroy() -{ - if (m_impl) - { - m_impl->Destroy(); - delete m_impl; - m_impl = nullptr; - } -} - -bool NzBuffer::Fill(const void* data, unsigned int offset, unsigned int length) -{ - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Buffer not created"); - return false; - } - - if (offset+length > m_length) - { - NazaraError("Exceeding buffer size"); - return false; - } - #endif - - return m_impl->Fill(data, offset*m_typeSize, length*m_typeSize); -} - -void* NzBuffer::GetBufferPtr() -{ - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Buffer not created"); - return nullptr; - } - #endif - - return m_impl->GetBufferPtr(); -} - -const void* NzBuffer::GetBufferPtr() const -{ - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Buffer not created"); - return nullptr; - } - #endif - - return m_impl->GetBufferPtr(); -} - -NzBufferImpl* NzBuffer::GetImpl() const -{ - return m_impl; -} - -unsigned int NzBuffer::GetLength() const -{ - return m_length; -} - -unsigned int NzBuffer::GetSize() const -{ - return m_length*m_typeSize; -} - -nzBufferStorage NzBuffer::GetStorage() const -{ - return m_storage; -} - -nzBufferType NzBuffer::GetType() const -{ - return m_type; -} - -nzUInt8 NzBuffer::GetTypeSize() const -{ - return m_typeSize; -} - -nzBufferUsage NzBuffer::GetUsage() const -{ - return m_usage; -} - -bool NzBuffer::IsHardware() const -{ - return m_storage == nzBufferStorage_Hardware; -} - -void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length) -{ - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Buffer not created"); - return nullptr; - } - - if (offset+length > m_length) - { - NazaraError("Exceeding buffer size"); - return nullptr; - } - #endif - - return m_impl->Map(access, offset*m_typeSize, length*m_typeSize); -} - -bool NzBuffer::Unmap() -{ - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Buffer not created"); - return false; - } - #endif - - return m_impl->Unmap(); -} - -bool NzBuffer::IsSupported(nzBufferStorage storage) -{ - return NazaraRenderer->HasCapability(storageToCapability[storage]); -} 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 7518a3643..b5d37d905 100644 --- a/src/Nazara/Renderer/GLSLShader.cpp +++ b/src/Nazara/Renderer/GLSLShader.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include namespace @@ -24,7 +24,7 @@ namespace 4 // nzElementUsage_TexCoord }; - const GLenum shaderType[nzShaderType_Count] = { + const GLenum shaderType[nzShaderType_Max+1] = { GL_FRAGMENT_SHADER, // nzShaderType_Fragment GL_GEOMETRY_SHADER, // nzShaderType_Geometry GL_VERTEX_SHADER // nzShaderType_Vertex @@ -98,6 +98,7 @@ bool NzGLSLShader::Compile() glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &length); if (length > 1) { + m_log.Clear(true); m_log.Reserve(length+19-1); // La taille retournée est celle du buffer (Avec caractère de fin) m_log.Prepend("Linkage error: "); m_log.Resize(length+19-1); // Extension du buffer d'écriture pour ajouter le log @@ -129,14 +130,15 @@ bool NzGLSLShader::Create() glBindAttribLocation(m_program, attribIndex[nzElementUsage_Diffuse], "Diffuse"); glBindAttribLocation(m_program, attribIndex[nzElementUsage_Tangent], "Tangent"); - NzString uniformName = "TexCoordi"; - 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()); } - for (int i = 0; i < nzShaderType_Count; ++i) + for (int i = 0; i <= nzShaderType_Max; ++i) m_shaders[i] = 0; return true; @@ -242,6 +244,7 @@ bool NzGLSLShader::Load(nzShaderType type, const NzString& source) glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); if (length > 1) { + m_log.Clear(true); m_log.Reserve(length+19-1); // La taille retournée est celle du buffer (Avec caractère de fin) m_log.Prepend("Compilation error: "); m_log.Resize(length+19-1); // Extension du buffer d'écriture pour ajouter le log diff --git a/src/Nazara/Renderer/GLSLShader.hpp b/src/Nazara/Renderer/GLSLShader.hpp index 658e6e67d..f32d783ec 100644 --- a/src/Nazara/Renderer/GLSLShader.hpp +++ b/src/Nazara/Renderer/GLSLShader.hpp @@ -63,7 +63,7 @@ class NzGLSLShader : public NzShaderImpl mutable std::map m_idCache; std::map m_textures; GLuint m_program; - GLuint m_shaders[nzShaderType_Count]; + GLuint m_shaders[nzShaderType_Max+1]; NzShader* m_parent; NzString m_log; }; diff --git a/src/Nazara/Renderer/HardwareBuffer.cpp b/src/Nazara/Renderer/HardwareBuffer.cpp index c017967be..af6401074 100644 --- a/src/Nazara/Renderer/HardwareBuffer.cpp +++ b/src/Nazara/Renderer/HardwareBuffer.cpp @@ -52,14 +52,14 @@ namespace if (access == nzBufferAccess_DiscardAndWrite) { - GLint size; - glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_SIZE, &size); + GLint bufferSize; + glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_SIZE, &bufferSize); - GLint usage; - glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_USAGE, &usage); + GLint bufferUsage; + glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_USAGE, &bufferUsage); // On discard le buffer - glBufferData(bufferTargetBinding[type], size, nullptr, usage); + glBufferData(bufferTargetBinding[type], bufferSize, nullptr, bufferUsage); } void* ptr = glMapBuffer(bufferTarget[type], bufferLock[access]); @@ -154,8 +154,8 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int if (size < 32*1024) { // http://www.opengl.org/wiki/Vertex_Specification_Best_Practices - if (size == m_parent->GetLength()) - glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetStorage()]); // Discard + if (size == m_parent->GetSize()) + glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetUsage()]); // Discard glBufferSubData(bufferTarget[m_type], offset, size, data); } @@ -188,7 +188,7 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int return true; } -void* NzHardwareBuffer::GetBufferPtr() +void* NzHardwareBuffer::GetPointer() { return nullptr; } @@ -198,7 +198,7 @@ bool NzHardwareBuffer::IsHardware() const return true; } -void* NzHardwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length) +void* NzHardwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size) { NzContext::EnsureContext(); @@ -209,7 +209,7 @@ void* NzHardwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned if (previous != m_buffer) glBindBuffer(bufferTarget[m_type], m_buffer); - void* ptr = mapBuffer(m_type, access, offset, length); + void* ptr = mapBuffer(m_type, access, offset, size); // Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérrations chaînées) if (previous != m_buffer && previous != 0) @@ -235,14 +235,14 @@ bool NzHardwareBuffer::Unmap() glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetStorage()]); - // Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérrations chaînées) + // Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées) if (previous != m_buffer && previous != 0) glBindBuffer(bufferTarget[m_type], previous); return false; } - // Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérrations chaînées) + // Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées) if (previous != m_buffer && previous != 0) glBindBuffer(bufferTarget[m_type], previous); diff --git a/src/Nazara/Renderer/HardwareBuffer.hpp b/src/Nazara/Renderer/HardwareBuffer.hpp index f1652098e..c2451adc2 100644 --- a/src/Nazara/Renderer/HardwareBuffer.hpp +++ b/src/Nazara/Renderer/HardwareBuffer.hpp @@ -8,8 +8,8 @@ #define NAZARA_HARDWAREBUFFER_HPP #include -#include #include +#include class NzHardwareBuffer : public NzBufferImpl { @@ -22,13 +22,13 @@ class NzHardwareBuffer : public NzBufferImpl bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static); void Destroy(); - bool Fill(const void* data, unsigned int offset, unsigned int length); + bool Fill(const void* data, unsigned int offset, unsigned int size); - void* GetBufferPtr(); + void* GetPointer(); bool IsHardware() const; - void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0); + void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0); bool Unmap(); private: diff --git a/src/Nazara/Renderer/OpenGL.cpp b/src/Nazara/Renderer/OpenGL.cpp index d6144728d..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,10 +395,13 @@ 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()) + ")"); } } + // PixelBufferObject + openGLextensions[NzOpenGL::PixelBufferObject] = (openGLversion >= 210 || IsSupported("GL_ARB_pixel_buffer_object")); + // SeparateShaderObjects if (openGLversion >= 400 || IsSupported("GL_ARB_gpu_shader_fp64")) { @@ -449,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())); } } } @@ -470,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())); } } @@ -487,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) @@ -502,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 ce8e0ab53..d5865277f 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -6,16 +6,17 @@ #include #include #include -#include #include #include -#include +#include #include #include #include -#include -#include +#include +#include #include +#include +#include #include #include @@ -27,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) }; @@ -128,6 +130,11 @@ namespace GL_REPLACE, // nzStencilOperation_Replace GL_ZERO // nzStencilOperation_Zero }; + + NzBufferImpl* HardwareBufferFunction(NzBuffer* parent, nzBufferType type) + { + return new NzHardwareBuffer(parent, type); + } } NzRenderer::NzRenderer() @@ -197,29 +204,34 @@ void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int f return; } - nzUInt8 indexSize = m_indexBuffer->GetIndexSize(); - - GLenum type; - switch (indexSize) + if (m_indexBuffer->IsSequential()) + glDrawArrays(openglPrimitive[primitive], m_indexBuffer->GetStartIndex(), m_indexBuffer->GetIndexCount()); + else { - case 1: - type = GL_UNSIGNED_BYTE; - break; + nzUInt8 indexSize = m_indexBuffer->GetIndexSize(); - case 2: - type = GL_UNSIGNED_SHORT; - break; + GLenum type; + switch (indexSize) + { + case 1: + type = GL_UNSIGNED_BYTE; + break; - case 4: - type = GL_UNSIGNED_INT; - break; + case 2: + type = GL_UNSIGNED_SHORT; + break; - default: - NazaraError("Invalid index size (" + NzString::Number(indexSize) + ')'); - return; + case 4: + type = GL_UNSIGNED_INT; + break; + + default: + NazaraError("Invalid index size (" + NzString::Number(indexSize) + ')'); + return; + } + + glDrawElements(openglPrimitive[primitive], indexCount, type, reinterpret_cast(m_indexBuffer->GetPointer()) + firstIndex*indexSize); } - - glDrawElements(openglPrimitive[primitive], indexCount, type, reinterpret_cast(m_indexBuffer->GetBufferPtr()) + firstIndex*indexSize); } void NzRenderer::DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount) @@ -333,15 +345,13 @@ bool NzRenderer::Initialize() m_utilityModule = new NzUtility; m_utilityModule->Initialize(); } + else + m_utilityModule = nullptr; if (NzOpenGL::Initialize()) { NzContext::EnsureContext(); - const NzContext* context = NzContext::GetReference(); - bool compatibility = context->GetParameters().compatibilityProfile; - - m_vaoUpdated = false; m_indexBuffer = nullptr; m_shader = nullptr; m_stencilCompare = nzRendererComparison_Always; @@ -353,6 +363,7 @@ bool NzRenderer::Initialize() m_stencilReference = 0; m_stencilZFail = nzStencilOperation_Keep; m_target = nullptr; + m_vaoUpdated = false; m_vertexBuffer = nullptr; m_vertexDeclaration = nullptr; @@ -362,7 +373,7 @@ bool NzRenderer::Initialize() m_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 1.5 m_capabilities[nzRendererCap_MultipleRenderTargets] = true; // Natif depuis OpenGL 2.0 m_capabilities[nzRendererCap_OcclusionQuery] = true; // Natif depuis OpenGL 1.5 - m_capabilities[nzRendererCap_SoftwareBuffer] = compatibility || NzOpenGL::GetVersion() <= 300; // Déprécié en OpenGL 3 + m_capabilities[nzRendererCap_PixelBufferObject] = NzOpenGL::IsSupported(NzOpenGL::PixelBufferObject); m_capabilities[nzRendererCap_Texture3D] = NzOpenGL::IsSupported(NzOpenGL::Texture3D); m_capabilities[nzRendererCap_TextureCubemap] = true; // Natif depuis OpenGL 1.3 m_capabilities[nzRendererCap_TextureMulti] = true; // Natif depuis OpenGL 1.3 @@ -393,11 +404,17 @@ 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; + NzBuffer::SetBufferFunction(nzBufferStorage_Hardware, HardwareBufferFunction); + s_initialized = true; return true; @@ -497,9 +514,16 @@ void NzRenderer::SetFaceFilling(nzFaceFilling fillingMode) glPolygonMode(GL_FRONT_AND_BACK, faceFillingMode[fillingMode]); } - bool NzRenderer::SetIndexBuffer(const NzIndexBuffer* indexBuffer) { + #if NAZARA_RENDERER_SAFE + if (indexBuffer && !indexBuffer->IsHardware() && !indexBuffer->IsSequential()) + { + NazaraError("Buffer must be hardware"); + return false; + } + #endif + if (indexBuffer != m_indexBuffer) { m_indexBuffer = indexBuffer; @@ -537,8 +561,6 @@ bool NzRenderer::SetShader(NzShader* shader) return false; } } - else - m_shader = nullptr; m_shader = shader; @@ -635,6 +657,14 @@ bool NzRenderer::SetTarget(NzRenderTarget* target) bool NzRenderer::SetVertexBuffer(const NzVertexBuffer* vertexBuffer) { + #if NAZARA_RENDERER_SAFE + if (vertexBuffer && !vertexBuffer->IsHardware()) + { + NazaraError("Buffer must be hardware"); + return false; + } + #endif + if (m_vertexBuffer != vertexBuffer) { m_vertexBuffer = vertexBuffer; @@ -675,13 +705,7 @@ void NzRenderer::SetViewport(const NzRectui& viewport) } unsigned int width = m_target->GetWidth(); - if (viewport.x+viewport.width >= width) - { - NazaraError("Rectangle dimensions are out of bounds"); - return; - } - - if (viewport.y+viewport.height >= height) + if (viewport.x+viewport.width > width || viewport.y+viewport.height > height) { NazaraError("Rectangle dimensions are out of bounds"); return; @@ -812,31 +836,35 @@ bool NzRenderer::EnsureStateUpdate() if (update) { - m_vertexBuffer->GetBuffer()->GetImpl()->Bind(); + NzHardwareBuffer* vertexBuffer = static_cast(m_vertexBuffer->GetBuffer()->GetImpl()); + vertexBuffer->Bind(); - const nzUInt8* buffer = reinterpret_cast(m_vertexBuffer->GetBufferPtr()); + 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) - m_indexBuffer->GetBuffer()->GetImpl()->Bind(); + { + NzHardwareBuffer* indexBuffer = static_cast(m_indexBuffer->GetBuffer()->GetImpl()); + indexBuffer->Bind(); + } } if (vaoSupported) diff --git a/src/Nazara/Renderer/Texture.cpp b/src/Nazara/Renderer/Texture.cpp index 8283fc32c..abd54b992 100644 --- a/src/Nazara/Renderer/Texture.cpp +++ b/src/Nazara/Renderer/Texture.cpp @@ -124,7 +124,6 @@ namespace return true; case nzPixelFormat_Undefined: - case nzPixelFormat_Count: NazaraInternalError("Invalid pixel format"); return false; } @@ -252,8 +251,8 @@ namespace return true; } - static unsigned short lockedLevel[nzImageType_Count] = {0}; - static GLuint lockedPrevious[nzImageType_Count] = {0}; + static unsigned short lockedLevel[nzImageType_Max+1] = {0}; + static GLuint lockedPrevious[nzImageType_Max+1] = {0}; void LockTexture(NzTextureImpl* impl) { @@ -342,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; @@ -434,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); @@ -478,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); @@ -578,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; @@ -849,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)) @@ -873,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)) { @@ -943,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); @@ -982,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); @@ -991,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); @@ -1354,12 +1346,13 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve nzUInt8 bpp = NzPixelFormat::GetBPP(m_impl->format); // Inversion de la texture pour le repère d'OpenGL - NzImage mirrored; - mirrored.Create(m_impl->type, m_impl->format, cube.width, cube.height, cube.depth); - mirrored.Update(pixels); - - if (!mirrored.FlipVertically()) + unsigned int size = cube.width*cube.height*cube.depth*bpp; + nzUInt8* mirrored = new nzUInt8[size]; + if (!NzPixelFormat::Flip(nzPixelFlipping_Vertically, m_impl->format, cube.width, cube.height, cube.depth, pixels, mirrored)) + { NazaraWarning("Failed to flip image"); + std::memcpy(mirrored, pixels, size); + } SetUnpackAlignement(bpp); @@ -1367,15 +1360,15 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve switch (m_impl->type) { case nzImageType_1D: - glTexSubImage1D(GL_TEXTURE_1D, level, cube.x, cube.width, format.dataFormat, format.dataType, mirrored.GetConstPixels()); + glTexSubImage1D(GL_TEXTURE_1D, level, cube.x, cube.width, format.dataFormat, format.dataType, mirrored); break; case nzImageType_2D: - glTexSubImage2D(GL_TEXTURE_2D, level, cube.x, height-cube.height-cube.y, cube.width, cube.height, format.dataFormat, format.dataType, mirrored.GetConstPixels()); + glTexSubImage2D(GL_TEXTURE_2D, level, cube.x, height-cube.height-cube.y, cube.width, cube.height, format.dataFormat, format.dataType, mirrored); break; case nzImageType_3D: - glTexSubImage3D(GL_TEXTURE_3D, level, cube.x, height-cube.height-cube.y, cube.z, cube.width, cube.height, cube.depth, format.dataFormat, format.dataType, mirrored.GetConstPixels()); + glTexSubImage3D(GL_TEXTURE_3D, level, cube.x, height-cube.height-cube.y, cube.z, cube.width, cube.height, cube.depth, format.dataFormat, format.dataType, mirrored); break; default: @@ -1383,6 +1376,8 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve } UnlockTexture(m_impl); + delete[] mirrored; + return true; } @@ -1503,19 +1498,21 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRe nzUInt8 bpp = NzPixelFormat::GetBPP(m_impl->format); // Inversion de la texture pour le repère d'OpenGL - NzImage mirrored; - mirrored.Create(m_impl->type, m_impl->format, rect.width, rect.height); - mirrored.Update(pixels); - - if (!mirrored.FlipVertically()) + unsigned int size = rect.width*rect.height*bpp; + nzUInt8* mirrored = new nzUInt8[size]; + if (!NzPixelFormat::Flip(nzPixelFlipping_Vertically, m_impl->format, rect.width, rect.height, 1, pixels, mirrored)) + { NazaraWarning("Failed to flip image"); + std::memcpy(mirrored, pixels, size); + } SetUnpackAlignement(bpp); LockTexture(m_impl); - glTexSubImage2D(cubemapFace[face], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, mirrored.GetConstPixels()); + glTexSubImage2D(cubemapFace[face], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, mirrored); UnlockTexture(m_impl); + return true; } @@ -1576,7 +1573,6 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format) } case nzPixelFormat_Undefined: - case nzPixelFormat_Count: break; } @@ -1585,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/Renderer/VertexDeclaration.cpp b/src/Nazara/Renderer/VertexDeclaration.cpp deleted file mode 100644 index e764543ca..000000000 --- a/src/Nazara/Renderer/VertexDeclaration.cpp +++ /dev/null @@ -1,127 +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 - -#include -#include -#include -#include -#include - -namespace -{ - const unsigned int size[] = - { - 4, // nzElementType_Color - 8, // nzElementType_Double1 - 16, // nzElementType_Double2 - 24, // nzElementType_Double3 - 32, // nzElementType_Double4 - 4, // nzElementType_Float1 - 8, // nzElementType_Float2 - 12, // nzElementType_Float3 - 16 // nzElementType_Float4 - }; -} - -bool NzVertexDeclaration::Create(const NzVertexElement* elements, unsigned int elementCount) -{ - for (unsigned int i = 0; i < elementCount; ++i) - { - unsigned int stream = elements[i].stream; - - if (stream >= m_streams.size()) - m_streams.resize(stream+1); - #if NAZARA_RENDERER_SAFE - else // Seulement si le stream ne vient pas d'être créé (Autrement c'est inutile) - { - bool fp64 = NazaraRenderer->HasCapability(nzRendererCap_FP64); - - for (unsigned int j = 0; j < i; ++j) - { - 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; - } - else if (!fp64 && elements[j].type >= nzElementType_Double1 && elements[j].type <= nzElementType_Double4) - { - NazaraError("FP64 not supported"); - 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; - - m_streams[stream].elements.push_back(element); - } - - 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 - stream.stride = ((static_cast(stream.stride)-1)/32+1)*32; - #endif - } - - return true; -} - -const NzVertexDeclaration::Element* NzVertexDeclaration::GetElement(unsigned int i, unsigned int stream) const -{ - #if NAZARA_RENDERER_SAFE - if (stream >= m_streams.size()) - { - NazaraError("Stream out of range"); - return nullptr; - } - - if (i >= m_streams[stream].elements.size()) - { - NazaraError("Index out of range"); - return nullptr; - } - #endif - - return &m_streams[stream].elements[i]; -} - -unsigned int NzVertexDeclaration::GetElementCount(unsigned int stream) const -{ - #if NAZARA_RENDERER_SAFE - if (stream >= m_streams.size()) - { - NazaraError("Stream out of range"); - return 0; - } - #endif - - return m_streams[stream].elements.size(); -} - -unsigned int NzVertexDeclaration::GetStreamCount() const -{ - return m_streams.size(); -} - -unsigned int NzVertexDeclaration::GetStride(unsigned int stream) const -{ - #if NAZARA_RENDERER_SAFE - if (stream >= m_streams.size()) - { - NazaraError("Stream out of range"); - return 0; - } - #endif - - return m_streams[stream].stride; -} 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/Buffer.cpp b/src/Nazara/Utility/Buffer.cpp new file mode 100644 index 000000000..0f35946aa --- /dev/null +++ b/src/Nazara/Utility/Buffer.cpp @@ -0,0 +1,336 @@ +// 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 +#include + +namespace +{ + NzBufferImpl* SoftwareBufferFunction(NzBuffer* parent, nzBufferType type) + { + return new NzSoftwareBuffer(parent, type); + } +} + +NzBuffer::NzBuffer(nzBufferType type) : +m_type(type), +m_typeSize(0), +m_impl(nullptr), +m_length(0) +{ +} + +NzBuffer::NzBuffer(nzBufferType type, unsigned int length, nzUInt8 typeSize, nzBufferStorage storage, nzBufferUsage usage) : +m_type(type), +m_impl(nullptr) +{ + Create(length, typeSize, storage, usage); + + #ifdef NAZARA_DEBUG + if (!m_impl) + { + NazaraError("Failed to create buffer"); + throw std::runtime_error("Constructor failed"); + } + #endif +} + +NzBuffer::~NzBuffer() +{ + Destroy(); +} + +bool NzBuffer::CopyContent(NzBuffer& buffer) +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Buffer must be valid"); + return false; + } + + if (!buffer.IsValid()) + { + NazaraError("Source buffer must be valid"); + return false; + } + + if (!buffer.GetTypeSize() != m_typeSize) + { + NazaraError("Source buffer type size does not match buffer type size"); + return false; + } + #endif + + void* ptr = buffer.Map(nzBufferAccess_ReadOnly); + if (!ptr) + { + NazaraError("Failed to map source buffer"); + return false; + } + + bool r = Fill(ptr, 0, buffer.GetLength()); + + if (!buffer.Unmap()) + NazaraWarning("Failed to unmap source buffer"); + + return r; +} + +bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferStorage storage, nzBufferUsage usage) +{ + Destroy(); + + // On tente d'abord de faire un buffer hardware, si supporté + if (s_bufferFunctions[storage]) + { + NzBufferImpl* impl = s_bufferFunctions[storage](this, m_type); + if (!impl->Create(length*typeSize, usage)) + { + NazaraError("Failed to create buffer"); + delete impl; + + return false; + } + + m_impl = impl; + } + else + { + NazaraError("Buffer storage not supported"); + return false; + } + + m_length = length; + m_typeSize = typeSize; + m_storage = storage; + m_usage = usage; + + // Si on arrive ici c'est que tout s'est bien passé. + return true; +} + +void NzBuffer::Destroy() +{ + if (m_impl) + { + m_impl->Destroy(); + delete m_impl; + m_impl = nullptr; + } +} + +bool NzBuffer::Fill(const void* data, unsigned int offset, unsigned int length) +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Buffer not valid"); + return false; + } + + if (offset+length > m_length) + { + NazaraError("Exceeding buffer size"); + return false; + } + #endif + + return m_impl->Fill(data, offset*m_typeSize, ((length == 0) ? m_length-offset : length)*m_typeSize); +} + +NzBufferImpl* NzBuffer::GetImpl() const +{ + return m_impl; +} + +unsigned int NzBuffer::GetLength() const +{ + return m_length; +} + +void* NzBuffer::GetPointer() +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Buffer not valid"); + return nullptr; + } + #endif + + return m_impl->GetPointer(); +} + +const void* NzBuffer::GetPointer() const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Buffer not valid"); + return nullptr; + } + #endif + + return m_impl->GetPointer(); +} + +unsigned int NzBuffer::GetSize() const +{ + return m_length*m_typeSize; +} + +nzBufferStorage NzBuffer::GetStorage() const +{ + return m_storage; +} + +nzBufferType NzBuffer::GetType() const +{ + return m_type; +} + +nzUInt8 NzBuffer::GetTypeSize() const +{ + return m_typeSize; +} + +nzBufferUsage NzBuffer::GetUsage() const +{ + return m_usage; +} + +bool NzBuffer::IsHardware() const +{ + return m_storage == nzBufferStorage_Hardware; +} + +bool NzBuffer::IsValid() const +{ + return m_impl != nullptr; +} + +void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length) +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Buffer not valid"); + return nullptr; + } + + if (offset+length > m_length) + { + NazaraError("Exceeding buffer size"); + return nullptr; + } + #endif + + return m_impl->Map(access, offset*m_typeSize, ((length == 0) ? m_length-offset : length)*m_typeSize); +} + +bool NzBuffer::SetStorage(nzBufferStorage storage) +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Buffer not valid"); + return false; + } + #endif + + if (m_storage == storage) + return true; + + #if NAZARA_UTILITY_SAFE + if (!IsSupported(storage)) + { + NazaraError("Storage not supported"); + return false; + } + #endif + + void* ptr = m_impl->Map(nzBufferAccess_ReadOnly, 0, m_length*m_typeSize); + if (!ptr) + { + NazaraError("Failed to map buffer"); + return false; + } + + NzBufferImpl* impl = s_bufferFunctions[storage](this, m_type); + if (!impl->Create(m_length*m_typeSize, m_usage)) + { + NazaraError("Failed to create buffer"); + delete impl; + + if (!m_impl->Unmap()) + NazaraWarning("Failed to unmap buffer"); + + return false; + } + + if (!impl->Fill(ptr, 0, m_length*m_typeSize)) + { + NazaraError("Failed to fill buffer"); + impl->Destroy(); + delete impl; + + if (!m_impl->Unmap()) + NazaraWarning("Failed to unmap buffer"); + + return false; + } + + m_impl->Unmap(); + m_impl->Destroy(); + delete m_impl; + + m_impl = impl; + m_storage = storage; + + return true; +} + +bool NzBuffer::Unmap() +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Buffer not valid"); + return false; + } + #endif + + return m_impl->Unmap(); +} + +bool NzBuffer::IsSupported(nzBufferStorage storage) +{ + return s_bufferFunctions[storage] != nullptr; +} + +void NzBuffer::SetBufferFunction(nzBufferStorage storage, BufferFunction func) +{ + s_bufferFunctions[storage] = func; +} + +bool NzBuffer::Initialize() +{ + s_bufferFunctions[nzBufferStorage_Software] = SoftwareBufferFunction; + + return true; +} + +void NzBuffer::Uninitialize() +{ + std::memset(s_bufferFunctions, 0, (nzBufferStorage_Max+1)*sizeof(NzBuffer::BufferFunction)); +} + +NzBuffer::BufferFunction NzBuffer::s_bufferFunctions[nzBufferStorage_Max+1] = {0}; diff --git a/src/Nazara/Renderer/BufferImpl.cpp b/src/Nazara/Utility/BufferImpl.cpp similarity index 72% rename from src/Nazara/Renderer/BufferImpl.cpp rename to src/Nazara/Utility/BufferImpl.cpp index 99f034067..93ad045c4 100644 --- a/src/Nazara/Renderer/BufferImpl.cpp +++ b/src/Nazara/Utility/BufferImpl.cpp @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp -#include -#include +#include +#include NzBufferImpl::~NzBufferImpl() = default; diff --git a/src/Nazara/Utility/Cursor.cpp b/src/Nazara/Utility/Cursor.cpp new file mode 100644 index 000000000..f19b61cae --- /dev/null +++ b/src/Nazara/Utility/Cursor.cpp @@ -0,0 +1,61 @@ +// 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 + +#if defined(NAZARA_PLATFORM_WINDOWS) + #include +#elif defined(NAZARA_PLATFORM_LINUX) + #include +#else + #error Lack of implementation: Cursor +#endif + +#include + +NzCursor::NzCursor() : +m_impl(nullptr) +{ +} + +NzCursor::~NzCursor() +{ + Destroy(); +} + +bool NzCursor::Create(const NzImage& cursor, int hotSpotX, int hotSpotY) +{ + Destroy(); + + m_impl = new NzCursorImpl; + if (!m_impl->Create(cursor, hotSpotX, hotSpotY)) + { + NazaraError("Failed to create cursor implementation"); + delete m_impl; + m_impl = nullptr; + return false; + } + + return true; +} + +bool NzCursor::Create(const NzImage& cursor, const NzVector2i& hotSpot) +{ + return Create(cursor, hotSpot.x, hotSpot.y); +} + +void NzCursor::Destroy() +{ + if (m_impl) + { + m_impl->Destroy(); + delete m_impl; + m_impl = nullptr; + } +} + +bool NzCursor::IsValid() const +{ + return m_impl != nullptr; +} diff --git a/src/Nazara/Utility/Icon.cpp b/src/Nazara/Utility/Icon.cpp new file mode 100644 index 000000000..e2b8db5ce --- /dev/null +++ b/src/Nazara/Utility/Icon.cpp @@ -0,0 +1,56 @@ +// 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 + +#if defined(NAZARA_PLATFORM_WINDOWS) + #include +#elif defined(NAZARA_PLATFORM_LINUX) + #include +#else + #error Lack of implementation: Icon +#endif + +#include + +NzIcon::NzIcon() : +m_impl(nullptr) +{ +} + +NzIcon::~NzIcon() +{ + Destroy(); +} + +bool NzIcon::Create(const NzImage& icon) +{ + Destroy(); + + m_impl = new NzIconImpl; + if (!m_impl->Create(icon)) + { + NazaraError("Failed to create icon implementation"); + delete m_impl; + m_impl = nullptr; + return false; + } + + return true; +} + +void NzIcon::Destroy() +{ + if (m_impl) + { + m_impl->Destroy(); + delete m_impl; + m_impl = nullptr; + } +} + +bool NzIcon::IsValid() const +{ + return m_impl != nullptr; +} diff --git a/src/Nazara/Utility/Image.cpp b/src/Nazara/Utility/Image.cpp index 11284bd52..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) { @@ -494,24 +498,12 @@ bool NzImage::FlipHorizontally() EnsureOwnership(); - nzUInt8 bpp = NzPixelFormat::GetBPP(m_sharedImage->format); unsigned int width = m_sharedImage->width; unsigned int height = m_sharedImage->height; unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : m_sharedImage->depth; for (unsigned int level = 0; level < m_sharedImage->levelCount; ++level) { - for (unsigned int z = 0; z < depth; ++z) - { - nzUInt8* ptr = &m_sharedImage->pixels[level][width*height*z]; - unsigned int lineStride = width*bpp; - for (unsigned int y = 0; y < height; ++y) - { - for (unsigned int x = 0; x < width/2; ++x) - std::swap_ranges(&ptr[x*bpp], &ptr[(x+1)*bpp], &ptr[(width-x)*bpp]); - - ptr += lineStride; - } - } + NzPixelFormat::Flip(nzPixelFlipping_Horizontally, m_sharedImage->format, width, height, depth, m_sharedImage->pixels[level], m_sharedImage->pixels[level]); if (width > 1U) width >>= 1; @@ -545,19 +537,12 @@ bool NzImage::FlipVertically() EnsureOwnership(); - nzUInt8 bpp = NzPixelFormat::GetBPP(m_sharedImage->format); unsigned int width = m_sharedImage->width; unsigned int height = m_sharedImage->height; unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : m_sharedImage->depth; for (unsigned int level = 0; level < m_sharedImage->levelCount; ++level) { - for (unsigned int z = 0; z < depth; ++z) - { - nzUInt8* ptr = &m_sharedImage->pixels[level][width*height*z]; - unsigned int lineStride = width*bpp; - for (unsigned int y = 0; y < height/2; ++y) - std::swap_ranges(&ptr[y*lineStride], &ptr[(y+1)*lineStride-1], &ptr[(height-y-1)*lineStride]); - } + NzPixelFormat::Flip(nzPixelFlipping_Vertically, m_sharedImage->format, width, height, depth, m_sharedImage->pixels[level], m_sharedImage->pixels[level]); if (width > 1U) width >>= 1; @@ -818,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) @@ -1110,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) @@ -1168,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]; @@ -1184,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/Renderer/IndexBuffer.cpp b/src/Nazara/Utility/IndexBuffer.cpp similarity index 67% rename from src/Nazara/Renderer/IndexBuffer.cpp rename to src/Nazara/Utility/IndexBuffer.cpp index 2e822d5d9..e14f30424 100644 --- a/src/Nazara/Renderer/IndexBuffer.cpp +++ b/src/Nazara/Utility/IndexBuffer.cpp @@ -2,11 +2,11 @@ // 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 +#include NzIndexBuffer::NzIndexBuffer(NzBuffer* buffer, unsigned int startIndex, unsigned int indexCount) : m_buffer(buffer), @@ -31,7 +31,7 @@ m_startIndex(startIndex) } } -NzIndexBuffer::NzIndexBuffer(unsigned int length, nzUInt8 indexSize, nzBufferUsage usage) : +NzIndexBuffer::NzIndexBuffer(unsigned int length, nzUInt8 indexSize, nzBufferStorage storage, nzBufferUsage usage) : m_ownsBuffer(true), m_indexCount(length), m_startIndex(0) @@ -46,13 +46,15 @@ m_startIndex(0) } #endif - m_buffer = new NzBuffer(nzBufferType_Index, length, indexSize, usage); + m_buffer = new NzBuffer(nzBufferType_Index, length, indexSize, storage, usage); m_buffer->AddResourceReference(); m_buffer->SetPersistent(false); } NzIndexBuffer::NzIndexBuffer(const NzIndexBuffer& indexBuffer) : +NzResource(true), m_buffer(indexBuffer.m_buffer), +m_ownsBuffer(indexBuffer.m_ownsBuffer), m_indexCount(indexBuffer.m_indexCount), m_startIndex(indexBuffer.m_startIndex) { @@ -60,7 +62,9 @@ m_startIndex(indexBuffer.m_startIndex) { if (m_ownsBuffer) { - m_buffer = new NzBuffer(nzBufferType_Index, indexBuffer.m_buffer->GetLength(), indexBuffer.m_buffer->GetSize(), indexBuffer.m_buffer->GetUsage()); + NzBuffer* buffer = indexBuffer.m_buffer; + + m_buffer = new NzBuffer(nzBufferType_Index, buffer->GetLength(), buffer->GetSize(), buffer->GetStorage(), buffer->GetUsage()); m_buffer->AddResourceReference(); m_buffer->SetPersistent(false); m_buffer->CopyContent(*indexBuffer.m_buffer); @@ -71,8 +75,6 @@ m_startIndex(indexBuffer.m_startIndex) m_buffer->AddResourceReference(); } } - else - m_buffer = nullptr; } NzIndexBuffer::~NzIndexBuffer() @@ -83,10 +85,10 @@ NzIndexBuffer::~NzIndexBuffer() bool NzIndexBuffer::Fill(const void* data, unsigned int offset, unsigned int length) { - #if NAZARA_RENDERER_SAFE + #if NAZARA_UTILITY_SAFE if (!m_buffer) { - NazaraError("Impossible to fill sequential buffer"); + NazaraError("Impossible to fill sequential buffers"); return false; } @@ -105,38 +107,12 @@ NzBuffer* NzIndexBuffer::GetBuffer() const return m_buffer; } -void* NzIndexBuffer::GetBufferPtr() -{ - #if NAZARA_RENDERER_SAFE - if (!m_buffer) - { - NazaraError("Sequential index buffer: Buffer has no pointer"); - return nullptr; - } - #endif - - return reinterpret_cast(m_buffer->GetBufferPtr()) + m_startIndex*m_buffer->GetTypeSize(); -} - -const void* NzIndexBuffer::GetBufferPtr() const -{ - #if NAZARA_RENDERER_SAFE - if (!m_buffer) - { - NazaraError("Sequential index buffer: Buffer has no pointer"); - return nullptr; - } - #endif - - return reinterpret_cast(m_buffer->GetBufferPtr()) + m_startIndex*m_buffer->GetTypeSize(); -} - nzUInt8 NzIndexBuffer::GetIndexSize() const { - #if NAZARA_RENDERER_SAFE + #if NAZARA_UTILITY_SAFE if (!m_buffer) { - NazaraError("Sequential index buffer: Buffer has no index size"); + NazaraError("Sequential buffers have no index size"); return 0; } #endif @@ -144,6 +120,32 @@ nzUInt8 NzIndexBuffer::GetIndexSize() const return m_buffer->GetTypeSize(); } +void* NzIndexBuffer::GetPointer() +{ + #if NAZARA_UTILITY_SAFE + if (!m_buffer) + { + NazaraError("Sequential buffers have no pointer"); + return nullptr; + } + #endif + + return reinterpret_cast(m_buffer->GetPointer()) + m_startIndex*m_buffer->GetTypeSize(); +} + +const void* NzIndexBuffer::GetPointer() const +{ + #if NAZARA_UTILITY_SAFE + if (!m_buffer) + { + NazaraError("Sequential buffers have no pointer"); + return nullptr; + } + #endif + + return reinterpret_cast(m_buffer->GetPointer()) + m_startIndex*m_buffer->GetTypeSize(); +} + unsigned int NzIndexBuffer::GetIndexCount() const { return m_indexCount; @@ -156,10 +158,10 @@ unsigned int NzIndexBuffer::GetStartIndex() const bool NzIndexBuffer::IsHardware() const { - #if NAZARA_RENDERER_SAFE + #if NAZARA_UTILITY_SAFE if (!m_buffer) { - NazaraError("Sequential index buffer is neither hardware or software"); + NazaraWarning("Sequential index buffers are neither hardware or software"); return false; } #endif @@ -174,10 +176,10 @@ bool NzIndexBuffer::IsSequential() const void* NzIndexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length) { - #if NAZARA_RENDERER_SAFE + #if NAZARA_UTILITY_SAFE if (!m_buffer) { - NazaraError("Impossible to map sequential index buffer"); + NazaraError("Impossible to map sequential buffers"); return nullptr; } @@ -191,12 +193,25 @@ void* NzIndexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned in return m_buffer->Map(access, m_startIndex+offset, (length) ? length : m_indexCount-offset); } -bool NzIndexBuffer::Unmap() +bool NzIndexBuffer::SetStorage(nzBufferStorage storage) { - #if NAZARA_RENDERER_SAFE + #if NAZARA_UTILITY_SAFE if (!m_buffer) { - NazaraError("Impossible to unlock sequential index buffer"); + NazaraWarning("Sequential buffers have no storage"); + return true; + } + #endif + + return m_buffer->SetStorage(storage); +} + +bool NzIndexBuffer::Unmap() +{ + #if NAZARA_UTILITY_SAFE + if (!m_buffer) + { + NazaraError("Impossible to unlock sequential buffers"); return false; } #endif 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/PixelFormat.cpp b/src/Nazara/Utility/PixelFormat.cpp index 1a189181e..c4178b4b4 100644 --- a/src/Nazara/Utility/PixelFormat.cpp +++ b/src/Nazara/Utility/PixelFormat.cpp @@ -1314,7 +1314,11 @@ bool NzPixelFormat::Initialize() void NzPixelFormat::Uninitialize() { - std::memset(s_convertFunctions, 0, nzPixelFormat_Count*nzPixelFormat_Count*sizeof(NzPixelFormat::ConvertFunction)); + std::memset(s_convertFunctions, 0, (nzPixelFormat_Max+1)*(nzPixelFormat_Max+1)*sizeof(NzPixelFormat::ConvertFunction)); + + for (unsigned int i = 0; i <= nzPixelFlipping_Max; ++i) + s_flipFunctions[i].clear(); } -NzPixelFormat::ConvertFunction NzPixelFormat::s_convertFunctions[nzPixelFormat_Count][nzPixelFormat_Count] = {{0}}; ///FIXME: Fonctionne correctement ? +NzPixelFormat::ConvertFunction NzPixelFormat::s_convertFunctions[nzPixelFormat_Max+1][nzPixelFormat_Max+1] = {{0}}; ///FIXME: Fonctionne correctement ? +std::map NzPixelFormat::s_flipFunctions[nzPixelFlipping_Max+1]; diff --git a/src/Nazara/Renderer/SoftwareBuffer.cpp b/src/Nazara/Utility/SoftwareBuffer.cpp similarity index 71% rename from src/Nazara/Renderer/SoftwareBuffer.cpp rename to src/Nazara/Utility/SoftwareBuffer.cpp index c579a7e40..0fb3537c9 100644 --- a/src/Nazara/Renderer/SoftwareBuffer.cpp +++ b/src/Nazara/Utility/SoftwareBuffer.cpp @@ -2,22 +2,12 @@ // 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 #include #include -#include - -namespace -{ - GLenum bufferTarget[] = { - GL_ELEMENT_ARRAY_BUFFER, // nzBufferType_Index, - GL_ARRAY_BUFFER, // nzBufferType_Vertex - }; -} +#include NzSoftwareBuffer::NzSoftwareBuffer(NzBuffer* parent, nzBufferType type) : m_type(type) @@ -29,19 +19,6 @@ NzSoftwareBuffer::~NzSoftwareBuffer() { } -void NzSoftwareBuffer::Bind() -{ - #ifdef NAZARA_DEBUG - if (NzContext::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - - glBindBuffer(bufferTarget[m_type], 0); -} - bool NzSoftwareBuffer::Create(unsigned int size, nzBufferUsage usage) { NazaraUnused(usage); @@ -69,7 +46,7 @@ void NzSoftwareBuffer::Destroy() bool NzSoftwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size) { - #if NAZARA_RENDERER_SAFE + #if NAZARA_UTILITY_SAFE if (m_mapped) { NazaraError("Buffer already mapped"); @@ -82,7 +59,7 @@ bool NzSoftwareBuffer::Fill(const void* data, unsigned int offset, unsigned int return true; } -void* NzSoftwareBuffer::GetBufferPtr() +void* NzSoftwareBuffer::GetPointer() { return m_buffer; } @@ -97,7 +74,7 @@ void* NzSoftwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned NazaraUnused(access); NazaraUnused(size); - #if NAZARA_RENDERER_SAFE + #if NAZARA_UTILITY_SAFE if (m_mapped) { NazaraError("Buffer already mapped"); @@ -112,7 +89,7 @@ void* NzSoftwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned bool NzSoftwareBuffer::Unmap() { - #if NAZARA_RENDERER_SAFE + #if NAZARA_UTILITY_SAFE if (!m_mapped) { NazaraError("Buffer not mapped"); diff --git a/src/Nazara/Renderer/SoftwareBuffer.hpp b/src/Nazara/Utility/SoftwareBuffer.hpp similarity index 87% rename from src/Nazara/Renderer/SoftwareBuffer.hpp rename to src/Nazara/Utility/SoftwareBuffer.hpp index 704f8e65f..8df91b919 100644 --- a/src/Nazara/Renderer/SoftwareBuffer.hpp +++ b/src/Nazara/Utility/SoftwareBuffer.hpp @@ -8,7 +8,7 @@ #define NAZARA_SOFTWAREBUFFER_HPP #include -#include +#include class NzSoftwareBuffer : public NzBufferImpl { @@ -16,18 +16,16 @@ class NzSoftwareBuffer : public NzBufferImpl NzSoftwareBuffer(NzBuffer* parent, nzBufferType type); ~NzSoftwareBuffer(); - void Bind(); - bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static); void Destroy(); - bool Fill(const void* data, unsigned int offset, unsigned int length); + bool Fill(const void* data, unsigned int offset, unsigned int size); - void* GetBufferPtr(); + void* GetPointer(); bool IsHardware() const; - void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0); + void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0); bool Unmap(); private: 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 3d1bfe716..0d5b541cb 100644 --- a/src/Nazara/Utility/Utility.cpp +++ b/src/Nazara/Utility/Utility.cpp @@ -4,7 +4,9 @@ #include #include +#include #include +#include #include #include #include @@ -31,9 +33,15 @@ bool NzUtility::Initialize() } #endif + if (!NzBuffer::Initialize()) + { + NazaraError("Failed to initialize buffers"); + return false; + } + if (!NzPixelFormat::Initialize()) { - NazaraError("Failed to initialize pixel format"); + NazaraError("Failed to initialize pixel formats"); return false; } @@ -45,10 +53,15 @@ bool NzUtility::Initialize() return false; } - // Loaders spécialisés + /// 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) + /// 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; @@ -66,12 +79,13 @@ void NzUtility::Uninitialize() } #endif - NzLoaders_STB_Unregister(); + NzLoaders_MD2_Unregister(); NzLoaders_PCX_Unregister(); + NzLoaders_STB_Unregister(); NzWindow::Uninitialize(); - NzPixelFormat::Uninitialize(); + NzBuffer::Uninitialize(); s_initialized = false; } diff --git a/src/Nazara/Renderer/VertexBuffer.cpp b/src/Nazara/Utility/VertexBuffer.cpp similarity index 70% rename from src/Nazara/Renderer/VertexBuffer.cpp rename to src/Nazara/Utility/VertexBuffer.cpp index fed64316b..639355e49 100644 --- a/src/Nazara/Renderer/VertexBuffer.cpp +++ b/src/Nazara/Utility/VertexBuffer.cpp @@ -2,9 +2,10 @@ // 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 NzVertexBuffer::NzVertexBuffer(NzBuffer* buffer, unsigned int startVertex, unsigned int vertexCount) : m_buffer(buffer), @@ -12,27 +13,38 @@ m_ownsBuffer(false), m_startVertex(startVertex), m_vertexCount(vertexCount) { + #ifdef NAZARA_DEBUG + if (!m_buffer) + { + NazaraError("Buffer is null"); + throw std::invalid_argument("Buffer must be valid"); + } + #endif + m_buffer->AddResourceReference(); } -NzVertexBuffer::NzVertexBuffer(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage) : +NzVertexBuffer::NzVertexBuffer(unsigned int length, nzUInt8 typeSize, nzBufferStorage storage, nzBufferUsage usage) : m_ownsBuffer(true), m_startVertex(0), m_vertexCount(length) { - m_buffer = new NzBuffer(nzBufferType_Vertex, length, typeSize, usage); + m_buffer = new NzBuffer(nzBufferType_Vertex, length, typeSize, storage, usage); m_buffer->AddResourceReference(); m_buffer->SetPersistent(false); } NzVertexBuffer::NzVertexBuffer(const NzVertexBuffer& vertexBuffer) : +NzResource(true), m_ownsBuffer(vertexBuffer.m_ownsBuffer), m_startVertex(vertexBuffer.m_startVertex), m_vertexCount(vertexBuffer.m_vertexCount) { if (m_ownsBuffer) { - m_buffer = new NzBuffer(nzBufferType_Vertex, vertexBuffer.m_buffer->GetLength(), vertexBuffer.m_buffer->GetSize(), vertexBuffer.m_buffer->GetUsage()); + NzBuffer* buffer = vertexBuffer.m_buffer; + + m_buffer = new NzBuffer(nzBufferType_Vertex, buffer->GetLength(), buffer->GetSize(), buffer->GetStorage(), buffer->GetUsage()); m_buffer->AddResourceReference(); m_buffer->SetPersistent(false); m_buffer->CopyContent(*vertexBuffer.m_buffer); @@ -51,7 +63,7 @@ NzVertexBuffer::~NzVertexBuffer() bool NzVertexBuffer::Fill(const void* data, unsigned int offset, unsigned int length) { - #if NAZARA_RENDERER_SAFE + #if NAZARA_UTILITY_SAFE if (offset+length > m_vertexCount) { NazaraError("Exceeding virtual buffer size"); @@ -67,14 +79,14 @@ NzBuffer* NzVertexBuffer::GetBuffer() const return m_buffer; } -void* NzVertexBuffer::GetBufferPtr() +void* NzVertexBuffer::GetPointer() { - return reinterpret_cast(m_buffer->GetBufferPtr()) + m_startVertex*m_buffer->GetTypeSize(); + return reinterpret_cast(m_buffer->GetPointer()) + m_startVertex*m_buffer->GetTypeSize(); } -const void* NzVertexBuffer::GetBufferPtr() const +const void* NzVertexBuffer::GetPointer() const { - return reinterpret_cast(m_buffer->GetBufferPtr()) + m_startVertex*m_buffer->GetTypeSize(); + return reinterpret_cast(m_buffer->GetPointer()) + m_startVertex*m_buffer->GetTypeSize(); } unsigned int NzVertexBuffer::GetStartVertex() const @@ -99,7 +111,7 @@ bool NzVertexBuffer::IsHardware() const void* NzVertexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length) { - #if NAZARA_RENDERER_SAFE + #if NAZARA_UTILITY_SAFE if (offset+length > m_vertexCount) { NazaraError("Exceeding virtual buffer size"); @@ -110,6 +122,11 @@ void* NzVertexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned i return m_buffer->Map(access, m_startVertex+offset, (length) ? length : m_vertexCount-offset); } +bool NzVertexBuffer::SetStorage(nzBufferStorage storage) +{ + return m_buffer->SetStorage(storage); +} + bool NzVertexBuffer::Unmap() { return m_buffer->Unmap(); diff --git a/src/Nazara/Utility/VertexDeclaration.cpp b/src/Nazara/Utility/VertexDeclaration.cpp new file mode 100644 index 000000000..8db74ddd2 --- /dev/null +++ b/src/Nazara/Utility/VertexDeclaration.cpp @@ -0,0 +1,346 @@ +// 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 + +#if NAZARA_THREADSAFETY_VERTEXDECLARATION +#include +#else +#include +#endif + +#include + +namespace +{ + const unsigned int size[] = + { + 4, // nzElementType_Color + 8, // nzElementType_Double1 + 16, // nzElementType_Double2 + 24, // nzElementType_Double3 + 32, // nzElementType_Double4 + 4, // nzElementType_Float1 + 8, // nzElementType_Float2 + 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) + { + NzVertexElement& current = impl->elements[i]; + #if NAZARA_UTILITY_SAFE + // Notre tableau étant trié, s'il y a collision, les deux éléments identiques se suivent... + if (i > 0) + { + 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) + { + // 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 + + if (current.usageIndex == 0) + impl->elementPos[current.stream][current.usage] = i; + + 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]; + } + + #if NAZARA_RENDERER_FORCE_DECLARATION_STRIDE_MULTIPLE_OF_32 + for (unsigned int& stride : impl->stride) + stride = ((static_cast(stride)-1)/32+1)*32; + #endif + + m_sharedImpl = impl; + + return true; +} + +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 (!m_sharedImpl) + { + NazaraError("Declaration not created"); + return nullptr; + } + + if (i >= m_sharedImpl->elements.size()) + { + NazaraError("Element index out of range (" + NzString::Number(i) + " >= " + NzString::Number(m_sharedImpl->elements.size()) + ')'); + return nullptr; + } + #endif + + return &m_sharedImpl->elements[i]; +} + +const NzVertexElement* NzVertexDeclaration::GetElement(nzElementStream stream, unsigned int i) const +{ + #if NAZARA_UTILITY_SAFE + if (!m_sharedImpl) + { + 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_sharedImpl->elements.size(); +} + +unsigned int NzVertexDeclaration::GetElementCount(nzElementStream stream) const +{ + #if NAZARA_UTILITY_SAFE + if (!m_sharedImpl) + { + NazaraError("Declaration not created"); + return 0; + } + #endif + + 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; +} diff --git a/src/Nazara/Utility/Win32/CursorImpl.cpp b/src/Nazara/Utility/Win32/CursorImpl.cpp new file mode 100644 index 000000000..10010535f --- /dev/null +++ b/src/Nazara/Utility/Win32/CursorImpl.cpp @@ -0,0 +1,52 @@ +// 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 + +bool NzCursorImpl::Create(const NzImage& cursor, int hotSpotX, int hotSpotY) +{ + NzImage windowsCursor(cursor); + if (!windowsCursor.Convert(nzPixelFormat_BGRA8)) + { + NazaraError("Failed to convert cursor to BGRA8"); + return false; + } + + HBITMAP bitmap = CreateBitmap(windowsCursor.GetWidth(), windowsCursor.GetHeight(), 1, 32, windowsCursor.GetConstPixels()); + HBITMAP monoBitmap = CreateBitmap(windowsCursor.GetWidth(), windowsCursor.GetHeight(), 1, 1, nullptr); + + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms648052(v=vs.85).aspx + ICONINFO iconInfo; + iconInfo.fIcon = FALSE; + iconInfo.xHotspot = hotSpotX; + iconInfo.yHotspot = hotSpotY; + iconInfo.hbmMask = monoBitmap; + iconInfo.hbmColor = bitmap; + + m_cursor = CreateIconIndirect(&iconInfo); + + DeleteObject(bitmap); + DeleteObject(monoBitmap); + + if (!m_cursor) + { + NazaraError("Failed to create cursor: " + NzGetLastSystemError()); + return false; + } + + return true; +} + +void NzCursorImpl::Destroy() +{ + DestroyIcon(m_cursor); +} + +HCURSOR NzCursorImpl::GetCursor() +{ + return m_cursor; +} diff --git a/src/Nazara/Utility/Win32/CursorImpl.hpp b/src/Nazara/Utility/Win32/CursorImpl.hpp new file mode 100644 index 000000000..ba9fa63b7 --- /dev/null +++ b/src/Nazara/Utility/Win32/CursorImpl.hpp @@ -0,0 +1,26 @@ +// 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_CURSORIMPL_HPP +#define NAZARA_CURSORIMPL_HPP + +#include + +class NzImage; + +class NzCursorImpl +{ + public: + bool Create(const NzImage& image, int hotSpotX, int hotSpotY); + void Destroy(); + + HCURSOR GetCursor(); + + private: + HICON m_cursor = nullptr; +}; + +#endif // NAZARA_CURSORIMPL_HPP diff --git a/src/Nazara/Utility/Win32/IconImpl.cpp b/src/Nazara/Utility/Win32/IconImpl.cpp new file mode 100644 index 000000000..730017241 --- /dev/null +++ b/src/Nazara/Utility/Win32/IconImpl.cpp @@ -0,0 +1,49 @@ +// 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 + +bool NzIconImpl::Create(const NzImage& icon) +{ + NzImage windowsIcon(icon); + if (!windowsIcon.Convert(nzPixelFormat_BGRA8)) + { + NazaraError("Failed to convert icon to BGRA8"); + return false; + } + + HBITMAP bitmap = CreateBitmap(windowsIcon.GetWidth(), windowsIcon.GetHeight(), 1, 32, windowsIcon.GetConstPixels()); + HBITMAP monoBitmap = CreateBitmap(windowsIcon.GetWidth(), windowsIcon.GetHeight(), 1, 1, nullptr); + + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms648052(v=vs.85).aspx + ICONINFO iconInfo; + iconInfo.fIcon = TRUE; + iconInfo.hbmMask = monoBitmap; + iconInfo.hbmColor = bitmap; + + m_icon = CreateIconIndirect(&iconInfo); + + DeleteObject(bitmap); + DeleteObject(monoBitmap); + + if (!m_icon) + { + NazaraError("Failed to create icon: " + NzGetLastSystemError()); + return false; + } + + return true; +} + +void NzIconImpl::Destroy() +{ + DestroyIcon(m_icon); +} + +HICON NzIconImpl::GetIcon() +{ + return m_icon; +} diff --git a/src/Nazara/Utility/Win32/IconImpl.hpp b/src/Nazara/Utility/Win32/IconImpl.hpp new file mode 100644 index 000000000..9747283c3 --- /dev/null +++ b/src/Nazara/Utility/Win32/IconImpl.hpp @@ -0,0 +1,26 @@ +// 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_ICONIMPL_HPP +#define NAZARA_ICONIMPL_HPP + +#include + +class NzImage; + +class NzIconImpl +{ + public: + bool Create(const NzImage& image); + void Destroy(); + + HICON GetIcon(); + + private: + HICON m_icon = nullptr; +}; + +#endif // NAZARA_ICONIMPL_HPP diff --git a/src/Nazara/Utility/Win32/WindowImpl.cpp b/src/Nazara/Utility/Win32/WindowImpl.cpp index d241ef1ab..5b525c959 100644 --- a/src/Nazara/Utility/Win32/WindowImpl.cpp +++ b/src/Nazara/Utility/Win32/WindowImpl.cpp @@ -12,13 +12,18 @@ #include #include #include +#include +#include +#include +#include +#include #include #include #include #ifdef _WIN64 - #define GWL_USERDATA GWLP_USERDATA #define GCL_HCURSOR GCLP_HCURSOR + #define GWL_USERDATA GWLP_USERDATA #endif // N'est pas définit avec MinGW apparemment @@ -72,7 +77,7 @@ void NzWindowImpl::Close() bool NzWindowImpl::Create(NzVideoMode mode, const NzString& title, nzUInt32 style) { - bool fullscreen = (style & NzWindow::Fullscreen) != 0; + bool fullscreen = (style & nzWindowStyle_Fullscreen) != 0; DWORD win32Style, win32StyleEx; unsigned int x, y; unsigned int width = mode.width; @@ -109,13 +114,13 @@ bool NzWindowImpl::Create(NzVideoMode mode, const NzString& title, nzUInt32 styl else { win32Style = WS_VISIBLE; - if (style & NzWindow::Titlebar) + if (style & nzWindowStyle_Titlebar) { win32Style |= WS_CAPTION | WS_MINIMIZEBOX; - if (style & NzWindow::Closable) + if (style & nzWindowStyle_Closable) win32Style |= WS_SYSMENU; - if (style & NzWindow::Resizable) + if (style & nzWindowStyle_Resizable) win32Style |= WS_MAXIMIZEBOX | WS_SIZEBOX; } else @@ -272,6 +277,80 @@ bool NzWindowImpl::IsVisible() const return IsWindowVisible(m_handle); } +void NzWindowImpl::SetCursor(nzWindowCursor cursor) +{ + switch (cursor) + { + case nzWindowCursor_Crosshair: + m_cursor = reinterpret_cast(LoadImage(nullptr, IDC_CROSS, IMAGE_CURSOR, 0, 0, LR_SHARED)); + break; + + case nzWindowCursor_Default: + m_cursor = reinterpret_cast(LoadImage(nullptr, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED)); + break; + + case nzWindowCursor_Hand: + case nzWindowCursor_Pointer: + m_cursor = reinterpret_cast(LoadImage(nullptr, IDC_HAND, IMAGE_CURSOR, 0, 0, LR_SHARED)); + break; + + case nzWindowCursor_Help: + m_cursor = reinterpret_cast(LoadImage(nullptr, IDC_HELP, IMAGE_CURSOR, 0, 0, LR_SHARED)); + break; + + case nzWindowCursor_Move: + m_cursor = reinterpret_cast(LoadImage(nullptr, IDC_SIZEALL, IMAGE_CURSOR, 0, 0, LR_SHARED)); + break; + + case nzWindowCursor_None: + m_cursor = nullptr; + break; + + case nzWindowCursor_Progress: + m_cursor = reinterpret_cast(LoadImage(nullptr, IDC_APPSTARTING, IMAGE_CURSOR, 0, 0, LR_SHARED)); + break; + + case nzWindowCursor_ResizeN: + case nzWindowCursor_ResizeS: + m_cursor = reinterpret_cast(LoadImage(nullptr, IDC_SIZENS, IMAGE_CURSOR, 0, 0, LR_SHARED)); + break; + + case nzWindowCursor_ResizeNW: + case nzWindowCursor_ResizeSE: + m_cursor = reinterpret_cast(LoadImage(nullptr, IDC_SIZENESW, IMAGE_CURSOR, 0, 0, LR_SHARED)); + break; + + case nzWindowCursor_ResizeNE: + case nzWindowCursor_ResizeSW: + m_cursor = reinterpret_cast(LoadImage(nullptr, IDC_SIZENWSE, IMAGE_CURSOR, 0, 0, LR_SHARED)); + break; + + case nzWindowCursor_ResizeE: + case nzWindowCursor_ResizeW: + m_cursor = reinterpret_cast(LoadImage(nullptr, IDC_SIZEWE, IMAGE_CURSOR, 0, 0, LR_SHARED)); + break; + + case nzWindowCursor_Text: + m_cursor = reinterpret_cast(LoadImage(nullptr, IDC_IBEAM, IMAGE_CURSOR, 0, 0, LR_SHARED)); + break; + + case nzWindowCursor_Wait: + m_cursor = reinterpret_cast(LoadImage(nullptr, IDC_WAIT, IMAGE_CURSOR, 0, 0, LR_SHARED)); + break; + } + + // Pas besoin de libérer le curseur par la suite s'il est partagé + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms648045(v=vs.85).aspx + ::SetCursor(m_cursor); +} + +void NzWindowImpl::SetCursor(const NzCursor& cursor) +{ + m_cursor = cursor.m_impl->GetCursor(); + + ::SetCursor(m_cursor); +} + void NzWindowImpl::SetEventListener(bool listener) { if (m_ownsWindow) @@ -297,6 +376,14 @@ void NzWindowImpl::SetFocus() SetForegroundWindow(m_handle); } +void NzWindowImpl::SetIcon(const NzIcon& icon) +{ + HICON iconHandle = icon.m_impl->GetIcon(); + + SendMessage(m_handle, WM_SETICON, ICON_BIG, reinterpret_cast(iconHandle)); + SendMessage(m_handle, WM_SETICON, ICON_SMALL, reinterpret_cast(iconHandle)); +} + void NzWindowImpl::SetMaximumSize(int width, int height) { RECT rect = {0, 0, width, height}; @@ -355,19 +442,6 @@ void NzWindowImpl::SetVisible(bool visible) ShowWindow(m_handle, (visible) ? SW_SHOW : SW_HIDE); } -void NzWindowImpl::ShowMouseCursor(bool show) -{ - // Pas besoin de libérer le curseur par la suite s'il est partagé - // http://msdn.microsoft.com/en-us/library/windows/desktop/ms648045(v=vs.85).aspx - - if (show) - m_cursor = reinterpret_cast(LoadImage(nullptr, MAKEINTRESOURCE(OCR_NORMAL), IMAGE_CURSOR, 0, 0, LR_SHARED)); - else - m_cursor = nullptr; - - SetCursor(m_cursor); -} - void NzWindowImpl::StayOnTop(bool stayOnTop) { SetWindowPos(m_handle, (stayOnTop) ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); @@ -390,7 +464,7 @@ bool NzWindowImpl::HandleMessage(HWND window, UINT message, WPARAM wParam, LPARA case WM_SETCURSOR: // http://msdn.microsoft.com/en-us/library/windows/desktop/ms648382(v=vs.85).aspx if (LOWORD(lParam) == HTCLIENT) - SetCursor(m_cursor); + ::SetCursor(m_cursor); break; diff --git a/src/Nazara/Utility/Win32/WindowImpl.hpp b/src/Nazara/Utility/Win32/WindowImpl.hpp index 2cc727ab0..16c28b70a 100644 --- a/src/Nazara/Utility/Win32/WindowImpl.hpp +++ b/src/Nazara/Utility/Win32/WindowImpl.hpp @@ -56,8 +56,11 @@ class NzWindowImpl : NzNonCopyable bool IsMinimized() const; bool IsVisible() const; + void SetCursor(nzWindowCursor cursor); + void SetCursor(const NzCursor& cursor); void SetEventListener(bool listener); void SetFocus(); + void SetIcon(const NzIcon& icon); void SetMaximumSize(int width, int height); void SetMinimumSize(int width, int height); void SetPosition(int x, int y); @@ -65,7 +68,6 @@ class NzWindowImpl : NzNonCopyable void SetTitle(const NzString& title); void SetVisible(bool visible); - void ShowMouseCursor(bool show); void StayOnTop(bool stayOnTop); static bool Initialize(); diff --git a/src/Nazara/Utility/Window.cpp b/src/Nazara/Utility/Window.cpp index 5f83ff6f2..2c02557db 100644 --- a/src/Nazara/Utility/Window.cpp +++ b/src/Nazara/Utility/Window.cpp @@ -5,11 +5,18 @@ #include #include #include +#include +#include +#include #include #if defined(NAZARA_PLATFORM_WINDOWS) + #include + #include #include #elif defined(NAZARA_PLATFORM_LINUX) + #include + #include #include #else #error Lack of implementation: Window @@ -103,12 +110,12 @@ bool NzWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style) Close(); // Inspiré du code de la SFML par Laurent Gomila - if (style & Fullscreen) + if (style & nzWindowStyle_Fullscreen) { if (fullscreenWindow) { NazaraError("Window (" + NzString::Pointer(fullscreenWindow) + ") already in fullscreen mode"); - style &= ~Fullscreen; + style &= ~nzWindowStyle_Fullscreen; } else { @@ -121,8 +128,8 @@ bool NzWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style) fullscreenWindow = this; } } - else if (style & Closable || style & Resizable) - style |= Titlebar; + else if (style & nzWindowStyle_Closable || style & nzWindowStyle_Resizable) + style |= nzWindowStyle_Titlebar; m_impl = new NzWindowImpl(this); if (!m_impl->Create(mode, title, style)) @@ -147,10 +154,10 @@ bool NzWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style) m_impl->EnableKeyRepeat(true); m_impl->EnableSmoothScrolling(false); + m_impl->SetCursor(nzWindowCursor_Default); m_impl->SetMaximumSize(-1, -1); m_impl->SetMinimumSize(-1, -1); m_impl->SetVisible(true); - m_impl->ShowMouseCursor(true); if (opened) m_impl->SetPosition(position.x, position.y); @@ -299,6 +306,26 @@ bool NzWindow::PollEvent(NzEvent* event) return false; } +void NzWindow::SetCursor(nzWindowCursor cursor) +{ + if (m_impl) + m_impl->SetCursor(cursor); +} + +void NzWindow::SetCursor(const NzCursor& cursor) +{ + #if NAZARA_UTILITY_SAFE + if (!cursor.IsValid()) + { + NazaraError("Cursor is not valid"); + return; + } + #endif + + if (m_impl) + m_impl->SetCursor(cursor); +} + void NzWindow::SetEventListener(bool listener) { if (!m_impl) @@ -331,6 +358,20 @@ void NzWindow::SetFocus() m_impl->SetFocus(); } +void NzWindow::SetIcon(const NzIcon& icon) +{ + #if NAZARA_UTILITY_SAFE + if (!icon.IsValid()) + { + NazaraError("Icon is not valid"); + return; + } + #endif + + if (m_impl) + m_impl->SetIcon(icon); +} + void NzWindow::SetMaximumSize(const NzVector2i& maxSize) { if (m_impl) @@ -391,12 +432,6 @@ void NzWindow::SetVisible(bool visible) m_impl->SetVisible(visible); } -void NzWindow::ShowMouseCursor(bool show) -{ - if (m_impl) - m_impl->ShowMouseCursor(show); -} - void NzWindow::StayOnTop(bool stayOnTop) { if (m_impl)