Added RenderTextures (And many others things)

-Added Forward, left and up vector (Vector3)
-Added Matrix4::ConcatenateAffine shortcut
-Added Quaternion::GetInverse() and Quaternion::Inverse()
-Added Resource listeners
-Added Depth and stencil pixel formats
-All enums now have an ending "max" entry
-Animation/Mesh::Add[Sequence/Skin/SubMesh] now returns a boolean
-Contexts are now resources
-Enhanced AnimatedMesh demo
-Fixed MD2 facing
-Fixed Vector3::CrossProduct
-Made Resource thread-safe
-Made OpenGL translation table global
-Many bugfixes
-MLT will now write malloc failure to the log
-Most of the strcpy were replaced with faster memcpy
-Occlusion queries availability is now always tested
-OpenGL-related includes now requires NAZARA_RENDERER_OPENGL to be
defined to have any effect
-Pixel formats now have a type
-Renamed RenderTarget::IsValid to IsRenderable
-Renamed Quaternion::GetNormalized() to GetNormal()
-Renamed Texture::Bind() to Prepare()
-Renamed VectorX::Make[Ceil|Floor] to Maximize/Minimize
-Removed MATH_MATRIX_COLUMN_MAJOR option (all matrices are column-major)
-Removed RENDERER_ACTIVATE_RENDERWINDOW_ON_CREATION option (Render
windows are active upon their creation)


Former-commit-id: 0d1da1e32c156a958221edf04a5315c75b354450
This commit is contained in:
Jérôme Leclercq 2012-09-20 22:07:30 +02:00
parent a6ed70123b
commit cd5a1b7a5e
65 changed files with 24385 additions and 22703 deletions

View File

@ -1,40 +1,42 @@
if (not _OPTIONS["one-library"]) then if (not _OPTIONS["one-library"]) then
project "NazaraRenderer" project "NazaraRenderer"
end end
files defines "NAZARA_RENDERER_OPENGL"
{
"../include/Nazara/Renderer/**.hpp", files
"../include/Nazara/Renderer/**.inl", {
"../src/Nazara/Renderer/**.hpp", "../include/Nazara/Renderer/**.hpp",
"../src/Nazara/Renderer/**.cpp" "../include/Nazara/Renderer/**.inl",
} "../src/Nazara/Renderer/**.hpp",
"../src/Nazara/Renderer/**.cpp"
if (os.is("windows")) then }
excludes { "../src/Nazara/Renderer/Posix/*.hpp", "../src/Nazara/Renderer/Posix/*.cpp" }
links "gdi32" if (os.is("windows")) then
links "opengl32" excludes { "../src/Nazara/Renderer/Posix/*.hpp", "../src/Nazara/Renderer/Posix/*.cpp" }
links "winmm" links "gdi32"
else links "opengl32"
excludes { "../src/Nazara/Renderer/Win32/*.hpp", "../src/Nazara/Renderer/Win32/*.cpp" } links "winmm"
end else
excludes { "../src/Nazara/Renderer/Win32/*.hpp", "../src/Nazara/Renderer/Win32/*.cpp" }
if (_OPTIONS["one-library"]) then end
excludes "../src/Nazara/Renderer/Debug/Leaks.cpp"
else if (_OPTIONS["one-library"]) then
configuration "DebugStatic" excludes "../src/Nazara/Renderer/Debug/Leaks.cpp"
links "NazaraCore-s-d" else
links "NazaraUtility-s-d" configuration "DebugStatic"
links "NazaraCore-s-d"
configuration "ReleaseStatic" links "NazaraUtility-s-d"
links "NazaraCore-s"
links "NazaraUtility-s" configuration "ReleaseStatic"
links "NazaraCore-s"
configuration "DebugDLL" links "NazaraUtility-s"
links "NazaraCore-d"
links "NazaraUtility-d" configuration "DebugDLL"
links "NazaraCore-d"
configuration "ReleaseDLL" links "NazaraUtility-d"
links "NazaraCore"
links "NazaraUtility" configuration "ReleaseDLL"
links "NazaraCore"
links "NazaraUtility"
end end

File diff suppressed because it is too large Load Diff

View File

@ -1,61 +1,62 @@
// This file was automatically generated by Nazara // This file was automatically generated by Nazara
/* /*
Nazara Engine - Core module Nazara Engine - Core module
Copyright (C) 2012 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) Copyright (C) 2012 Jérôme "Lynix" Leclercq (Lynix680@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions: so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#pragma once #pragma once
#include <Nazara/Core/ByteArray.hpp> #include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/Clock.hpp> #include <Nazara/Core/Clock.hpp>
#include <Nazara/Core/Color.hpp> #include <Nazara/Core/Color.hpp>
#include <Nazara/Core/ConditionVariable.hpp> #include <Nazara/Core/ConditionVariable.hpp>
#include <Nazara/Core/Config.hpp> #include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Core.hpp> #include <Nazara/Core/Core.hpp>
#include <Nazara/Core/Directory.hpp> #include <Nazara/Core/Directory.hpp>
#include <Nazara/Core/DynLib.hpp> #include <Nazara/Core/DynLib.hpp>
#include <Nazara/Core/Endianness.hpp> #include <Nazara/Core/Endianness.hpp>
#include <Nazara/Core/Enums.hpp> #include <Nazara/Core/Enums.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Core/File.hpp> #include <Nazara/Core/File.hpp>
#include <Nazara/Core/Format.hpp> #include <Nazara/Core/Format.hpp>
#include <Nazara/Core/Functor.hpp> #include <Nazara/Core/Functor.hpp>
#include <Nazara/Core/Hash.hpp> #include <Nazara/Core/Hash.hpp>
#include <Nazara/Core/Hashable.hpp> #include <Nazara/Core/Hashable.hpp>
#include <Nazara/Core/HashDigest.hpp> #include <Nazara/Core/HashDigest.hpp>
#include <Nazara/Core/HashImpl.hpp> #include <Nazara/Core/HashImpl.hpp>
#include <Nazara/Core/Initializer.hpp> #include <Nazara/Core/Initializer.hpp>
#include <Nazara/Core/InputStream.hpp> #include <Nazara/Core/InputStream.hpp>
#include <Nazara/Core/LockGuard.hpp> #include <Nazara/Core/LockGuard.hpp>
#include <Nazara/Core/Log.hpp> #include <Nazara/Core/Log.hpp>
#include <Nazara/Core/MemoryStream.hpp> #include <Nazara/Core/MemoryStream.hpp>
#include <Nazara/Core/Mutex.hpp> #include <Nazara/Core/Mutex.hpp>
#include <Nazara/Core/NonCopyable.hpp> #include <Nazara/Core/NonCopyable.hpp>
#include <Nazara/Core/Resource.hpp> #include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceLoader.hpp> #include <Nazara/Core/ResourceListener.hpp>
#include <Nazara/Core/Semaphore.hpp> #include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/String.hpp> #include <Nazara/Core/Semaphore.hpp>
#include <Nazara/Core/StringStream.hpp> #include <Nazara/Core/String.hpp>
#include <Nazara/Core/Thread.hpp> #include <Nazara/Core/StringStream.hpp>
#include <Nazara/Core/Tuple.hpp> #include <Nazara/Core/Thread.hpp>
#include <Nazara/Core/Unicode.hpp> #include <Nazara/Core/Tuple.hpp>
#include <Nazara/Core/Unicode.hpp>

View File

@ -1,84 +1,85 @@
/* /*
Nazara Engine - Core module Nazara Engine - Core module
Copyright (C) 2012 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) Copyright (C) 2012 Jérôme "Lynix" Leclercq (Lynix680@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions: so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#pragma once #pragma once
#ifndef NAZARA_CONFIG_CORE_HPP #ifndef NAZARA_CONFIG_CORE_HPP
#define NAZARA_CONFIG_CORE_HPP #define NAZARA_CONFIG_CORE_HPP
/// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci /// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci
// Appelle exit dès qu'une assertion est invalide // Appelle exit dès qu'une assertion est invalide
#define NAZARA_CORE_EXIT_ON_ASSERT_FAILURE 1 #define NAZARA_CORE_EXIT_ON_ASSERT_FAILURE 1
// Teste les assertions // Teste les assertions
#define NAZARA_CORE_ENABLE_ASSERTS 0 #define NAZARA_CORE_ENABLE_ASSERTS 0
// Taille du buffer lors d'une lecture complète d'un fichier (ex: Hash) // Taille du buffer lors d'une lecture complète d'un fichier (ex: Hash)
#define NAZARA_CORE_FILE_BUFFERSIZE 4096 #define NAZARA_CORE_FILE_BUFFERSIZE 4096
// Le moteur doit-il incorporer les Unicode Character Data (Nécessaires pour faire fonctionner le flag NzString::HandleUTF8) // Le moteur doit-il incorporer les Unicode Character Data (Nécessaires pour faire fonctionner le flag NzString::HandleUTF8)
#define NAZARA_CORE_INCLUDE_UNICODEDATA 0 #define NAZARA_CORE_INCLUDE_UNICODEDATA 0
// Utilise un tracker pour repérer les éventuels leaks (Ralentit l'exécution) // Utilise un tracker pour repérer les éventuels leaks (Ralentit l'exécution)
#define NAZARA_CORE_MEMORYLEAKTRACKER 0 #define NAZARA_CORE_MEMORYLEAKTRACKER 0
// Standardise les séparateurs des dossiers selon le système d'exploitation courant (Léger coût à l'exécution) // Standardise les séparateurs des dossiers selon le système d'exploitation courant (Léger coût à l'exécution)
#define NAZARA_CORE_NORMALIZE_DIRECTORY_SEPARATORS 1 #define NAZARA_CORE_NORMALIZE_DIRECTORY_SEPARATORS 1
// Précision des réels lors de la transformation en texte (Max. chiffres après la virgule) // Précision des réels lors de la transformation en texte (Max. chiffres après la virgule)
#define NAZARA_CORE_REAL_PRECISION 6 #define NAZARA_CORE_REAL_PRECISION 6
// Duplique la sortie du log sur le flux de sortie standard (cout) // Duplique la sortie du log sur le flux de sortie standard (cout)
#define NAZARA_CORE_DUPLICATE_TO_COUT 0 #define NAZARA_CORE_DUPLICATE_TO_COUT 0
// Active les tests de sécurité basés sur le code (Conseillé pour le développement) // Active les tests de sécurité basés sur le code (Conseillé pour le développement)
#define NAZARA_CORE_SAFE 1 #define NAZARA_CORE_SAFE 1
// Protège les classes des accès concurrentiels // Protège les classes des accès concurrentiels
#define NAZARA_CORE_THREADSAFE 1 #define NAZARA_CORE_THREADSAFE 1
// Les classes à protéger des accès concurrentiels // Les classes à protéger des accès concurrentiels
#define NAZARA_THREADSAFETY_BYTEARRAY 1 // NzByteArray (COW) #define NAZARA_THREADSAFETY_BYTEARRAY 1 // NzByteArray (COW)
#define NAZARA_THREADSAFETY_CLOCK 0 // NzClock #define NAZARA_THREADSAFETY_CLOCK 0 // NzClock
#define NAZARA_THREADSAFETY_DIRECTORY 1 // NzDirectory #define NAZARA_THREADSAFETY_DIRECTORY 1 // NzDirectory
#define NAZARA_THREADSAFETY_DYNLIB 1 // NzDynLib #define NAZARA_THREADSAFETY_DYNLIB 1 // NzDynLib
#define NAZARA_THREADSAFETY_FILE 1 // NzFile #define NAZARA_THREADSAFETY_FILE 1 // NzFile
#define NAZARA_THREADSAFETY_HASHDIGEST 0 // NzHashDigest #define NAZARA_THREADSAFETY_HASHDIGEST 0 // NzHashDigest
#define NAZARA_THREADSAFETY_LOG 1 // NzLog #define NAZARA_THREADSAFETY_LOG 1 // NzLog
#define NAZARA_THREADSAFETY_STRING 1 // NzString (COW) #define NAZARA_THREADSAFETY_RESOURCE 1 // NzResource
#define NAZARA_THREADSAFETY_STRINGSTREAM 0 // NzStringStream #define NAZARA_THREADSAFETY_STRING 1 // NzString (COW)
#define NAZARA_THREADSAFETY_STRINGSTREAM 0 // NzStringStream
// Le nombre de spinlocks à utiliser avec les critical sections de Windows (0 pour désactiver)
#define NAZARA_CORE_WINDOWS_CS_SPINLOCKS 4096 // Le nombre de spinlocks à utiliser avec les critical sections de Windows (0 pour désactiver)
#define NAZARA_CORE_WINDOWS_CS_SPINLOCKS 4096
// Optimise certaines parties du code avec certaines avancées venues de Windows Vista (Casse la compatibilité XP mais n'affecte pas les autres OS)
#define NAZARA_CORE_WINDOWS_VISTA 0 // Optimise certaines parties du code avec certaines avancées venues de Windows Vista (Casse la compatibilité XP mais n'affecte pas les autres OS)
#define NAZARA_CORE_WINDOWS_VISTA 0
/*
// Règle le temps entre le réveil du thread des timers et l'activation d'un timer (En millisecondes) /*
#define NAZARA_CORE_TIMER_WAKEUPTIME 10 // Règle le temps entre le réveil du thread des timers et l'activation d'un timer (En millisecondes)
*/ #define NAZARA_CORE_TIMER_WAKEUPTIME 10
*/
#endif // NAZARA_CONFIG_CORE_HPP
#endif // NAZARA_CONFIG_CORE_HPP

View File

@ -1,26 +1,30 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module" // This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once #pragma once
#ifndef NAZARA_ENUMS_CORE_HPP #ifndef NAZARA_ENUMS_CORE_HPP
#define NAZARA_ENUMS_CORE_HPP #define NAZARA_ENUMS_CORE_HPP
enum nzEndianness enum nzEndianness
{ {
nzEndianness_Unknown = -1, nzEndianness_Unknown = -1,
nzEndianness_BigEndian, nzEndianness_BigEndian,
nzEndianness_LittleEndian nzEndianness_LittleEndian,
};
nzEndianness_Max = nzEndianness_LittleEndian
enum nzErrorType };
{
nzErrorType_AssertFailed, enum nzErrorType
nzErrorType_Internal, {
nzErrorType_Normal, nzErrorType_AssertFailed,
nzErrorType_Warning nzErrorType_Internal,
}; nzErrorType_Normal,
nzErrorType_Warning,
#endif // NAZARA_ENUMS_CORE_HPP
nzErrorType_Max = nzErrorType_Warning
};
#endif // NAZARA_ENUMS_CORE_HPP

View File

@ -1,30 +1,72 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module" // This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once #pragma once
#ifndef NAZARA_RESOURCE_HPP #ifndef NAZARA_RESOURCE_HPP
#define NAZARA_RESOURCE_HPP #define NAZARA_RESOURCE_HPP
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <set>
class NAZARA_API NzResource
{ #if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_RESOURCE
public: #include <Nazara/Core/ThreadSafety.hpp>
NzResource(bool persistent = true); #else
NzResource(const NzResource& resource); #include <Nazara/Core/ThreadSafetyOff.hpp>
virtual ~NzResource(); #endif
void AddResourceReference() const; class NzResourceListener;
bool IsPersistent() const;
void RemoveResourceReference() const; struct NzResourceEntry
void SetPersistent(bool persistent = true); {
NzResourceEntry(NzResourceListener* resourceListener, int i = 0) :
private: listener(resourceListener),
// Je fais précéder le nom par 'resource' pour éviter les éventuels conflits de noms index(i)
mutable bool m_resourcePersistent; {
mutable unsigned int m_resourceReferenceCount; }
};
bool operator<(const NzResourceEntry& rhs) const
#endif // NAZARA_RESOURCE_HPP {
return listener < rhs.listener;
}
NzResourceListener* listener;
int index;
};
class NAZARA_API NzResource
{
public:
NzResource(bool persistent = true);
NzResource(const NzResource& resource);
virtual ~NzResource();
void AddResourceListener(NzResourceListener* listener, int index = 0) const;
void AddResourceReference() const;
bool IsPersistent() const;
void RemoveResourceListener(NzResourceListener* listener) const;
void RemoveResourceReference() const;
void SetPersistent(bool persistent = true);
protected:
void NotifyCreated();
void NotifyDestroy();
private:
void EnsureResourceListenerUpdate() const;
NazaraMutexAttrib(m_mutex, mutable)
// Je fais précéder le nom par 'resource' pour éviter les éventuels conflits de noms
mutable std::set<NzResourceEntry> m_resourceListeners;
mutable std::set<NzResourceEntry> m_resourceListenersCache;
mutable bool m_resourceListenerUpdated;
bool m_resourcePersistent;
mutable unsigned int m_resourceReferenceCount;
};
#endif // NAZARA_RESOURCE_HPP

View File

@ -0,0 +1,25 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_RESOURCELISTENER_HPP
#define NAZARA_RESOURCELISTENER_HPP
#include <Nazara/Prerequesites.hpp>
class NzResource;
class NAZARA_API NzResourceListener
{
public:
NzResourceListener() = default;
virtual ~NzResourceListener();
virtual void OnResourceCreated(const NzResource* resource, int index);
virtual void OnResourceDestroy(const NzResource* resource, int index);
virtual void OnResourceReleased(const NzResource* resource, int index);
};
#endif // NAZARA_RESOURCELISTENER_HPP

View File

@ -1,142 +1,142 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module" // This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Config.hpp> #include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Core/File.hpp> #include <Nazara/Core/File.hpp>
#include <Nazara/Core/InputStream.hpp> #include <Nazara/Core/InputStream.hpp>
#include <Nazara/Core/MemoryStream.hpp> #include <Nazara/Core/MemoryStream.hpp>
#include <Nazara/Core/Debug.hpp> #include <Nazara/Core/Debug.hpp>
template<typename Type, typename Parameters> template<typename Type, typename Parameters>
bool NzResourceLoader<Type, Parameters>::LoadFromFile(Type* resource, const NzString& filePath, const Parameters& parameters) bool NzResourceLoader<Type, Parameters>::LoadFromFile(Type* resource, const NzString& filePath, const Parameters& parameters)
{ {
#if NAZARA_CORE_SAFE #if NAZARA_CORE_SAFE
if (!parameters.IsValid()) if (!parameters.IsValid())
{ {
NazaraError("Invalid Parameters"); NazaraError("Invalid parameters");
return false; return false;
} }
#endif #endif
NzString path = NzFile::NormalizePath(filePath); NzString path = NzFile::NormalizePath(filePath);
NzString ext = path.SubstrFrom('.', -1, true); NzString ext = path.SubstrFrom('.', -1, true);
if (ext.IsEmpty()) if (ext.IsEmpty())
{ {
NazaraError("Failed to get file extension"); NazaraError("Failed to get file extension");
return false; return false;
} }
NzFile file(path, NzFile::ReadOnly); NzFile file(path, NzFile::ReadOnly);
if (!file.IsOpen()) if (!file.IsOpen())
{ {
NazaraError("Failed to open file"); NazaraError("Failed to open file");
return false; return false;
} }
for (auto loader = Type::s_loaders.begin(); loader != Type::s_loaders.end(); ++loader) for (auto loader = Type::s_loaders.begin(); loader != Type::s_loaders.end(); ++loader)
{ {
for (const NzString& loaderExt : std::get<0>(*loader)) for (const NzString& loaderExt : std::get<0>(*loader))
{ {
int cmp = NzString::Compare(loaderExt, ext); int cmp = NzString::Compare(loaderExt, ext);
if (cmp == 0) if (cmp == 0)
{ {
if (!std::get<1>(*loader)(file, parameters)) if (!std::get<1>(*loader)(file, parameters))
continue; continue;
file.SetCursorPos(0); file.SetCursorPos(0);
// Chargement de la ressource // Chargement de la ressource
if (std::get<2>(*loader)(resource, file, parameters)) if (std::get<2>(*loader)(resource, file, parameters))
return true; return true;
NazaraWarning("Loader failed"); NazaraWarning("Loader failed");
file.SetCursorPos(0); file.SetCursorPos(0);
} }
else if (cmp < 0) // S'il est encore possible que l'extension se situe après else if (cmp < 0) // S'il est encore possible que l'extension se situe après
continue; continue;
break; break;
} }
} }
NazaraError("Failed to load file: no loader"); NazaraError("Failed to load file: no loader");
return false; return false;
} }
template<typename Type, typename Parameters> template<typename Type, typename Parameters>
bool NzResourceLoader<Type, Parameters>::LoadFromMemory(Type* resource, const void* data, unsigned int size, const Parameters& parameters) bool NzResourceLoader<Type, Parameters>::LoadFromMemory(Type* resource, const void* data, unsigned int size, const Parameters& parameters)
{ {
NzMemoryStream stream(data, size); NzMemoryStream stream(data, size);
return LoadFromStream(resource, stream, parameters); return LoadFromStream(resource, stream, parameters);
} }
template<typename Type, typename Parameters> template<typename Type, typename Parameters>
bool NzResourceLoader<Type, Parameters>::LoadFromStream(Type* resource, NzInputStream& stream, const Parameters& parameters) bool NzResourceLoader<Type, Parameters>::LoadFromStream(Type* resource, NzInputStream& stream, const Parameters& parameters)
{ {
#if NAZARA_CORE_SAFE #if NAZARA_CORE_SAFE
if (!parameters.IsValid()) if (!parameters.IsValid())
{ {
NazaraError("Invalid Parameters"); NazaraError("Invalid parameters");
return false; return false;
} }
if (stream.GetSize() == 0 || stream.GetCursorPos() >= stream.GetSize()) if (stream.GetSize() == 0 || stream.GetCursorPos() >= stream.GetSize())
{ {
NazaraError("No data to load"); NazaraError("No data to load");
return false; return false;
} }
#endif #endif
nzUInt64 streamPos = stream.GetCursorPos(); nzUInt64 streamPos = stream.GetCursorPos();
for (auto loader = Type::s_loaders.begin(); loader != Type::s_loaders.end(); ++loader) for (auto loader = Type::s_loaders.begin(); loader != Type::s_loaders.end(); ++loader)
{ {
// Le loader supporte-t-il les données ? // Le loader supporte-t-il les données ?
if (!std::get<1>(*loader)(stream, parameters)) if (!std::get<1>(*loader)(stream, parameters))
continue; continue;
// On repositionne le stream au début // On repositionne le stream au début
stream.SetCursorPos(streamPos); stream.SetCursorPos(streamPos);
// Chargement de la ressource // Chargement de la ressource
if (std::get<2>(*loader)(resource, stream, parameters)) if (std::get<2>(*loader)(resource, stream, parameters))
return true; return true;
NazaraWarning("Loader failed"); NazaraWarning("Loader failed");
stream.SetCursorPos(streamPos); // On repositionne au début stream.SetCursorPos(streamPos); // On repositionne au début
} }
NazaraError("Failed to load file: no loader"); NazaraError("Failed to load file: no loader");
return false; return false;
} }
template<typename Type, typename Parameters> template<typename Type, typename Parameters>
void NzResourceLoader<Type, Parameters>::RegisterLoader(const NzString& fileExtensions, CheckFunction checkFunc, LoadFunction loadFunc) void NzResourceLoader<Type, Parameters>::RegisterLoader(const NzString& fileExtensions, CheckFunction checkFunc, LoadFunction loadFunc)
{ {
/// Trouver une alternative à ce code monstrueux ///FIXME: Trouver une alternative à ce code monstrueux
std::vector<NzString> exts; std::vector<NzString> exts;
fileExtensions.SplitAny(exts, " /\\.,;|-_"); fileExtensions.SplitAny(exts, " /\\.,;|-_");
std::set<NzString> extensions; std::set<NzString> extensions;
std::copy(exts.begin(), exts.end(), std::inserter(extensions, extensions.begin())); std::copy(exts.begin(), exts.end(), std::inserter(extensions, extensions.begin()));
Type::s_loaders.insert(std::make_tuple(std::move(extensions), checkFunc, loadFunc)); Type::s_loaders.insert(std::make_tuple(std::move(extensions), checkFunc, loadFunc));
} }
template<typename Type, typename Parameters> template<typename Type, typename Parameters>
void NzResourceLoader<Type, Parameters>::UnregisterLoader(const NzString& fileExtensions, CheckFunction checkFunc, LoadFunction loadFunc) void NzResourceLoader<Type, Parameters>::UnregisterLoader(const NzString& fileExtensions, CheckFunction checkFunc, LoadFunction loadFunc)
{ {
std::vector<NzString> exts; std::vector<NzString> exts;
fileExtensions.SplitAny(exts, " /\\.,;|-_"); fileExtensions.SplitAny(exts, " /\\.,;|-_");
std::set<NzString> extensions; std::set<NzString> extensions;
std::copy(exts.begin(), exts.end(), std::inserter(extensions, extensions.begin())); std::copy(exts.begin(), exts.end(), std::inserter(extensions, extensions.begin()));
Type::s_loaders.erase(std::make_tuple(std::move(extensions), checkFunc, loadFunc)); Type::s_loaders.erase(std::make_tuple(std::move(extensions), checkFunc, loadFunc));
} }
#include <Nazara/Core/DebugOff.hpp> #include <Nazara/Core/DebugOff.hpp>

View File

@ -1,321 +1,321 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module" // This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once #pragma once
#ifndef NAZARA_STRING_HPP #ifndef NAZARA_STRING_HPP
#define NAZARA_STRING_HPP #define NAZARA_STRING_HPP
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Hashable.hpp> #include <Nazara/Core/Hashable.hpp>
#include <iosfwd> #include <iosfwd>
#include <string> #include <string>
#include <vector> #include <vector>
#if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_STRING #if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_STRING
#include <Nazara/Core/ThreadSafety.hpp> #include <Nazara/Core/ThreadSafety.hpp>
#else #else
#include <Nazara/Core/ThreadSafetyOff.hpp> #include <Nazara/Core/ThreadSafetyOff.hpp>
#endif #endif
class NzAbstractHash; class NzAbstractHash;
class NzHashDigest; class NzHashDigest;
class NAZARA_API NzString : public NzHashable class NAZARA_API NzString : public NzHashable
{ {
public: public:
enum Flags enum Flags
{ {
None = 0x00, // Mode par défaut None = 0x00, // Mode par défaut
CaseInsensitive = 0x01, // Insensible à la casse CaseInsensitive = 0x01, // Insensible à la casse
HandleUtf8 = 0x02, // Traite les octets comme une suite de caractères UTF-8 HandleUtf8 = 0x02, // Traite les octets comme une suite de caractères UTF-8
TrimOnlyLeft = 0x04, // Trim(med), ne coupe que la partie gauche de la chaîne TrimOnlyLeft = 0x04, // Trim(med), ne coupe que la partie gauche de la chaîne
TrimOnlyRight = 0x08 // Trim(med), ne coupe que la partie droite de la chaîne TrimOnlyRight = 0x08 // Trim(med), ne coupe que la partie droite de la chaîne
}; };
struct SharedString; struct SharedString;
NzString(); NzString();
NzString(char character); NzString(char character);
NzString(const char* string); NzString(const char* string);
NzString(const std::string& string); NzString(const std::string& string);
NzString(const NzString& string); NzString(const NzString& string);
NzString(NzString&& string) noexcept; NzString(NzString&& string) noexcept;
NzString(SharedString* sharedString); NzString(SharedString* sharedString);
~NzString(); ~NzString();
NzString& Append(char character); NzString& Append(char character);
NzString& Append(const char* string); NzString& Append(const char* string);
NzString& Append(const NzString& string); NzString& Append(const NzString& string);
void Clear(bool keepBuffer = false); void Clear(bool keepBuffer = false);
bool Contains(char character, int start = 0, nzUInt32 flags = None) const; bool Contains(char character, int start = 0, nzUInt32 flags = None) const;
bool Contains(const char* string, int start = 0, nzUInt32 flags = None) const; bool Contains(const char* string, int start = 0, nzUInt32 flags = None) const;
bool Contains(const NzString& string, int start = 0, nzUInt32 flags = None) const; bool Contains(const NzString& string, int start = 0, nzUInt32 flags = None) const;
unsigned int Count(char character, int start = 0, nzUInt32 flags = None) const; unsigned int Count(char character, int start = 0, nzUInt32 flags = None) const;
unsigned int Count(const char* string, int start = 0, nzUInt32 flags = None) const; unsigned int Count(const char* string, int start = 0, nzUInt32 flags = None) const;
unsigned int Count(const NzString& string, int start = 0, nzUInt32 flags = None) const; unsigned int Count(const NzString& string, int start = 0, nzUInt32 flags = None) const;
unsigned int CountAny(const char* string, int start = 0, nzUInt32 flags = None) const; unsigned int CountAny(const char* string, int start = 0, nzUInt32 flags = None) const;
unsigned int CountAny(const NzString& string, int start = 0, nzUInt32 flags = None) const; unsigned int CountAny(const NzString& string, int start = 0, nzUInt32 flags = None) const;
bool EndsWith(char character, nzUInt32 flags = None) const; bool EndsWith(char character, nzUInt32 flags = None) const;
bool EndsWith(const char* string, nzUInt32 flags = None) const; bool EndsWith(const char* string, nzUInt32 flags = None) const;
bool EndsWith(const NzString& string, nzUInt32 flags = None) const; bool EndsWith(const NzString& string, nzUInt32 flags = None) const;
unsigned int Find(char character, int start = 0, nzUInt32 flags = None) const; unsigned int Find(char character, int start = 0, nzUInt32 flags = None) const;
unsigned int Find(const char* string, int start = 0, nzUInt32 flags = None) const; unsigned int Find(const char* string, int start = 0, nzUInt32 flags = None) const;
unsigned int Find(const NzString& string, int start = 0, nzUInt32 flags = None) const; unsigned int Find(const NzString& string, int start = 0, nzUInt32 flags = None) const;
unsigned int FindAny(const char* string, int start = 0, nzUInt32 flags = None) const; unsigned int FindAny(const char* string, int start = 0, nzUInt32 flags = None) const;
unsigned int FindAny(const NzString& string, int start = 0, nzUInt32 flags = None) const; unsigned int FindAny(const NzString& string, int start = 0, nzUInt32 flags = None) const;
unsigned int FindLast(char character, int start = -1, nzUInt32 flags = None) const; unsigned int FindLast(char character, int start = -1, nzUInt32 flags = None) const;
unsigned int FindLast(const char *string, int start = -1, nzUInt32 flags = None) const; unsigned int FindLast(const char *string, int start = -1, nzUInt32 flags = None) const;
unsigned int FindLast(const NzString& string, int start = -1, nzUInt32 flags = None) const; unsigned int FindLast(const NzString& string, int start = -1, nzUInt32 flags = None) const;
unsigned int FindLastAny(const char* string, int start = -1, nzUInt32 flags = None) const; unsigned int FindLastAny(const char* string, int start = -1, nzUInt32 flags = None) const;
unsigned int FindLastAny(const NzString& string, int start = -1, nzUInt32 flags = None) const; unsigned int FindLastAny(const NzString& string, int start = -1, nzUInt32 flags = None) const;
unsigned int FindLastWord(const char* string, int start = -1, nzUInt32 flags = None) const; unsigned int FindLastWord(const char* string, int start = -1, nzUInt32 flags = None) const;
unsigned int FindLastWord(const NzString& string, int start = -1, nzUInt32 flags = None) const; unsigned int FindLastWord(const NzString& string, int start = -1, nzUInt32 flags = None) const;
unsigned int FindWord(const char* string, int start = 0, nzUInt32 flags = None) const; unsigned int FindWord(const char* string, int start = 0, nzUInt32 flags = None) const;
unsigned int FindWord(const NzString& string, int start = 0, nzUInt32 flags = None) const; unsigned int FindWord(const NzString& string, int start = 0, nzUInt32 flags = None) const;
char* GetBuffer(); char* GetBuffer();
unsigned int GetCapacity() const; unsigned int GetCapacity() const;
const char* GetConstBuffer() const; const char* GetConstBuffer() const;
unsigned int GetLength() const; unsigned int GetLength() const;
unsigned int GetSize() const; unsigned int GetSize() const;
char* GetUtf8Buffer(unsigned int* size = nullptr) const; char* GetUtf8Buffer(unsigned int* size = nullptr) const;
char16_t* GetUtf16Buffer(unsigned int* size = nullptr) const; char16_t* GetUtf16Buffer(unsigned int* size = nullptr) const;
char32_t* GetUtf32Buffer(unsigned int* size = nullptr) const; char32_t* GetUtf32Buffer(unsigned int* size = nullptr) const;
wchar_t* GetWideBuffer(unsigned int* size = nullptr) const; wchar_t* GetWideBuffer(unsigned int* size = nullptr) const;
NzString GetWord(unsigned int index, nzUInt32 flags = None) const; NzString GetWord(unsigned int index, nzUInt32 flags = None) const;
unsigned int GetWordPosition(unsigned int index, nzUInt32 flags = None) const; unsigned int GetWordPosition(unsigned int index, nzUInt32 flags = None) const;
NzString& Insert(int pos, char character); NzString& Insert(int pos, char character);
NzString& Insert(int pos, const char* string); NzString& Insert(int pos, const char* string);
NzString& Insert(int pos, const NzString& string); NzString& Insert(int pos, const NzString& string);
bool IsEmpty() const; bool IsEmpty() const;
bool IsNull() const; bool IsNull() const;
bool IsNumber(nzUInt8 radix = 10, nzUInt32 flags = CaseInsensitive) const; bool IsNumber(nzUInt8 radix = 10, nzUInt32 flags = CaseInsensitive) const;
bool Match(const char* pattern) const; bool Match(const char* pattern) const;
bool Match(const NzString& pattern) const; bool Match(const NzString& pattern) const;
NzString& Prepend(char character); NzString& Prepend(char character);
NzString& Prepend(const char* string); NzString& Prepend(const char* string);
NzString& Prepend(const NzString& string); NzString& Prepend(const NzString& string);
unsigned int Replace(char oldCharacter, char newCharacter, int start = 0, nzUInt32 flags = None); unsigned int Replace(char oldCharacter, char newCharacter, int start = 0, nzUInt32 flags = None);
unsigned int Replace(const char* oldString, const char* replaceString, int start = 0, nzUInt32 flags = None); unsigned int Replace(const char* oldString, const char* replaceString, int start = 0, nzUInt32 flags = None);
unsigned int Replace(const NzString& oldString, const NzString& replaceString, int start = 0, nzUInt32 flags = None); unsigned int Replace(const NzString& oldString, const NzString& replaceString, int start = 0, nzUInt32 flags = None);
unsigned int ReplaceAny(const char* oldCharacters, char replaceCharacter, int start = 0, nzUInt32 flags = None); unsigned int ReplaceAny(const char* oldCharacters, char replaceCharacter, int start = 0, nzUInt32 flags = None);
//unsigned int ReplaceAny(const char* oldCharacters, const char* replaceString, int start = 0, nzUInt32 flags = None); //unsigned int ReplaceAny(const char* oldCharacters, const char* replaceString, int start = 0, nzUInt32 flags = None);
//unsigned int ReplaceAny(const NzString& oldCharacters, const NzString& replaceString, int start = 0, nzUInt32 flags = None); //unsigned int ReplaceAny(const NzString& oldCharacters, const NzString& replaceString, int start = 0, nzUInt32 flags = None);
void Reserve(unsigned int bufferSize); void Reserve(unsigned int bufferSize);
NzString& Resize(int size, char character = ' '); NzString& Resize(int size, char character = ' ');
NzString Resized(int size, char character = ' ') const; NzString Resized(int size, char character = ' ') const;
NzString& Reverse(); NzString& Reverse();
NzString Reversed() const; NzString Reversed() const;
NzString Simplified(nzUInt32 flags = None) const; NzString Simplified(nzUInt32 flags = None) const;
NzString& Simplify(nzUInt32 flags = None); NzString& Simplify(nzUInt32 flags = None);
unsigned int Split(std::vector<NzString>& result, char separation = ' ', int start = 0, nzUInt32 flags = None) const; unsigned int Split(std::vector<NzString>& result, char separation = ' ', int start = 0, nzUInt32 flags = None) const;
unsigned int Split(std::vector<NzString>& result, const char* separation, int start = 0, nzUInt32 flags = None) const; unsigned int Split(std::vector<NzString>& result, const char* separation, int start = 0, nzUInt32 flags = None) const;
unsigned int Split(std::vector<NzString>& result, const NzString& separation, int start = 0, nzUInt32 flags = None) const; unsigned int Split(std::vector<NzString>& result, const NzString& separation, int start = 0, nzUInt32 flags = None) const;
unsigned int SplitAny(std::vector<NzString>& result, const char* separations, int start = 0, nzUInt32 flags = None) const; unsigned int SplitAny(std::vector<NzString>& result, const char* separations, int start = 0, nzUInt32 flags = None) const;
unsigned int SplitAny(std::vector<NzString>& result, const NzString& separations, int start = 0, nzUInt32 flags = None) const; unsigned int SplitAny(std::vector<NzString>& result, const NzString& separations, int start = 0, nzUInt32 flags = None) const;
bool StartsWith(char character, nzUInt32 flags = None) const; bool StartsWith(char character, nzUInt32 flags = None) const;
bool StartsWith(const char* string, nzUInt32 flags = None) const; bool StartsWith(const char* string, nzUInt32 flags = None) const;
bool StartsWith(const NzString& string, nzUInt32 flags = None) const; bool StartsWith(const NzString& string, nzUInt32 flags = None) const;
NzString Substr(int startPos, int endPos = -1) const; NzString Substr(int startPos, int endPos = -1) const;
NzString SubstrFrom(char character, int startPos = 0, bool fromLast = false, bool include = false, nzUInt32 flags = None) const; NzString SubstrFrom(char character, int startPos = 0, bool fromLast = false, bool include = false, nzUInt32 flags = None) const;
NzString SubstrFrom(const char *string, int startPos = 0, bool fromLast = false, bool include = false, nzUInt32 flags = None) const; NzString SubstrFrom(const char *string, int startPos = 0, bool fromLast = false, bool include = false, nzUInt32 flags = None) const;
NzString SubstrFrom(const NzString& string, int startPos = 0, bool fromLast = false, bool include = false, nzUInt32 flags = None) const; NzString SubstrFrom(const NzString& string, int startPos = 0, bool fromLast = false, bool include = false, nzUInt32 flags = None) const;
NzString SubstrTo(char character, int startPos = 0, bool toLast = false, bool include = false, nzUInt32 flags = None) const; NzString SubstrTo(char character, int startPos = 0, bool toLast = false, bool include = false, nzUInt32 flags = None) const;
NzString SubstrTo(const char *string, int startPos = 0, bool toLast = false, bool include = false, nzUInt32 flags = None) const; NzString SubstrTo(const char *string, int startPos = 0, bool toLast = false, bool include = false, nzUInt32 flags = None) const;
NzString SubstrTo(const NzString& string, int startPos = 0, bool toLast = false, bool include = false, nzUInt32 flags = None) const; NzString SubstrTo(const NzString& string, int startPos = 0, bool toLast = false, bool include = false, nzUInt32 flags = None) const;
void Swap(NzString& str); void Swap(NzString& str);
bool ToBool(bool* value, nzUInt32 flags = None) const; bool ToBool(bool* value, nzUInt32 flags = None) const;
bool ToDouble(double* value) const; bool ToDouble(double* value) const;
bool ToInteger(long long* value, nzUInt8 radix = 10) const; bool ToInteger(long long* value, nzUInt8 radix = 10) const;
NzString ToLower(nzUInt32 flags = None) const; NzString ToLower(nzUInt32 flags = None) const;
NzString ToUpper(nzUInt32 flags = None) const; NzString ToUpper(nzUInt32 flags = None) const;
NzString& Trim(nzUInt32 flags = None); NzString& Trim(nzUInt32 flags = None);
NzString& Trim(char character, nzUInt32 flags = None); NzString& Trim(char character, nzUInt32 flags = None);
NzString Trimmed(nzUInt32 flags = None) const; NzString Trimmed(nzUInt32 flags = None) const;
NzString Trimmed(char character, nzUInt32 flags = None) const; NzString Trimmed(char character, nzUInt32 flags = None) const;
// Méthodes STD // Méthodes STD
char* begin(); char* begin();
const char* begin() const; const char* begin() const;
char* end(); char* end();
const char* end() const; const char* end() const;
void push_front(char c); void push_front(char c);
void push_back(char c); void push_back(char c);
/*char* rbegin(); /*char* rbegin();
const char* rbegin() const; const char* rbegin() const;
char* rend(); char* rend();
const char* rend() const;*/ const char* rend() const;*/
typedef const char& const_reference; typedef const char& const_reference;
typedef char* iterator; typedef char* iterator;
//typedef char* reverse_iterator; //typedef char* reverse_iterator;
typedef char value_type; typedef char value_type;
// Méthodes STD // Méthodes STD
operator std::string() const; operator std::string() const;
char& operator[](unsigned int pos); char& operator[](unsigned int pos);
char operator[](unsigned int pos) const; char operator[](unsigned int pos) const;
NzString& operator=(char character); NzString& operator=(char character);
NzString& operator=(const char* string); NzString& operator=(const char* string);
NzString& operator=(const std::string& string); NzString& operator=(const std::string& string);
NzString& operator=(const NzString& string); NzString& operator=(const NzString& string);
NzString& operator=(NzString&& string) noexcept; NzString& operator=(NzString&& string) noexcept;
NzString operator+(char character) const; NzString operator+(char character) const;
NzString operator+(const char* string) const; NzString operator+(const char* string) const;
NzString operator+(const std::string& string) const; NzString operator+(const std::string& string) const;
NzString operator+(const NzString& string) const; NzString operator+(const NzString& string) const;
NzString& operator+=(char character); NzString& operator+=(char character);
NzString& operator+=(const char* string); NzString& operator+=(const char* string);
NzString& operator+=(const std::string& string); NzString& operator+=(const std::string& string);
NzString& operator+=(const NzString& string); NzString& operator+=(const NzString& string);
bool operator==(char character) const; bool operator==(char character) const;
bool operator==(const char* string) const; bool operator==(const char* string) const;
bool operator==(const std::string& string) const; bool operator==(const std::string& string) const;
bool operator!=(char character) const; bool operator!=(char character) const;
bool operator!=(const char* string) const; bool operator!=(const char* string) const;
bool operator!=(const std::string& string) const; bool operator!=(const std::string& string) const;
bool operator<(char character) const; bool operator<(char character) const;
bool operator<(const char* string) const; bool operator<(const char* string) const;
bool operator<(const std::string& string) const; bool operator<(const std::string& string) const;
bool operator<=(char character) const; bool operator<=(char character) const;
bool operator<=(const char* string) const; bool operator<=(const char* string) const;
bool operator<=(const std::string& string) const; bool operator<=(const std::string& string) const;
bool operator>(char character) const; bool operator>(char character) const;
bool operator>(const char* string) const; bool operator>(const char* string) const;
bool operator>(const std::string& string) const; bool operator>(const std::string& string) const;
bool operator>=(char character) const; bool operator>=(char character) const;
bool operator>=(const char* string) const; bool operator>=(const char* string) const;
bool operator>=(const std::string& string) const; bool operator>=(const std::string& string) const;
static NzString Boolean(bool boolean); static NzString Boolean(bool boolean);
static int Compare(const NzString& first, const NzString& second); static int Compare(const NzString& first, const NzString& second);
static NzString Number(float number); static NzString Number(float number);
static NzString Number(double number); static NzString Number(double number);
static NzString Number(long double number); static NzString Number(long double number);
static NzString Number(signed char number, nzUInt8 radix = 10); static NzString Number(signed char number, nzUInt8 radix = 10);
static NzString Number(unsigned char number, nzUInt8 radix = 10); static NzString Number(unsigned char number, nzUInt8 radix = 10);
static NzString Number(short number, nzUInt8 radix = 10); static NzString Number(short number, nzUInt8 radix = 10);
static NzString Number(unsigned short number, nzUInt8 radix = 10); static NzString Number(unsigned short number, nzUInt8 radix = 10);
static NzString Number(int number, nzUInt8 radix = 10); static NzString Number(int number, nzUInt8 radix = 10);
static NzString Number(unsigned int number, nzUInt8 radix = 10); static NzString Number(unsigned int number, nzUInt8 radix = 10);
static NzString Number(long number, nzUInt8 radix = 10); static NzString Number(long number, nzUInt8 radix = 10);
static NzString Number(unsigned long number, nzUInt8 radix = 10); static NzString Number(unsigned long number, nzUInt8 radix = 10);
static NzString Number(long long number, nzUInt8 radix = 10); static NzString Number(long long number, nzUInt8 radix = 10);
static NzString Number(unsigned long long number, nzUInt8 radix = 10); static NzString Number(unsigned long long number, nzUInt8 radix = 10);
static NzString Pointer(const void* ptr); static NzString Pointer(const void* ptr);
static NzString Unicode(char32_t character); static NzString Unicode(char32_t character);
static NzString Unicode(const char* u8String); static NzString Unicode(const char* u8String);
static NzString Unicode(const char16_t* u16String); static NzString Unicode(const char16_t* u16String);
static NzString Unicode(const char32_t* u32String); static NzString Unicode(const char32_t* u32String);
static NzString Unicode(const wchar_t* wString); static NzString Unicode(const wchar_t* wString);
NAZARA_API friend std::istream& operator>>(std::istream& in, NzString& string); NAZARA_API friend std::istream& operator>>(std::istream& in, NzString& string);
NAZARA_API friend std::ostream& operator<<(std::ostream& out, const NzString& string); NAZARA_API friend std::ostream& operator<<(std::ostream& out, const NzString& string);
NAZARA_API friend NzString operator+(char character, const NzString& string); NAZARA_API friend NzString operator+(char character, const NzString& string);
NAZARA_API friend NzString operator+(const char* string, const NzString& nstring); NAZARA_API friend NzString operator+(const char* string, const NzString& nstring);
NAZARA_API friend NzString operator+(const std::string& string, const NzString& nstring); NAZARA_API friend NzString operator+(const std::string& string, const NzString& nstring);
NAZARA_API friend bool operator==(const NzString& first, const NzString& second); NAZARA_API friend bool operator==(const NzString& first, const NzString& second);
NAZARA_API friend bool operator!=(const NzString& first, const NzString& second); NAZARA_API friend bool operator!=(const NzString& first, const NzString& second);
NAZARA_API friend bool operator<(const NzString& first, const NzString& second); NAZARA_API friend bool operator<(const NzString& first, const NzString& second);
NAZARA_API friend bool operator<=(const NzString& first, const NzString& second); NAZARA_API friend bool operator<=(const NzString& first, const NzString& second);
NAZARA_API friend bool operator>(const NzString& first, const NzString& second); NAZARA_API friend bool operator>(const NzString& first, const NzString& second);
NAZARA_API friend bool operator>=(const NzString& first, const NzString& second); NAZARA_API friend bool operator>=(const NzString& first, const NzString& second);
NAZARA_API friend bool operator==(char character, const NzString& nstring); NAZARA_API friend bool operator==(char character, const NzString& nstring);
NAZARA_API friend bool operator==(const char* string, const NzString& nstring); NAZARA_API friend bool operator==(const char* string, const NzString& nstring);
NAZARA_API friend bool operator==(const std::string& string, const NzString& nstring); NAZARA_API friend bool operator==(const std::string& string, const NzString& nstring);
NAZARA_API friend bool operator!=(char character, const NzString& nstring); NAZARA_API friend bool operator!=(char character, const NzString& nstring);
NAZARA_API friend bool operator!=(const char* string, const NzString& nstring); NAZARA_API friend bool operator!=(const char* string, const NzString& nstring);
NAZARA_API friend bool operator!=(const std::string& string, const NzString& nstring); NAZARA_API friend bool operator!=(const std::string& string, const NzString& nstring);
NAZARA_API friend bool operator<(char character, const NzString& nstring); NAZARA_API friend bool operator<(char character, const NzString& nstring);
NAZARA_API friend bool operator<(const char* string, const NzString& nstring); NAZARA_API friend bool operator<(const char* string, const NzString& nstring);
NAZARA_API friend bool operator<(const std::string& string, const NzString& nstring); NAZARA_API friend bool operator<(const std::string& string, const NzString& nstring);
NAZARA_API friend bool operator<=(char character, const NzString& nstring); NAZARA_API friend bool operator<=(char character, const NzString& nstring);
NAZARA_API friend bool operator<=(const char* string, const NzString& nstring); NAZARA_API friend bool operator<=(const char* string, const NzString& nstring);
NAZARA_API friend bool operator<=(const std::string& string, const NzString& nstring); NAZARA_API friend bool operator<=(const std::string& string, const NzString& nstring);
NAZARA_API friend bool operator>(char character, const NzString& nstring); NAZARA_API friend bool operator>(char character, const NzString& nstring);
NAZARA_API friend bool operator>(const char* string, const NzString& nstring); NAZARA_API friend bool operator>(const char* string, const NzString& nstring);
NAZARA_API friend bool operator>(const std::string& string, const NzString& nstring); NAZARA_API friend bool operator>(const std::string& string, const NzString& nstring);
NAZARA_API friend bool operator>=(char character, const NzString& nstring); NAZARA_API friend bool operator>=(char character, const NzString& nstring);
NAZARA_API friend bool operator>=(const char* string, const NzString& nstring); NAZARA_API friend bool operator>=(const char* string, const NzString& nstring);
NAZARA_API friend bool operator>=(const std::string& string, const NzString& nstring); NAZARA_API friend bool operator>=(const std::string& string, const NzString& nstring);
struct NAZARA_API SharedString struct NAZARA_API SharedString
{ {
SharedString() = default; SharedString() = default;
SharedString(unsigned short referenceCount, unsigned int bufferSize, unsigned int stringSize, char* str) : SharedString(unsigned short referenceCount, unsigned int bufferSize, unsigned int stringSize, char* str) :
capacity(bufferSize), capacity(bufferSize),
size(stringSize), size(stringSize),
string(str), string(str),
refCount(referenceCount) refCount(referenceCount)
{ {
} }
unsigned int capacity; unsigned int capacity;
unsigned int size; unsigned int size;
char* string; char* string;
unsigned short refCount = 1; unsigned short refCount = 1;
NazaraMutex(mutex) NazaraMutex(mutex)
}; };
static SharedString emptyString; static SharedString emptyString;
static unsigned int npos; static const unsigned int npos;
private: private:
void EnsureOwnership(); void EnsureOwnership();
bool FillHash(NzHashImpl* hash) const; bool FillHash(NzHashImpl* hash) const;
void ReleaseString(); void ReleaseString();
SharedString* m_sharedString; SharedString* m_sharedString;
}; };
namespace std namespace std
{ {
NAZARA_API istream& getline(istream& is, NzString& str); NAZARA_API istream& getline(istream& is, NzString& str);
NAZARA_API istream& getline(istream& is, NzString& str, char delim); NAZARA_API istream& getline(istream& is, NzString& str, char delim);
NAZARA_API void swap(NzString& lhs, NzString& rhs); NAZARA_API void swap(NzString& lhs, NzString& rhs);
} }
#endif // NAZARA_STRING_HPP #endif // NAZARA_STRING_HPP

View File

@ -1,52 +1,49 @@
/* /*
Nazara Engine - Mathematics module Nazara Engine - Mathematics module
Copyright (C) 2012 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) Copyright (C) 2012 Jérôme "Lynix" Leclercq (Lynix680@gmail.com)
Rémi "overdrivr" Bèges (remi.beges@laposte.net) Rémi "overdrivr" Bèges (remi.beges@laposte.net)
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions: so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#pragma once #pragma once
#ifndef NAZARA_CONFIG_MATH_HPP #ifndef NAZARA_CONFIG_MATH_HPP
#define NAZARA_CONFIG_MATH_HPP #define NAZARA_CONFIG_MATH_HPP
/// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci /// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci
// Définit le radian comme l'unité utilisée pour les angles // Définit le radian comme l'unité utilisée pour les angles
#define NAZARA_MATH_ANGLE_RADIAN 0 #define NAZARA_MATH_ANGLE_RADIAN 0
// Définit la disposition des matrices en colonnes (Façon OpenGL) // Optimise les opérations entre matrices affines (Demande plusieurs comparaisons pour déterminer si une matrice est affine)
#define NAZARA_MATH_MATRIX_COLUMN_MAJOR 1 #define NAZARA_MATH_MATRIX4_CHECK_AFFINE 0
// Optimise les opérations entre matrices affines (Demande plusieurs comparaisons pour déterminer si une matrice est affine) // Active les tests de sécurité basés sur le code (Conseillé pour le développement)
#define NAZARA_MATH_MATRIX4_CHECK_AFFINE 0 #define NAZARA_MATH_SAFE 1
// Active les tests de sécurité basés sur le code (Conseillé pour le développement) // Protège les classes des accès concurrentiels
#define NAZARA_MATH_SAFE 1 #define NAZARA_MATH_THREADSAFE 1
// Protège les classes des accès concurrentiels // Les classes à protéger des accès concurrentiels
#define NAZARA_MATH_THREADSAFE 1 #define NAZARA_THREADSAFETY_MATRIX3 1 // NzMatrix3 (COW)
#define NAZARA_THREADSAFETY_MATRIX4 1 // NzMatrix4 (COW)
// Les classes à protéger des accès concurrentiels
#define NAZARA_THREADSAFETY_MATRIX3 1 // NzMatrix3 (COW) #endif // NAZARA_CONFIG_MATH_HPP
#define NAZARA_THREADSAFETY_MATRIX4 1 // NzMatrix4 (COW)
#endif // NAZARA_CONFIG_MATH_HPP

View File

@ -1,144 +1,145 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Mathematics module" // This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once #pragma once
#ifndef NAZARA_MATRIX4_HPP #ifndef NAZARA_MATRIX4_HPP
#define NAZARA_MATRIX4_HPP #define NAZARA_MATRIX4_HPP
#include <Nazara/Core/String.hpp> #include <Nazara/Core/String.hpp>
#include <Nazara/Math/Config.hpp> #include <Nazara/Math/Config.hpp>
#if NAZARA_MATH_THREADSAFE && NAZARA_THREADSAFETY_MATRIX4 #if NAZARA_MATH_THREADSAFE && NAZARA_THREADSAFETY_MATRIX4
#include <Nazara/Core/ThreadSafety.hpp> #include <Nazara/Core/ThreadSafety.hpp>
#else #else
#include <Nazara/Core/ThreadSafetyOff.hpp> #include <Nazara/Core/ThreadSafetyOff.hpp>
#endif #endif
template<typename T> class NzEulerAngles; template<typename T> class NzEulerAngles;
template<typename T> class NzQuaternion; template<typename T> class NzQuaternion;
template<typename T> class NzVector2; template<typename T> class NzVector2;
template<typename T> class NzVector3; template<typename T> class NzVector3;
template<typename T> class NzVector4; template<typename T> class NzVector4;
template<typename T> class NzMatrix4 template<typename T> class NzMatrix4
{ {
public: public:
NzMatrix4(); NzMatrix4();
NzMatrix4(T r11, T r12, T r13, T r14, NzMatrix4(T r11, T r12, T r13, T r14,
T r21, T r22, T r23, T r24, T r21, T r22, T r23, T r24,
T r31, T r32, T r33, T r34, T r31, T r32, T r33, T r34,
T r41, T r42, T r43, T r44); T r41, T r42, T r43, T r44);
NzMatrix4(const T matrix[16]); NzMatrix4(const T matrix[16]);
//NzMatrix4(const NzMatrix3<T>& matrix); //NzMatrix4(const NzMatrix3<T>& matrix);
template<typename U> explicit NzMatrix4(const NzMatrix4<U>& matrix); template<typename U> explicit NzMatrix4(const NzMatrix4<U>& matrix);
NzMatrix4(const NzMatrix4& matrix); NzMatrix4(const NzMatrix4& matrix);
NzMatrix4(NzMatrix4&& matrix) noexcept; NzMatrix4(NzMatrix4&& matrix) noexcept;
~NzMatrix4(); ~NzMatrix4();
NzMatrix4 Concatenate(const NzMatrix4& matrix) const; NzMatrix4 Concatenate(const NzMatrix4& matrix) const;
NzMatrix4 ConcatenateAffine(const NzMatrix4& matrix) const;
T GetDeterminant() const;
NzMatrix4 GetInverse() const; T GetDeterminant() const;
NzQuaternion<T> GetRotation() const; NzMatrix4 GetInverse() const;
//NzMatrix3 GetRotationMatrix() const; NzQuaternion<T> GetRotation() const;
NzVector3<T> GetScale() const; //NzMatrix3 GetRotationMatrix() const;
NzVector3<T> GetTranslation() const; NzVector3<T> GetScale() const;
NzMatrix4 GetTransposed() const; NzVector3<T> GetTranslation() const;
NzMatrix4 GetTransposed() const;
bool HasNegativeScale() const;
bool HasScale() const; bool HasNegativeScale() const;
bool HasScale() const;
bool IsAffine() const;
bool IsDefined() const; bool IsAffine() const;
bool IsDefined() const;
void MakeIdentity();
void MakeLookAt(const NzVector3<T>& eye, const NzVector3<T>& center, const NzVector3<T>& up); void MakeIdentity();
void MakeOrtho(T left, T top, T width, T height, T zNear = -1.0, T zFar = 1.0); void MakeLookAt(const NzVector3<T>& eye, const NzVector3<T>& target, const NzVector3<T>& up = NzVector3<T>::Up());
void MakePerspective(T angle, T ratio, T zNear, T zFar); void MakeOrtho(T left, T top, T width, T height, T zNear = -1.0, T zFar = 1.0);
void MakeRotation(const NzQuaternion<T>& rotation); void MakePerspective(T angle, T ratio, T zNear, T zFar);
void MakeScale(const NzVector3<T>& scale); void MakeRotation(const NzQuaternion<T>& rotation);
void MakeTranslation(const NzVector3<T>& translation); void MakeScale(const NzVector3<T>& scale);
void MakeZero(); void MakeTranslation(const NzVector3<T>& translation);
void MakeZero();
void Set(T r11, T r12, T r13, T r14,
T r21, T r22, T r23, T r24, void Set(T r11, T r12, T r13, T r14,
T r31, T r32, T r33, T r34, T r21, T r22, T r23, T r24,
T r41, T r42, T r43, T r44); T r31, T r32, T r33, T r34,
void Set(const T matrix[16]); T r41, T r42, T r43, T r44);
//NzMatrix4(const NzMatrix3<T>& matrix); void Set(const T matrix[16]);
void Set(const NzMatrix4& matrix); //NzMatrix4(const NzMatrix3<T>& matrix);
void Set(NzMatrix4&& matrix); void Set(const NzMatrix4& matrix);
template<typename U> void Set(const NzMatrix4<U>& matrix); void Set(NzMatrix4&& matrix);
void SetRotation(const NzQuaternion<T>& rotation); template<typename U> void Set(const NzMatrix4<U>& matrix);
void SetScale(const NzVector3<T>& scale); void SetRotation(const NzQuaternion<T>& rotation);
void SetTranslation(const NzVector3<T>& translation); void SetScale(const NzVector3<T>& scale);
void SetTranslation(const NzVector3<T>& translation);
NzString ToString() const;
NzString ToString() const;
NzVector2<T> Transform(const NzVector2<T>& vector, T z = 0.0, T w = 1.0) const;
NzVector3<T> Transform(const NzVector3<T>& vector, T w = 1.0) const; NzVector2<T> Transform(const NzVector2<T>& vector, T z = 0.0, T w = 1.0) const;
NzVector4<T> Transform(const NzVector4<T>& vector) const; NzVector3<T> Transform(const NzVector3<T>& vector, T w = 1.0) const;
NzVector4<T> Transform(const NzVector4<T>& vector) const;
NzMatrix4& Transpose();
NzMatrix4& Transpose();
operator NzString() const;
operator NzString() const;
operator T*();
operator const T*() const; operator T*();
operator const T*() const;
T& operator()(unsigned int x, unsigned int y);
const T& operator()(unsigned int x, unsigned int y) const; T& operator()(unsigned int x, unsigned int y);
const T& operator()(unsigned int x, unsigned int y) const;
NzMatrix4& operator=(const NzMatrix4& matrix);
NzMatrix4& operator=(NzMatrix4&& matrix) noexcept; NzMatrix4& operator=(const NzMatrix4& matrix);
NzMatrix4& operator=(NzMatrix4&& matrix) noexcept;
NzMatrix4 operator*(const NzMatrix4& matrix) const;
NzVector2<T> operator*(const NzVector2<T>& vector) const; NzMatrix4 operator*(const NzMatrix4& matrix) const;
NzVector3<T> operator*(const NzVector3<T>& vector) const; NzVector2<T> operator*(const NzVector2<T>& vector) const;
NzVector4<T> operator*(const NzVector4<T>& vector) const; NzVector3<T> operator*(const NzVector3<T>& vector) const;
NzMatrix4 operator*(T scalar) const; NzVector4<T> operator*(const NzVector4<T>& vector) const;
NzMatrix4 operator*(T scalar) const;
NzMatrix4& operator*=(const NzMatrix4& matrix);
NzMatrix4& operator*=(T scalar); NzMatrix4& operator*=(const NzMatrix4& matrix);
NzMatrix4& operator*=(T scalar);
static NzMatrix4 Concatenate(const NzMatrix4& m1, const NzMatrix4& m2);
static NzMatrix4 ConcatenateAffine(const NzMatrix4& m1, const NzMatrix4& m2); static NzMatrix4 Concatenate(const NzMatrix4& m1, const NzMatrix4& m2);
static NzMatrix4 Identity(); static NzMatrix4 ConcatenateAffine(const NzMatrix4& m1, const NzMatrix4& m2);
static NzMatrix4 LookAt(const NzVector3<T>& eye, const NzVector3<T>& center, const NzVector3<T>& up); static NzMatrix4 Identity();
static NzMatrix4 Ortho(T left, T top, T width, T height, T zNear = -1.0, T zFar = 1.0); static NzMatrix4 LookAt(const NzVector3<T>& eye, const NzVector3<T>& target, const NzVector3<T>& up = NzVector3<T>::Up());
static NzMatrix4 Perspective(T angle, T ratio, T zNear, T zFar); static NzMatrix4 Ortho(T left, T top, T width, T height, T zNear = -1.0, T zFar = 1.0);
static NzMatrix4 Rotate(const NzQuaternion<T>& rotation); static NzMatrix4 Perspective(T angle, T ratio, T zNear, T zFar);
static NzMatrix4 Scale(const NzVector3<T>& scale); static NzMatrix4 Rotate(const NzQuaternion<T>& rotation);
static NzMatrix4 Translate(const NzVector3<T>& translation); static NzMatrix4 Scale(const NzVector3<T>& scale);
static NzMatrix4 Zero(); static NzMatrix4 Translate(const NzVector3<T>& translation);
static NzMatrix4 Zero();
struct SharedMatrix
{ struct SharedMatrix
T m11, m12, m13, m14, {
m21, m22, m23, m24, T m11, m12, m13, m14,
m31, m32, m33, m34, m21, m22, m23, m24,
m41, m42, m43, m44; m31, m32, m33, m34,
m41, m42, m43, m44;
unsigned short refCount = 1;
NazaraMutex(mutex) unsigned short refCount = 1;
}; NazaraMutex(mutex)
};
private:
void EnsureOwnership(); private:
void ReleaseMatrix(); void EnsureOwnership();
void ReleaseMatrix();
SharedMatrix* m_sharedMatrix = nullptr;
}; SharedMatrix* m_sharedMatrix = nullptr;
};
template<typename T> std::ostream& operator<<(std::ostream& out, const NzMatrix4<T>& matrix);
template<typename T> std::ostream& operator<<(std::ostream& out, const NzMatrix4<T>& matrix);
template<typename T> NzMatrix4<T> operator*(T scale, const NzMatrix4<T>& matrix);
template<typename T> NzMatrix4<T> operator*(T scale, const NzMatrix4<T>& matrix);
typedef NzMatrix4<double> NzMatrix4d;
typedef NzMatrix4<float> NzMatrix4f; typedef NzMatrix4<double> NzMatrix4d;
typedef NzMatrix4<float> NzMatrix4f;
#include <Nazara/Math/Matrix4.inl>
#include <Nazara/Math/Matrix4.inl>
#endif // NAZARA_MATRIX4_HPP
#endif // NAZARA_MATRIX4_HPP

File diff suppressed because it is too large Load Diff

View File

@ -1,90 +1,93 @@
// Copyright (C) 2012 Rémi Bèges - Jérôme Leclercq // Copyright (C) 2012 Rémi Bèges - Jérôme Leclercq
// This file is part of the "Nazara Engine - Mathematics module" // This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once #pragma once
#ifndef NAZARA_QUATERNION_HPP #ifndef NAZARA_QUATERNION_HPP
#define NAZARA_QUATERNION_HPP #define NAZARA_QUATERNION_HPP
#include <Nazara/Core/String.hpp> #include <Nazara/Core/String.hpp>
template<typename T> class NzEulerAngles; template<typename T> class NzEulerAngles;
template<typename T> class NzVector3; template<typename T> class NzVector3;
template<typename T> class NzQuaternion template<typename T> class NzQuaternion
{ {
public: public:
NzQuaternion(); NzQuaternion();
NzQuaternion(T W, T X, T Y, T Z); NzQuaternion(T W, T X, T Y, T Z);
NzQuaternion(T quat[4]); NzQuaternion(T quat[4]);
NzQuaternion(T angle, const NzVector3<T>& axis); NzQuaternion(T angle, const NzVector3<T>& axis);
NzQuaternion(const NzEulerAngles<T>& angles); NzQuaternion(const NzEulerAngles<T>& angles);
//NzQuaternion(const NzMatrix3<T>& mat); //NzQuaternion(const NzMatrix3<T>& mat);
template<typename U> explicit NzQuaternion(const NzQuaternion<U>& quat); template<typename U> explicit NzQuaternion(const NzQuaternion<U>& quat);
NzQuaternion(const NzQuaternion& quat) = default; NzQuaternion(const NzQuaternion& quat) = default;
~NzQuaternion() = default; ~NzQuaternion() = default;
T DotProduct(const NzQuaternion& vec) const; T DotProduct(const NzQuaternion& vec) const;
NzQuaternion GetConjugate() const; NzQuaternion GetConjugate() const;
NzQuaternion GetNormalized() const; NzQuaternion GetInverse() const;
NzQuaternion GetNormal() const;
void MakeIdentity();
void MakeZero(); void Inverse();
T Magnitude() const; void MakeIdentity();
void MakeZero();
T Normalize();
T Magnitude() const;
void Set(T W, T X, T Y, T Z);
void Set(T quat[4]); T Normalize();
void Set(T angle, const NzVector3<T>& normalizedAxis);
void Set(const NzEulerAngles<T>& angles); void Set(T W, T X, T Y, T Z);
//void Set(const NzMatrix3<T>& mat); void Set(T quat[4]);
void Set(const NzQuaternion& quat); void Set(T angle, const NzVector3<T>& normalizedAxis);
template<typename U> void Set(const NzQuaternion<U>& quat); void Set(const NzEulerAngles<T>& angles);
//void Set(const NzMatrix3<T>& mat);
T SquaredMagnitude() const; void Set(const NzQuaternion& quat);
template<typename U> void Set(const NzQuaternion<U>& quat);
NzEulerAngles<T> ToEulerAngles() const;
//NzMatrix3<T> ToRotationMatrix() const; T SquaredMagnitude() const;
NzString ToString() const;
NzEulerAngles<T> ToEulerAngles() const;
operator NzString() const; //NzMatrix3<T> ToRotationMatrix() const;
NzString ToString() const;
NzQuaternion& operator=(const NzQuaternion& quat);
operator NzString() const;
NzQuaternion operator+(const NzQuaternion& quat) const;
NzQuaternion operator*(const NzQuaternion& quat) const; NzQuaternion& operator=(const NzQuaternion& quat);
NzVector3<T> operator*(const NzVector3<T>& vec) const;
NzQuaternion operator*(T scale) const; NzQuaternion operator+(const NzQuaternion& quat) const;
NzQuaternion operator/(const NzQuaternion& quat) const; NzQuaternion operator*(const NzQuaternion& quat) const;
NzVector3<T> operator*(const NzVector3<T>& vec) const;
NzQuaternion& operator+=(const NzQuaternion& quat); NzQuaternion operator*(T scale) const;
NzQuaternion& operator*=(const NzQuaternion& quat); NzQuaternion operator/(const NzQuaternion& quat) const;
NzQuaternion& operator*=(T scale);
NzQuaternion& operator/=(const NzQuaternion& quat); NzQuaternion& operator+=(const NzQuaternion& quat);
NzQuaternion& operator*=(const NzQuaternion& quat);
bool operator==(const NzQuaternion& quat) const; NzQuaternion& operator*=(T scale);
bool operator!=(const NzQuaternion& quat) const; NzQuaternion& operator/=(const NzQuaternion& quat);
bool operator<(const NzQuaternion& quat) const;
bool operator<=(const NzQuaternion& quat) const; bool operator==(const NzQuaternion& quat) const;
bool operator>(const NzQuaternion& quat) const; bool operator!=(const NzQuaternion& quat) const;
bool operator>=(const NzQuaternion& quat) const; bool operator<(const NzQuaternion& quat) const;
bool operator<=(const NzQuaternion& quat) const;
static NzQuaternion Identity(); bool operator>(const NzQuaternion& quat) const;
static NzQuaternion Slerp(const NzQuaternion& quatA, const NzQuaternion& quatB, T interp); bool operator>=(const NzQuaternion& quat) const;
static NzQuaternion Zero();
static NzQuaternion Identity();
T w, x, y, z; static NzQuaternion Slerp(const NzQuaternion& quatA, const NzQuaternion& quatB, T interp);
}; static NzQuaternion Zero();
template<typename T> std::ostream& operator<<(std::ostream& out, const NzQuaternion<T>& quat); T w, x, y, z;
};
typedef NzQuaternion<double> NzQuaterniond;
typedef NzQuaternion<float> NzQuaternionf; template<typename T> std::ostream& operator<<(std::ostream& out, const NzQuaternion<T>& quat);
#include <Nazara/Math/Quaternion.inl> typedef NzQuaternion<double> NzQuaterniond;
typedef NzQuaternion<float> NzQuaternionf;
#endif // NAZARA_QUATERNION_HPP
#include <Nazara/Math/Quaternion.inl>
#endif // NAZARA_QUATERNION_HPP

View File

@ -1,403 +1,428 @@
// Copyright (C) 2012 Rémi Bèges - Jérôme Leclercq // Copyright (C) 2012 Rémi Bèges - Jérôme Leclercq
// This file is part of the "Nazara Engine - Mathematics module" // This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/StringStream.hpp> #include <Nazara/Core/StringStream.hpp>
#include <Nazara/Math/Basic.hpp> #include <Nazara/Math/Basic.hpp>
#include <Nazara/Math/Config.hpp> #include <Nazara/Math/Config.hpp>
#include <Nazara/Math/EulerAngles.hpp> #include <Nazara/Math/EulerAngles.hpp>
#include <Nazara/Math/Vector3.hpp> #include <Nazara/Math/Vector3.hpp>
#include <limits> #include <limits>
#include <Nazara/Core/Debug.hpp> #include <Nazara/Core/Debug.hpp>
#define F(a) static_cast<T>(a) #define F(a) static_cast<T>(a)
template<typename T> template<typename T>
NzQuaternion<T>::NzQuaternion() NzQuaternion<T>::NzQuaternion()
{ {
} }
template<typename T> template<typename T>
NzQuaternion<T>::NzQuaternion(T W, T X, T Y, T Z) NzQuaternion<T>::NzQuaternion(T W, T X, T Y, T Z)
{ {
Set(W, X, Y, Z); Set(W, X, Y, Z);
} }
template<typename T> template<typename T>
NzQuaternion<T>::NzQuaternion(T quat[4]) NzQuaternion<T>::NzQuaternion(T quat[4])
{ {
Set(quat); Set(quat);
} }
template<typename T> template<typename T>
NzQuaternion<T>::NzQuaternion(T angle, const NzVector3<T>& axis) NzQuaternion<T>::NzQuaternion(T angle, const NzVector3<T>& axis)
{ {
Set(angle, axis); Set(angle, axis);
} }
template<typename T> template<typename T>
NzQuaternion<T>::NzQuaternion(const NzEulerAngles<T>& angles) NzQuaternion<T>::NzQuaternion(const NzEulerAngles<T>& angles)
{ {
Set(angles); Set(angles);
} }
/* /*
template<typename T> template<typename T>
NzQuaternion<T>::NzQuaternion(const NzMatrix3<T>& mat) NzQuaternion<T>::NzQuaternion(const NzMatrix3<T>& mat)
{ {
Set(mat); Set(mat);
} }
*/ */
template<typename T> template<typename T>
template<typename U> template<typename U>
NzQuaternion<T>::NzQuaternion(const NzQuaternion<U>& quat) NzQuaternion<T>::NzQuaternion(const NzQuaternion<U>& quat)
{ {
Set(quat); Set(quat);
} }
template<typename T> template<typename T>
T NzQuaternion<T>::DotProduct(const NzQuaternion& quat) const T NzQuaternion<T>::DotProduct(const NzQuaternion& quat) const
{ {
return w*quat.w + x*quat.x + y*quat.y + z*quat.z; return w*quat.w + x*quat.x + y*quat.y + z*quat.z;
} }
template<typename T> template<typename T>
NzQuaternion<T> NzQuaternion<T>::GetConjugate() const NzQuaternion<T> NzQuaternion<T>::GetConjugate() const
{ {
return NzQuaternion(w, -x, -y, -z); return NzQuaternion(w, -x, -y, -z);
} }
template<typename T> template<typename T>
NzQuaternion<T> NzQuaternion<T>::GetNormalized() const NzQuaternion<T> NzQuaternion<T>::GetInverse() const
{ {
NzQuaternion<T> quat(*this); NzQuaternion<T> quat(*this);
quat.Normalize(); quat.Inverse();
return quat; return quat;
} }
template<typename T> template<typename T>
void NzQuaternion<T>::MakeIdentity() NzQuaternion<T> NzQuaternion<T>::GetNormal() const
{ {
Set(1.0, 0.0, 0.0, 0.0); NzQuaternion<T> quat(*this);
} quat.Normalize();
template<typename T> return quat;
void NzQuaternion<T>::MakeZero() }
{
Set(0.0, 0.0, 0.0, 0.0); template<typename T>
} void NzQuaternion<T>::Inverse()
{
template<typename T> T norm = SquaredMagnitude();
T NzQuaternion<T>::Magnitude() const if (norm > F(0.0))
{ {
return std::sqrt(SquaredMagnitude()); T invNorm = F(1.0) / norm;
}
w *= invNorm;
template<typename T> x *= -invNorm;
T NzQuaternion<T>::Normalize() y *= -invNorm;
{ z *= -invNorm;
T squaredMagnitude = SquaredMagnitude(); }
}
if (squaredMagnitude-F(1.0) > std::numeric_limits<T>::epsilon())
{ template<typename T>
T magnitude = std::sqrt(squaredMagnitude); void NzQuaternion<T>::MakeIdentity()
{
w /= magnitude; Set(F(1.0), F(0.0), F(0.0), F(0.0));
x /= magnitude; }
y /= magnitude;
z /= magnitude; template<typename T>
void NzQuaternion<T>::MakeZero()
return magnitude; {
} Set(F(0.0), F(0.0), F(0.0), F(0.0));
else }
return F(1.0); // Le quaternion est déjà normalisé
} template<typename T>
T NzQuaternion<T>::Magnitude() const
template<typename T> {
void NzQuaternion<T>::Set(T W, T X, T Y, T Z) return std::sqrt(SquaredMagnitude());
{ }
w = W;
x = X; template<typename T>
y = Y; T NzQuaternion<T>::Normalize()
z = Z; {
} T squaredMagnitude = SquaredMagnitude();
template<typename T> // Inutile de vérifier si la magnitude au carrée est négative (Elle ne peut pas l'être)
void NzQuaternion<T>::Set(T quat[4]) if (!NzNumberEquals(squaredMagnitude, F(1.0)))
{ {
w = quat[0]; T norm = std::sqrt(squaredMagnitude);
x = quat[1]; T invNorm = F(1.0) / norm;
y = quat[2];
z = quat[3]; w *= invNorm;
} x *= invNorm;
y *= invNorm;
template<typename T> z *= invNorm;
void NzQuaternion<T>::Set(T angle, const NzVector3<T>& normalizedAxis)
{ return norm;
#if !NAZARA_MATH_ANGLE_RADIAN }
angle = NzDegreeToRadian(angle); else
#endif return F(1.0); // Le quaternion est déjà normalisé
}
angle /= 2;
template<typename T>
auto sinAngle = std::sin(angle); void NzQuaternion<T>::Set(T W, T X, T Y, T Z)
{
w = std::cos(angle); w = W;
x = normalizedAxis.x * sinAngle; x = X;
y = normalizedAxis.y * sinAngle; y = Y;
z = normalizedAxis.z * sinAngle; z = Z;
} }
template<typename T> template<typename T>
void NzQuaternion<T>::Set(const NzEulerAngles<T>& angles) void NzQuaternion<T>::Set(T quat[4])
{ {
Set(angles.ToQuaternion()); w = quat[0];
} x = quat[1];
y = quat[2];
template<typename T> z = quat[3];
template<typename U> }
void NzQuaternion<T>::Set(const NzQuaternion<U>& quat)
{ template<typename T>
w = static_cast<T>(quat.w); void NzQuaternion<T>::Set(T angle, const NzVector3<T>& axis)
x = static_cast<T>(quat.x); {
y = static_cast<T>(quat.y); angle /= F(2.0);
z = static_cast<T>(quat.z);
} #if !NAZARA_MATH_ANGLE_RADIAN
angle = NzDegreeToRadian(angle);
template<typename T> #endif
void NzQuaternion<T>::Set(const NzQuaternion& quat)
{ NzVector3<T> normalizedAxis = axis.GetNormal();
w = quat.w;
x = quat.x; T sinAngle = std::sin(angle);
y = quat.y;
z = quat.z; w = std::cos(angle);
} x = normalizedAxis.x * sinAngle;
y = normalizedAxis.y * sinAngle;
template<typename T> z = normalizedAxis.z * sinAngle;
T NzQuaternion<T>::SquaredMagnitude() const
{ Normalize();
return w*w + x*x + y*y + z*z; }
}
template<typename T>
template<typename T> void NzQuaternion<T>::Set(const NzEulerAngles<T>& angles)
NzEulerAngles<T> NzQuaternion<T>::ToEulerAngles() const {
{ Set(angles.ToQuaternion());
T test = x*y + z*w; }
if (test > F(0.499))
// singularity at north pole template<typename T>
return NzEulerAngles<T>(NzDegrees(F(90.0)), NzRadians(F(2.0) * std::atan2(x, w)), F(0.0)); template<typename U>
void NzQuaternion<T>::Set(const NzQuaternion<U>& quat)
if (test < F(-0.499)) {
return NzEulerAngles<T>(NzDegrees(F(-90.0)), NzRadians(F(-2.0) * std::atan2(x, w)), F(0.0)); w = static_cast<T>(quat.w);
x = static_cast<T>(quat.x);
T xx = x*x; y = static_cast<T>(quat.y);
T yy = y*y; z = static_cast<T>(quat.z);
T zz = z*z; }
return NzEulerAngles<T>(NzRadians(std::atan2(F(2.0)*x*w - F(2.0)*y*z, F(1.0) - F(2.0)*xx - F(2.0)*zz)), template<typename T>
NzRadians(std::atan2(F(2.0)*y*w - F(2.0)*x*z, F(1.0) - F(2.0)*yy - F(2.0)*zz)), void NzQuaternion<T>::Set(const NzQuaternion& quat)
NzRadians(std::asin(F(2.0)*test))); {
} w = quat.w;
x = quat.x;
template<typename T> y = quat.y;
NzString NzQuaternion<T>::ToString() const z = quat.z;
{ }
NzStringStream ss;
template<typename T>
return ss << "Quaternion(" << w << " | " << x << ", " << y << ", " << z << ')'; T NzQuaternion<T>::SquaredMagnitude() const
} {
return w*w + x*x + y*y + z*z;
template<typename T> }
NzQuaternion<T>::operator NzString() const
{ template<typename T>
return ToString(); NzEulerAngles<T> NzQuaternion<T>::ToEulerAngles() const
} {
T test = x*y + z*w;
template<typename T> if (test > F(0.499))
NzQuaternion<T>& NzQuaternion<T>::operator=(const NzQuaternion& quat) // singularity at north pole
{ return NzEulerAngles<T>(NzDegrees(F(90.0)), NzRadians(F(2.0) * std::atan2(x, w)), F(0.0));
Set(quat);
if (test < F(-0.499))
return *this; return NzEulerAngles<T>(NzDegrees(F(-90.0)), NzRadians(F(-2.0) * std::atan2(x, w)), F(0.0));
}
return NzEulerAngles<T>(NzRadians(std::atan2(F(2.0)*x*w - F(2.0)*y*z, F(1.0) - F(2.0)*x* - F(2.0)*z*z)),
template<typename T> NzRadians(std::atan2(F(2.0)*y*w - F(2.0)*x*z, F(1.0) - F(2.0)*y*y - F(2.0)*z*z)),
NzQuaternion<T> NzQuaternion<T>::operator+(const NzQuaternion& quat) const NzRadians(std::asin(F(2.0)*test)));
{ }
return NzQuaternion(w + quat.w,
x + quat.x, template<typename T>
y + quat.y, NzString NzQuaternion<T>::ToString() const
z + quat.z); {
} NzStringStream ss;
template<typename T> return ss << "Quaternion(" << w << " | " << x << ", " << y << ", " << z << ')';
NzQuaternion<T> NzQuaternion<T>::operator*(const NzQuaternion& quat) const }
{
return NzQuaternion(w*quat.w - x*quat.x - y*quat.y - z*quat.z, template<typename T>
w*quat.x + x*quat.w + y*quat.z - z*quat.y, NzQuaternion<T>::operator NzString() const
w*quat.y + y*quat.w + z*quat.x - x*quat.z, {
w*quat.z + z*quat.w + x*quat.y - y*quat.x); return ToString();
} }
template<typename T> template<typename T>
NzVector3<T> NzQuaternion<T>::operator*(const NzVector3<T>& vec) const NzQuaternion<T>& NzQuaternion<T>::operator=(const NzQuaternion& quat)
{ {
NzVector3<T> normal(vec); Set(quat);
normal.Normalize();
return *this;
NzQuaternion qvec(0.0, normal.x, normal.y, normal.z); }
NzQuaternion result(operator*(qvec * GetConjugate()));
template<typename T>
return NzVector3<T>(result.x, result.y, result.z); NzQuaternion<T> NzQuaternion<T>::operator+(const NzQuaternion& quat) const
{
} return NzQuaternion(w + quat.w,
x + quat.x,
template<typename T> y + quat.y,
NzQuaternion<T> NzQuaternion<T>::operator*(T scale) const z + quat.z);
{ }
return NzQuaternion(w * scale,
x * scale, template<typename T>
y * scale, NzQuaternion<T> NzQuaternion<T>::operator*(const NzQuaternion& quat) const
z * scale); {
} return NzQuaternion(w*quat.w - x*quat.x - y*quat.y - z*quat.z,
w*quat.x + x*quat.w + y*quat.z - z*quat.y,
template<typename T> w*quat.y + y*quat.w + z*quat.x - x*quat.z,
NzQuaternion<T> NzQuaternion<T>::operator/(const NzQuaternion& quat) const w*quat.z + z*quat.w + x*quat.y - y*quat.x);
{ }
return GetConjugate(quat) * (*this);
} template<typename T>
NzVector3<T> NzQuaternion<T>::operator*(const NzVector3<T>& vec) const
template<typename T> {
NzQuaternion<T>& NzQuaternion<T>::operator+=(const NzQuaternion& quat) NzVector3f quatVec(x, y, z);
{ NzVector3f uv = quatVec.CrossProduct(vec);
return operator=(operator+(quat)); NzVector3f uuv = quatVec.CrossProduct(uv);
} uv *= F(2.0) * w;
uuv *= F(2.0);
template<typename T>
NzQuaternion<T>& NzQuaternion<T>::operator*=(const NzQuaternion& quat) return vec + uv + uuv;
{ }
return operator=(operator*(quat));
} template<typename T>
NzQuaternion<T> NzQuaternion<T>::operator*(T scale) const
template<typename T> {
NzQuaternion<T>& NzQuaternion<T>::operator*=(T scale) return NzQuaternion(w * scale,
{ x * scale,
return operator=(operator*(scale)); y * scale,
} z * scale);
}
template<typename T>
NzQuaternion<T>& NzQuaternion<T>::operator/=(const NzQuaternion& quat) template<typename T>
{ NzQuaternion<T> NzQuaternion<T>::operator/(const NzQuaternion& quat) const
return operator=(operator/(quat)); {
} return GetConjugate(quat) * (*this);
}
template<typename T>
bool NzQuaternion<T>::operator==(const NzQuaternion& quat) const template<typename T>
{ NzQuaternion<T>& NzQuaternion<T>::operator+=(const NzQuaternion& quat)
return NzNumberEquals(w, quat.w) && {
NzNumberEquals(x, quat.x) && return operator=(operator+(quat));
NzNumberEquals(y, quat.y) && }
NzNumberEquals(z, quat.z);
} template<typename T>
NzQuaternion<T>& NzQuaternion<T>::operator*=(const NzQuaternion& quat)
template<typename T> {
bool NzQuaternion<T>::operator!=(const NzQuaternion& quat) const return operator=(operator*(quat));
{ }
return !operator==(quat);
} template<typename T>
NzQuaternion<T>& NzQuaternion<T>::operator*=(T scale)
template<typename T> {
bool NzQuaternion<T>::operator<(const NzQuaternion& quat) const return operator=(operator*(scale));
{ }
return w < quat.w && x < quat.x && y < quat.y && z < quat.z;
} template<typename T>
NzQuaternion<T>& NzQuaternion<T>::operator/=(const NzQuaternion& quat)
template<typename T> {
bool NzQuaternion<T>::operator<=(const NzQuaternion& quat) const return operator=(operator/(quat));
{ }
return operator<(quat) || operator==(quat);
} template<typename T>
bool NzQuaternion<T>::operator==(const NzQuaternion& quat) const
template<typename T> {
bool NzQuaternion<T>::operator>(const NzQuaternion& quat) const return NzNumberEquals(w, quat.w) &&
{ NzNumberEquals(x, quat.x) &&
return !operator<=(quat); NzNumberEquals(y, quat.y) &&
} NzNumberEquals(z, quat.z);
}
template<typename T>
bool NzQuaternion<T>::operator>=(const NzQuaternion& quat) const template<typename T>
{ bool NzQuaternion<T>::operator!=(const NzQuaternion& quat) const
return !operator<(quat); {
} return !operator==(quat);
}
template<typename T>
NzQuaternion<T> NzQuaternion<T>::Identity() template<typename T>
{ bool NzQuaternion<T>::operator<(const NzQuaternion& quat) const
NzQuaternion quaternion; {
quaternion.MakeIdentity(); return w < quat.w && x < quat.x && y < quat.y && z < quat.z;
}
return quaternion;
} template<typename T>
bool NzQuaternion<T>::operator<=(const NzQuaternion& quat) const
template<typename T> {
NzQuaternion<T> NzQuaternion<T>::Slerp(const NzQuaternion& quatA, const NzQuaternion& quatB, T interp) return operator<(quat) || operator==(quat);
{ }
if (interp <= F(0.0))
return quatA; template<typename T>
bool NzQuaternion<T>::operator>(const NzQuaternion& quat) const
if (interp >= F(1.0)) {
return quatB; return !operator<=(quat);
}
NzQuaternion q;
template<typename T>
T cosOmega = quatA.DotProduct(quatB); bool NzQuaternion<T>::operator>=(const NzQuaternion& quat) const
if (cosOmega < F(0.0)) {
{ return !operator<(quat);
// On inverse tout }
q.Set(-quatB.w, -quatB.x, -quatB.y, -quatB.z);
cosOmega = -cosOmega; template<typename T>
} NzQuaternion<T> NzQuaternion<T>::Identity()
else {
q.Set(quatB); NzQuaternion quaternion;
quaternion.MakeIdentity();
T k0, k1;
if (cosOmega > F(0.9999)) return quaternion;
{ }
// Interpolation linéaire pour éviter une division par zéro
k0 = F(1.0) - interp; template<typename T>
k1 = interp; NzQuaternion<T> NzQuaternion<T>::Slerp(const NzQuaternion& quatA, const NzQuaternion& quatB, T interp)
} {
else if (interp <= F(0.0))
{ return quatA;
T sinOmega = std::sqrt(F(1.0) - cosOmega*cosOmega);
T omega = std::atan2(sinOmega, cosOmega); if (interp >= F(1.0))
return quatB;
// Pour éviter deux divisions
sinOmega = F(1.0)/sinOmega; NzQuaternion q;
k0 = std::sin((F(1.0) - interp) * omega) * sinOmega; T cosOmega = quatA.DotProduct(quatB);
k1 = std::sin(interp*omega) * sinOmega; if (cosOmega < F(0.0))
} {
// On inverse tout
NzQuaternion result(k0 * quatA.w, k0 * quatA.x, k0 * quatA.y, k0 * quatA.z); q.Set(-quatB.w, -quatB.x, -quatB.y, -quatB.z);
return result += q*k1; cosOmega = -cosOmega;
} }
else
template<typename T> q.Set(quatB);
NzQuaternion<T> NzQuaternion<T>::Zero()
{ T k0, k1;
NzQuaternion quaternion; if (cosOmega > F(0.9999))
quaternion.MakeZero(); {
// Interpolation linéaire pour éviter une division par zéro
return quaternion; k0 = F(1.0) - interp;
} k1 = interp;
}
template<typename T> else
std::ostream& operator<<(std::ostream& out, const NzQuaternion<T>& quat) {
{ T sinOmega = std::sqrt(F(1.0) - cosOmega*cosOmega);
return out << quat.ToString(); T omega = std::atan2(sinOmega, cosOmega);
}
// Pour éviter deux divisions
#undef F sinOmega = F(1.0)/sinOmega;
#include <Nazara/Core/DebugOff.hpp> k0 = std::sin((F(1.0) - interp) * omega) * sinOmega;
k1 = std::sin(interp*omega) * sinOmega;
}
NzQuaternion result(k0 * quatA.w, k0 * quatA.x, k0 * quatA.y, k0 * quatA.z);
return result += q*k1;
}
template<typename T>
NzQuaternion<T> NzQuaternion<T>::Zero()
{
NzQuaternion quaternion;
quaternion.MakeZero();
return quaternion;
}
template<typename T>
std::ostream& operator<<(std::ostream& out, const NzQuaternion<T>& quat)
{
return out << quat.ToString();
}
#undef F
#include <Nazara/Core/DebugOff.hpp>

View File

@ -1,104 +1,105 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Mathematics module" // This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once #pragma once
#ifndef NAZARA_VECTOR2_HPP #ifndef NAZARA_VECTOR2_HPP
#define NAZARA_VECTOR2_HPP #define NAZARA_VECTOR2_HPP
#include <Nazara/Core/String.hpp> #include <Nazara/Core/String.hpp>
template<typename T> class NzVector2 template<typename T> class NzVector2
{ {
public: public:
NzVector2(); NzVector2();
NzVector2(T X, T Y); NzVector2(T X, T Y);
explicit NzVector2(T scale); explicit NzVector2(T scale);
NzVector2(T vec[2]); NzVector2(T vec[2]);
template<typename U> explicit NzVector2(const NzVector2<U>& vec); template<typename U> explicit NzVector2(const NzVector2<U>& vec);
NzVector2(const NzVector2& vec) = default; NzVector2(const NzVector2& vec) = default;
~NzVector2() = default; ~NzVector2() = default;
T AbsDotProduct(const NzVector2& vec) const; T AbsDotProduct(const NzVector2& vec) const;
T Distance(const NzVector2& vec) const; T Distance(const NzVector2& vec) const;
float Distancef(const NzVector2& vec) const; float Distancef(const NzVector2& vec) const;
T DotProduct(const NzVector2& vec) const; T DotProduct(const NzVector2& vec) const;
NzVector2 GetNormal() const; NzVector2 GetNormal() const;
void MakeCeil(const NzVector2& vec); T Length() const;
void MakeFloor(const NzVector2& vec); float Lengthf() const;
void MakeUnitX();
void MakeUnitY(); void MakeUnitX();
void MakeZero(); void MakeUnitY();
void MakeZero();
T Length() const;
float Lengthf() const; void Maximize(const NzVector2& vec);
void Minimize(const NzVector2& vec);
void Normalize();
void Normalize();
void Set(T X, T Y);
void Set(T scale); void Set(T X, T Y);
void Set(T vec[2]); void Set(T scale);
template<typename U> void Set(const NzVector2<U>& vec); void Set(T vec[2]);
template<typename U> void Set(const NzVector2<U>& vec);
T SquaredDistance(const NzVector2& vec) const;
T SquaredLength() const; T SquaredDistance(const NzVector2& vec) const;
T SquaredLength() const;
NzString ToString() const;
NzString ToString() const;
operator NzString() const;
operator NzString() const;
operator T*();
operator const T*() const; operator T*();
operator const T*() const;
T& operator[](unsigned int i);
T operator[](unsigned int i) const; T& operator[](unsigned int i);
T operator[](unsigned int i) const;
const NzVector2& operator+() const;
NzVector2 operator-() const; const NzVector2& operator+() const;
NzVector2 operator-() const;
NzVector2 operator+(const NzVector2& vec) const;
NzVector2 operator-(const NzVector2& vec) const; NzVector2 operator+(const NzVector2& vec) const;
NzVector2 operator*(const NzVector2& vec) const; NzVector2 operator-(const NzVector2& vec) const;
NzVector2 operator*(T scale) const; NzVector2 operator*(const NzVector2& vec) const;
NzVector2 operator/(const NzVector2& vec) const; NzVector2 operator*(T scale) const;
NzVector2 operator/(T scale) const; NzVector2 operator/(const NzVector2& vec) const;
NzVector2 operator/(T scale) const;
NzVector2& operator+=(const NzVector2& vec);
NzVector2& operator-=(const NzVector2& vec); NzVector2& operator+=(const NzVector2& vec);
NzVector2& operator*=(const NzVector2& vec); NzVector2& operator-=(const NzVector2& vec);
NzVector2& operator*=(T scale); NzVector2& operator*=(const NzVector2& vec);
NzVector2& operator/=(const NzVector2& vec); NzVector2& operator*=(T scale);
NzVector2& operator/=(T scale); NzVector2& operator/=(const NzVector2& vec);
NzVector2& operator/=(T scale);
bool operator==(const NzVector2& vec) const;
bool operator!=(const NzVector2& vec) const; bool operator==(const NzVector2& vec) const;
bool operator<(const NzVector2& vec) const; bool operator!=(const NzVector2& vec) const;
bool operator<=(const NzVector2& vec) const; bool operator<(const NzVector2& vec) const;
bool operator>(const NzVector2& vec) const; bool operator<=(const NzVector2& vec) const;
bool operator>=(const NzVector2& vec) const; bool operator>(const NzVector2& vec) const;
bool operator>=(const NzVector2& vec) const;
static NzVector2 UnitX();
static NzVector2 UnitY(); static NzVector2 UnitX();
static NzVector2 Zero(); static NzVector2 UnitY();
static NzVector2 Zero();
T x, y;
}; T x, y;
};
template<typename T> std::ostream& operator<<(std::ostream& out, const NzVector2<T>& vec);
template<typename T> std::ostream& operator<<(std::ostream& out, const NzVector2<T>& vec);
template<typename T> NzVector2<T> operator*(T scale, const NzVector2<T>& vec);
template<typename T> NzVector2<T> operator/(T scale, const NzVector2<T>& vec); template<typename T> NzVector2<T> operator*(T scale, const NzVector2<T>& vec);
template<typename T> NzVector2<T> operator/(T scale, const NzVector2<T>& vec);
typedef NzVector2<double> NzVector2d;
typedef NzVector2<float> NzVector2f; typedef NzVector2<double> NzVector2d;
typedef NzVector2<int> NzVector2i; typedef NzVector2<float> NzVector2f;
typedef NzVector2<unsigned int> NzVector2ui; typedef NzVector2<int> NzVector2i;
typedef NzVector2<unsigned int> NzVector2ui;
#include <Nazara/Math/Vector2.inl>
#include <Nazara/Math/Vector2.inl>
#endif // NAZARA_VECTOR2_HPP
#endif // NAZARA_VECTOR2_HPP

View File

@ -1,488 +1,488 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Mathematics module" // This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/StringStream.hpp> #include <Nazara/Core/StringStream.hpp>
#include <Nazara/Math/Basic.hpp> #include <Nazara/Math/Basic.hpp>
#include <cmath> #include <cmath>
#include <cstdlib> #include <cstdlib>
#include <limits> #include <limits>
#include <stdexcept> #include <stdexcept>
#include <Nazara/Core/Debug.hpp> #include <Nazara/Core/Debug.hpp>
#define F(a) static_cast<T>(a) #define F(a) static_cast<T>(a)
template<typename T> template<typename T>
NzVector2<T>::NzVector2() NzVector2<T>::NzVector2()
{ {
} }
template<typename T> template<typename T>
NzVector2<T>::NzVector2(T X, T Y) NzVector2<T>::NzVector2(T X, T Y)
{ {
Set(X, Y); Set(X, Y);
} }
template<typename T> template<typename T>
NzVector2<T>::NzVector2(T scale) NzVector2<T>::NzVector2(T scale)
{ {
Set(scale); Set(scale);
} }
template<typename T> template<typename T>
NzVector2<T>::NzVector2(T vec[2]) NzVector2<T>::NzVector2(T vec[2])
{ {
Set(vec); Set(vec);
} }
template<typename T> template<typename T>
template<typename U> template<typename U>
NzVector2<T>::NzVector2(const NzVector2<U>& vec) NzVector2<T>::NzVector2(const NzVector2<U>& vec)
{ {
Set(vec); Set(vec);
} }
template<typename T> template<typename T>
T NzVector2<T>::AbsDotProduct(const NzVector2& vec) const T NzVector2<T>::AbsDotProduct(const NzVector2& vec) const
{ {
return std::fabs(x * vec.x) + std::fabs(y * vec.y); return std::fabs(x * vec.x) + std::fabs(y * vec.y);
} }
template<> template<>
inline int NzVector2<int>::AbsDotProduct(const NzVector2<int>& vec) const inline int NzVector2<int>::AbsDotProduct(const NzVector2<int>& vec) const
{ {
return std::labs(x * vec.x) + std::labs(y * vec.y); return std::labs(x * vec.x) + std::labs(y * vec.y);
} }
template<> template<>
inline unsigned int NzVector2<unsigned int>::AbsDotProduct(const NzVector2<unsigned int>& vec) const inline unsigned int NzVector2<unsigned int>::AbsDotProduct(const NzVector2<unsigned int>& vec) const
{ {
return std::labs(x * vec.x) + std::labs(y * vec.y); return std::labs(x * vec.x) + std::labs(y * vec.y);
} }
template<typename T> template<typename T>
T NzVector2<T>::Distance(const NzVector2& vec) const T NzVector2<T>::Distance(const NzVector2& vec) const
{ {
return std::sqrt(SquaredDistance(vec)); return std::sqrt(SquaredDistance(vec));
} }
template<typename T> template<typename T>
float NzVector2<T>::Distancef(const NzVector2& vec) const float NzVector2<T>::Distancef(const NzVector2& vec) const
{ {
return std::sqrt(static_cast<float>(SquaredDistance(vec))); return std::sqrt(static_cast<float>(SquaredDistance(vec)));
} }
template<typename T> template<typename T>
T NzVector2<T>::DotProduct(const NzVector2& vec) const T NzVector2<T>::DotProduct(const NzVector2& vec) const
{ {
return x*vec.x + y*vec.y; return x*vec.x + y*vec.y;
} }
template<typename T> template<typename T>
NzVector2<T> NzVector2<T>::GetNormal() const NzVector2<T> NzVector2<T>::GetNormal() const
{ {
NzVector2 vec(*this); NzVector2 vec(*this);
vec.Normalize(); vec.Normalize();
return vec; return vec;
} }
template<typename T> template<typename T>
T NzVector2<T>::Length() const T NzVector2<T>::Length() const
{ {
return std::sqrt(SquaredLength()); return std::sqrt(SquaredLength());
} }
template<typename T> template<typename T>
float NzVector2<T>::Lengthf() const float NzVector2<T>::Lengthf() const
{ {
return std::sqrt(static_cast<float>(SquaredLength())); return std::sqrt(static_cast<float>(SquaredLength()));
} }
template<typename T> template<typename T>
void NzVector2<T>::MakeCeil(const NzVector2& vec) void NzVector2<T>::MakeUnitX()
{ {
if (vec.x > x) Set(F(1.0), F(0.0));
x = vec.x; }
if (vec.y > y) template<typename T>
y = vec.y; void NzVector2<T>::MakeUnitY()
} {
Set(F(0.0), F(1.0));
template<typename T> }
void NzVector2<T>::MakeFloor(const NzVector2& vec)
{ template<typename T>
if (vec.x < x) void NzVector2<T>::MakeZero()
x = vec.x; {
Set(F(0.0), F(0.0));
if (vec.y < y) }
y = vec.y;
} template<typename T>
void NzVector2<T>::Maximize(const NzVector2& vec)
template<typename T> {
void NzVector2<T>::MakeUnitX() if (vec.x > x)
{ x = vec.x;
Set(F(1.0), F(0.0));
} if (vec.y > y)
y = vec.y;
template<typename T> }
void NzVector2<T>::MakeUnitY()
{ template<typename T>
Set(F(0.0), F(1.0)); void NzVector2<T>::Minimize(const NzVector2& vec)
} {
if (vec.x < x)
template<typename T> x = vec.x;
void NzVector2<T>::MakeZero()
{ if (vec.y < y)
Set(F(0.0), F(0.0)); y = vec.y;
} }
template<typename T> template<typename T>
void NzVector2<T>::Normalize() void NzVector2<T>::Normalize()
{ {
T squaredLength = SquaredLength(); T squaredLength = SquaredLength();
if (squaredLength-F(1.0) > std::numeric_limits<T>::epsilon()) if (squaredLength-F(1.0) > std::numeric_limits<T>::epsilon())
{ {
T length = std::sqrt(squaredLength); T length = std::sqrt(squaredLength);
x /= length; x /= length;
y /= length; y /= length;
} }
} }
template<typename T> template<typename T>
void NzVector2<T>::Set(T X, T Y) void NzVector2<T>::Set(T X, T Y)
{ {
x = X; x = X;
y = Y; y = Y;
} }
template<typename T> template<typename T>
void NzVector2<T>::Set(T scale) void NzVector2<T>::Set(T scale)
{ {
x = scale; x = scale;
y = scale; y = scale;
} }
template<typename T> template<typename T>
void NzVector2<T>::Set(T vec[2]) void NzVector2<T>::Set(T vec[2])
{ {
std::memcpy(&x, vec, 2*sizeof(T)); std::memcpy(&x, vec, 2*sizeof(T));
} }
template<typename T> template<typename T>
template<typename U> template<typename U>
void NzVector2<T>::Set(const NzVector2<U>& vec) void NzVector2<T>::Set(const NzVector2<U>& vec)
{ {
x = F(vec.x); x = F(vec.x);
y = F(vec.y); y = F(vec.y);
} }
template<typename T> template<typename T>
T NzVector2<T>::SquaredDistance(const NzVector2& vec) const T NzVector2<T>::SquaredDistance(const NzVector2& vec) const
{ {
return operator-(vec).SquaredLength(); return operator-(vec).SquaredLength();
} }
template<typename T> template<typename T>
T NzVector2<T>::SquaredLength() const T NzVector2<T>::SquaredLength() const
{ {
return x*x + y*y; return x*x + y*y;
} }
template<typename T> template<typename T>
NzString NzVector2<T>::ToString() const NzString NzVector2<T>::ToString() const
{ {
NzStringStream ss; NzStringStream ss;
return ss << "Vector2(" << x << ", " << y << ')'; return ss << "Vector2(" << x << ", " << y << ')';
} }
template<typename T> template<typename T>
NzVector2<T>::operator NzString() const NzVector2<T>::operator NzString() const
{ {
return ToString(); return ToString();
} }
template<typename T> template<typename T>
NzVector2<T>::operator T*() NzVector2<T>::operator T*()
{ {
return &x; return &x;
} }
template<typename T> template<typename T>
NzVector2<T>::operator const T*() const NzVector2<T>::operator const T*() const
{ {
return &x; return &x;
} }
template<typename T> template<typename T>
T& NzVector2<T>::operator[](unsigned int i) T& NzVector2<T>::operator[](unsigned int i)
{ {
#if NAZARA_MATH_SAFE #if NAZARA_MATH_SAFE
if (i >= 2) if (i >= 2)
{ {
NzStringStream ss; NzStringStream ss;
ss << __FILE__ << ':' << __LINE__ << ": Index out of range (" << i << " >= 2)"; ss << __FILE__ << ':' << __LINE__ << ": Index out of range (" << i << " >= 2)";
throw std::domain_error(ss.ToString()); throw std::domain_error(ss.ToString());
} }
#endif #endif
return *(&x+i); return *(&x+i);
} }
template<typename T> template<typename T>
T NzVector2<T>::operator[](unsigned int i) const T NzVector2<T>::operator[](unsigned int i) const
{ {
#if NAZARA_MATH_SAFE #if NAZARA_MATH_SAFE
if (i >= 2) if (i >= 2)
{ {
NzStringStream ss; NzStringStream ss;
ss << __FILE__ << ':' << __LINE__ << ": Index out of range (" << i << " >= 2)"; ss << __FILE__ << ':' << __LINE__ << ": Index out of range (" << i << " >= 2)";
throw std::domain_error(ss.ToString()); throw std::domain_error(ss.ToString());
} }
#endif #endif
return *(&x+i); return *(&x+i);
} }
template<typename T> template<typename T>
const NzVector2<T>& NzVector2<T>::operator+() const const NzVector2<T>& NzVector2<T>::operator+() const
{ {
return *this; return *this;
} }
template<typename T> template<typename T>
NzVector2<T> NzVector2<T>::operator-() const NzVector2<T> NzVector2<T>::operator-() const
{ {
return NzVector2(-x, -y); return NzVector2(-x, -y);
} }
template<typename T> template<typename T>
NzVector2<T> NzVector2<T>::operator+(const NzVector2& vec) const NzVector2<T> NzVector2<T>::operator+(const NzVector2& vec) const
{ {
return NzVector2(x + vec.x, y + vec.y); return NzVector2(x + vec.x, y + vec.y);
} }
template<typename T> template<typename T>
NzVector2<T> NzVector2<T>::operator-(const NzVector2& vec) const NzVector2<T> NzVector2<T>::operator-(const NzVector2& vec) const
{ {
return NzVector2(x - vec.x, y - vec.y); return NzVector2(x - vec.x, y - vec.y);
} }
template<typename T> template<typename T>
NzVector2<T> NzVector2<T>::operator*(const NzVector2& vec) const NzVector2<T> NzVector2<T>::operator*(const NzVector2& vec) const
{ {
return NzVector2(x * vec.x, y * vec.y); return NzVector2(x * vec.x, y * vec.y);
} }
template<typename T> template<typename T>
NzVector2<T> NzVector2<T>::operator*(T scale) const NzVector2<T> NzVector2<T>::operator*(T scale) const
{ {
return NzVector2(x * scale, y * scale); return NzVector2(x * scale, y * scale);
} }
template<typename T> template<typename T>
NzVector2<T> NzVector2<T>::operator/(const NzVector2& vec) const NzVector2<T> NzVector2<T>::operator/(const NzVector2& vec) const
{ {
#if NAZARA_MATH_SAFE #if NAZARA_MATH_SAFE
if (NzNumberEquals(vec.x, F(0.0)) || NzNumberEquals(vec.y, F(0.0))) if (NzNumberEquals(vec.x, F(0.0)) || NzNumberEquals(vec.y, F(0.0)))
{ {
NzStringStream ss; NzStringStream ss;
ss << __FILE__ << ':' << __LINE__ << ": Division by zero"; ss << __FILE__ << ':' << __LINE__ << ": Division by zero";
throw std::domain_error(ss.ToString()); throw std::domain_error(ss.ToString());
} }
#endif #endif
return NzVector2(x / vec.x, y / vec.y); return NzVector2(x / vec.x, y / vec.y);
} }
template<typename T> template<typename T>
NzVector2<T> NzVector2<T>::operator/(T scale) const NzVector2<T> NzVector2<T>::operator/(T scale) const
{ {
#if NAZARA_MATH_SAFE #if NAZARA_MATH_SAFE
if (NzNumberEquals(scale, F(0.0))) if (NzNumberEquals(scale, F(0.0)))
{ {
NzStringStream ss; NzStringStream ss;
ss << __FILE__ << ':' << __LINE__ << ": Division by zero"; ss << __FILE__ << ':' << __LINE__ << ": Division by zero";
throw std::domain_error(ss.ToString()); throw std::domain_error(ss.ToString());
} }
#endif #endif
return NzVector2(x / scale, y / scale); return NzVector2(x / scale, y / scale);
} }
template<typename T> template<typename T>
NzVector2<T>& NzVector2<T>::operator+=(const NzVector2& vec) NzVector2<T>& NzVector2<T>::operator+=(const NzVector2& vec)
{ {
x += vec.x; x += vec.x;
y += vec.y; y += vec.y;
return *this; return *this;
} }
template<typename T> template<typename T>
NzVector2<T>& NzVector2<T>::operator-=(const NzVector2& vec) NzVector2<T>& NzVector2<T>::operator-=(const NzVector2& vec)
{ {
x -= vec.x; x -= vec.x;
y -= vec.y; y -= vec.y;
return *this; return *this;
} }
template<typename T> template<typename T>
NzVector2<T>& NzVector2<T>::operator*=(const NzVector2& vec) NzVector2<T>& NzVector2<T>::operator*=(const NzVector2& vec)
{ {
x *= vec.x; x *= vec.x;
y *= vec.y; y *= vec.y;
return *this; return *this;
} }
template<typename T> template<typename T>
NzVector2<T>& NzVector2<T>::operator*=(T scale) NzVector2<T>& NzVector2<T>::operator*=(T scale)
{ {
x *= scale; x *= scale;
y *= scale; y *= scale;
return *this; return *this;
} }
template<typename T> template<typename T>
NzVector2<T>& NzVector2<T>::operator/=(const NzVector2& vec) NzVector2<T>& NzVector2<T>::operator/=(const NzVector2& vec)
{ {
#if NAZARA_MATH_SAFE #if NAZARA_MATH_SAFE
if (NzNumberEquals(vec.x, F(0.0)) || NzNumberEquals(vec.y, F(0.0)) || NzNumberEquals(vec.z, F(0.0))) if (NzNumberEquals(vec.x, F(0.0)) || NzNumberEquals(vec.y, F(0.0)) || NzNumberEquals(vec.z, F(0.0)))
{ {
NzStringStream ss; NzStringStream ss;
ss << __FILE__ << ':' << __LINE__ << ": Division by zero"; ss << __FILE__ << ':' << __LINE__ << ": Division by zero";
throw std::domain_error(ss.ToString()); throw std::domain_error(ss.ToString());
} }
#endif #endif
x /= vec.x; x /= vec.x;
y /= vec.y; y /= vec.y;
return *this; return *this;
} }
template<typename T> template<typename T>
NzVector2<T>& NzVector2<T>::operator/=(T scale) NzVector2<T>& NzVector2<T>::operator/=(T scale)
{ {
#if NAZARA_MATH_SAFE #if NAZARA_MATH_SAFE
if (NzNumberEquals(scale, F(0.0))) if (NzNumberEquals(scale, F(0.0)))
{ {
NzStringStream ss; NzStringStream ss;
ss << __FILE__ << ':' << __LINE__ << ": Division by zero"; ss << __FILE__ << ':' << __LINE__ << ": Division by zero";
throw std::domain_error(ss.ToString()); throw std::domain_error(ss.ToString());
} }
#endif #endif
x /= scale; x /= scale;
y /= scale; y /= scale;
return *this; return *this;
} }
template<typename T> template<typename T>
bool NzVector2<T>::operator==(const NzVector2& vec) const bool NzVector2<T>::operator==(const NzVector2& vec) const
{ {
return NzNumberEquals(x, vec.x) && return NzNumberEquals(x, vec.x) &&
NzNumberEquals(y, vec.y); NzNumberEquals(y, vec.y);
} }
template<typename T> template<typename T>
bool NzVector2<T>::operator!=(const NzVector2& vec) const bool NzVector2<T>::operator!=(const NzVector2& vec) const
{ {
return !operator==(vec); return !operator==(vec);
} }
template<typename T> template<typename T>
bool NzVector2<T>::operator<(const NzVector2& vec) const bool NzVector2<T>::operator<(const NzVector2& vec) const
{ {
return x < vec.x && y < vec.y; return x < vec.x && y < vec.y;
} }
template<typename T> template<typename T>
bool NzVector2<T>::operator<=(const NzVector2& vec) const bool NzVector2<T>::operator<=(const NzVector2& vec) const
{ {
return operator<(vec) || operator==(vec); return operator<(vec) || operator==(vec);
} }
template<typename T> template<typename T>
bool NzVector2<T>::operator>(const NzVector2& vec) const bool NzVector2<T>::operator>(const NzVector2& vec) const
{ {
return !operator<=(vec); return !operator<=(vec);
} }
template<typename T> template<typename T>
bool NzVector2<T>::operator>=(const NzVector2& vec) const bool NzVector2<T>::operator>=(const NzVector2& vec) const
{ {
return !operator<(vec); return !operator<(vec);
} }
template<typename T> template<typename T>
NzVector2<T> NzVector2<T>::UnitX() NzVector2<T> NzVector2<T>::UnitX()
{ {
NzVector2 vector; NzVector2 vector;
vector.MakeUnitX(); vector.MakeUnitX();
return vector; return vector;
} }
template<typename T> template<typename T>
NzVector2<T> NzVector2<T>::UnitY() NzVector2<T> NzVector2<T>::UnitY()
{ {
NzVector2 vector; NzVector2 vector;
vector.MakeUnitY(); vector.MakeUnitY();
return vector; return vector;
} }
template<typename T> template<typename T>
NzVector2<T> NzVector2<T>::Zero() NzVector2<T> NzVector2<T>::Zero()
{ {
NzVector2 vector; NzVector2 vector;
vector.MakeZero(); vector.MakeZero();
return vector; return vector;
} }
template<typename T> template<typename T>
std::ostream& operator<<(std::ostream& out, const NzVector2<T>& vec) std::ostream& operator<<(std::ostream& out, const NzVector2<T>& vec)
{ {
return out << vec.ToString(); return out << vec.ToString();
} }
template<typename T> template<typename T>
NzVector2<T> operator*(T scale, const NzVector2<T>& vec) NzVector2<T> operator*(T scale, const NzVector2<T>& vec)
{ {
return NzVector2<T>(scale * vec.x, scale * vec.y); return NzVector2<T>(scale * vec.x, scale * vec.y);
} }
template<typename T> template<typename T>
NzVector2<T> operator/(T scale, const NzVector2<T>& vec) NzVector2<T> operator/(T scale, const NzVector2<T>& vec)
{ {
#if NAZARA_MATH_SAFE #if NAZARA_MATH_SAFE
if (NzNumberEquals(vec.x, F(0.0)) || NzNumberEquals(vec.y, F(0.0)) || NzNumberEquals(vec.z, F(0.0))) if (NzNumberEquals(vec.x, F(0.0)) || NzNumberEquals(vec.y, F(0.0)) || NzNumberEquals(vec.z, F(0.0)))
{ {
NzStringStream ss; NzStringStream ss;
ss << __FILE__ << ':' << __LINE__ << ": Division by zero"; ss << __FILE__ << ':' << __LINE__ << ": Division by zero";
throw std::domain_error(ss.ToString()); throw std::domain_error(ss.ToString());
} }
#endif #endif
return NzVector2<T>(scale/vec.x, scale/vec.y); return NzVector2<T>(scale/vec.x, scale/vec.y);
} }
#undef F #undef F
#include <Nazara/Core/DebugOff.hpp> #include <Nazara/Core/DebugOff.hpp>

View File

@ -1,111 +1,121 @@
// Copyright (C) 2012 Rémi Bèges - Jérôme Leclercq // Copyright (C) 2012 Rémi Bèges - Jérôme Leclercq
// This file is part of the "Nazara Engine - Mathematics module" // This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once #pragma once
#ifndef NAZARA_VECTOR3_HPP #ifndef NAZARA_VECTOR3_HPP
#define NAZARA_VECTOR3_HPP #define NAZARA_VECTOR3_HPP
#include <Nazara/Core/String.hpp> #include <Nazara/Core/String.hpp>
#include <Nazara/Math/Vector2.hpp> #include <Nazara/Math/Vector2.hpp>
template<typename T> class NzVector3 template<typename T> class NzVector3
{ {
public: public:
NzVector3(); NzVector3();
NzVector3(T X, T Y, T Z); NzVector3(T X, T Y, T Z);
explicit NzVector3(T scale); explicit NzVector3(T scale);
NzVector3(T vec[3]); NzVector3(T vec[3]);
NzVector3(const NzVector2<T>& vec, T Z = 0.0); NzVector3(const NzVector2<T>& vec, T Z = 0.0);
template<typename U> explicit NzVector3(const NzVector3<U>& vec); template<typename U> explicit NzVector3(const NzVector3<U>& vec);
NzVector3(const NzVector3& vec) = default; NzVector3(const NzVector3& vec) = default;
~NzVector3() = default; ~NzVector3() = default;
T AbsDotProduct(const NzVector3& vec) const; T AbsDotProduct(const NzVector3& vec) const;
NzVector3 CrossProduct(const NzVector3& vec) const; NzVector3 CrossProduct(const NzVector3& vec) const;
T Distance(const NzVector3& vec) const; T Distance(const NzVector3& vec) const;
float Distancef(const NzVector3& vec) const; float Distancef(const NzVector3& vec) const;
T DotProduct(const NzVector3& vec) const; T DotProduct(const NzVector3& vec) const;
NzVector3 GetNormal() const; NzVector3 GetNormal() const;
T Length() const; T Length() const;
float Lengthf() const; float Lengthf() const;
void MakeCeil(const NzVector3& vec); void MakeForward();
void MakeFloor(const NzVector3& vec); void MakeLeft();
void MakeUnitX(); void MakeUnitX();
void MakeUnitY(); void MakeUnitY();
void MakeUnitZ(); void MakeUnitZ();
void MakeZero(); void MakeUp();
void MakeZero();
void Normalize();
void Maximize(const NzVector3& vec);
void Set(T X, T Y, T Z); void Minimize(const NzVector3& vec);
void Set(T scale);
void Set(T vec[3]); void Normalize();
void Set(const NzVector2<T>& vec, T Z = 0.0);
template<typename U> void Set(const NzVector3<U>& vec); void Set(T X, T Y, T Z);
void Set(T scale);
T SquaredDistance(const NzVector3& vec) const; void Set(T vec[3]);
T SquaredLength() const; void Set(const NzVector2<T>& vec, T Z = 0.0);
template<typename U> void Set(const NzVector3<U>& vec);
NzString ToString() const;
T SquaredDistance(const NzVector3& vec) const;
operator NzString() const; T SquaredLength() const;
operator T*(); NzString ToString() const;
operator const T*() const;
operator NzString() const;
T& operator[](unsigned int i);
T operator[](unsigned int i) const; operator T*();
operator const T*() const;
const NzVector3& operator+() const;
NzVector3 operator-() const; T& operator[](unsigned int i);
T operator[](unsigned int i) const;
NzVector3 operator+(const NzVector3& vec) const;
NzVector3 operator-(const NzVector3& vec) const; const NzVector3& operator+() const;
NzVector3 operator*(const NzVector3& vec) const; NzVector3 operator-() const;
NzVector3 operator*(T scale) const;
NzVector3 operator/(const NzVector3& vec) const; NzVector3 operator+(const NzVector3& vec) const;
NzVector3 operator/(T scale) const; NzVector3 operator-(const NzVector3& vec) const;
NzVector3 operator*(const NzVector3& vec) const;
NzVector3& operator+=(const NzVector3& vec); NzVector3 operator*(T scale) const;
NzVector3& operator-=(const NzVector3& vec); NzVector3 operator/(const NzVector3& vec) const;
NzVector3& operator*=(const NzVector3& vec); NzVector3 operator/(T scale) const;
NzVector3& operator*=(T scale);
NzVector3& operator/=(const NzVector3& vec); NzVector3& operator+=(const NzVector3& vec);
NzVector3& operator/=(T scale); NzVector3& operator-=(const NzVector3& vec);
NzVector3& operator*=(const NzVector3& vec);
bool operator==(const NzVector3& vec) const; NzVector3& operator*=(T scale);
bool operator!=(const NzVector3& vec) const; NzVector3& operator/=(const NzVector3& vec);
bool operator<(const NzVector3& vec) const; NzVector3& operator/=(T scale);
bool operator<=(const NzVector3& vec) const;
bool operator>(const NzVector3& vec) const; bool operator==(const NzVector3& vec) const;
bool operator>=(const NzVector3& vec) const; bool operator!=(const NzVector3& vec) const;
bool operator<(const NzVector3& vec) const;
static NzVector3 UnitX(); bool operator<=(const NzVector3& vec) const;
static NzVector3 UnitY(); bool operator>(const NzVector3& vec) const;
static NzVector3 UnitZ(); bool operator>=(const NzVector3& vec) const;
static NzVector3 Zero();
static NzVector3 CrossProduct(const NzVector3& vec1, const NzVector3& vec2);
T x, y, z; static T DotProduct(const NzVector3& vec1, const NzVector3& vec2);
}; static NzVector3 Forward();
static NzVector3 Left();
template<typename T> std::ostream& operator<<(std::ostream& out, const NzVector3<T>& vec); static NzVector3 Normalize(const NzVector3& vec);
static NzVector3 UnitX();
template<typename T> NzVector3<T> operator*(T scale, const NzVector3<T>& vec); static NzVector3 UnitY();
template<typename T> NzVector3<T> operator/(T scale, const NzVector3<T>& vec); static NzVector3 UnitZ();
static NzVector3 Up();
typedef NzVector3<double> NzVector3d; static NzVector3 Zero();
typedef NzVector3<float> NzVector3f;
typedef NzVector3<int> NzVector3i; T x, y, z;
typedef NzVector3<unsigned int> NzVector3ui; };
#include <Nazara/Math/Vector3.inl> template<typename T> std::ostream& operator<<(std::ostream& out, const NzVector3<T>& vec);
#endif // NAZARA_VECTOR3_HPP template<typename T> NzVector3<T> operator*(T scale, const NzVector3<T>& vec);
template<typename T> NzVector3<T> operator/(T scale, const NzVector3<T>& vec);
typedef NzVector3<double> NzVector3d;
typedef NzVector3<float> NzVector3f;
typedef NzVector3<int> NzVector3i;
typedef NzVector3<unsigned int> NzVector3ui;
#include <Nazara/Math/Vector3.inl>
#endif // NAZARA_VECTOR3_HPP

File diff suppressed because it is too large Load Diff

View File

@ -1,97 +1,98 @@
// Copyright (C) 2012 Rémi Bèges - Jérôme Leclercq // Copyright (C) 2012 Rémi Bèges - Jérôme Leclercq
// This file is part of the "Nazara Engine - Mathematics module" // This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once #pragma once
#ifndef NAZARA_VECTOR4_HPP #ifndef NAZARA_VECTOR4_HPP
#define NAZARA_VECTOR4_HPP #define NAZARA_VECTOR4_HPP
#include <Nazara/Core/String.hpp> #include <Nazara/Core/String.hpp>
#include <Nazara/Math/Vector3.hpp> #include <Nazara/Math/Vector3.hpp>
template<typename T> class NzVector4 template<typename T> class NzVector4
{ {
public: public:
NzVector4(); NzVector4();
NzVector4(T X, T Y, T Z, T W = 1.0); NzVector4(T X, T Y, T Z, T W = 1.0);
explicit NzVector4(T scale); explicit NzVector4(T scale);
NzVector4(T vec[4]); NzVector4(T vec[4]);
NzVector4(const NzVector3<T>& vec, T W = 1.0); NzVector4(const NzVector3<T>& vec, T W = 1.0);
template<typename U> explicit NzVector4(const NzVector4<U>& vec); template<typename U> explicit NzVector4(const NzVector4<U>& vec);
NzVector4(const NzVector4& vec) = default; NzVector4(const NzVector4& vec) = default;
~NzVector4() = default; ~NzVector4() = default;
T AbsDotProduct(const NzVector4& vec) const; T AbsDotProduct(const NzVector4& vec) const;
T DotProduct(const NzVector4& vec) const; T DotProduct(const NzVector4& vec) const;
void MakeCeil(const NzVector4& vec); void MakeUnitX();
void MakeFloor(const NzVector4& vec); void MakeUnitY();
void MakeUnitX(); void MakeUnitZ();
void MakeUnitY(); void MakeZero();
void MakeUnitZ();
void MakeZero(); void Maximize(const NzVector4& vec);
void Minimize(const NzVector4& vec);
void Normalize();
void Normalize();
void Set(T X, T Y, T Z, T W = 1.0);
void Set(T scale); void Set(T X, T Y, T Z, T W = 1.0);
void Set(T vec[4]); void Set(T scale);
void Set(const NzVector3<T>& vec, T W = 1.0); void Set(T vec[4]);
template<typename U> void Set(const NzVector4<U>& vec); void Set(const NzVector3<T>& vec, T W = 1.0);
template<typename U> void Set(const NzVector4<U>& vec);
NzString ToString() const;
NzString ToString() const;
operator NzString() const;
operator NzString() const;
operator T*();
operator const T*() const; operator T*();
operator const T*() const;
T& operator[](unsigned int i);
T operator[](unsigned int i) const; T& operator[](unsigned int i);
T operator[](unsigned int i) const;
const NzVector4& operator+() const;
NzVector4 operator-() const; const NzVector4& operator+() const;
NzVector4 operator-() const;
NzVector4 operator+(const NzVector4& vec) const;
NzVector4 operator-(const NzVector4& vec) const; NzVector4 operator+(const NzVector4& vec) const;
NzVector4 operator*(const NzVector4& vec) const; NzVector4 operator-(const NzVector4& vec) const;
NzVector4 operator*(T scale) const; NzVector4 operator*(const NzVector4& vec) const;
NzVector4 operator/(const NzVector4& vec) const; NzVector4 operator*(T scale) const;
NzVector4 operator/(T scale) const; NzVector4 operator/(const NzVector4& vec) const;
NzVector4 operator/(T scale) const;
NzVector4& operator+=(const NzVector4& vec);
NzVector4& operator-=(const NzVector4& vec); NzVector4& operator+=(const NzVector4& vec);
NzVector4& operator*=(const NzVector4& vec); NzVector4& operator-=(const NzVector4& vec);
NzVector4& operator*=(T scale); NzVector4& operator*=(const NzVector4& vec);
NzVector4& operator/=(const NzVector4& vec); NzVector4& operator*=(T scale);
NzVector4& operator/=(T scale); NzVector4& operator/=(const NzVector4& vec);
NzVector4& operator/=(T scale);
bool operator==(const NzVector4& vec) const;
bool operator!=(const NzVector4& vec) const; bool operator==(const NzVector4& vec) const;
bool operator<(const NzVector4& vec) const; bool operator!=(const NzVector4& vec) const;
bool operator<=(const NzVector4& vec) const; bool operator<(const NzVector4& vec) const;
bool operator>(const NzVector4& vec) const; bool operator<=(const NzVector4& vec) const;
bool operator>=(const NzVector4& vec) const; bool operator>(const NzVector4& vec) const;
bool operator>=(const NzVector4& vec) const;
static NzVector4 UnitX();
static NzVector4 UnitY(); static NzVector4 UnitX();
static NzVector4 UnitZ(); static NzVector4 UnitY();
static NzVector4 Zero(); static NzVector4 UnitZ();
static NzVector4 Zero();
T x, y, z, w;
}; T x, y, z, w;
};
template<typename T> std::ostream& operator<<(std::ostream& out, const NzVector4<T>& vec);
template<typename T> std::ostream& operator<<(std::ostream& out, const NzVector4<T>& vec);
template<typename T> NzVector4<T> operator*(T scale, const NzVector4<T>& vec);
template<typename T> NzVector4<T> operator/(T scale, const NzVector4<T>& vec); template<typename T> NzVector4<T> operator*(T scale, const NzVector4<T>& vec);
template<typename T> NzVector4<T> operator/(T scale, const NzVector4<T>& vec);
typedef NzVector4<double> NzVector4d;
typedef NzVector4<float> NzVector4f; typedef NzVector4<double> NzVector4d;
typedef NzVector4<int> NzVector4i; typedef NzVector4<float> NzVector4f;
typedef NzVector4<int> NzVector4i;
#include <Nazara/Math/Vector4.inl>
#include <Nazara/Math/Vector4.inl>
#endif // NAZARA_VECTOR4_HPP
#endif // NAZARA_VECTOR4_HPP

File diff suppressed because it is too large Load Diff

View File

@ -1,40 +1,41 @@
// This file was automatically generated by Nazara // This file was automatically generated by Nazara
/* /*
Nazara Engine - Renderer module Nazara Engine - Renderer module
Copyright (C) 2012 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) Copyright (C) 2012 Jérôme "Lynix" Leclercq (Lynix680@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions: so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#pragma once #pragma once
#include <Nazara/Renderer/Config.hpp> #include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/Context.hpp> #include <Nazara/Renderer/Context.hpp>
#include <Nazara/Renderer/ContextParameters.hpp> #include <Nazara/Renderer/ContextParameters.hpp>
#include <Nazara/Renderer/Enums.hpp> #include <Nazara/Renderer/Enums.hpp>
#include <Nazara/Renderer/OcclusionQuery.hpp> #include <Nazara/Renderer/OcclusionQuery.hpp>
#include <Nazara/Renderer/OpenGL.hpp> #include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/Renderer.hpp> #include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/RenderTarget.hpp> #include <Nazara/Renderer/RenderTarget.hpp>
#include <Nazara/Renderer/RenderTargetParameters.hpp> #include <Nazara/Renderer/RenderTargetParameters.hpp>
#include <Nazara/Renderer/RenderWindow.hpp> #include <Nazara/Renderer/RenderTexture.hpp>
#include <Nazara/Renderer/Shader.hpp> #include <Nazara/Renderer/RenderWindow.hpp>
#include <Nazara/Renderer/Texture.hpp> #include <Nazara/Renderer/Shader.hpp>
#include <Nazara/Renderer/Texture.hpp>

View File

@ -1,44 +1,41 @@
/* /*
Nazara Engine - Renderer module Nazara Engine - Renderer module
Copyright (C) 2012 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) Copyright (C) 2012 Jérôme "Lynix" Leclercq (Lynix680@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions: so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#pragma once #pragma once
#ifndef NAZARA_CONFIG_RENDERER_HPP #ifndef NAZARA_CONFIG_RENDERER_HPP
#define NAZARA_CONFIG_RENDERER_HPP #define NAZARA_CONFIG_RENDERER_HPP
/// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci /// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci
// Active une fenêtre de rendu (NzRenderWindow) lors de sa création // Utilise un tracker pour repérer les éventuels leaks (Ralentit l'exécution)
#define NAZARA_RENDERER_ACTIVATE_RENDERWINDOW_ON_CREATION 1 #define NAZARA_RENDERER_MEMORYLEAKTRACKER 0
// Utilise un tracker pour repérer les éventuels leaks (Ralentit l'exécution) // Active le paramère debug des paramètres des contextes par défaut (Perte de performances mais capable de recevoir des messages d'OpenGL)
#define NAZARA_RENDERER_MEMORYLEAKTRACKER 0 #define NAZARA_RENDERER_OPENGL_DEBUG 0
// Active le paramère debug des paramètres des contextes par défaut (Perte de performances mais capable de recevoir des messages d'OpenGL) // Active les tests de sécurité basés sur le code (Conseillé pour le développement)
#define NAZARA_RENDERER_OPENGL_DEBUG 0 #define NAZARA_RENDERER_SAFE 1
// Active les tests de sécurité basés sur le code (Conseillé pour le développement) #endif // NAZARA_CONFIG_MODULENAME_HPP
#define NAZARA_RENDERER_SAFE 1
#endif // NAZARA_CONFIG_MODULENAME_HPP

View File

@ -1,47 +1,49 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module" // This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#ifdef NAZARA_RENDERER_COMMON #pragma once
#error This file is not part of the common renderer interface, you must undefine NAZARA_RENDERER_COMMON to use it
#endif #ifndef NAZARA_CONTEXT_HPP
#define NAZARA_CONTEXT_HPP
#pragma once
#ifdef NAZARA_RENDERER_OPENGL
#ifndef NAZARA_CONTEXT_HPP
#define NAZARA_CONTEXT_HPP #include <Nazara/Core/Resource.hpp>
#include <Nazara/Renderer/ContextParameters.hpp>
#include <Nazara/Renderer/ContextParameters.hpp>
class NzContextImpl;
class NzContextImpl;
class NAZARA_API NzContext : public NzResource
class NAZARA_API NzContext {
{ friend NzContextImpl;
friend NzContextImpl;
public:
public: NzContext();
NzContext(); ~NzContext();
~NzContext();
bool Create(const NzContextParameters& parameters = NzContextParameters());
bool Create(const NzContextParameters& parameters = NzContextParameters()); void Destroy();
void Destroy();
const NzContextParameters& GetParameters() const; const NzContextParameters& GetParameters() const;
bool IsActive() const; bool IsActive() const;
bool SetActive(bool active); bool SetActive(bool active);
void SwapBuffers(); void SwapBuffers();
static bool EnsureContext(); static bool EnsureContext();
static NzContext* GetCurrent(); static NzContext* GetCurrent();
static const NzContext* GetReference(); static const NzContext* GetReference();
static NzContext* GetThreadContext(); static NzContext* GetThreadContext();
static bool Initialize(); static bool Initialize();
static void Uninitialize(); static void Uninitialize();
private: private:
NzContextParameters m_parameters; NzContextParameters m_parameters;
NzContextImpl* m_impl; NzContextImpl* m_impl;
static NzContext* s_reference; static NzContext* s_reference;
}; };
#endif // NAZARA_CONTEXT_HPP #endif // NAZARA_RENDERER_OPENGL
#endif // NAZARA_CONTEXT_HPP

View File

@ -1,141 +1,174 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module" // This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once #pragma once
#ifndef NAZARA_ENUMS_RENDERER_HPP #ifndef NAZARA_ENUMS_RENDERER_HPP
#define NAZARA_ENUMS_RENDERER_HPP #define NAZARA_ENUMS_RENDERER_HPP
enum nzBlendFunc enum nzAttachmentPoint
{ {
nzBlendFunc_DestAlpha, nzAttachmentPoint_Color,
nzBlendFunc_DestColor, nzAttachmentPoint_Depth,
nzBlendFunc_SrcAlpha, nzAttachmentPoint_DepthStencil,
nzBlendFunc_SrcColor, nzAttachmentPoint_Stencil,
nzBlendFunc_InvDestAlpha,
nzBlendFunc_InvDestColor, nzAttachmentPoint_Max = nzAttachmentPoint_Stencil
nzBlendFunc_InvSrcAlpha, };
nzBlendFunc_InvSrcColor,
nzBlendFunc_One, enum nzBlendFunc
nzBlendFunc_Zero {
}; nzBlendFunc_DestAlpha,
nzBlendFunc_DestColor,
enum nzFaceCulling nzBlendFunc_SrcAlpha,
{ nzBlendFunc_SrcColor,
nzFaceCulling_Back, nzBlendFunc_InvDestAlpha,
nzFaceCulling_Front, nzBlendFunc_InvDestColor,
nzFaceCulling_FrontAndBack nzBlendFunc_InvSrcAlpha,
}; nzBlendFunc_InvSrcColor,
nzBlendFunc_One,
enum nzFaceFilling nzBlendFunc_Zero,
{
nzFaceFilling_Point, nzBlendFunc_Max = nzBlendFunc_Zero
nzFaceFilling_Line, };
nzFaceFilling_Fill
}; enum nzFaceCulling
{
enum nzMatrixType nzFaceCulling_Back,
{ nzFaceCulling_Front,
nzMatrixType_Projection, nzFaceCulling_FrontAndBack,
nzMatrixType_View,
nzMatrixType_World, nzFaceCulling_Max = nzFaceCulling_FrontAndBack
};
nzMatrixType_Max = nzMatrixType_World
}; enum nzFaceFilling
{
enum nzPixelBufferType nzFaceFilling_Point,
{ nzFaceFilling_Line,
nzPixelBufferType_Pack, nzFaceFilling_Fill,
nzPixelBufferType_Unpack
}; nzFaceFilling_Max = nzFaceFilling_Fill
};
enum nzRendererCap
{ enum nzMatrixType
nzRendererCap_AnisotropicFilter, {
nzRendererCap_FP64, nzMatrixType_Projection,
nzRendererCap_HardwareBuffer, nzMatrixType_View,
nzRendererCap_MultipleRenderTargets, nzMatrixType_World,
nzRendererCap_OcclusionQuery,
nzRendererCap_PixelBufferObject, nzMatrixType_Max = nzMatrixType_World
nzRendererCap_Texture3D, };
nzRendererCap_TextureCubemap,
nzRendererCap_TextureMulti, enum nzPixelBufferType
nzRendererCap_TextureNPOT, {
nzPixelBufferType_Pack,
nzRendererCap_Max = nzRendererCap_TextureNPOT nzPixelBufferType_Unpack,
};
nzPixelBufferType_Max = nzPixelBufferType_Unpack
enum nzRendererClear };
{
nzRendererClear_Color = 0x01, enum nzRendererCap
nzRendererClear_Depth = 0x02, {
nzRendererClear_Stencil = 0x04 nzRendererCap_AnisotropicFilter,
}; nzRendererCap_FP64,
nzRendererCap_HardwareBuffer,
enum nzRendererComparison nzRendererCap_MultipleRenderTargets,
{ nzRendererCap_OcclusionQuery,
nzRendererComparison_Always, nzRendererCap_PixelBufferObject,
nzRendererComparison_Equal, nzRendererCap_RenderTexture,
nzRendererComparison_Greater, nzRendererCap_Texture3D,
nzRendererComparison_GreaterOrEqual, nzRendererCap_TextureCubemap,
nzRendererComparison_Less, nzRendererCap_TextureMulti,
nzRendererComparison_LessOrEqual, nzRendererCap_TextureNPOT,
nzRendererComparison_Never
}; nzRendererCap_Max = nzRendererCap_TextureNPOT
};
enum nzRendererParameter
{ enum nzRendererClearFlags
nzRendererParameter_Blend, {
nzRendererParameter_ColorWrite, nzRendererClear_Color = 0x01,
nzRendererParameter_DepthTest, nzRendererClear_Depth = 0x02,
nzRendererParameter_DepthWrite, nzRendererClear_Stencil = 0x04
nzRendererParameter_FaceCulling, };
nzRendererParameter_Stencil
}; enum nzRendererComparison
{
enum nzShaderLanguage nzRendererComparison_Always,
{ nzRendererComparison_Equal,
nzShaderLanguage_Unknown, nzRendererComparison_Greater,
nzRendererComparison_GreaterOrEqual,
nzShaderLanguage_Cg, nzRendererComparison_Less,
nzShaderLanguage_GLSL nzRendererComparison_LessOrEqual,
}; nzRendererComparison_Never,
enum nzShaderType nzRendererComparison_Max = nzRendererComparison_Never
{ };
nzShaderType_Fragment,
nzShaderType_Geometry, enum nzRendererParameter
nzShaderType_Vertex, {
nzRendererParameter_Blend,
nzShaderType_Max = nzShaderType_Vertex nzRendererParameter_ColorWrite,
}; nzRendererParameter_DepthTest,
nzRendererParameter_DepthWrite,
enum nzStencilOperation nzRendererParameter_FaceCulling,
{ nzRendererParameter_Stencil,
nzStencilOperation_Decrement,
nzStencilOperation_DecrementToSaturation, nzRendererParameter_Max = nzRendererParameter_Stencil
nzStencilOperation_Increment, };
nzStencilOperation_IncrementToSaturation,
nzStencilOperation_Invert, enum nzShaderLanguage
nzStencilOperation_Keep, {
nzStencilOperation_Replace, nzShaderLanguage_Unknown = -1,
nzStencilOperation_Zero
}; nzShaderLanguage_Cg,
nzShaderLanguage_GLSL,
enum nzTextureFilter
{ nzShaderLanguage_Max = nzShaderLanguage_GLSL
nzTextureFilter_Bilinear, };
nzTextureFilter_Nearest,
nzTextureFilter_Trilinear, enum nzShaderType
nzTextureFilter_Unknown {
}; nzShaderType_Fragment,
nzShaderType_Geometry,
enum nzTextureWrap nzShaderType_Vertex,
{
nzTextureWrap_Clamp, nzShaderType_Max = nzShaderType_Vertex
nzTextureWrap_Repeat, };
nzTextureWrap_Unknown
}; enum nzStencilOperation
{
#endif // NAZARA_ENUMS_RENDERER_HPP nzStencilOperation_Decrement,
nzStencilOperation_DecrementToSaturation,
nzStencilOperation_Increment,
nzStencilOperation_IncrementToSaturation,
nzStencilOperation_Invert,
nzStencilOperation_Keep,
nzStencilOperation_Replace,
nzStencilOperation_Zero,
nzStencilOperation_Max = nzStencilOperation_Zero
};
enum nzTextureFilter
{
nzTextureFilter_Unknown = -1,
nzTextureFilter_Bilinear,
nzTextureFilter_Nearest,
nzTextureFilter_Trilinear,
nzTextureFilter_Max = nzTextureFilter_Trilinear
};
enum nzTextureWrap
{
nzTextureWrap_Unknown = -1,
nzTextureWrap_Clamp,
nzTextureWrap_Repeat,
nzTextureWrap_Max = nzTextureWrap_Repeat
};
#endif // NAZARA_ENUMS_RENDERER_HPP

View File

@ -1,192 +1,233 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module" // This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#ifdef NAZARA_RENDERER_COMMON #pragma once
#error This file is not part of the common renderer interface, you must undefine NAZARA_RENDERER_COMMON to use it
#endif #ifndef NAZARA_OPENGL_HPP
#define NAZARA_OPENGL_HPP
#pragma once
#ifdef NAZARA_RENDERER_OPENGL
#ifndef NAZARA_OPENGL_HPP
#define NAZARA_OPENGL_HPP // gl3.h définit WIN32_LEAN_AND_MEAN qui entre en conflit avec la définition de Nazara et doit donc être inclut en premier
#include <GL3/glcorearb.h>
// gl3.h définit WIN32_LEAN_AND_MEAN qui entre en conflit avec la définition de Nazara et doit donc être inclut en premier #include <Nazara/Prerequesites.hpp>
#include <GL3/glcorearb.h> #include <Nazara/Core/String.hpp>
#include <Nazara/Prerequesites.hpp> #include <Nazara/Utility/Enums.hpp>
#include <Nazara/Core/String.hpp> #include <Nazara/Renderer/Enums.hpp>
// Inclusion des extensions // Inclusion des extensions
#include <GL3/glext.h> #include <GL3/glext.h>
#if defined(NAZARA_PLATFORM_WINDOWS) #if defined(NAZARA_PLATFORM_WINDOWS)
#include <GL3/wglext.h> #include <GL3/wglext.h>
#elif defined(NAZARA_PLATFORM_LINUX) #elif defined(NAZARA_PLATFORM_LINUX)
#include <GL3/glxext.h> #include <GL3/glxext.h>
#endif #endif
using NzOpenGLFunc = void (*)(); enum nzOpenGLExtension
{
class NAZARA_API NzOpenGL nzOpenGLExtension_AnisotropicFilter,
{ nzOpenGLExtension_DebugOutput,
public: nzOpenGLExtension_FP64,
enum Extension nzOpenGLExtension_FrameBufferObject,
{ nzOpenGLExtension_PixelBufferObject,
AnisotropicFilter, nzOpenGLExtension_SeparateShaderObjects,
DebugOutput, nzOpenGLExtension_TextureArray,
FP64, nzOpenGLExtension_TextureCompression_s3tc,
FrameBufferObject, nzOpenGLExtension_TextureStorage,
PixelBufferObject, nzOpenGLExtension_VertexArrayObject,
SeparateShaderObjects,
Texture3D, nzOpenGLExtension_Max = nzOpenGLExtension_VertexArrayObject
TextureArray, };
TextureCompression_s3tc,
TextureStorage, using NzOpenGLFunc = void (*)();
VertexArrayObject,
namespace NzOpenGL
Max = VertexArrayObject {
}; enum FormatType
{
static NzOpenGLFunc GetEntry(const NzString& entryPoint); FormatType_RenderBuffer,
static unsigned int GetVersion(); // FormatType_MultisampleTexture,
static bool Initialize(); FormatType_Texture
static bool IsSupported(Extension extension); };
static bool IsSupported(const NzString& string);
static void Uninitialize(); struct Format
}; {
GLenum dataFormat;
NAZARA_API extern PFNGLACTIVETEXTUREPROC glActiveTexture; GLenum dataType;
NAZARA_API extern PFNGLATTACHSHADERPROC glAttachShader; GLint internalFormat;
NAZARA_API extern PFNGLBEGINQUERYPROC glBeginQuery; };
NAZARA_API extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
NAZARA_API extern PFNGLBINDBUFFERPROC glBindBuffer; NzOpenGLFunc GetEntry(const NzString& entryPoint);
NAZARA_API extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer; unsigned int GetVersion();
NAZARA_API extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer; bool Initialize();
NAZARA_API extern PFNGLBINDTEXTUREPROC glBindTexture; bool IsSupported(nzOpenGLExtension extension);
NAZARA_API extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray; bool IsSupported(const NzString& string);
NAZARA_API extern PFNGLBLENDFUNCPROC glBlendFunc; bool TranslateFormat(nzPixelFormat pixelFormat, Format* format, FormatType target);
NAZARA_API extern PFNGLBUFFERDATAPROC glBufferData; void Uninitialize();
NAZARA_API extern PFNGLBUFFERSUBDATAPROC glBufferSubData;
NAZARA_API extern PFNGLCLEARPROC glClear; extern GLenum Attachment[nzAttachmentPoint_Max+1];
NAZARA_API extern PFNGLCLEARCOLORPROC glClearColor; extern nzUInt8 AttributeIndex[nzElementUsage_Max+1];
NAZARA_API extern PFNGLCLEARDEPTHPROC glClearDepth; extern GLenum BlendFunc[nzBlendFunc_Max+1];
NAZARA_API extern PFNGLCLEARSTENCILPROC glClearStencil; extern GLenum BufferLock[nzBufferAccess_Max+1];
NAZARA_API extern PFNGLCREATEPROGRAMPROC glCreateProgram; extern GLenum BufferLockRange[nzBufferAccess_Max+1];
NAZARA_API extern PFNGLCREATESHADERPROC glCreateShader; extern GLenum BufferTarget[nzBufferType_Max+1];
NAZARA_API extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus; extern GLenum BufferTargetBinding[nzBufferType_Max+1];
NAZARA_API extern PFNGLCOLORMASKPROC glColorMask; extern GLenum BufferUsage[nzBufferUsage_Max+1];
NAZARA_API extern PFNGLCULLFACEPROC glCullFace; extern GLenum CubemapFace[6]; // Un cube possède six faces et ça n'est pas prêt de changer
NAZARA_API extern PFNGLCOMPILESHADERPROC glCompileShader; extern GLenum ElementType[nzElementType_Max+1];
NAZARA_API extern PFNGLCOPYTEXSUBIMAGE2DPROC glCopyTexSubImage2D; extern GLenum FaceCulling[nzFaceCulling_Max+1];
NAZARA_API extern PFNGLDEBUGMESSAGECALLBACKPROC glDebugMessageCallback; extern GLenum FaceFilling[nzFaceFilling_Max+1];
NAZARA_API extern PFNGLDEBUGMESSAGECONTROLPROC glDebugMessageControl; extern GLenum PrimitiveType[nzPrimitiveType_Max+1];
NAZARA_API extern PFNGLDEBUGMESSAGEINSERTPROC glDebugMessageInsert; extern GLenum RendererComparison[nzRendererComparison_Max+1];
NAZARA_API extern PFNGLDELETEBUFFERSPROC glDeleteBuffers; extern GLenum RendererParameter[nzRendererParameter_Max+1];
NAZARA_API extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers; extern GLenum ShaderType[nzShaderType_Max+1];
NAZARA_API extern PFNGLDELETEPROGRAMPROC glDeleteProgram; extern GLenum StencilOperation[nzStencilOperation_Max+1];
NAZARA_API extern PFNGLDELETEQUERIESPROC glDeleteQueries; extern GLenum TextureTarget[nzImageType_Max+1];
NAZARA_API extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers; extern GLenum TextureTargetBinding[nzImageType_Max+1];
NAZARA_API extern PFNGLDELETESHADERPROC glDeleteShader; extern GLenum TextureTargetProxy[nzImageType_Max+1];
NAZARA_API extern PFNGLDELETETEXTURESPROC glDeleteTextures; }
NAZARA_API extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
NAZARA_API extern PFNGLDEPTHFUNCPROC glDepthFunc; NAZARA_API extern PFNGLACTIVETEXTUREPROC glActiveTexture;
NAZARA_API extern PFNGLDEPTHMASKPROC glDepthMask; NAZARA_API extern PFNGLATTACHSHADERPROC glAttachShader;
NAZARA_API extern PFNGLDISABLEPROC glDisable; NAZARA_API extern PFNGLBEGINQUERYPROC glBeginQuery;
NAZARA_API extern PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray; NAZARA_API extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
NAZARA_API extern PFNGLDRAWARRAYSPROC glDrawArrays; NAZARA_API extern PFNGLBINDBUFFERPROC glBindBuffer;
NAZARA_API extern PFNGLDRAWBUFFERPROC glDrawBuffer; NAZARA_API extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
NAZARA_API extern PFNGLDRAWBUFFERSPROC glDrawBuffers; NAZARA_API extern PFNGLBINDFRAGDATALOCATIONPROC glBindFragDataLocation;
NAZARA_API extern PFNGLDRAWELEMENTSPROC glDrawElements; NAZARA_API extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
NAZARA_API extern PFNGLENDQUERYPROC glEndQuery; NAZARA_API extern PFNGLBINDTEXTUREPROC glBindTexture;
NAZARA_API extern PFNGLFLUSHPROC glFlush; NAZARA_API extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
NAZARA_API extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer; NAZARA_API extern PFNGLBLENDFUNCPROC glBlendFunc;
NAZARA_API extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D; NAZARA_API extern PFNGLBUFFERDATAPROC glBufferData;
NAZARA_API extern PFNGLENABLEPROC glEnable; NAZARA_API extern PFNGLBUFFERSUBDATAPROC glBufferSubData;
NAZARA_API extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray; NAZARA_API extern PFNGLCLEARPROC glClear;
NAZARA_API extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap; NAZARA_API extern PFNGLCLEARCOLORPROC glClearColor;
NAZARA_API extern PFNGLGENBUFFERSPROC glGenBuffers; NAZARA_API extern PFNGLCLEARDEPTHPROC glClearDepth;
NAZARA_API extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; NAZARA_API extern PFNGLCLEARSTENCILPROC glClearStencil;
NAZARA_API extern PFNGLGENQUERIESPROC glGenQueries; NAZARA_API extern PFNGLCREATEPROGRAMPROC glCreateProgram;
NAZARA_API extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers; NAZARA_API extern PFNGLCREATESHADERPROC glCreateShader;
NAZARA_API extern PFNGLGENTEXTURESPROC glGenTextures; NAZARA_API extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
NAZARA_API extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; NAZARA_API extern PFNGLCOLORMASKPROC glColorMask;
NAZARA_API extern PFNGLGETBUFFERPARAMETERIVPROC glGetBufferParameteriv; NAZARA_API extern PFNGLCULLFACEPROC glCullFace;
NAZARA_API extern PFNGLGETDEBUGMESSAGELOGPROC glGetDebugMessageLog; NAZARA_API extern PFNGLCOMPILESHADERPROC glCompileShader;
NAZARA_API extern PFNGLGETERRORPROC glGetError; NAZARA_API extern PFNGLCOPYTEXSUBIMAGE2DPROC glCopyTexSubImage2D;
NAZARA_API extern PFNGLGETINTEGERVPROC glGetIntegerv; NAZARA_API extern PFNGLDEBUGMESSAGECALLBACKPROC glDebugMessageCallback;
NAZARA_API extern PFNGLGETPROGRAMIVPROC glGetProgramiv; NAZARA_API extern PFNGLDEBUGMESSAGECONTROLPROC glDebugMessageControl;
NAZARA_API extern PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog; NAZARA_API extern PFNGLDEBUGMESSAGEINSERTPROC glDebugMessageInsert;
NAZARA_API extern PFNGLGETQUERYIVPROC glGetQueryiv; NAZARA_API extern PFNGLDELETEBUFFERSPROC glDeleteBuffers;
NAZARA_API extern PFNGLGETQUERYOBJECTIVPROC glGetQueryObjectiv; NAZARA_API extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
NAZARA_API extern PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectuiv; NAZARA_API extern PFNGLDELETEPROGRAMPROC glDeleteProgram;
NAZARA_API extern PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog; NAZARA_API extern PFNGLDELETEQUERIESPROC glDeleteQueries;
NAZARA_API extern PFNGLGETSHADERIVPROC glGetShaderiv; NAZARA_API extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers;
NAZARA_API extern PFNGLGETSHADERSOURCEPROC glGetShaderSource; NAZARA_API extern PFNGLDELETESHADERPROC glDeleteShader;
NAZARA_API extern PFNGLGETSTRINGPROC glGetString; NAZARA_API extern PFNGLDELETETEXTURESPROC glDeleteTextures;
NAZARA_API extern PFNGLGETSTRINGIPROC glGetStringi; NAZARA_API extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
NAZARA_API extern PFNGLGETTEXIMAGEPROC glGetTexImage; NAZARA_API extern PFNGLDEPTHFUNCPROC glDepthFunc;
NAZARA_API extern PFNGLGETTEXLEVELPARAMETERFVPROC glGetTexLevelParameterfv; NAZARA_API extern PFNGLDEPTHMASKPROC glDepthMask;
NAZARA_API extern PFNGLGETTEXLEVELPARAMETERIVPROC glGetTexLevelParameteriv; NAZARA_API extern PFNGLDISABLEPROC glDisable;
NAZARA_API extern PFNGLGETTEXPARAMETERFVPROC glGetTexParameterfv; NAZARA_API extern PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
NAZARA_API extern PFNGLGETTEXPARAMETERIVPROC glGetTexParameteriv; NAZARA_API extern PFNGLDRAWARRAYSPROC glDrawArrays;
NAZARA_API extern PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation; NAZARA_API extern PFNGLDRAWBUFFERPROC glDrawBuffer;
NAZARA_API extern PFNGLLINKPROGRAMPROC glLinkProgram; NAZARA_API extern PFNGLDRAWBUFFERSPROC glDrawBuffers;
NAZARA_API extern PFNGLMAPBUFFERPROC glMapBuffer; NAZARA_API extern PFNGLDRAWELEMENTSPROC glDrawElements;
NAZARA_API extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange; NAZARA_API extern PFNGLENDQUERYPROC glEndQuery;
NAZARA_API extern PFNGLPIXELSTOREIPROC glPixelStorei; NAZARA_API extern PFNGLFLUSHPROC glFlush;
NAZARA_API extern PFNGLPOLYGONMODEPROC glPolygonMode; NAZARA_API extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
NAZARA_API extern PFNGLPROGRAMUNIFORM1DPROC glProgramUniform1d; NAZARA_API extern PFNGLFRAMEBUFFERTEXTUREPROC glFramebufferTexture;
NAZARA_API extern PFNGLPROGRAMUNIFORM1FPROC glProgramUniform1f; NAZARA_API extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D;
NAZARA_API extern PFNGLPROGRAMUNIFORM1IPROC glProgramUniform1i; NAZARA_API extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
NAZARA_API extern PFNGLPROGRAMUNIFORM2DVPROC glProgramUniform2dv; NAZARA_API extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D;
NAZARA_API extern PFNGLPROGRAMUNIFORM2FVPROC glProgramUniform2fv; NAZARA_API extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
NAZARA_API extern PFNGLPROGRAMUNIFORM3DVPROC glProgramUniform3dv; NAZARA_API extern PFNGLENABLEPROC glEnable;
NAZARA_API extern PFNGLPROGRAMUNIFORM3FVPROC glProgramUniform3fv; NAZARA_API extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
NAZARA_API extern PFNGLPROGRAMUNIFORM4DVPROC glProgramUniform4dv; NAZARA_API extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
NAZARA_API extern PFNGLPROGRAMUNIFORM4FVPROC glProgramUniform4fv; NAZARA_API extern PFNGLGENBUFFERSPROC glGenBuffers;
NAZARA_API extern PFNGLPROGRAMUNIFORMMATRIX4DVPROC glProgramUniformMatrix4dv; NAZARA_API extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
NAZARA_API extern PFNGLPROGRAMUNIFORMMATRIX4FVPROC glProgramUniformMatrix4fv; NAZARA_API extern PFNGLGENQUERIESPROC glGenQueries;
NAZARA_API extern PFNGLREADPIXELSPROC glReadPixels; NAZARA_API extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
NAZARA_API extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage; NAZARA_API extern PFNGLGENTEXTURESPROC glGenTextures;
NAZARA_API extern PFNGLSCISSORPROC glScissor; NAZARA_API extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
NAZARA_API extern PFNGLSHADERSOURCEPROC glShaderSource; NAZARA_API extern PFNGLGETBUFFERPARAMETERIVPROC glGetBufferParameteriv;
NAZARA_API extern PFNGLSTENCILFUNCPROC glStencilFunc; NAZARA_API extern PFNGLGETDEBUGMESSAGELOGPROC glGetDebugMessageLog;
NAZARA_API extern PFNGLSTENCILOPPROC glStencilOp; NAZARA_API extern PFNGLGETERRORPROC glGetError;
NAZARA_API extern PFNGLTEXIMAGE1DPROC glTexImage1D; NAZARA_API extern PFNGLGETINTEGERVPROC glGetIntegerv;
NAZARA_API extern PFNGLTEXIMAGE2DPROC glTexImage2D; NAZARA_API extern PFNGLGETPROGRAMIVPROC glGetProgramiv;
NAZARA_API extern PFNGLTEXIMAGE3DPROC glTexImage3D; NAZARA_API extern PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
NAZARA_API extern PFNGLTEXPARAMETERFPROC glTexParameterf; NAZARA_API extern PFNGLGETQUERYIVPROC glGetQueryiv;
NAZARA_API extern PFNGLTEXPARAMETERIPROC glTexParameteri; NAZARA_API extern PFNGLGETQUERYOBJECTIVPROC glGetQueryObjectiv;
NAZARA_API extern PFNGLTEXSTORAGE1DPROC glTexStorage1D; NAZARA_API extern PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectuiv;
NAZARA_API extern PFNGLTEXSTORAGE2DPROC glTexStorage2D; NAZARA_API extern PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
NAZARA_API extern PFNGLTEXSTORAGE3DPROC glTexStorage3D; NAZARA_API extern PFNGLGETSHADERIVPROC glGetShaderiv;
NAZARA_API extern PFNGLTEXSUBIMAGE1DPROC glTexSubImage1D; NAZARA_API extern PFNGLGETSHADERSOURCEPROC glGetShaderSource;
NAZARA_API extern PFNGLTEXSUBIMAGE2DPROC glTexSubImage2D; NAZARA_API extern PFNGLGETSTRINGPROC glGetString;
NAZARA_API extern PFNGLTEXSUBIMAGE3DPROC glTexSubImage3D; NAZARA_API extern PFNGLGETSTRINGIPROC glGetStringi;
NAZARA_API extern PFNGLUNIFORM1DPROC glUniform1d; NAZARA_API extern PFNGLGETTEXIMAGEPROC glGetTexImage;
NAZARA_API extern PFNGLUNIFORM1FPROC glUniform1f; NAZARA_API extern PFNGLGETTEXLEVELPARAMETERFVPROC glGetTexLevelParameterfv;
NAZARA_API extern PFNGLUNIFORM1IPROC glUniform1i; NAZARA_API extern PFNGLGETTEXLEVELPARAMETERIVPROC glGetTexLevelParameteriv;
NAZARA_API extern PFNGLUNIFORM2DVPROC glUniform2dv; NAZARA_API extern PFNGLGETTEXPARAMETERFVPROC glGetTexParameterfv;
NAZARA_API extern PFNGLUNIFORM2FVPROC glUniform2fv; NAZARA_API extern PFNGLGETTEXPARAMETERIVPROC glGetTexParameteriv;
NAZARA_API extern PFNGLUNIFORM3DVPROC glUniform3dv; NAZARA_API extern PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
NAZARA_API extern PFNGLUNIFORM3FVPROC glUniform3fv; NAZARA_API extern PFNGLLINKPROGRAMPROC glLinkProgram;
NAZARA_API extern PFNGLUNIFORM4DVPROC glUniform4dv; NAZARA_API extern PFNGLMAPBUFFERPROC glMapBuffer;
NAZARA_API extern PFNGLUNIFORM4FVPROC glUniform4fv; NAZARA_API extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
NAZARA_API extern PFNGLUNIFORMMATRIX4DVPROC glUniformMatrix4dv; NAZARA_API extern PFNGLPIXELSTOREIPROC glPixelStorei;
NAZARA_API extern PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv; NAZARA_API extern PFNGLPOLYGONMODEPROC glPolygonMode;
NAZARA_API extern PFNGLUNMAPBUFFERPROC glUnmapBuffer; NAZARA_API extern PFNGLPROGRAMUNIFORM1DPROC glProgramUniform1d;
NAZARA_API extern PFNGLUSEPROGRAMPROC glUseProgram; NAZARA_API extern PFNGLPROGRAMUNIFORM1FPROC glProgramUniform1f;
NAZARA_API extern PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f; NAZARA_API extern PFNGLPROGRAMUNIFORM1IPROC glProgramUniform1i;
NAZARA_API extern PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer; NAZARA_API extern PFNGLPROGRAMUNIFORM2DVPROC glProgramUniform2dv;
NAZARA_API extern PFNGLVIEWPORTPROC glViewport; NAZARA_API extern PFNGLPROGRAMUNIFORM2FVPROC glProgramUniform2fv;
#if defined(NAZARA_PLATFORM_WINDOWS) NAZARA_API extern PFNGLPROGRAMUNIFORM3DVPROC glProgramUniform3dv;
NAZARA_API extern PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormat; NAZARA_API extern PFNGLPROGRAMUNIFORM3FVPROC glProgramUniform3fv;
NAZARA_API extern PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs; NAZARA_API extern PFNGLPROGRAMUNIFORM4DVPROC glProgramUniform4dv;
NAZARA_API extern PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB; NAZARA_API extern PFNGLPROGRAMUNIFORM4FVPROC glProgramUniform4fv;
NAZARA_API extern PFNWGLGETEXTENSIONSSTRINGEXTPROC wglGetExtensionsStringEXT; NAZARA_API extern PFNGLPROGRAMUNIFORMMATRIX4DVPROC glProgramUniformMatrix4dv;
NAZARA_API extern PFNWGLSWAPINTERVALEXTPROC wglSwapInterval; NAZARA_API extern PFNGLPROGRAMUNIFORMMATRIX4FVPROC glProgramUniformMatrix4fv;
#elif defined(NAZARA_PLATFORM_LINUX) NAZARA_API extern PFNGLREADPIXELSPROC glReadPixels;
NAZARA_API extern PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs; NAZARA_API extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
NAZARA_API extern PFNGLXSWAPINTERVALSGIPROC glXSwapInterval; NAZARA_API extern PFNGLSCISSORPROC glScissor;
#endif NAZARA_API extern PFNGLSHADERSOURCEPROC glShaderSource;
NAZARA_API extern PFNGLSTENCILFUNCPROC glStencilFunc;
#endif // NAZARA_OPENGL_HPP NAZARA_API extern PFNGLSTENCILOPPROC glStencilOp;
NAZARA_API extern PFNGLTEXIMAGE1DPROC glTexImage1D;
NAZARA_API extern PFNGLTEXIMAGE2DPROC glTexImage2D;
NAZARA_API extern PFNGLTEXIMAGE3DPROC glTexImage3D;
NAZARA_API extern PFNGLTEXPARAMETERFPROC glTexParameterf;
NAZARA_API extern PFNGLTEXPARAMETERIPROC glTexParameteri;
NAZARA_API extern PFNGLTEXSTORAGE1DPROC glTexStorage1D;
NAZARA_API extern PFNGLTEXSTORAGE2DPROC glTexStorage2D;
NAZARA_API extern PFNGLTEXSTORAGE3DPROC glTexStorage3D;
NAZARA_API extern PFNGLTEXSUBIMAGE1DPROC glTexSubImage1D;
NAZARA_API extern PFNGLTEXSUBIMAGE2DPROC glTexSubImage2D;
NAZARA_API extern PFNGLTEXSUBIMAGE3DPROC glTexSubImage3D;
NAZARA_API extern PFNGLUNIFORM1DPROC glUniform1d;
NAZARA_API extern PFNGLUNIFORM1FPROC glUniform1f;
NAZARA_API extern PFNGLUNIFORM1IPROC glUniform1i;
NAZARA_API extern PFNGLUNIFORM2DVPROC glUniform2dv;
NAZARA_API extern PFNGLUNIFORM2FVPROC glUniform2fv;
NAZARA_API extern PFNGLUNIFORM3DVPROC glUniform3dv;
NAZARA_API extern PFNGLUNIFORM3FVPROC glUniform3fv;
NAZARA_API extern PFNGLUNIFORM4DVPROC glUniform4dv;
NAZARA_API extern PFNGLUNIFORM4FVPROC glUniform4fv;
NAZARA_API extern PFNGLUNIFORMMATRIX4DVPROC glUniformMatrix4dv;
NAZARA_API extern PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
NAZARA_API extern PFNGLUNMAPBUFFERPROC glUnmapBuffer;
NAZARA_API extern PFNGLUSEPROGRAMPROC glUseProgram;
NAZARA_API extern PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f;
NAZARA_API extern PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
NAZARA_API extern PFNGLVIEWPORTPROC glViewport;
#if defined(NAZARA_PLATFORM_WINDOWS)
NAZARA_API extern PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormat;
NAZARA_API extern PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs;
NAZARA_API extern PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;
NAZARA_API extern PFNWGLGETEXTENSIONSSTRINGEXTPROC wglGetExtensionsStringEXT;
NAZARA_API extern PFNWGLSWAPINTERVALEXTPROC wglSwapInterval;
#elif defined(NAZARA_PLATFORM_LINUX)
NAZARA_API extern PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs;
NAZARA_API extern PFNGLXSWAPINTERVALSGIPROC glXSwapInterval;
#endif
#endif // NAZARA_RENDERER_OPENGL
#endif // NAZARA_OPENGL_HPP

View File

@ -1,42 +1,41 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module" // This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once #pragma once
#ifndef NAZARA_RENDERTARGET_HPP #ifndef NAZARA_RENDERTARGET_HPP
#define NAZARA_RENDERTARGET_HPP #define NAZARA_RENDERTARGET_HPP
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Renderer/Config.hpp> #include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/RenderTargetParameters.hpp> #include <Nazara/Renderer/RenderTargetParameters.hpp>
class NzRenderer; class NzRenderer;
class NAZARA_API NzRenderTarget class NAZARA_API NzRenderTarget
{ {
friend class NzRenderer; friend class NzRenderer;
public: public:
NzRenderTarget() = default; NzRenderTarget() = default;
virtual ~NzRenderTarget(); virtual ~NzRenderTarget();
#ifndef NAZARA_RENDERER_COMMON virtual unsigned int GetHeight() const = 0;
virtual bool HasContext() const = 0; virtual NzRenderTargetParameters GetParameters() const = 0;
#endif virtual unsigned int GetWidth() const = 0;
virtual unsigned int GetHeight() const = 0; bool IsActive() const;
virtual NzRenderTargetParameters GetParameters() const = 0; virtual bool IsRenderable() const = 0;
virtual unsigned int GetWidth() const = 0;
bool SetActive(bool active);
bool IsActive() const;
virtual bool IsValid() const = 0; // Fonctions OpenGL
virtual bool HasContext() const = 0;
bool SetActive(bool active);
protected:
protected: virtual bool Activate() = 0;
virtual bool Activate() = 0; virtual void Desactivate();
virtual void Desactivate(); };
};
#endif // NAZARA_RENDERTARGET_HPP
#endif // NAZARA_RENDERTARGET_HPP

View File

@ -0,0 +1,60 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_RENDERTEXTURE_HPP
#define NAZARA_RENDERTEXTURE_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/NonCopyable.hpp>
#include <Nazara/Core/ResourceListener.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/RenderTarget.hpp>
#include <Nazara/Renderer/Texture.hpp>
struct NzRenderTextureImpl;
class NAZARA_API NzRenderTexture : public NzRenderTarget, NzResourceListener, NzNonCopyable
{
public:
NzRenderTexture() = default;
~NzRenderTexture();
bool AttachBuffer(nzAttachmentPoint attachmentPoint, nzUInt8 index, nzPixelFormat format);
bool AttachTexture(nzAttachmentPoint attachmentPoint, nzUInt8 index, NzTexture* texture);
bool AttachTexture(nzAttachmentPoint attachmentPoint, nzUInt8 index, NzTexture* texture, unsigned int z);
bool Create(unsigned int width, unsigned int height, bool lock = false);
void Destroy();
void Detach(nzAttachmentPoint attachmentPoint, nzUInt8 index);
unsigned int GetHeight() const;
NzRenderTargetParameters GetParameters() const;
unsigned int GetWidth() const;
bool IsComplete() const;
bool IsRenderable() const;
bool IsValid() const;
bool Lock() const;
void Unlock() const;
// Fonctions OpenGL
bool HasContext() const;
static bool IsSupported();
protected:
bool Activate() override;
void Desactivate() override;
private:
void OnResourceDestroy(const NzResource* resource, int index) override;
NzRenderTextureImpl* m_impl = nullptr;
};
#endif // NAZARA_RENDERTEXTURE_HPP

View File

@ -1,71 +1,68 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module" // This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
// Interface inspirée de la SFML par Laurent Gomila // Interface inspirée de la SFML par Laurent Gomila
#pragma once #pragma once
#ifndef NAZARA_RENDERWINDOW_HPP #ifndef NAZARA_RENDERWINDOW_HPP
#define NAZARA_RENDERWINDOW_HPP #define NAZARA_RENDERWINDOW_HPP
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Clock.hpp> #include <Nazara/Core/Clock.hpp>
#include <Nazara/Renderer/Config.hpp> #include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/ContextParameters.hpp> #include <Nazara/Renderer/ContextParameters.hpp>
#include <Nazara/Renderer/RenderTarget.hpp> #include <Nazara/Renderer/RenderTarget.hpp>
#include <Nazara/Utility/Window.hpp> #include <Nazara/Utility/Window.hpp>
class NzContext; class NzContext;
class NzImage; class NzImage;
class NzTexture; class NzTexture;
struct NzContextParameters; struct NzContextParameters;
class NAZARA_API NzRenderWindow : public NzRenderTarget, public NzWindow class NAZARA_API NzRenderWindow : public NzRenderTarget, public NzWindow
{ {
public: public:
NzRenderWindow() = default; NzRenderWindow() = default;
NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style = nzWindowStyle_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()); NzRenderWindow(NzWindowHandle handle, const NzContextParameters& parameters = NzContextParameters());
virtual ~NzRenderWindow(); virtual ~NzRenderWindow();
bool CopyToImage(NzImage* image); ///TODO: Const bool CopyToImage(NzImage* image); ///TODO: Const
bool CopyToTexture(NzTexture* texture); ///TODO: Const bool CopyToTexture(NzTexture* texture); ///TODO: Const
bool Create(NzVideoMode mode, const NzString& title, nzUInt32 style = nzWindowStyle_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()); bool Create(NzWindowHandle handle, const NzContextParameters& parameters = NzContextParameters());
void Display(); void Display();
void EnableVerticalSync(bool enabled); void EnableVerticalSync(bool enabled);
#ifndef NAZARA_RENDERER_COMMON unsigned int GetHeight() const;
NzContextParameters GetContextParameters() const; NzRenderTargetParameters GetParameters() const;
#endif unsigned int GetWidth() const;
unsigned int GetHeight() const; bool IsRenderable() const;
NzRenderTargetParameters GetParameters() const; bool IsValid() const;
unsigned int GetWidth() const;
void SetFramerateLimit(unsigned int limit);
#ifndef NAZARA_RENDERER_COMMON
bool HasContext() const; // Fonctions OpenGL
#endif NzContextParameters GetContextParameters() const;
bool HasContext() const;
bool IsValid() const;
protected:
void SetFramerateLimit(unsigned int limit); bool Activate() override;
protected: private:
virtual bool Activate() override; bool OnWindowCreated() override;
void OnWindowDestroy() override;
private:
virtual void OnWindowDestroying() override; NzClock m_clock;
virtual bool OnWindowCreated() override; NzContextParameters m_parameters;
NzContext* m_context = nullptr;
NzClock m_clock; unsigned int m_framerateLimit = 0;
NzContextParameters m_parameters; };
NzContext* m_context = nullptr;
unsigned int m_framerateLimit = 0; #endif // NAZARA_RENDERWINDOW_HPP
};
#endif // NAZARA_RENDERWINDOW_HPP

View File

@ -1,89 +1,92 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module" // This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once #pragma once
#ifndef NAZARA_TEXTURE_HPP #ifndef NAZARA_TEXTURE_HPP
#define NAZARA_TEXTURE_HPP #define NAZARA_TEXTURE_HPP
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/NonCopyable.hpp> #include <Nazara/Core/NonCopyable.hpp>
#include <Nazara/Renderer/Enums.hpp> #include <Nazara/Renderer/Enums.hpp>
#include <Nazara/Utility/Image.hpp> #include <Nazara/Utility/Image.hpp>
#include <Nazara/Utility/PixelFormat.hpp> #include <Nazara/Utility/PixelFormat.hpp>
struct NzTextureImpl; class NzRenderTexture;
struct NzTextureImpl;
class NAZARA_API NzTexture : public NzResource, NzNonCopyable
{ class NAZARA_API NzTexture : public NzResource, NzNonCopyable
friend class NzShader; {
friend NzRenderTexture;
public: friend class NzShader;
NzTexture();
explicit NzTexture(const NzImage& image); public:
~NzTexture(); NzTexture();
explicit NzTexture(const NzImage& image);
#ifndef NAZARA_RENDERER_COMMON ~NzTexture();
bool Bind() const;
#endif bool Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth = 1, nzUInt8 levelCount = 1, bool lock = false);
void Destroy();
bool Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth = 1, nzUInt8 levelCount = 1, bool lock = false);
void Destroy(); bool Download(NzImage* image) const;
bool Download(NzImage* image) const; bool EnableMipmapping(bool enable);
bool EnableMipmapping(bool enable); unsigned int GetAnisotropyLevel() const;
nzUInt8 GetBPP() const;
unsigned int GetAnisotropyLevel() const; unsigned int GetDepth() const;
nzUInt8 GetBPP() const; nzTextureFilter GetFilterMode() const;
unsigned int GetDepth() const; nzPixelFormat GetFormat() const;
nzTextureFilter GetFilterMode() const; unsigned int GetHeight() const;
nzPixelFormat GetFormat() const; nzImageType GetType() const;
unsigned int GetHeight() const; unsigned int GetWidth() const;
nzImageType GetType() const; nzTextureWrap GetWrapMode() const;
unsigned int GetWidth() const;
nzTextureWrap GetWrapMode() const; bool IsCompressed() const;
bool IsCubemap() const;
bool IsCompressed() const; bool IsTarget() const;
bool IsCubemap() const; bool IsValid() const;
bool IsTarget() const;
bool IsValid() const; bool LoadFromFile(const NzString& filePath, const NzImageParams& params = NzImageParams());
bool LoadFromImage(const NzImage& image);
bool LoadFromFile(const NzString& filePath, const NzImageParams& params = NzImageParams()); bool LoadFromMemory(const void* data, std::size_t size, const NzImageParams& params = NzImageParams());
bool LoadFromImage(const NzImage& image); bool LoadFromStream(NzInputStream& stream, const NzImageParams& params = NzImageParams());
bool LoadFromMemory(const void* data, std::size_t size, const NzImageParams& params = NzImageParams());
bool LoadFromStream(NzInputStream& stream, const NzImageParams& params = NzImageParams()); bool Lock();
bool Lock(); bool SetAnisotropyLevel(unsigned int anistropyLevel);
bool SetFilterMode(nzTextureFilter filter);
bool SetAnisotropyLevel(unsigned int anistropyLevel); bool SetMipmapRange(nzUInt8 minLevel, nzUInt8 maxLevel);
bool SetFilterMode(nzTextureFilter filter); bool SetWrapMode(nzTextureWrap wrap);
bool SetMipmapRange(nzUInt8 minLevel, nzUInt8 maxLevel);
bool SetWrapMode(nzTextureWrap wrap); bool Update(const NzImage& image, nzUInt8 level = 0);
bool Update(const NzImage& image, const NzRectui& rect, unsigned int z = 0, nzUInt8 level = 0);
bool Update(const NzImage& image, nzUInt8 level = 0); bool Update(const NzImage& image, const NzCubeui& cube, nzUInt8 level = 0);
bool Update(const NzImage& image, const NzRectui& rect, unsigned int z = 0, nzUInt8 level = 0); bool Update(const nzUInt8* pixels, nzUInt8 level = 0);
bool Update(const NzImage& image, const NzCubeui& cube, nzUInt8 level = 0); bool Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z = 0, nzUInt8 level = 0);
bool Update(const nzUInt8* pixels, nzUInt8 level = 0); bool Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 level = 0);
bool Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z = 0, nzUInt8 level = 0); bool UpdateFace(nzCubemapFace face, const NzImage& image, nzUInt8 level = 0);
bool Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 level = 0); bool UpdateFace(nzCubemapFace face, const NzImage& image, const NzRectui& rect, nzUInt8 level = 0);
bool UpdateFace(nzCubemapFace face, const NzImage& image, nzUInt8 level = 0); bool UpdateFace(nzCubemapFace face, const nzUInt8* pixels, nzUInt8 level = 0);
bool UpdateFace(nzCubemapFace face, const NzImage& image, const NzRectui& rect, nzUInt8 level = 0); bool UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRectui& rect, nzUInt8 level = 0);
bool UpdateFace(nzCubemapFace face, const nzUInt8* pixels, nzUInt8 level = 0);
bool UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRectui& rect, nzUInt8 level = 0); void Unlock();
void Unlock(); // Fonctions OpenGL
unsigned int GetOpenGLID() const;
static unsigned int GetValidSize(unsigned int size); bool Prepare() const;
static bool IsFormatSupported(nzPixelFormat format);
static bool IsMipmappingSupported(); static unsigned int GetValidSize(unsigned int size);
static bool IsTypeSupported(nzImageType type); static bool IsFormatSupported(nzPixelFormat format);
static bool IsMipmappingSupported();
private: static bool IsTypeSupported(nzImageType type);
void SetTarget(bool isTarget);
private:
NzTextureImpl* m_impl; NzRenderTexture* GetRenderTexture() const;
}; void SetRenderTexture(NzRenderTexture* renderTexture);
#endif // NAZARA_TEXTURE_HPP NzTextureImpl* m_impl;
};
#endif // NAZARA_TEXTURE_HPP

View File

@ -1,77 +1,78 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module" // This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once #pragma once
#ifndef NAZARA_ANIMATION_HPP #ifndef NAZARA_ANIMATION_HPP
#define NAZARA_ANIMATION_HPP #define NAZARA_ANIMATION_HPP
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Resource.hpp> #include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceLoader.hpp> #include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/String.hpp> #include <Nazara/Core/String.hpp>
#include <Nazara/Utility/Enums.hpp> #include <Nazara/Utility/Enums.hpp>
struct NzAnimationParams struct NzAnimationParams
{ {
unsigned int endFrame = static_cast<unsigned int>(-1); unsigned int endFrame = static_cast<unsigned int>(-1);
unsigned int startFrame = 0; unsigned int startFrame = 0;
bool IsValid() const; bool IsValid() const;
}; };
struct NzSequence struct NzSequence
{ {
NzString name; NzString name;
unsigned int firstFrame; unsigned int firstFrame;
unsigned int lastFrame; unsigned int lastFrame;
unsigned int framePerSecond; unsigned int framePerSecond;
}; };
class NzAnimation; class NzAnimation;
using NzAnimationLoader = NzResourceLoader<NzAnimation, NzAnimationParams>; using NzAnimationLoader = NzResourceLoader<NzAnimation, NzAnimationParams>;
struct NzAnimationImpl; struct NzAnimationImpl;
class NAZARA_API NzAnimation : public NzResource class NAZARA_API NzAnimation : public NzResource
{ {
friend NzAnimationLoader; friend NzAnimationLoader;
public: public:
NzAnimation() = default; NzAnimation() = default;
~NzAnimation(); ~NzAnimation();
unsigned int AddSequence(const NzSequence& sequence); bool AddSequence(const NzSequence& sequence);
bool Create(nzAnimationType type, unsigned int frameCount); bool Create(nzAnimationType type, unsigned int frameCount);
void Destroy(); void Destroy();
unsigned int GetFrameCount() const; unsigned int GetFrameCount() const;
NzSequence* GetSequence(const NzString& sequenceName); NzSequence* GetSequence(const NzString& sequenceName);
NzSequence* GetSequence(unsigned int index); NzSequence* GetSequence(unsigned int index);
const NzSequence* GetSequence(const NzString& sequenceName) const; const NzSequence* GetSequence(const NzString& sequenceName) const;
const NzSequence* GetSequence(unsigned int index) const; const NzSequence* GetSequence(unsigned int index) const;
unsigned int GetSequenceCount() const; unsigned int GetSequenceCount() const;
nzAnimationType GetType() const; int GetSequenceIndex(const NzString& sequenceName) const;
nzAnimationType GetType() const;
bool HasSequence(const NzString& sequenceName) const;
bool HasSequence(unsigned int index = 0) const; bool HasSequence(const NzString& sequenceName) const;
bool HasSequence(unsigned int index = 0) const;
bool IsValid() 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 LoadFromFile(const NzString& filePath, const NzAnimationParams& params = NzAnimationParams());
bool LoadFromStream(NzInputStream& stream, 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); void RemoveSequence(const NzString& sequenceName);
void RemoveSequence(unsigned int index);
private:
NzAnimationImpl* m_impl = nullptr; private:
NzAnimationImpl* m_impl = nullptr;
static NzAnimationLoader::LoaderList s_loaders;
}; static NzAnimationLoader::LoaderList s_loaders;
};
#endif // NAZARA_ANIMATION_HPP
#endif // NAZARA_ANIMATION_HPP

View File

@ -1,220 +1,250 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module" // This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once #pragma once
#ifndef NAZARA_ENUMS_UTILITY_HPP #ifndef NAZARA_ENUMS_UTILITY_HPP
#define NAZARA_ENUMS_UTILITY_HPP #define NAZARA_ENUMS_UTILITY_HPP
enum nzAnimationType enum nzAnimationType
{ {
nzAnimationType_Keyframe, nzAnimationType_Keyframe,
nzAnimationType_Skeletal, nzAnimationType_Skeletal,
nzAnimationType_Static nzAnimationType_Static,
};
nzAnimationType_Max = nzAnimationType_Static
enum nzBufferAccess };
{
nzBufferAccess_DiscardAndWrite, enum nzBufferAccess
nzBufferAccess_ReadOnly, {
nzBufferAccess_ReadWrite, nzBufferAccess_DiscardAndWrite,
nzBufferAccess_WriteOnly nzBufferAccess_ReadOnly,
}; nzBufferAccess_ReadWrite,
nzBufferAccess_WriteOnly,
enum nzBufferStorage
{ nzBufferAccess_Max = nzBufferAccess_WriteOnly
//nzBufferStorage_Both, };
nzBufferStorage_Hardware,
nzBufferStorage_Software, enum nzBufferStorage
{
nzBufferStorage_Max = nzBufferStorage_Software //nzBufferStorage_Both,
}; nzBufferStorage_Hardware,
nzBufferStorage_Software,
enum nzBufferType
{ nzBufferStorage_Max = nzBufferStorage_Software
nzBufferType_Index, };
nzBufferType_Vertex
}; enum nzBufferType
{
enum nzBufferUsage nzBufferType_Index,
{ nzBufferType_Vertex,
nzBufferUsage_Dynamic,
nzBufferUsage_Static nzBufferType_Max = nzBufferType_Vertex
}; };
enum nzCubemapFace enum nzBufferUsage
{ {
// Cette énumération est prévue pour remplacer l'argument "z" des méthodes de NzImage contenant un cubemap nzBufferUsage_Dynamic,
// L'ordre est X, -X, Y, -Y, Z, -Z nzBufferUsage_Static,
nzCubemapFace_PositiveX = 0,
nzCubemapFace_PositiveY = 2, nzBufferUsage_Max = nzBufferUsage_Static
nzCubemapFace_PositiveZ = 4, };
nzCubemapFace_NegativeX = 1,
nzCubemapFace_NegativeY = 3, enum nzCubemapFace
nzCubemapFace_NegativeZ = 5 {
}; // Cette énumération est prévue pour remplacer l'argument "z" des méthodes de NzImage contenant un cubemap
// L'ordre est X, -X, Y, -Y, Z, -Z
enum nzElementStream nzCubemapFace_PositiveX = 0,
{ nzCubemapFace_PositiveY = 2,
nzElementStream_VertexData, nzCubemapFace_PositiveZ = 4,
nzElementStream_InstancedData, nzCubemapFace_NegativeX = 1,
nzCubemapFace_NegativeY = 3,
nzElementStream_Max = nzElementStream_InstancedData nzCubemapFace_NegativeZ = 5,
};
nzCubemapFace_Max = nzCubemapFace_NegativeZ
enum nzElementType };
{
nzElementType_Color, enum nzElementStream
nzElementType_Double1, {
nzElementType_Double2, nzElementStream_VertexData,
nzElementType_Double3, nzElementStream_InstancedData,
nzElementType_Double4,
nzElementType_Float1, nzElementStream_Max = nzElementStream_InstancedData
nzElementType_Float2, };
nzElementType_Float3,
nzElementType_Float4 enum nzElementType
}; {
nzElementType_Color,
enum nzElementUsage nzElementType_Double1,
{ nzElementType_Double2,
nzElementUsage_Diffuse, nzElementType_Double3,
nzElementUsage_Normal, nzElementType_Double4,
nzElementUsage_Position, nzElementType_Float1,
nzElementUsage_Tangent, nzElementType_Float2,
nzElementUsage_TexCoord, nzElementType_Float3,
nzElementType_Float4,
nzElementUsage_Max = nzElementUsage_TexCoord
}; nzElementType_Max = nzElementType_Float4
};
enum nzEventType
{ enum nzElementUsage
nzEventType_GainedFocus, {
nzEventType_LostFocus, nzElementUsage_Diffuse,
nzEventType_KeyPressed, nzElementUsage_Normal,
nzEventType_KeyReleased, nzElementUsage_Position,
nzEventType_MouseButtonDoubleClicked, nzElementUsage_Tangent,
nzEventType_MouseButtonPressed, nzElementUsage_TexCoord,
nzEventType_MouseButtonReleased,
nzEventType_MouseEntered, nzElementUsage_Max = nzElementUsage_TexCoord
nzEventType_MouseLeft, };
nzEventType_MouseMoved,
nzEventType_MouseWheelMoved, enum nzEventType
nzEventType_Moved, {
nzEventType_Quit, nzEventType_GainedFocus,
nzEventType_Resized, nzEventType_LostFocus,
nzEventType_TextEntered nzEventType_KeyPressed,
}; nzEventType_KeyReleased,
nzEventType_MouseButtonDoubleClicked,
enum nzExtend nzEventType_MouseButtonPressed,
{ nzEventType_MouseButtonReleased,
nzExtend_Finite, nzEventType_MouseEntered,
nzExtend_Infinite, nzEventType_MouseLeft,
nzExtend_Null nzEventType_MouseMoved,
}; nzEventType_MouseWheelMoved,
nzEventType_Moved,
enum nzImageType nzEventType_Quit,
{ nzEventType_Resized,
nzImageType_1D, nzEventType_TextEntered,
nzImageType_1D_Array,
nzImageType_2D, nzEventType_Max = nzEventType_TextEntered
nzImageType_2D_Array, };
nzImageType_3D,
nzImageType_Cubemap, enum nzExtend
{
nzImageType_Max = nzImageType_Cubemap nzExtend_Finite,
}; nzExtend_Infinite,
nzExtend_Null,
enum nzPixelFormat
{ nzExtend_Max = nzExtend_Null
nzPixelFormat_Undefined = -1, };
nzPixelFormat_BGR8, // 3*nzUInt8 enum nzImageType
nzPixelFormat_BGRA8, // 4*nzUInt8 {
nzPixelFormat_DXT1, nzImageType_1D,
nzPixelFormat_DXT3, nzImageType_1D_Array,
nzPixelFormat_DXT5, nzImageType_2D,
nzPixelFormat_L8, // 1*nzUInt8 nzImageType_2D_Array,
nzPixelFormat_LA8, // 2*nzUInt8 nzImageType_3D,
/* nzImageType_Cubemap,
nzPixelFormat_RGB16F,
nzPixelFormat_RGB16I, // 4*nzUInt16 nzImageType_Max = nzImageType_Cubemap
nzPixelFormat_RGB32F, };
nzPixelFormat_RGB32I, // 4*nzUInt32
nzPixelFormat_RGBA16F, enum nzPixelFormat
nzPixelFormat_RGBA16I, // 4*nzUInt16 {
nzPixelFormat_RGBA32F, nzPixelFormat_Undefined = -1,
nzPixelFormat_RGBA32I, // 4*nzUInt32
*/ nzPixelFormat_BGR8, // 3*nzUInt8
nzPixelFormat_RGBA4, // 1*nzUInt16 nzPixelFormat_BGRA8, // 4*nzUInt8
nzPixelFormat_RGB5A1, // 1*nzUInt16 nzPixelFormat_DXT1,
nzPixelFormat_RGB8, // 3*nzUInt8 nzPixelFormat_DXT3,
nzPixelFormat_RGBA8, // 4*nzUInt8 nzPixelFormat_DXT5,
/* nzPixelFormat_L8, // 1*nzUInt8
nzPixelFormat_Depth16, nzPixelFormat_LA8, // 2*nzUInt8
nzPixelFormat_Depth24, /*
nzPixelFormat_Depth24Stencil8, nzPixelFormat_RGB16F,
nzPixelFormat_Depth32, nzPixelFormat_RGB16I, // 4*nzUInt16
nzPixelFormat_Stencil1, nzPixelFormat_RGB32F,
nzPixelFormat_Stencil4, nzPixelFormat_RGB32I, // 4*nzUInt32
nzPixelFormat_Stencil8, nzPixelFormat_RGBA16F,
nzPixelFormat_Stencil16, nzPixelFormat_RGBA16I, // 4*nzUInt16
*/ nzPixelFormat_RGBA32F,
nzPixelFormat_RGBA32I, // 4*nzUInt32
nzPixelFormat_Max = nzPixelFormat_RGBA8 */
}; nzPixelFormat_RGBA4, // 1*nzUInt16
nzPixelFormat_RGB5A1, // 1*nzUInt16
enum nzPixelFlipping nzPixelFormat_RGB8, // 3*nzUInt8
{ nzPixelFormat_RGBA8, // 4*nzUInt8
nzPixelFlipping_Horizontally, nzPixelFormat_Depth16,
nzPixelFlipping_Vertically, nzPixelFormat_Depth24,
nzPixelFormat_Depth24Stencil8,
nzPixelFlipping_Max = nzPixelFlipping_Vertically nzPixelFormat_Depth32,
}; nzPixelFormat_Stencil1,
nzPixelFormat_Stencil4,
enum nzPrimitiveType nzPixelFormat_Stencil8,
{ nzPixelFormat_Stencil16,
nzPrimitiveType_LineList,
nzPrimitiveType_LineStrip, nzPixelFormat_Max = nzPixelFormat_Stencil16
nzPrimitiveType_PointList, };
nzPrimitiveType_TriangleList,
nzPrimitiveType_TriangleStrip, enum nzPixelFormatType
nzPrimitiveType_TriangleFan {
}; nzPixelFormatType_Undefined = -1,
enum nzWindowCursor nzPixelFormatType_Color,
{ nzPixelFormatType_Depth,
nzWindowCursor_None, nzPixelFormatType_DepthStencil,
nzWindowCursor_Default, nzPixelFormatType_Stencil,
nzWindowCursor_Crosshair, nzPixelFormatType_Max = nzPixelFormatType_Stencil
nzWindowCursor_Hand, };
nzWindowCursor_Help,
nzWindowCursor_Move, enum nzPixelFlipping
nzWindowCursor_Pointer, {
nzWindowCursor_Progress, nzPixelFlipping_Horizontally,
nzWindowCursor_ResizeE, nzPixelFlipping_Vertically,
nzWindowCursor_ResizeN,
nzWindowCursor_ResizeNE, nzPixelFlipping_Max = nzPixelFlipping_Vertically
nzWindowCursor_ResizeNW, };
nzWindowCursor_ResizeS,
nzWindowCursor_ResizeSE, enum nzPrimitiveType
nzWindowCursor_ResizeSW, {
nzWindowCursor_ResizeW, nzPrimitiveType_LineList,
nzWindowCursor_Text, nzPrimitiveType_LineStrip,
nzWindowCursor_Wait nzPrimitiveType_PointList,
}; nzPrimitiveType_TriangleList,
nzPrimitiveType_TriangleStrip,
enum nzWindowStyle nzPrimitiveType_TriangleFan,
{
nzWindowStyle_None = 0x0, nzPrimitiveType_Max = nzPrimitiveType_TriangleFan
nzWindowStyle_Fullscreen = 0x1, };
nzWindowStyle_Closable = 0x2, enum nzWindowCursor
nzWindowStyle_Resizable = 0x4, {
nzWindowStyle_Titlebar = 0x4, nzWindowCursor_None,
nzWindowCursor_Default,
nzWindowStyle_Default = nzWindowStyle_Closable | nzWindowStyle_Resizable | nzWindowStyle_Titlebar
}; nzWindowCursor_Crosshair,
nzWindowCursor_Hand,
#endif // NAZARA_ENUMS_UTILITY_HPP 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,
nzWindowCursor_Max = nzWindowCursor_Wait
};
enum nzWindowStyleFlags
{
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

View File

@ -1,93 +1,98 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module" // This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once #pragma once
#ifndef NAZARA_MESH_HPP #ifndef NAZARA_MESH_HPP
#define NAZARA_MESH_HPP #define NAZARA_MESH_HPP
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/InputStream.hpp> #include <Nazara/Core/InputStream.hpp>
#include <Nazara/Core/Resource.hpp> #include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceLoader.hpp> #include <Nazara/Core/ResourceListener.hpp>
#include <Nazara/Core/String.hpp> #include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Utility/Animation.hpp> #include <Nazara/Core/String.hpp>
#include <Nazara/Utility/AxisAlignedBox.hpp> #include <Nazara/Utility/Animation.hpp>
#include <Nazara/Utility/SubMesh.hpp> #include <Nazara/Utility/AxisAlignedBox.hpp>
#include <Nazara/Utility/SubMesh.hpp>
class NzVertexDeclaration;
class NzVertexDeclaration;
struct NzMeshParams
{ struct NzMeshParams
NzAnimationParams animation; {
//const NzVertexDeclaration* declaration = nullptr; NzAnimationParams animation;
nzBufferStorage storage = nzBufferStorage_Hardware; //const NzVertexDeclaration* declaration = nullptr;
bool loadAnimations = true; nzBufferStorage storage = nzBufferStorage_Hardware;
bool loadAnimations = true;
bool IsValid() const;
}; bool IsValid() const;
};
class NzMesh;
class NzMesh;
using NzMeshLoader = NzResourceLoader<NzMesh, NzMeshParams>;
using NzMeshLoader = NzResourceLoader<NzMesh, NzMeshParams>;
struct NzMeshImpl;
struct NzMeshImpl;
class NAZARA_API NzMesh : public NzResource
{ class NAZARA_API NzMesh : public NzResource, NzResourceListener
friend NzMeshLoader; {
friend NzMeshLoader;
public:
NzMesh() = default; public:
~NzMesh(); NzMesh() = default;
~NzMesh();
unsigned int AddSkin(const NzString& skin, bool setDefault = false);
nzUInt8 AddSubMesh(NzSubMesh* subMesh); bool AddSkin(const NzString& skin, bool setDefault = false);
nzUInt8 AddSubMesh(const NzString& identifier, NzSubMesh* subMesh); bool AddSubMesh(NzSubMesh* subMesh);
bool AddSubMesh(const NzString& identifier, NzSubMesh* subMesh);
void Animate(unsigned int frameA, unsigned int frameB, float interpolation);
void Animate(unsigned int frameA, unsigned int frameB, float interpolation);
bool Create(nzAnimationType type);
void Destroy(); bool Create(nzAnimationType type);
void Destroy();
const NzAxisAlignedBox& GetAABB() const;
const NzAnimation* GetAnimation() const; const NzAxisAlignedBox& GetAABB() const;
nzAnimationType GetAnimationType() const; const NzAnimation* GetAnimation() const;
unsigned int GetFrameCount() const; nzAnimationType GetAnimationType() const;
NzString GetSkin(unsigned int index = 0) const; unsigned int GetFrameCount() const;
unsigned int GetSkinCount() const; NzString GetSkin(unsigned int index = 0) const;
NzSubMesh* GetSubMesh(const NzString& identifier); unsigned int GetSkinCount() const;
NzSubMesh* GetSubMesh(nzUInt8 index); NzSubMesh* GetSubMesh(const NzString& identifier);
const NzSubMesh* GetSubMesh(const NzString& identifier) const; NzSubMesh* GetSubMesh(unsigned int index);
const NzSubMesh* GetSubMesh(nzUInt8 index) const; const NzSubMesh* GetSubMesh(const NzString& identifier) const;
nzUInt8 GetSubMeshCount() const; const NzSubMesh* GetSubMesh(unsigned int index) const;
unsigned int GetVertexCount() const; unsigned int GetSubMeshCount() const;
int GetSubMeshIndex(const NzString& identifier) const;
bool HasAnimation() const; unsigned int GetVertexCount() const;
bool HasSkin(unsigned int index = 0) const;
bool HasSubMesh(const NzString& identifier) const; bool HasAnimation() const;
bool HasSubMesh(nzUInt8 index = 0) const; bool HasSkin(unsigned int index = 0) const;
bool HasSubMesh(const NzString& identifier) const;
void InvalidateAABB() const; bool HasSubMesh(unsigned int index = 0) const;
bool IsAnimable() const; void InvalidateAABB() const;
bool IsValid() const;
bool IsAnimable() const;
bool LoadFromFile(const NzString& filePath, const NzMeshParams& params = NzMeshParams()); bool IsValid() const;
bool LoadFromMemory(const void* data, std::size_t size, const NzMeshParams& params = NzMeshParams());
bool LoadFromStream(NzInputStream& stream, const NzMeshParams& params = NzMeshParams()); bool LoadFromFile(const NzString& filePath, const NzMeshParams& params = NzMeshParams());
bool LoadFromMemory(const void* data, std::size_t size, const NzMeshParams& params = NzMeshParams());
void RemoveSkin(unsigned int index = 0); bool LoadFromStream(NzInputStream& stream, const NzMeshParams& params = NzMeshParams());
void RemoveSubMesh(const NzString& identifier);
void RemoveSubMesh(nzUInt8 index = 0); void RemoveSkin(unsigned int index = 0);
void RemoveSubMesh(const NzString& identifier);
bool SetAnimation(const NzAnimation* animation); void RemoveSubMesh(unsigned int index = 0);
private: bool SetAnimation(const NzAnimation* animation);
NzMeshImpl* m_impl = nullptr;
private:
static NzMeshLoader::LoaderList s_loaders; void OnResourceCreated(const NzResource* resource, int index) override;
}; void OnResourceReleased(const NzResource* resource, int index) override;
#endif // NAZARA_MESH_HPP NzMeshImpl* m_impl = nullptr;
static NzMeshLoader::LoaderList s_loaders;
};
#endif // NAZARA_MESH_HPP

View File

@ -1,53 +1,54 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module" // This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once #pragma once
#ifndef NAZARA_PIXELFORMAT_HPP #ifndef NAZARA_PIXELFORMAT_HPP
#define NAZARA_PIXELFORMAT_HPP #define NAZARA_PIXELFORMAT_HPP
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/String.hpp> #include <Nazara/Core/String.hpp>
#include <Nazara/Utility/Enums.hpp> #include <Nazara/Utility/Enums.hpp>
#include <map> #include <map>
class NzUtility; class NzUtility;
class NzPixelFormat class NzPixelFormat
{ {
friend class NzUtility; friend class NzUtility;
public: public:
using ConvertFunction = nzUInt8* (*)(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst); using ConvertFunction = nzUInt8* (*)(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst);
using FlipFunction = void (*)(unsigned int width, unsigned int height, unsigned int depth, const nzUInt8* src, nzUInt8* dst); using FlipFunction = void (*)(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* src, void* dst);
static bool Convert(nzPixelFormat srcFormat, nzPixelFormat dstFormat, const void* start, const void* end, 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 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 nzUInt8 GetBPP(nzPixelFormat format);
static nzPixelFormatType GetType(nzPixelFormat format);
static bool HasAlpha(nzPixelFormat format);
static bool HasAlpha(nzPixelFormat format);
static bool IsCompressed(nzPixelFormat format);
static bool IsConversionSupported(nzPixelFormat srcFormat, nzPixelFormat dstFormat); static bool IsCompressed(nzPixelFormat format);
static bool IsValid(nzPixelFormat format); static bool IsConversionSupported(nzPixelFormat srcFormat, nzPixelFormat dstFormat);
static bool IsValid(nzPixelFormat format);
static void SetConvertFunction(nzPixelFormat srcFormat, nzPixelFormat dstFormat, ConvertFunction func);
static void SetFlipFunction(nzPixelFlipping flipping, nzPixelFormat format, FlipFunction func); static void SetConvertFunction(nzPixelFormat srcFormat, nzPixelFormat dstFormat, ConvertFunction func);
static void SetFlipFunction(nzPixelFlipping flipping, nzPixelFormat format, FlipFunction func);
static NzString ToString(nzPixelFormat format);
static NzString ToString(nzPixelFormat format);
private:
static bool Initialize(); private:
static void Uninitialize(); static bool Initialize();
static void Uninitialize();
static NAZARA_API ConvertFunction s_convertFunctions[nzPixelFormat_Max+1][nzPixelFormat_Max+1];
static NAZARA_API std::map<nzPixelFormat, FlipFunction> s_flipFunctions[nzPixelFlipping_Max+1]; static NAZARA_API ConvertFunction s_convertFunctions[nzPixelFormat_Max+1][nzPixelFormat_Max+1];
}; static NAZARA_API std::map<nzPixelFormat, FlipFunction> s_flipFunctions[nzPixelFlipping_Max+1];
};
#include <Nazara/Utility/PixelFormat.inl>
#include <Nazara/Utility/PixelFormat.inl>
#endif // NAZARA_PIXELFORMAT_HPP
#endif // NAZARA_PIXELFORMAT_HPP

View File

@ -1,371 +1,487 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module" // This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <cstring> #include <cstring>
#include <Nazara/Utility/Debug.hpp> #include <Nazara/Utility/Debug.hpp>
inline bool NzPixelFormat::Convert(nzPixelFormat srcFormat, nzPixelFormat dstFormat, const void* src, void* dst) inline bool NzPixelFormat::Convert(nzPixelFormat srcFormat, nzPixelFormat dstFormat, const void* src, void* dst)
{ {
if (srcFormat == dstFormat) if (srcFormat == dstFormat)
{ {
std::memcpy(dst, src, GetBPP(srcFormat)); std::memcpy(dst, src, GetBPP(srcFormat));
return true; return true;
} }
#if NAZARA_UTILITY_SAFE #if NAZARA_UTILITY_SAFE
if (IsCompressed(srcFormat)) if (IsCompressed(srcFormat))
{ {
NazaraError("Cannot convert single pixel from compressed format"); NazaraError("Cannot convert single pixel from compressed format");
return false; return false;
} }
if (IsCompressed(dstFormat)) if (IsCompressed(dstFormat))
{ {
NazaraError("Cannot convert single pixel to compressed format"); NazaraError("Cannot convert single pixel to compressed format");
return false; return false;
} }
#endif #endif
ConvertFunction func = s_convertFunctions[srcFormat][dstFormat]; ConvertFunction func = s_convertFunctions[srcFormat][dstFormat];
if (!func) if (!func)
{ {
NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " is not supported"); NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " is not supported");
return false; return false;
} }
if (!func(reinterpret_cast<const nzUInt8*>(src), reinterpret_cast<const nzUInt8*>(src) + GetBPP(srcFormat), reinterpret_cast<nzUInt8*>(dst))) if (!func(reinterpret_cast<const nzUInt8*>(src), reinterpret_cast<const nzUInt8*>(src) + GetBPP(srcFormat), reinterpret_cast<nzUInt8*>(dst)))
{ {
NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " failed"); NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " failed");
return false; return false;
} }
return true; return true;
} }
inline bool NzPixelFormat::Convert(nzPixelFormat srcFormat, nzPixelFormat dstFormat, const void* start, const void* end, void* dst) inline bool NzPixelFormat::Convert(nzPixelFormat srcFormat, nzPixelFormat dstFormat, const void* start, const void* end, void* dst)
{ {
if (srcFormat == dstFormat) if (srcFormat == dstFormat)
{ {
std::memcpy(dst, start, reinterpret_cast<const nzUInt8*>(end)-reinterpret_cast<const nzUInt8*>(start)); std::memcpy(dst, start, reinterpret_cast<const nzUInt8*>(end)-reinterpret_cast<const nzUInt8*>(start));
return true; return true;
} }
ConvertFunction func = s_convertFunctions[srcFormat][dstFormat]; ConvertFunction func = s_convertFunctions[srcFormat][dstFormat];
if (!func) if (!func)
{ {
NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " is not supported"); NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " is not supported");
return false; return false;
} }
if (!func(reinterpret_cast<const nzUInt8*>(start), reinterpret_cast<const nzUInt8*>(end), reinterpret_cast<nzUInt8*>(dst))) if (!func(reinterpret_cast<const nzUInt8*>(start), reinterpret_cast<const nzUInt8*>(end), reinterpret_cast<nzUInt8*>(dst)))
{ {
NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " failed"); NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " failed");
return false; return false;
} }
return true; return true;
} }
inline bool NzPixelFormat::Flip(nzPixelFlipping flipping, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, const void* src, void* dst) 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 NAZARA_UTILITY_SAFE
if (!IsValid(format)) if (!IsValid(format))
{ {
NazaraError("Invalid pixel format"); NazaraError("Invalid pixel format");
return false; return false;
} }
#endif #endif
auto it = s_flipFunctions[flipping].find(format); auto it = s_flipFunctions[flipping].find(format);
if (it != s_flipFunctions[flipping].end()) if (it != s_flipFunctions[flipping].end())
it->second(width, height, depth, reinterpret_cast<const nzUInt8*>(src), reinterpret_cast<nzUInt8*>(dst)); it->second(width, height, depth, reinterpret_cast<const nzUInt8*>(src), reinterpret_cast<nzUInt8*>(dst));
else else
{ {
// Flipping générique // Flipping générique
#if NAZARA_UTILITY_SAFE #if NAZARA_UTILITY_SAFE
if (IsCompressed(format)) if (IsCompressed(format))
{ {
NazaraError("No function to flip compressed format"); NazaraError("No function to flip compressed format");
return false; return false;
} }
#endif #endif
nzUInt8 bpp = GetBPP(format); nzUInt8 bpp = GetBPP(format);
unsigned int lineStride = width*bpp; unsigned int lineStride = width*bpp;
switch (flipping) switch (flipping)
{ {
case nzPixelFlipping_Horizontally: case nzPixelFlipping_Horizontally:
{ {
if (src == dst) if (src == dst)
{ {
for (unsigned int z = 0; z < depth; ++z) for (unsigned int z = 0; z < depth; ++z)
{ {
nzUInt8* ptr = reinterpret_cast<nzUInt8*>(dst) + width*height*z; nzUInt8* ptr = reinterpret_cast<nzUInt8*>(dst) + width*height*z;
for (unsigned int y = 0; y < height; ++y) for (unsigned int y = 0; y < height; ++y)
{ {
for (unsigned int x = 0; x < width/2; ++x) for (unsigned int x = 0; x < width/2; ++x)
std::swap_ranges(&ptr[x*bpp], &ptr[(x+1)*bpp], &ptr[(width-x)*bpp]); std::swap_ranges(&ptr[x*bpp], &ptr[(x+1)*bpp], &ptr[(width-x)*bpp]);
ptr += lineStride; ptr += lineStride;
} }
} }
} }
else else
{ {
for (unsigned int z = 0; z < depth; ++z) for (unsigned int z = 0; z < depth; ++z)
{ {
nzUInt8* ptr = reinterpret_cast<nzUInt8*>(dst) + width*height*z; nzUInt8* ptr = reinterpret_cast<nzUInt8*>(dst) + width*height*z;
for (unsigned int y = 0; y < height; ++y) for (unsigned int y = 0; y < height; ++y)
{ {
for (unsigned int x = 0; x < width; ++x) for (unsigned int x = 0; x < width; ++x)
std::memcpy(&ptr[x*bpp], &ptr[(width-x)*bpp], bpp); std::memcpy(&ptr[x*bpp], &ptr[(width-x)*bpp], bpp);
ptr += lineStride; ptr += lineStride;
} }
} }
} }
break; break;
} }
case nzPixelFlipping_Vertically: case nzPixelFlipping_Vertically:
{ {
if (src == dst) if (src == dst)
{ {
for (unsigned int z = 0; z < depth; ++z) for (unsigned int z = 0; z < depth; ++z)
{ {
nzUInt8* ptr = reinterpret_cast<nzUInt8*>(dst) + width*height*z; nzUInt8* ptr = reinterpret_cast<nzUInt8*>(dst) + width*height*z;
for (unsigned int y = 0; y < height/2; ++y) 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]); std::swap_ranges(&ptr[y*lineStride], &ptr[(y+1)*lineStride-1], &ptr[(height-y-1)*lineStride]);
} }
} }
else else
{ {
for (unsigned int z = 0; z < depth; ++z) for (unsigned int z = 0; z < depth; ++z)
{ {
const nzUInt8* srcPtr = reinterpret_cast<const nzUInt8*>(src); const nzUInt8* srcPtr = reinterpret_cast<const nzUInt8*>(src);
nzUInt8* dstPtr = reinterpret_cast<nzUInt8*>(dst) + (width-1)*height*depth*bpp; nzUInt8* dstPtr = reinterpret_cast<nzUInt8*>(dst) + (width-1)*height*depth*bpp;
for (unsigned int y = 0; y < height; ++y) for (unsigned int y = 0; y < height; ++y)
{ {
std::memcpy(dstPtr, srcPtr, lineStride); std::memcpy(dstPtr, srcPtr, lineStride);
srcPtr += lineStride; srcPtr += lineStride;
dstPtr -= lineStride; dstPtr -= lineStride;
} }
} }
} }
break; break;
} }
} }
} }
return true; return true;
} }
inline nzUInt8 NzPixelFormat::GetBPP(nzPixelFormat format) inline nzUInt8 NzPixelFormat::GetBPP(nzPixelFormat format)
{ {
switch (format) switch (format)
{ {
case nzPixelFormat_BGR8: case nzPixelFormat_BGR8:
return 3; return 3;
case nzPixelFormat_BGRA8: case nzPixelFormat_BGRA8:
return 4; return 4;
case nzPixelFormat_DXT1: case nzPixelFormat_DXT1:
return 1; return 1;
case nzPixelFormat_DXT3: case nzPixelFormat_DXT3:
return 2; return 2;
case nzPixelFormat_DXT5: case nzPixelFormat_DXT5:
return 2; return 2;
case nzPixelFormat_L8: case nzPixelFormat_L8:
return 1; return 1;
case nzPixelFormat_LA8: case nzPixelFormat_LA8:
return 2; return 2;
/* /*
case nzPixelFormat_RGB16F: case nzPixelFormat_RGB16F:
return 6; return 6;
case nzPixelFormat_RGB16I: case nzPixelFormat_RGB16I:
return 6; return 6;
case nzPixelFormat_RGB32F: case nzPixelFormat_RGB32F:
return 12; return 12;
case nzPixelFormat_RGB32I: case nzPixelFormat_RGB32I:
return 12; return 12;
case nzPixelFormat_RGBA16F: case nzPixelFormat_RGBA16F:
return 8; return 8;
case nzPixelFormat_RGBA16I: case nzPixelFormat_RGBA16I:
return 8; return 8;
case nzPixelFormat_RGBA32F: case nzPixelFormat_RGBA32F:
return 16; return 16;
case nzPixelFormat_RGBA32I: case nzPixelFormat_RGBA32I:
return 16; return 16;
*/ */
case nzPixelFormat_RGBA4: case nzPixelFormat_RGBA4:
return 2; return 2;
case nzPixelFormat_RGB5A1: case nzPixelFormat_RGB5A1:
return 2; return 2;
case nzPixelFormat_RGB8: case nzPixelFormat_RGB8:
return 3; return 3;
case nzPixelFormat_RGBA8: case nzPixelFormat_RGBA8:
return 4; return 4;
case nzPixelFormat_Undefined: case nzPixelFormat_Depth16:
NazaraError("Invalid pixel format"); return 2;
return 0;
} case nzPixelFormat_Depth24:
return 3;
NazaraInternalError("Invalid pixel format");
case nzPixelFormat_Depth24Stencil8:
return 0; return 4;
}
case nzPixelFormat_Depth32:
inline bool NzPixelFormat::HasAlpha(nzPixelFormat format) return 4;
{
switch (format) case nzPixelFormat_Stencil1:
{ NazaraWarning("This format uses less than one byte per pixel");
case nzPixelFormat_BGRA8: return 0;
case nzPixelFormat_DXT3:
case nzPixelFormat_DXT5: case nzPixelFormat_Stencil4:
case nzPixelFormat_LA8: NazaraWarning("This format uses less than one byte per pixel");
case nzPixelFormat_RGB5A1: return 0;
case nzPixelFormat_RGBA4:
case nzPixelFormat_RGBA8: case nzPixelFormat_Stencil8:
return true; return 1;
case nzPixelFormat_BGR8: case nzPixelFormat_Stencil16:
case nzPixelFormat_DXT1: return 2;
case nzPixelFormat_L8:
case nzPixelFormat_RGB8: case nzPixelFormat_Undefined:
return false; break;
}
case nzPixelFormat_Undefined:
break; NazaraError("Invalid pixel format");
} return 0;
}
NazaraError("Invalid pixel format");
return false; inline nzPixelFormatType NzPixelFormat::GetType(nzPixelFormat format)
} {
switch (format)
inline bool NzPixelFormat::IsCompressed(nzPixelFormat format) {
{ case nzPixelFormat_BGR8:
switch (format) case nzPixelFormat_BGRA8:
{ case nzPixelFormat_DXT1:
case nzPixelFormat_DXT1: case nzPixelFormat_DXT3:
case nzPixelFormat_DXT3: case nzPixelFormat_DXT5:
case nzPixelFormat_DXT5: case nzPixelFormat_L8:
return true; case nzPixelFormat_LA8:
case nzPixelFormat_RGB5A1:
default: case nzPixelFormat_RGB8:
return false; case nzPixelFormat_RGBA4:
} case nzPixelFormat_RGBA8:
} return nzPixelFormatType_Color;
inline bool NzPixelFormat::IsConversionSupported(nzPixelFormat srcFormat, nzPixelFormat dstFormat) case nzPixelFormat_Depth16:
{ case nzPixelFormat_Depth24:
if (srcFormat == dstFormat) case nzPixelFormat_Depth32:
return true; return nzPixelFormatType_Depth;
return s_convertFunctions[srcFormat][dstFormat] != nullptr; case nzPixelFormat_Depth24Stencil8:
} return nzPixelFormatType_DepthStencil;
inline bool NzPixelFormat::IsValid(nzPixelFormat format) case nzPixelFormat_Stencil1:
{ case nzPixelFormat_Stencil4:
return format != nzPixelFormat_Undefined; case nzPixelFormat_Stencil8:
} case nzPixelFormat_Stencil16:
return nzPixelFormatType_Stencil;
inline void NzPixelFormat::SetConvertFunction(nzPixelFormat srcFormat, nzPixelFormat dstFormat, ConvertFunction func)
{ case nzPixelFormat_Undefined:
s_convertFunctions[srcFormat][dstFormat] = func; break;
} }
inline void NzPixelFormat::SetFlipFunction(nzPixelFlipping flipping, nzPixelFormat format, FlipFunction func) NazaraError("Invalid pixel format");
{ return nzPixelFormatType_Undefined;
s_flipFunctions[flipping][format] = func; }
}
inline bool NzPixelFormat::HasAlpha(nzPixelFormat format)
inline NzString NzPixelFormat::ToString(nzPixelFormat format) {
{ switch (format)
switch (format) {
{ case nzPixelFormat_BGRA8:
case nzPixelFormat_BGR8: case nzPixelFormat_DXT3:
return "BGR8"; case nzPixelFormat_DXT5:
case nzPixelFormat_LA8:
case nzPixelFormat_BGRA8: case nzPixelFormat_RGB5A1:
return "BGRA8"; case nzPixelFormat_RGBA4:
case nzPixelFormat_RGBA8:
case nzPixelFormat_DXT1: return true;
return "DXT1";
case nzPixelFormat_BGR8:
case nzPixelFormat_DXT3: case nzPixelFormat_DXT1:
return "DXT3"; case nzPixelFormat_L8:
case nzPixelFormat_RGB8:
case nzPixelFormat_DXT5: case nzPixelFormat_Depth16:
return "DXT5"; case nzPixelFormat_Depth24:
case nzPixelFormat_Depth24Stencil8:
case nzPixelFormat_L8: case nzPixelFormat_Depth32:
return "L8"; case nzPixelFormat_Stencil1:
case nzPixelFormat_Stencil4:
case nzPixelFormat_LA8: case nzPixelFormat_Stencil8:
return "LA8"; case nzPixelFormat_Stencil16:
/* return false;
case nzPixelFormat_RGB16F:
return "RGB16F"; case nzPixelFormat_Undefined:
break;
case nzPixelFormat_RGB16I: }
return "RGB16I";
NazaraError("Invalid pixel format");
case nzPixelFormat_RGB32F: return false;
return "RGB32F"; }
case nzPixelFormat_RGB32I: inline bool NzPixelFormat::IsCompressed(nzPixelFormat format)
return "RGB32I"; {
switch (format)
case nzPixelFormat_RGBA16F: {
return "RGBA16F"; case nzPixelFormat_DXT1:
case nzPixelFormat_DXT3:
case nzPixelFormat_RGBA16I: case nzPixelFormat_DXT5:
return "RGBA16I"; return true;
case nzPixelFormat_RGBA32F: case nzPixelFormat_BGRA8:
return "RGBA32F"; case nzPixelFormat_LA8:
case nzPixelFormat_RGB5A1:
case nzPixelFormat_RGBA32I: case nzPixelFormat_RGBA4:
return "RGBA32I"; case nzPixelFormat_RGBA8:
*/ case nzPixelFormat_BGR8:
case nzPixelFormat_RGBA4: case nzPixelFormat_L8:
return "RGBA4"; case nzPixelFormat_RGB8:
case nzPixelFormat_Depth16:
case nzPixelFormat_RGB5A1: case nzPixelFormat_Depth24:
return "RGB5A1"; case nzPixelFormat_Depth24Stencil8:
case nzPixelFormat_Depth32:
case nzPixelFormat_RGB8: case nzPixelFormat_Stencil1:
return "RGB8"; case nzPixelFormat_Stencil4:
case nzPixelFormat_Stencil8:
case nzPixelFormat_RGBA8: case nzPixelFormat_Stencil16:
return "RGBA8"; return false;
case nzPixelFormat_Undefined: case nzPixelFormat_Undefined:
return "Undefined"; break;
} }
NazaraError("Invalid pixel format"); NazaraError("Invalid pixel format");
return "Invalid format"; return false;
} }
#include <Nazara/Utility/DebugOff.hpp> inline bool NzPixelFormat::IsConversionSupported(nzPixelFormat srcFormat, nzPixelFormat dstFormat)
{
if (srcFormat == dstFormat)
return true;
return s_convertFunctions[srcFormat][dstFormat] != nullptr;
}
inline bool NzPixelFormat::IsValid(nzPixelFormat format)
{
return format != nzPixelFormat_Undefined;
}
inline void NzPixelFormat::SetConvertFunction(nzPixelFormat srcFormat, nzPixelFormat dstFormat, ConvertFunction func)
{
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)
{
case nzPixelFormat_BGR8:
return "BGR8";
case nzPixelFormat_BGRA8:
return "BGRA8";
case nzPixelFormat_DXT1:
return "DXT1";
case nzPixelFormat_DXT3:
return "DXT3";
case nzPixelFormat_DXT5:
return "DXT5";
case nzPixelFormat_L8:
return "L8";
case nzPixelFormat_LA8:
return "LA8";
/*
case nzPixelFormat_RGB16F:
return "RGB16F";
case nzPixelFormat_RGB16I:
return "RGB16I";
case nzPixelFormat_RGB32F:
return "RGB32F";
case nzPixelFormat_RGB32I:
return "RGB32I";
case nzPixelFormat_RGBA16F:
return "RGBA16F";
case nzPixelFormat_RGBA16I:
return "RGBA16I";
case nzPixelFormat_RGBA32F:
return "RGBA32F";
case nzPixelFormat_RGBA32I:
return "RGBA32I";
*/
case nzPixelFormat_RGBA4:
return "RGBA4";
case nzPixelFormat_RGB5A1:
return "RGB5A1";
case nzPixelFormat_RGB8:
return "RGB8";
case nzPixelFormat_RGBA8:
return "RGBA8";
case nzPixelFormat_Depth16:
return "Depth16";
case nzPixelFormat_Depth24:
return "Depth24";
case nzPixelFormat_Depth24Stencil8:
return "Depth24Stencil8";
case nzPixelFormat_Depth32:
return "Depth32";
case nzPixelFormat_Stencil1:
return "Stencil1";
case nzPixelFormat_Stencil4:
return "Stencil4";
case nzPixelFormat_Stencil8:
return "Stencil8";
case nzPixelFormat_Stencil16:
return "Stencil16";
case nzPixelFormat_Undefined:
return "Undefined";
}
NazaraError("Invalid pixel format");
return "Invalid format";
}
#include <Nazara/Utility/DebugOff.hpp>

View File

@ -1,49 +1,51 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module" // This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once #pragma once
#ifndef NAZARA_STATICMESH_HPP #ifndef NAZARA_STATICMESH_HPP
#define NAZARA_STATICMESH_HPP #define NAZARA_STATICMESH_HPP
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Utility/SubMesh.hpp> #include <Nazara/Core/ResourceListener.hpp>
#include <Nazara/Utility/SubMesh.hpp>
class NAZARA_API NzStaticMesh final : public NzSubMesh
{ class NAZARA_API NzStaticMesh final : public NzSubMesh, NzResourceListener
public: {
NzStaticMesh(const NzMesh* parent); public:
NzStaticMesh(const NzMesh* parent, const NzVertexDeclaration* vertexDeclaration, NzVertexBuffer* vertexBuffer, NzIndexBuffer* indexBuffer = nullptr); NzStaticMesh(const NzMesh* parent);
virtual ~NzStaticMesh(); NzStaticMesh(const NzMesh* parent, const NzVertexDeclaration* vertexDeclaration, NzVertexBuffer* vertexBuffer, NzIndexBuffer* indexBuffer = nullptr);
virtual ~NzStaticMesh();
bool Create(const NzVertexDeclaration* vertexDeclaration, NzVertexBuffer* vertexBuffer, NzIndexBuffer* indexBuffer = nullptr);
void Destroy(); bool Create(const NzVertexDeclaration* vertexDeclaration, NzVertexBuffer* vertexBuffer, NzIndexBuffer* indexBuffer = nullptr);
void Destroy();
bool GenerateAABB();
bool GenerateAABB();
const NzAxisAlignedBox& GetAABB() const;
nzAnimationType GetAnimationType() const; const NzAxisAlignedBox& GetAABB() const;
unsigned int GetFrameCount() const; nzAnimationType GetAnimationType() const;
const NzIndexBuffer* GetIndexBuffer() const; unsigned int GetFrameCount() const;
nzPrimitiveType GetPrimitiveType() const; const NzIndexBuffer* GetIndexBuffer() const;
const NzVertexBuffer* GetVertexBuffer() const; nzPrimitiveType GetPrimitiveType() const;
const NzVertexDeclaration* GetVertexDeclaration() const; const NzVertexBuffer* GetVertexBuffer() const;
const NzVertexDeclaration* GetVertexDeclaration() const;
bool IsAnimated() const;
bool IsValid() const; bool IsAnimated() const;
bool IsValid() const;
void SetAABB(const NzAxisAlignedBox& aabb);
void SetPrimitiveType(nzPrimitiveType primitiveType); void SetAABB(const NzAxisAlignedBox& aabb);
void SetPrimitiveType(nzPrimitiveType primitiveType);
private:
void AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation); private:
void AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation);
nzPrimitiveType m_primitiveType = nzPrimitiveType_TriangleList; void OnResourceReleased(const NzResource* resource, int index) override;
NzAxisAlignedBox m_aabb;
NzIndexBuffer* m_indexBuffer = nullptr; nzPrimitiveType m_primitiveType = nzPrimitiveType_TriangleList;
NzVertexBuffer* m_vertexBuffer = nullptr; NzAxisAlignedBox m_aabb;
const NzVertexDeclaration* m_vertexDeclaration = nullptr; NzIndexBuffer* m_indexBuffer = nullptr;
}; NzVertexBuffer* m_vertexBuffer = nullptr;
const NzVertexDeclaration* m_vertexDeclaration = nullptr;
#endif // NAZARA_STATICMESH_HPP };
#endif // NAZARA_STATICMESH_HPP

View File

@ -1,53 +1,56 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module" // This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#ifndef NAZARA_VERTEXDECLARATION_HPP #ifndef NAZARA_VERTEXDECLARATION_HPP
#define NAZARA_VERTEXDECLARATION_HPP #define NAZARA_VERTEXDECLARATION_HPP
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Resource.hpp> #include <Nazara/Core/Resource.hpp>
#include <Nazara/Utility/Enums.hpp> #include <Nazara/Utility/Enums.hpp>
struct NzVertexElement struct NzVertexElement
{ {
unsigned int offset; unsigned int offset;
unsigned int usageIndex = 0; unsigned int usageIndex = 0;
nzElementStream stream = nzElementStream_VertexData; nzElementStream stream = nzElementStream_VertexData;
nzElementType type; nzElementType type;
nzElementUsage usage; nzElementUsage usage;
}; };
struct NzVertexDeclarationImpl; struct NzVertexDeclarationImpl;
class NAZARA_API NzVertexDeclaration : public NzResource class NAZARA_API NzVertexDeclaration : public NzResource
{ {
public: public:
NzVertexDeclaration() = default; NzVertexDeclaration() = default;
NzVertexDeclaration(const NzVertexElement* elements, unsigned int elementCount); NzVertexDeclaration(const NzVertexElement* elements, unsigned int elementCount);
NzVertexDeclaration(const NzVertexDeclaration& declaration); NzVertexDeclaration(const NzVertexDeclaration& declaration);
NzVertexDeclaration(NzVertexDeclaration&& declaration) noexcept; NzVertexDeclaration(NzVertexDeclaration&& declaration) noexcept;
~NzVertexDeclaration(); ~NzVertexDeclaration();
bool Create(const NzVertexElement* elements, unsigned int elementCount); bool Create(const NzVertexElement* elements, unsigned int elementCount);
void Destroy(); void Destroy();
const NzVertexElement* GetElement(unsigned int i) const; const NzVertexElement* GetElement(unsigned int i) const;
const NzVertexElement* GetElement(nzElementStream stream, 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; const NzVertexElement* GetElement(nzElementStream stream, nzElementUsage usage, unsigned int usageIndex = 0) const;
unsigned int GetElementCount() const; unsigned int GetElementCount() const;
unsigned int GetElementCount(nzElementStream stream) const; unsigned int GetElementCount(nzElementStream stream) const;
unsigned int GetStride(nzElementStream stream) const; unsigned int GetStride(nzElementStream stream) const;
bool HasStream(nzElementStream stream) const; bool HasStream(nzElementStream stream) const;
bool IsValid() const; bool IsValid() const;
NzVertexDeclaration& operator=(const NzVertexDeclaration& declaration); NzVertexDeclaration& operator=(const NzVertexDeclaration& declaration);
NzVertexDeclaration& operator=(NzVertexDeclaration&& declaration) noexcept; NzVertexDeclaration& operator=(NzVertexDeclaration&& declaration) noexcept;
private: static unsigned int GetElementCount(nzElementType type);
NzVertexDeclarationImpl* m_sharedImpl = nullptr; static unsigned int GetElementSize(nzElementType type);
};
private:
#endif // NAZARA_VERTEXDECLARATION_HPP NzVertexDeclarationImpl* m_sharedImpl = nullptr;
};
#endif // NAZARA_VERTEXDECLARATION_HPP

View File

@ -1,111 +1,112 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module" // This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
// Interface inspirée de la SFML par Laurent Gomila // Interface inspirée de la SFML par Laurent Gomila
#pragma once #pragma once
#ifndef NAZARA_WINDOW_HPP #ifndef NAZARA_WINDOW_HPP
#define NAZARA_WINDOW_HPP #define NAZARA_WINDOW_HPP
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/NonCopyable.hpp> #include <Nazara/Core/NonCopyable.hpp>
#include <Nazara/Core/String.hpp> #include <Nazara/Core/String.hpp>
#include <Nazara/Math/Vector2.hpp> #include <Nazara/Math/Vector2.hpp>
#include <Nazara/Utility/Config.hpp> #include <Nazara/Utility/Config.hpp>
#include <Nazara/Utility/Enums.hpp> #include <Nazara/Utility/Enums.hpp>
#include <Nazara/Utility/Event.hpp> #include <Nazara/Utility/Event.hpp>
#include <Nazara/Utility/VideoMode.hpp> #include <Nazara/Utility/VideoMode.hpp>
#include <Nazara/Utility/WindowHandle.hpp> #include <Nazara/Utility/WindowHandle.hpp>
#include <queue> #include <queue>
#if NAZARA_UTILITY_THREADED_WINDOW #if NAZARA_UTILITY_THREADED_WINDOW
#include <Nazara/Core/Mutex.hpp> #include <Nazara/Core/ConditionVariable.hpp>
#include <Nazara/Core/ThreadCondition.hpp> #include <Nazara/Core/Mutex.hpp>
#endif #endif
class NzCursor; class NzCursor;
class NzImage; class NzImage;
class NzIcon; class NzIcon;
class NzWindowImpl; class NzWindowImpl;
class NAZARA_API NzWindow : NzNonCopyable class NAZARA_API NzWindow : NzNonCopyable
{ {
friend NzWindowImpl; friend NzWindowImpl;
friend class NzMouse; friend class NzMouse;
friend class NzUtility; friend class NzUtility;
public: public:
NzWindow(); NzWindow();
NzWindow(NzVideoMode mode, const NzString& title, nzUInt32 style = nzWindowStyle_Default); NzWindow(NzVideoMode mode, const NzString& title, nzUInt32 style = nzWindowStyle_Default);
NzWindow(NzWindowHandle handle); NzWindow(NzWindowHandle handle);
virtual ~NzWindow(); virtual ~NzWindow();
bool Create(NzVideoMode mode, const NzString& title, nzUInt32 style = nzWindowStyle_Default); bool Create(NzVideoMode mode, const NzString& title, nzUInt32 style = nzWindowStyle_Default);
bool Create(NzWindowHandle handle); bool Create(NzWindowHandle handle);
void Destroy(); void Destroy();
void EnableKeyRepeat(bool enable); void EnableKeyRepeat(bool enable);
void EnableSmoothScrolling(bool enable); void EnableSmoothScrolling(bool enable);
NzWindowHandle GetHandle() const; NzWindowHandle GetHandle() const;
unsigned int GetHeight() const; unsigned int GetHeight() const;
NzVector2i GetPosition() const; NzVector2i GetPosition() const;
NzVector2ui GetSize() const; NzVector2ui GetSize() const;
NzString GetTitle() const; NzString GetTitle() const;
unsigned int GetWidth() const; unsigned int GetWidth() const;
bool HasFocus() const; bool HasFocus() const;
bool IsMinimized() const; bool IsMinimized() const;
bool IsOpen() const; bool IsOpen() const;
bool IsVisible() const; bool IsValid() const;
bool IsVisible() const;
bool PollEvent(NzEvent* event);
bool PollEvent(NzEvent* event);
void SetCursor(nzWindowCursor cursor);
void SetCursor(const NzCursor& cursor); void SetCursor(nzWindowCursor cursor);
void SetEventListener(bool listener); void SetCursor(const NzCursor& cursor);
void SetFocus(); void SetEventListener(bool listener);
void SetIcon(const NzIcon& icon); void SetFocus();
void SetMaximumSize(const NzVector2i& maxSize); void SetIcon(const NzIcon& icon);
void SetMaximumSize(int width, int height); void SetMaximumSize(const NzVector2i& maxSize);
void SetMinimumSize(const NzVector2i& minSize); void SetMaximumSize(int width, int height);
void SetMinimumSize(int width, int height); void SetMinimumSize(const NzVector2i& minSize);
void SetPosition(const NzVector2i& position); void SetMinimumSize(int width, int height);
void SetPosition(int x, int y); void SetPosition(const NzVector2i& position);
void SetSize(const NzVector2i& size); void SetPosition(int x, int y);
void SetSize(unsigned int width, unsigned int height); void SetSize(const NzVector2i& size);
void SetStayOnTop(bool stayOnTop); void SetSize(unsigned int width, unsigned int height);
void SetTitle(const NzString& title); void SetStayOnTop(bool stayOnTop);
void SetVisible(bool visible); void SetTitle(const NzString& title);
void SetVisible(bool visible);
bool WaitEvent(NzEvent* event);
bool WaitEvent(NzEvent* event);
protected:
virtual void OnWindowDestroying(); protected:
virtual bool OnWindowCreated(); virtual bool OnWindowCreated();
virtual void OnWindowDestroy();
NzWindowImpl* m_impl;
NzWindowImpl* m_impl;
private:
void IgnoreNextMouseEvent(int mouseX, int mouseY) const; private:
void PushEvent(const NzEvent& event); void IgnoreNextMouseEvent(int mouseX, int mouseY) const;
void PushEvent(const NzEvent& event);
static bool Initialize();
static void Uninitialize(); static bool Initialize();
static void Uninitialize();
std::queue<NzEvent> m_events;
#if NAZARA_UTILITY_THREADED_WINDOW std::queue<NzEvent> m_events;
NzConditionVariable m_eventCondition; #if NAZARA_UTILITY_THREADED_WINDOW
NzMutex m_eventMutex; NzConditionVariable m_eventCondition;
NzMutex m_eventConditionMutex; NzMutex m_eventMutex;
bool m_eventListener; NzMutex m_eventConditionMutex;
bool m_waitForEvent; bool m_eventListener;
#endif bool m_waitForEvent;
bool m_ownsWindow; #endif
}; bool m_ownsWindow;
};
#endif // NAZARA_WINDOW_HPP
#endif // NAZARA_WINDOW_HPP

View File

@ -1,223 +1,229 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Audio module" // This file is part of the "Nazara Engine - Audio module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Audio/SoundBuffer.hpp> #include <Nazara/Audio/SoundBuffer.hpp>
#include <Nazara/Audio/Audio.hpp> #include <Nazara/Audio/Audio.hpp>
#include <Nazara/Audio/Config.hpp> #include <Nazara/Audio/Config.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <cstring> #include <cstring>
#include <stdexcept> #include <stdexcept>
#include <AL/al.h> #include <AL/al.h>
#include <Nazara/Audio/Debug.hpp> #include <Nazara/Audio/Debug.hpp>
///FIXME: Adapter la création ///FIXME: Adapter la création
bool NzSoundBufferParams::IsValid() const bool NzSoundBufferParams::IsValid() const
{ {
return true; return true;
} }
struct NzSoundBufferImpl struct NzSoundBufferImpl
{ {
ALuint buffer; ALuint buffer;
nzAudioFormat format; nzAudioFormat format;
nzUInt32 duration; nzUInt32 duration;
nzInt16* samples; nzInt16* samples;
unsigned int sampleCount; unsigned int sampleCount;
unsigned int sampleRate; unsigned int sampleRate;
}; };
NzSoundBuffer::NzSoundBuffer(nzAudioFormat format, unsigned int sampleCount, unsigned int sampleRate, const nzInt16* samples) NzSoundBuffer::NzSoundBuffer(nzAudioFormat format, unsigned int sampleCount, unsigned int sampleRate, const nzInt16* samples)
{ {
Create(format, sampleCount, sampleRate, samples); Create(format, sampleCount, sampleRate, samples);
#ifdef NAZARA_DEBUG #ifdef NAZARA_DEBUG
if (!m_impl) if (!m_impl)
{ {
NazaraError("Failed to create sound buffer"); NazaraError("Failed to create sound buffer");
throw std::runtime_error("Constructor failed"); throw std::runtime_error("Constructor failed");
} }
#endif #endif
} }
NzSoundBuffer::~NzSoundBuffer() NzSoundBuffer::~NzSoundBuffer()
{ {
Destroy(); Destroy();
} }
bool NzSoundBuffer::Create(nzAudioFormat format, unsigned int sampleCount, unsigned int sampleRate, const nzInt16* samples) bool NzSoundBuffer::Create(nzAudioFormat format, unsigned int sampleCount, unsigned int sampleRate, const nzInt16* samples)
{ {
Destroy(); Destroy();
if (sampleCount == 0) #if NAZARA_AUDIO_SAFE
return true; if (!IsFormatSupported(format))
{
#if NAZARA_AUDIO_SAFE NazaraError("Audio format is not supported");
if (!IsFormatSupported(format)) return false;
{ }
NazaraError("Audio format is not supported");
return false; if (sampleCount == 0)
} {
NazaraError("Sample rate must be different from zero");
if (sampleRate == 0) return false;
{ }
NazaraError("Sample rate must be different from zero");
return false; if (sampleRate == 0)
} {
NazaraError("Sample rate must be different from zero");
if (!samples) return false;
{ }
NazaraError("Invalid sample source");
return false; if (!samples)
} {
#endif NazaraError("Invalid sample source");
return false;
// On vide le stack d'erreurs }
while (alGetError() != AL_NO_ERROR); #endif
ALuint buffer; // On vide le stack d'erreurs
alGenBuffers(1, &buffer); while (alGetError() != AL_NO_ERROR);
if (alGetError() != AL_NO_ERROR) ALuint buffer;
{ alGenBuffers(1, &buffer);
NazaraError("Failed to create OpenAL buffer");
return false; if (alGetError() != AL_NO_ERROR)
} {
NazaraError("Failed to create OpenAL buffer");
alBufferData(buffer, NzAudio::GetOpenALFormat(format), samples, sampleCount*sizeof(nzInt16), sampleRate); return false;
}
if (alGetError() != AL_NO_ERROR)
{ alBufferData(buffer, NzAudio::GetOpenALFormat(format), samples, sampleCount*sizeof(nzInt16), sampleRate);
NazaraError("Failed to set OpenAL buffer");
alDeleteBuffers(1, &buffer); if (alGetError() != AL_NO_ERROR)
{
return false; NazaraError("Failed to set OpenAL buffer");
} alDeleteBuffers(1, &buffer);
m_impl = new NzSoundBufferImpl; return false;
m_impl->buffer = buffer; }
m_impl->duration = 1000 * (sampleCount / (format * sampleRate));
m_impl->format = format; m_impl = new NzSoundBufferImpl;
m_impl->sampleCount = sampleCount; m_impl->buffer = buffer;
m_impl->sampleRate = sampleRate; m_impl->duration = 1000 * (sampleCount / (format * sampleRate));
m_impl->samples = new nzInt16[sampleCount]; m_impl->format = format;
std::memcpy(&m_impl->samples[0], samples, sampleCount*sizeof(nzInt16)); m_impl->sampleCount = sampleCount;
m_impl->sampleRate = sampleRate;
return true; m_impl->samples = new nzInt16[sampleCount];
} std::memcpy(&m_impl->samples[0], samples, sampleCount*sizeof(nzInt16));
void NzSoundBuffer::Destroy() NotifyCreated();
{ return true;
if (m_impl) }
{
delete[] m_impl->samples; void NzSoundBuffer::Destroy()
delete m_impl; {
m_impl = nullptr; if (m_impl)
} {
} NotifyDestroy();
nzUInt32 NzSoundBuffer::GetDuration() const delete[] m_impl->samples;
{ delete m_impl;
#if NAZARA_AUDIO_SAFE m_impl = nullptr;
if (!m_impl) }
{ }
NazaraError("Sound buffer not created");
return 0; nzUInt32 NzSoundBuffer::GetDuration() const
} {
#endif #if NAZARA_AUDIO_SAFE
if (!m_impl)
return m_impl->duration; {
} NazaraError("Sound buffer not created");
return 0;
nzAudioFormat NzSoundBuffer::GetFormat() const }
{ #endif
#if NAZARA_AUDIO_SAFE
if (!m_impl) return m_impl->duration;
{ }
NazaraError("Sound buffer not created");
return nzAudioFormat_Unknown; nzAudioFormat NzSoundBuffer::GetFormat() const
} {
#endif #if NAZARA_AUDIO_SAFE
if (!m_impl)
return m_impl->format; {
} NazaraError("Sound buffer not created");
return nzAudioFormat_Unknown;
const nzInt16* NzSoundBuffer::GetSamples() const }
{ #endif
#if NAZARA_AUDIO_SAFE
if (!m_impl) return m_impl->format;
{ }
NazaraError("Sound buffer not created");
return nullptr; const nzInt16* NzSoundBuffer::GetSamples() const
} {
#endif #if NAZARA_AUDIO_SAFE
if (!m_impl)
return m_impl->samples; {
} NazaraError("Sound buffer not created");
return nullptr;
unsigned int NzSoundBuffer::GetSampleCount() const }
{ #endif
#if NAZARA_AUDIO_SAFE
if (!m_impl) return m_impl->samples;
{ }
NazaraError("Sound buffer not created");
return 0; unsigned int NzSoundBuffer::GetSampleCount() const
} {
#endif #if NAZARA_AUDIO_SAFE
if (!m_impl)
return m_impl->sampleCount; {
} NazaraError("Sound buffer not created");
return 0;
unsigned int NzSoundBuffer::GetSampleRate() const }
{ #endif
#if NAZARA_AUDIO_SAFE
if (!m_impl) return m_impl->sampleCount;
{ }
NazaraError("Sound buffer not created");
return 0; unsigned int NzSoundBuffer::GetSampleRate() const
} {
#endif #if NAZARA_AUDIO_SAFE
if (!m_impl)
return m_impl->sampleRate; {
} NazaraError("Sound buffer not created");
return 0;
bool NzSoundBuffer::IsValid() const }
{ #endif
return m_impl != nullptr;
} return m_impl->sampleRate;
}
bool NzSoundBuffer::LoadFromFile(const NzString& filePath, const NzSoundBufferParams& params)
{ bool NzSoundBuffer::IsValid() const
return NzSoundBufferLoader::LoadFromFile(this, filePath, params); {
} return m_impl != nullptr;
}
bool NzSoundBuffer::LoadFromMemory(const void* data, std::size_t size, const NzSoundBufferParams& params)
{ bool NzSoundBuffer::LoadFromFile(const NzString& filePath, const NzSoundBufferParams& params)
return NzSoundBufferLoader::LoadFromMemory(this, data, size, params); {
} return NzSoundBufferLoader::LoadFromFile(this, filePath, params);
}
bool NzSoundBuffer::LoadFromStream(NzInputStream& stream, const NzSoundBufferParams& params)
{ bool NzSoundBuffer::LoadFromMemory(const void* data, std::size_t size, const NzSoundBufferParams& params)
return NzSoundBufferLoader::LoadFromStream(this, stream, params); {
} return NzSoundBufferLoader::LoadFromMemory(this, data, size, params);
}
bool NzSoundBuffer::IsFormatSupported(nzAudioFormat format)
{ bool NzSoundBuffer::LoadFromStream(NzInputStream& stream, const NzSoundBufferParams& params)
return NzAudio::IsFormatSupported(format); {
} return NzSoundBufferLoader::LoadFromStream(this, stream, params);
}
unsigned int NzSoundBuffer::GetOpenALBuffer() const
{ bool NzSoundBuffer::IsFormatSupported(nzAudioFormat format)
#ifdef NAZARA_DEBUG {
if (!m_impl) return NzAudio::IsFormatSupported(format);
{ }
NazaraInternalError("Sound buffer not created");
return AL_NONE; unsigned int NzSoundBuffer::GetOpenALBuffer() const
} {
#endif #ifdef NAZARA_DEBUG
if (!m_impl)
return m_impl->buffer; {
} NazaraInternalError("Sound buffer not created");
return AL_NONE;
NzSoundBufferLoader::LoaderList NzSoundBuffer::s_loaders; }
#endif
return m_impl->buffer;
}
NzSoundBufferLoader::LoaderList NzSoundBuffer::s_loaders;

View File

@ -1,265 +1,265 @@
/* // Copyright (C) 2012 Jérôme Leclercq
// Copyright (C) 2012 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module"
// This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp
// For conditions of distribution and use, see copyright notice in Config.hpp
/*
#include <Nazara/Core/ByteArray.hpp> #include <Nazara/Core/ByteArray.hpp>
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include <Nazara/Core/Debug.hpp> #include <Nazara/Core/Debug.hpp>
inline unsigned int nzPow2(unsigned int n) inline unsigned int nzPow2(unsigned int n)
{ {
unsigned int x = 1; unsigned int x = 1;
while(x <= n) while(x <= n)
x <<= 1; x <<= 1;
return x; return x;
} }
// Cet algorithme est inspiré de la documentation de Qt // Cet algorithme est inspiré de la documentation de Qt
inline unsigned int nzGetNewSize(unsigned int newSize) inline unsigned int nzGetNewSize(unsigned int newSize)
{ {
if (newSize < 20) if (newSize < 20)
return newSize+4; return newSize+4;
else else
{ {
if (newSize < (1 << 12)-12) if (newSize < (1 << 12)-12)
return nzPow2(newSize << 1)-12; return nzPow2(newSize << 1)-12;
else else
return newSize + (1 << 11); return newSize + (1 << 11);
} }
} }
NzByteArray::NzByteArray() : NzByteArray::NzByteArray() :
m_sharedArray(&emptyArray) m_sharedArray(&emptyArray)
{ {
} }
NzByteArray::NzByteArray(const nzUInt8* buffer, unsigned int bufferLength) NzByteArray::NzByteArray(const nzUInt8* buffer, unsigned int bufferLength)
{ {
if (bufferLength > 0) if (bufferLength > 0)
{ {
m_sharedArray = new SharedArray; m_sharedArray = new SharedArray;
m_sharedArray->buffer = new nzUInt8[bufferLength]; m_sharedArray->buffer = new nzUInt8[bufferLength];
m_sharedArray->capacity = bufferLength; m_sharedArray->capacity = bufferLength;
m_sharedArray->size = bufferLength; m_sharedArray->size = bufferLength;
std::memcpy(m_sharedArray->buffer, buffer, bufferLength); std::memcpy(m_sharedArray->buffer, buffer, bufferLength);
} }
else else
m_sharedArray = &emptyArray; m_sharedArray = &emptyArray;
} }
NzByteArray::NzByteArray(const NzByteArray& buffer) : NzByteArray::NzByteArray(const NzByteArray& buffer) :
m_sharedArray(buffer.m_sharedArray) m_sharedArray(buffer.m_sharedArray)
{ {
if (m_sharedArray != &emptyArray) if (m_sharedArray != &emptyArray)
{ {
NazaraMutexLock(m_sharedArray->mutex); NazaraMutexLock(m_sharedArray->mutex);
m_sharedArray->refCount++; m_sharedArray->refCount++;
NazaraMutexUnlock(m_sharedArray->mutex); NazaraMutexUnlock(m_sharedArray->mutex);
} }
} }
NzByteArray::NzByteArray(NzByteArray&& buffer) : NzByteArray::NzByteArray(NzByteArray&& buffer) noexcept :
m_sharedArray(buffer.m_sharedArray) m_sharedArray(buffer.m_sharedArray)
{ {
buffer.m_sharedArray = &emptyArray; buffer.m_sharedArray = &emptyArray;
} }
NzByteArray::NzByteArray(SharedArray* sharedArray) : NzByteArray::NzByteArray(SharedArray* sharedArray) :
m_sharedArray(sharedArray) m_sharedArray(sharedArray)
{ {
} }
NzByteArray::~NzByteArray() NzByteArray::~NzByteArray()
{ {
ReleaseArray(); ReleaseArray();
} }
NzByteArray& NzByteArray::Append(const NzByteArray& byteArray) NzByteArray& NzByteArray::Append(const NzByteArray& byteArray)
{ {
if (byteArray.m_sharedArray->size == 0) if (byteArray.m_sharedArray->size == 0)
return *this; return *this;
if (m_sharedArray->size == 0 && m_sharedArray->capacity < byteArray.m_sharedArray->size) if (m_sharedArray->size == 0 && m_sharedArray->capacity < byteArray.m_sharedArray->size)
return operator=(byteArray); return operator=(byteArray);
if (m_sharedArray->capacity >= m_sharedArray->size + byteArray.m_sharedArray->size) if (m_sharedArray->capacity >= m_sharedArray->size + byteArray.m_sharedArray->size)
{ {
EnsureOwnership(); EnsureOwnership();
std::memcpy(&m_sharedArray->buffer[m_sharedArray->size], byteArray.m_sharedArray->buffer, byteArray.m_sharedArray->size); std::memcpy(&m_sharedArray->buffer[m_sharedArray->size], byteArray.m_sharedArray->buffer, byteArray.m_sharedArray->size);
m_sharedArray->size += byteArray.m_sharedArray->size; m_sharedArray->size += byteArray.m_sharedArray->size;
} }
else else
{ {
unsigned int newSize = m_sharedArray->size + byteArray.m_sharedArray->size; unsigned int newSize = m_sharedArray->size + byteArray.m_sharedArray->size;
unsigned int bufferSize = nzGetNewSize(newSize); unsigned int bufferSize = nzGetNewSize(newSize);
nzUInt8* buffer = new nzUInt8[bufferSize+1]; nzUInt8* buffer = new nzUInt8[bufferSize+1];
std::memcpy(buffer, m_sharedArray->buffer, m_sharedArray->size); std::memcpy(buffer, m_sharedArray->buffer, m_sharedArray->size);
std::memcpy(&buffer[m_sharedArray->size], byteArray.m_sharedArray->buffer, byteArray.m_sharedArray->size); std::memcpy(&buffer[m_sharedArray->size], byteArray.m_sharedArray->buffer, byteArray.m_sharedArray->size);
ReleaseArray(); ReleaseArray();
m_sharedArray = new SharedArray; m_sharedArray = new SharedArray;
m_sharedArray->buffer = buffer; m_sharedArray->buffer = buffer;
m_sharedArray->capacity = bufferSize; m_sharedArray->capacity = bufferSize;
m_sharedArray->size = newSize; m_sharedArray->size = newSize;
} }
return *this; return *this;
} }
void NzByteArray::Clear() void NzByteArray::Clear()
{ {
ReleaseArray(); ReleaseArray();
} }
nzUInt8* NzByteArray::GetBuffer() nzUInt8* NzByteArray::GetBuffer()
{ {
EnsureOwnership(); EnsureOwnership();
return m_sharedArray->buffer; return m_sharedArray->buffer;
} }
unsigned int NzByteArray::GetCapacity() const unsigned int NzByteArray::GetCapacity() const
{ {
return m_sharedArray->capacity; return m_sharedArray->capacity;
} }
const nzUInt8* NzByteArray::GetConstBuffer() const const nzUInt8* NzByteArray::GetConstBuffer() const
{ {
return m_sharedArray->buffer; return m_sharedArray->buffer;
} }
unsigned int NzByteArray::GetSize() const unsigned int NzByteArray::GetSize() const
{ {
return m_sharedArray->size; return m_sharedArray->size;
} }
NzByteArray& NzByteArray::Insert(int pos, const nzUInt8* buffer, unsigned int bufferLength) NzByteArray& NzByteArray::Insert(int pos, const nzUInt8* buffer, unsigned int bufferLength)
{ {
if (bufferLength == 0) if (bufferLength == 0)
return *this; return *this;
if (m_sharedArray->size == 0) if (m_sharedArray->size == 0)
return operator=(string); return operator=(string);
if (pos < 0) if (pos < 0)
pos = std::max(static_cast<int>(m_sharedArray->size + pos), 0); pos = std::max(static_cast<int>(m_sharedArray->size + pos), 0);
unsigned int start = std::min(static_cast<unsigned int>(pos), m_sharedArray->size); unsigned int start = std::min(static_cast<unsigned int>(pos), m_sharedArray->size);
// Si le buffer est déjà suffisamment grand // Si le buffer est déjà suffisamment grand
if (m_sharedArray->capacity >= m_sharedArray->size + bufferLength) if (m_sharedArray->capacity >= m_sharedArray->size + bufferLength)
{ {
EnsureOwnership(); EnsureOwnership();
std::memmove(&m_sharedArray->buffer[start+bufferLength], &m_sharedArray->buffer[start], m_sharedArray->size); std::memmove(&m_sharedArray->buffer[start+bufferLength], &m_sharedArray->buffer[start], m_sharedArray->size);
std::memcpy(&m_sharedArray->buffer[start], buffer, bufferLength); std::memcpy(&m_sharedArray->buffer[start], buffer, bufferLength);
m_sharedArray->size += bufferLength; m_sharedArray->size += bufferLength;
} }
else else
{ {
unsigned int newSize = m_sharedArray->size+bufferLength; unsigned int newSize = m_sharedArray->size+bufferLength;
nzUInt8* newBuffer = new nzUInt8[newSize+1]; nzUInt8* newBuffer = new nzUInt8[newSize+1];
nzUInt8* ptr = newBuffer; nzUInt8* ptr = newBuffer;
const nzUInt8* s = m_sharedArray->buffer; const nzUInt8* s = m_sharedArray->buffer;
while (ptr != &newBuffer[start]) while (ptr != &newBuffer[start])
*ptr++ = *s++; *ptr++ = *s++;
while (ptr != &newBuffer[start+bufferLength]) while (ptr != &newBuffer[start+bufferLength])
*ptr++ = *buffer++; *ptr++ = *buffer++;
std::strcpy(ptr, s); std::strcpy(ptr, s);
ReleaseString(); ReleaseString();
m_sharedArray = new SharedString; m_sharedArray = new SharedString;
m_sharedArray->allocatedSize = newSize; m_sharedArray->allocatedSize = newSize;
m_sharedArray->buffer = newBuffer; m_sharedArray->buffer = newBuffer;
m_sharedArray->size = newSize; m_sharedArray->size = newSize;
} }
return *this; return *this;
} }
NzByteArray& NzByteArray::Insert(int pos, const NzByteArray& byteArray) NzByteArray& NzByteArray::Insert(int pos, const NzByteArray& byteArray)
{ {
if (string.m_sharedArray->size == 0) if (string.m_sharedArray->size == 0)
return *this; return *this;
if (m_sharedArray->size == 0 && m_sharedArray->capacity < string.m_sharedArray->size) if (m_sharedArray->size == 0 && m_sharedArray->capacity < string.m_sharedArray->size)
return operator=(string); return operator=(string);
if (pos < 0) if (pos < 0)
pos = std::max(static_cast<int>(m_sharedArray->size + pos), 0); pos = std::max(static_cast<int>(m_sharedArray->size + pos), 0);
unsigned int start = std::min(static_cast<unsigned int>(pos), m_sharedArray->size); unsigned int start = std::min(static_cast<unsigned int>(pos), m_sharedArray->size);
// Si le buffer est déjà suffisamment grand // Si le buffer est déjà suffisamment grand
if (m_sharedArray->capacity >= m_sharedArray->size + string.m_sharedArray->size) if (m_sharedArray->capacity >= m_sharedArray->size + string.m_sharedArray->size)
{ {
EnsureOwnership(); EnsureOwnership();
std::memmove(&m_sharedArray->string[start+string.m_sharedArray->size], &m_sharedArray->string[start], m_sharedArray->size*sizeof(char)); std::memmove(&m_sharedArray->string[start+string.m_sharedArray->size], &m_sharedArray->string[start], m_sharedArray->size*sizeof(char));
std::memcpy(&m_sharedArray->string[start], string.m_sharedArray->string, string.m_sharedArray->size*sizeof(char)); std::memcpy(&m_sharedArray->string[start], string.m_sharedArray->string, string.m_sharedArray->size*sizeof(char));
m_sharedArray->size += string.m_sharedArray->size; m_sharedArray->size += string.m_sharedArray->size;
} }
else else
{ {
unsigned int newSize = m_sharedArray->size+string.m_sharedArray->size; unsigned int newSize = m_sharedArray->size+string.m_sharedArray->size;
char* newString = new char[newSize+1]; char* newString = new char[newSize+1];
char* ptr = newString; char* ptr = newString;
const char* s = m_sharedArray->string; const char* s = m_sharedArray->string;
while (ptr != &newString[start]) while (ptr != &newString[start])
*ptr++ = *s++; *ptr++ = *s++;
const char* p = string.m_sharedArray->string; const char* p = string.m_sharedArray->string;
while (ptr != &newString[start+string.m_sharedArray->size]) while (ptr != &newString[start+string.m_sharedArray->size])
*ptr++ = *p++; *ptr++ = *p++;
std::strcpy(ptr, s); std::strcpy(ptr, s);
ReleaseString(); ReleaseString();
m_sharedArray = new SharedString; m_sharedArray = new SharedString;
m_sharedArray->capacity = newSize; m_sharedArray->capacity = newSize;
m_sharedArray->size = newSize; m_sharedArray->size = newSize;
m_sharedArray->string = newString; m_sharedArray->string = newString;
} }
return *this; return *this;
} }
bool NzByteArray::IsEmpty() const bool NzByteArray::IsEmpty() const
{ {
return m_sharedArray->size == 0; return m_sharedArray->size == 0;
} }
void NzByteArray::Reserve(unsigned int bufferSize) void NzByteArray::Reserve(unsigned int bufferSize)
{ {
if (m_sharedArray->allocatedSize >= bufferSize) if (m_sharedArray->allocatedSize >= bufferSize)
return; return;
nzUInt8* ptr = new nzUInt8[bufferSize+1]; nzUInt8* ptr = new nzUInt8[bufferSize+1];
if (m_sharedArray->size > 0) if (m_sharedArray->size > 0)
std::memcpy(ptr, m_sharedArray->buffer, m_sharedArray->size); std::memcpy(ptr, m_sharedArray->buffer, m_sharedArray->size);
unsigned int size = m_sharedArray->size; unsigned int size = m_sharedArray->size;
ReleaseArray(); ReleaseArray();
m_sharedArray = new SharedString; m_sharedArray = new SharedString;
m_sharedArray->allocatedSize = bufferSize; m_sharedArray->allocatedSize = bufferSize;
m_sharedArray->buffer = ptr; m_sharedArray->buffer = ptr;
m_sharedArray->size = size; m_sharedArray->size = size;
} }
NzByteArray::SharedString NzByteArray::emptyArray(0, 0, 0, nullptr); NzByteArray::SharedString NzByteArray::emptyArray(0, 0, 0, nullptr);
unsigned int NzByteArray::npos(static_cast<unsigned int>(-1)); unsigned int NzByteArray::npos(static_cast<unsigned int>(-1));
*/ */

View File

@ -1,264 +1,271 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module" // This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Debug/MemoryLeakTracker.hpp> #include <Nazara/Core/Debug/MemoryLeakTracker.hpp>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <ctime> #include <ctime>
#include <stdexcept> #include <stdexcept>
#if defined(NAZARA_PLATFORM_WINDOWS) #if defined(NAZARA_PLATFORM_WINDOWS)
#include <windows.h> #include <windows.h>
#elif defined(NAZARA_PLATFORM_POSIX) #elif defined(NAZARA_PLATFORM_POSIX)
#include <pthread.h> #include <pthread.h>
#endif #endif
namespace namespace
{ {
struct Block struct Block
{ {
std::size_t size; std::size_t size;
const char* file; const char* file;
Block* prev; Block* prev;
Block* next; Block* next;
bool array; bool array;
unsigned int line; unsigned int line;
unsigned int magic; unsigned int magic;
}; };
bool initialized = false; bool initialized = false;
const unsigned int magic = 0x51429EE; const unsigned int magic = 0x51429EE;
const char* MLTFileName = "NazaraLeaks.log"; const char* MLTFileName = "NazaraLeaks.log";
const char* nextFreeFile = "Internal error"; const char* nextFreeFile = "Internal error";
unsigned int nextFreeLine = 0; unsigned int nextFreeLine = 0;
Block ptrList = Block ptrList =
{ {
0, 0,
nullptr, nullptr,
&ptrList, &ptrList,
&ptrList, &ptrList,
false, false,
0, 0,
magic magic
}; };
#if defined(NAZARA_PLATFORM_WINDOWS) #if defined(NAZARA_PLATFORM_WINDOWS)
CRITICAL_SECTION mutex; CRITICAL_SECTION mutex;
#elif defined(NAZARA_PLATFORM_POSIX) #elif defined(NAZARA_PLATFORM_POSIX)
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
#endif #endif
} }
NzMemoryManager::NzMemoryManager() NzMemoryManager::NzMemoryManager()
{ {
} }
NzMemoryManager::~NzMemoryManager() NzMemoryManager::~NzMemoryManager()
{ {
Uninitialize(); Uninitialize();
} }
void* NzMemoryManager::Allocate(std::size_t size, bool multi, const char* file, unsigned int line) void* NzMemoryManager::Allocate(std::size_t size, bool multi, const char* file, unsigned int line)
{ {
if (!initialized) if (!initialized)
Initialize(); Initialize();
#if defined(NAZARA_PLATFORM_WINDOWS) #if defined(NAZARA_PLATFORM_WINDOWS)
EnterCriticalSection(&mutex); EnterCriticalSection(&mutex);
#elif defined(NAZARA_PLATFORM_POSIX) #elif defined(NAZARA_PLATFORM_POSIX)
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
#endif #endif
Block* ptr = reinterpret_cast<Block*>(std::malloc(size+sizeof(Block))); Block* ptr = reinterpret_cast<Block*>(std::malloc(size+sizeof(Block)));
if (!ptr) if (!ptr)
return nullptr; // Impossible d'envoyer une exception car cela allouerait de la mémoire avec new (boucle infinie) {
// Pas d'information de temps (Car nécessitant une allocation)
ptr->array = multi; FILE* log = std::fopen(MLTFileName, "a");
ptr->file = file; std::fprintf(log, "Failed to allocate memory (%d bytes)\n", size);
ptr->line = line; std::fclose(log);
ptr->size = size;
ptr->magic = magic; return nullptr; // Impossible d'envoyer une exception car cela allouerait de la mémoire avec new (boucle infinie)
}
ptr->prev = ptrList.prev;
ptr->next = &ptrList; ptr->array = multi;
ptrList.prev->next = ptr; ptr->file = file;
ptrList.prev = ptr; ptr->line = line;
ptr->size = size;
#if defined(NAZARA_PLATFORM_WINDOWS) ptr->magic = magic;
LeaveCriticalSection(&mutex);
#elif defined(NAZARA_PLATFORM_POSIX) ptr->prev = ptrList.prev;
pthread_mutex_unlock(&mutex); ptr->next = &ptrList;
#endif ptrList.prev->next = ptr;
ptrList.prev = ptr;
return reinterpret_cast<char*>(ptr)+sizeof(Block);
} #if defined(NAZARA_PLATFORM_WINDOWS)
LeaveCriticalSection(&mutex);
void NzMemoryManager::Free(void* pointer, bool multi) #elif defined(NAZARA_PLATFORM_POSIX)
{ pthread_mutex_unlock(&mutex);
if (!pointer) #endif
return;
return reinterpret_cast<char*>(ptr)+sizeof(Block);
Block* ptr = reinterpret_cast<Block*>(reinterpret_cast<char*>(pointer)-sizeof(Block)); }
if (ptr->magic != magic)
return; void NzMemoryManager::Free(void* pointer, bool multi)
{
#if defined(NAZARA_PLATFORM_WINDOWS) if (!pointer)
EnterCriticalSection(&mutex); return;
#elif defined(NAZARA_PLATFORM_POSIX)
pthread_mutex_lock(&mutex); Block* ptr = reinterpret_cast<Block*>(reinterpret_cast<char*>(pointer)-sizeof(Block));
#endif if (ptr->magic != magic)
return;
if (ptr->array != multi)
{ #if defined(NAZARA_PLATFORM_WINDOWS)
char* time = TimeInfo(); EnterCriticalSection(&mutex);
#elif defined(NAZARA_PLATFORM_POSIX)
FILE* log = std::fopen(MLTFileName, "a"); pthread_mutex_lock(&mutex);
#endif
if (nextFreeFile)
{ if (ptr->array != multi)
if (multi) {
std::fprintf(log, "%s Warning: delete[] after new at %s:%d\n", time, nextFreeFile, nextFreeLine); char* time = TimeInfo();
else
std::fprintf(log, "%s Warning: delete after new[] at %s:%d\n", time, nextFreeFile, nextFreeLine); FILE* log = std::fopen(MLTFileName, "a");
}
else if (nextFreeFile)
{ {
if (multi) if (multi)
std::fprintf(log, "%s Warning: delete[] after new at unknown position\n", time); std::fprintf(log, "%s Warning: delete[] after new at %s:%d\n", time, nextFreeFile, nextFreeLine);
else else
std::fprintf(log, "%s Warning: delete after new[] at unknown position\n", time); std::fprintf(log, "%s Warning: delete after new[] at %s:%d\n", time, nextFreeFile, nextFreeLine);
} }
else
std::fclose(log); {
if (multi)
std::free(time); std::fprintf(log, "%s Warning: delete[] after new at unknown position\n", time);
} else
std::fprintf(log, "%s Warning: delete after new[] at unknown position\n", time);
ptr->magic = 0; }
ptr->prev->next = ptr->next;
ptr->next->prev = ptr->prev; std::fclose(log);
std::free(ptr); std::free(time);
}
nextFreeFile = nullptr;
nextFreeLine = 0; ptr->magic = 0;
ptr->prev->next = ptr->next;
#if defined(NAZARA_PLATFORM_WINDOWS) ptr->next->prev = ptr->prev;
LeaveCriticalSection(&mutex);
#elif defined(NAZARA_PLATFORM_POSIX) std::free(ptr);
pthread_mutex_unlock(&mutex);
#endif nextFreeFile = nullptr;
} nextFreeLine = 0;
void NzMemoryManager::NextFree(const char* file, unsigned int line) #if defined(NAZARA_PLATFORM_WINDOWS)
{ LeaveCriticalSection(&mutex);
nextFreeFile = file; #elif defined(NAZARA_PLATFORM_POSIX)
nextFreeLine = line; pthread_mutex_unlock(&mutex);
} #endif
}
void NzMemoryManager::Initialize()
{ void NzMemoryManager::NextFree(const char* file, unsigned int line)
char* time = TimeInfo(); {
nextFreeFile = file;
FILE* file = std::fopen(MLTFileName, "w"); nextFreeLine = line;
std::fprintf(file, "%s ==============================\n", time); }
std::fprintf(file, "%s Nazara Memory Leak Tracker \n", time);
std::fprintf(file, "%s ==============================\n", time); void NzMemoryManager::Initialize()
std::fclose(file); {
char* time = TimeInfo();
std::free(time);
FILE* file = std::fopen(MLTFileName, "w");
if (std::atexit(Uninitialize) != 0) std::fprintf(file, "%s ==============================\n", time);
{ std::fprintf(file, "%s Nazara Memory Leak Tracker \n", time);
static NzMemoryManager manager; std::fprintf(file, "%s ==============================\n", time);
} std::fclose(file);
#ifdef NAZARA_PLATFORM_WINDOWS std::free(time);
InitializeCriticalSection(&mutex);
#endif if (std::atexit(Uninitialize) != 0)
{
initialized = true; static NzMemoryManager manager;
} }
char* NzMemoryManager::TimeInfo() #ifdef NAZARA_PLATFORM_WINDOWS
{ InitializeCriticalSection(&mutex);
char* buffer = reinterpret_cast<char*>(std::malloc(23*sizeof(char))); #endif
time_t currentTime = std::time(nullptr); initialized = true;
std::strftime(buffer, 23, "%d/%m/%Y - %H:%M:%S:", std::localtime(&currentTime)); }
return buffer; char* NzMemoryManager::TimeInfo()
} {
char* buffer = reinterpret_cast<char*>(std::malloc(23*sizeof(char)));
void NzMemoryManager::Uninitialize()
{ time_t currentTime = std::time(nullptr);
#ifdef NAZARA_PLATFORM_WINDOWS std::strftime(buffer, 23, "%d/%m/%Y - %H:%M:%S:", std::localtime(&currentTime));
DeleteCriticalSection(&mutex);
#endif return buffer;
}
FILE* log = std::fopen(MLTFileName, "a");
void NzMemoryManager::Uninitialize()
char* time = TimeInfo(); {
#ifdef NAZARA_PLATFORM_WINDOWS
std::fprintf(log, "%s Application finished, checking leaks...\n", time); DeleteCriticalSection(&mutex);
#endif
if (ptrList.next == &ptrList)
{ FILE* log = std::fopen(MLTFileName, "a");
std::fprintf(log, "%s ==============================\n", time);
std::fprintf(log, "%s No leak detected \n", time); char* time = TimeInfo();
std::fprintf(log, "%s ==============================", time);
} std::fprintf(log, "%s Application finished, checking leaks...\n", time);
else
{ if (ptrList.next == &ptrList)
std::fprintf(log, "%s ==============================\n", time); {
std::fprintf(log, "%s Leaks have been detected \n", time); std::fprintf(log, "%s ==============================\n", time);
std::fprintf(log, "%s ==============================\n\n", time); std::fprintf(log, "%s No leak detected \n", time);
std::fputs("Leak list:\n", log); std::fprintf(log, "%s ==============================", time);
}
Block* ptr = ptrList.next; else
unsigned int count = 0; {
unsigned int totalSize = 0; std::fprintf(log, "%s ==============================\n", time);
while (ptr != &ptrList) std::fprintf(log, "%s Leaks have been detected \n", time);
{ std::fprintf(log, "%s ==============================\n\n", time);
count++; std::fputs("Leak list:\n", log);
totalSize += ptr->size;
if (ptr->file) Block* ptr = ptrList.next;
std::fprintf(log, "-0x%p -> %d bytes allocated at %s:%d\n", reinterpret_cast<char*>(ptr)+sizeof(Block), ptr->size, ptr->file, ptr->line); unsigned int count = 0;
else unsigned int totalSize = 0;
std::fprintf(log, "-0x%p -> %d bytes allocated at unknown position\n", reinterpret_cast<char*>(ptr)+sizeof(Block), ptr->size); while (ptr != &ptrList)
{
void* pointer = ptr; count++;
ptr = ptr->next; totalSize += ptr->size;
std::free(pointer); if (ptr->file)
} std::fprintf(log, "-0x%p -> %d bytes allocated at %s:%d\n", reinterpret_cast<char*>(ptr)+sizeof(Block), ptr->size, ptr->file, ptr->line);
else
std::fprintf(log, "\n%d blocks leaked (%d bytes)", count, totalSize); std::fprintf(log, "-0x%p -> %d bytes allocated at unknown position\n", reinterpret_cast<char*>(ptr)+sizeof(Block), ptr->size);
}
void* pointer = ptr;
std::free(time); ptr = ptr->next;
std::fclose(log); std::free(pointer);
} }
void* operator new(std::size_t size, const char* file, unsigned int line) std::fprintf(log, "\n%d blocks leaked (%d bytes)", count, totalSize);
{ }
return NzMemoryManager::Allocate(size, false, file, line);
} std::free(time);
std::fclose(log);
void* operator new[](std::size_t size, const char* file, unsigned int line) }
{
return NzMemoryManager::Allocate(size, true, file, line); void* operator new(std::size_t size, const char* file, unsigned int line)
} {
return NzMemoryManager::Allocate(size, false, file, line);
void operator delete(void* ptr, const char* file, unsigned int line) throw() }
{
NzMemoryManager::NextFree(file, line); void* operator new[](std::size_t size, const char* file, unsigned int line)
NzMemoryManager::Free(ptr, false); {
} return NzMemoryManager::Allocate(size, true, file, line);
}
void operator delete[](void* ptr, const char* file, unsigned int line) throw()
{ void operator delete(void* ptr, const char* file, unsigned int line) throw()
NzMemoryManager::NextFree(file, line); {
NzMemoryManager::Free(ptr, true); NzMemoryManager::NextFree(file, line);
} NzMemoryManager::Free(ptr, false);
}
void operator delete[](void* ptr, const char* file, unsigned int line) throw()
{
NzMemoryManager::NextFree(file, line);
NzMemoryManager::Free(ptr, true);
}

View File

@ -1,54 +1,138 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module" // This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Resource.hpp> #include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/Config.hpp> #include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Debug.hpp> #include <Nazara/Core/ResourceListener.hpp>
#include <Nazara/Core/Debug.hpp>
NzResource::NzResource(bool persistent) :
m_resourcePersistent(persistent), NzResource::NzResource(bool persistent) :
m_resourceReferenceCount(0) m_resourcePersistent(persistent),
{ m_resourceReferenceCount(0)
} {
}
NzResource::NzResource(const NzResource& resource) :
m_resourcePersistent(resource.m_resourcePersistent), NzResource::NzResource(const NzResource& resource) :
m_resourceReferenceCount(0) m_resourcePersistent(resource.m_resourcePersistent),
{ m_resourceReferenceCount(0)
} {
}
NzResource::~NzResource() = default;
NzResource::~NzResource()
void NzResource::AddResourceReference() const {
{ EnsureResourceListenerUpdate();
m_resourceReferenceCount++;
} for (auto it = m_resourceListenersCache.begin(); it != m_resourceListenersCache.end(); ++it)
(*it).listener->OnResourceReleased(this, (*it).index);
bool NzResource::IsPersistent() const }
{
return m_resourcePersistent; void NzResource::AddResourceListener(NzResourceListener* listener, int index) const
} {
NazaraLock(m_mutex)
void NzResource::RemoveResourceReference() const
{ if (m_resourceListeners.insert(NzResourceEntry(listener, index)).second)
#if NAZARA_CORE_SAFE {
if (m_resourceReferenceCount == 0) m_resourceListenerUpdated = false;
{
NazaraError("Impossible to remove reference (Ref. counter is already 0)"); // AddResourceReference()
return; m_resourceReferenceCount++;
} }
#endif }
if (--m_resourceReferenceCount == 0 && !m_resourcePersistent) void NzResource::AddResourceReference() const
delete this; {
} NazaraLock(m_mutex)
void NzResource::SetPersistent(bool persistent) m_resourceReferenceCount++;
{ }
m_resourcePersistent = persistent;
bool NzResource::IsPersistent() const
if (!persistent && m_resourceReferenceCount == 0) {
delete this; NazaraLock(m_mutex)
}
return m_resourcePersistent;
}
void NzResource::RemoveResourceListener(NzResourceListener* listener) const
{
NazaraLock(m_mutex)
if (m_resourceListeners.erase(listener) != 0)
m_resourceListenerUpdated = false;
else
NazaraError(NzString::Pointer(listener) + " is not listening to " + NzString::Pointer(this));
RemoveResourceReference();
}
void NzResource::RemoveResourceReference() const
{
NazaraMutexLock(m_mutex);
#if NAZARA_CORE_SAFE
if (m_resourceReferenceCount == 0)
{
NazaraError("Impossible to remove reference (Ref. counter is already 0)");
return;
}
#endif
if (--m_resourceReferenceCount == 0 && !m_resourcePersistent)
{
NazaraMutexUnlock(m_mutex);
delete this;
}
else
{
NazaraMutexUnlock(m_mutex);
}
}
void NzResource::SetPersistent(bool persistent)
{
NazaraMutexLock(m_mutex);
m_resourcePersistent = persistent;
if (!persistent && m_resourceReferenceCount == 0)
{
NazaraMutexUnlock(m_mutex);
delete this;
}
else
{
NazaraMutexUnlock(m_mutex);
}
}
void NzResource::NotifyCreated()
{
NazaraLock(m_mutex)
EnsureResourceListenerUpdate();
for (auto it = m_resourceListenersCache.begin(); it != m_resourceListenersCache.end(); ++it)
(*it).listener->OnResourceCreated(this, (*it).index);
}
void NzResource::NotifyDestroy()
{
NazaraLock(m_mutex)
EnsureResourceListenerUpdate();
for (auto it = m_resourceListenersCache.begin(); it != m_resourceListenersCache.end(); ++it)
(*it).listener->OnResourceDestroy(this, (*it).index);
}
void NzResource::EnsureResourceListenerUpdate() const
{
// Déjà bloqué par une mutex
if (!m_resourceListenerUpdated)
{
m_resourceListenersCache = m_resourceListeners;
m_resourceListenerUpdated = true;
}
}

View File

@ -0,0 +1,26 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/ResourceListener.hpp>
#include <Nazara/Core/Debug.hpp>
NzResourceListener::~NzResourceListener() = default;
void NzResourceListener::OnResourceCreated(const NzResource* resource, int index)
{
NazaraUnused(resource);
NazaraUnused(index);
}
void NzResourceListener::OnResourceDestroy(const NzResource* resource, int index)
{
NazaraUnused(resource);
NazaraUnused(index);
}
void NzResourceListener::OnResourceReleased(const NzResource* resource, int index)
{
NazaraUnused(resource);
NazaraUnused(index);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,355 +1,359 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module" // This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/OpenGL.hpp> #include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/Context.hpp> #include <Nazara/Renderer/Context.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Log.hpp> #include <Nazara/Core/Log.hpp>
#include <Nazara/Core/StringStream.hpp> #include <Nazara/Core/StringStream.hpp>
#include <Nazara/Renderer/Config.hpp> #include <Nazara/Renderer/Config.hpp>
#include <vector> #include <vector>
#if defined(NAZARA_PLATFORM_WINDOWS) #if defined(NAZARA_PLATFORM_WINDOWS)
#include <Nazara/Renderer/Win32/ContextImpl.hpp> #include <Nazara/Renderer/Win32/ContextImpl.hpp>
#elif defined(NAZARA_PLATFORM_LINUX) #elif defined(NAZARA_PLATFORM_LINUX)
#include <Nazara/Renderer/Linux/ContextImpl.hpp> #include <Nazara/Renderer/Linux/ContextImpl.hpp>
#else #else
#error Lack of implementation: Context #error Lack of implementation: Context
#endif #endif
#include <Nazara/Renderer/Debug.hpp> #include <Nazara/Renderer/Debug.hpp>
namespace namespace
{ {
NAZARA_THREADLOCAL NzContext* currentContext = nullptr; NAZARA_THREADLOCAL NzContext* currentContext = nullptr;
NAZARA_THREADLOCAL NzContext* threadContext = nullptr; NAZARA_THREADLOCAL NzContext* threadContext = nullptr;
std::vector<NzContext*> contexts; std::vector<NzContext*> contexts;
void CALLBACK DebugCallback(unsigned int source, unsigned int type, unsigned int id, unsigned int severity, int length, const char* message, void* userParam) void CALLBACK DebugCallback(unsigned int source, unsigned int type, unsigned int id, unsigned int severity, int length, const char* message, void* userParam)
{ {
NazaraUnused(length); NazaraUnused(length);
NzStringStream ss; NzStringStream ss;
ss << "OpenGL debug message (ID: 0x" << NzString::Number(id, 16) << "):\n"; ss << "OpenGL debug message (ID: 0x" << NzString::Number(id, 16) << "):\n";
ss << "Sent by context: " << userParam; ss << "Sent by context: " << userParam;
ss << "\n-Source: "; ss << "\n-Source: ";
switch (source) switch (source)
{ {
case GL_DEBUG_SOURCE_API_ARB: case GL_DEBUG_SOURCE_API_ARB:
ss << "OpenGL"; ss << "OpenGL";
break; break;
case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
ss << "Operating system"; ss << "Operating system";
break; break;
case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
ss << "Shader compiler"; ss << "Shader compiler";
break; break;
case GL_DEBUG_SOURCE_THIRD_PARTY_ARB: case GL_DEBUG_SOURCE_THIRD_PARTY_ARB:
ss << "Shader compiler"; ss << "Shader compiler";
break; break;
case GL_DEBUG_SOURCE_APPLICATION_ARB: case GL_DEBUG_SOURCE_APPLICATION_ARB:
ss << "Application"; ss << "Application";
break; break;
case GL_DEBUG_SOURCE_OTHER_ARB: case GL_DEBUG_SOURCE_OTHER_ARB:
ss << "Other"; ss << "Other";
break; break;
default: default:
// Peut être rajouté par une extension // Peut être rajouté par une extension
ss << "Unknown"; ss << "Unknown";
break; break;
} }
ss << '\n'; ss << '\n';
ss << "-Type: "; ss << "-Type: ";
switch (type) switch (type)
{ {
case GL_DEBUG_TYPE_ERROR_ARB: case GL_DEBUG_TYPE_ERROR_ARB:
ss << "Error"; ss << "Error";
break; break;
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
ss << "Deprecated behavior"; ss << "Deprecated behavior";
break; break;
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
ss << "Undefined behavior"; ss << "Undefined behavior";
break; break;
case GL_DEBUG_TYPE_PORTABILITY_ARB: case GL_DEBUG_TYPE_PORTABILITY_ARB:
ss << "Portability"; ss << "Portability";
break; break;
case GL_DEBUG_TYPE_PERFORMANCE_ARB: case GL_DEBUG_TYPE_PERFORMANCE_ARB:
ss << "Performance"; ss << "Performance";
break; break;
case GL_DEBUG_TYPE_OTHER_ARB: case GL_DEBUG_TYPE_OTHER_ARB:
ss << "Other"; ss << "Other";
break; break;
default: default:
// Peut être rajouté par une extension // Peut être rajouté par une extension
ss << "Unknown"; ss << "Unknown";
break; break;
} }
ss << '\n'; ss << '\n';
ss << "-Severity: "; ss << "-Severity: ";
switch (severity) switch (severity)
{ {
case GL_DEBUG_SEVERITY_HIGH_ARB: case GL_DEBUG_SEVERITY_HIGH_ARB:
ss << "High"; ss << "High";
break; break;
case GL_DEBUG_SEVERITY_MEDIUM_ARB: case GL_DEBUG_SEVERITY_MEDIUM_ARB:
ss << "Medium"; ss << "Medium";
break; break;
case GL_DEBUG_SEVERITY_LOW_ARB: case GL_DEBUG_SEVERITY_LOW_ARB:
ss << "Low"; ss << "Low";
break; break;
default: default:
// Peut être rajouté par une extension // Peut être rajouté par une extension
ss << "Unknown"; ss << "Unknown";
break; break;
} }
ss << '\n'; ss << '\n';
ss << "Message: " << message << '\n'; ss << "Message: " << message << '\n';
NazaraNotice(ss); NazaraNotice(ss);
} }
} }
NzContext::NzContext() : NzContext::NzContext() :
m_impl(nullptr) m_impl(nullptr)
{ {
} }
NzContext::~NzContext() NzContext::~NzContext()
{ {
Destroy(); Destroy();
} }
bool NzContext::Create(const NzContextParameters& parameters) bool NzContext::Create(const NzContextParameters& parameters)
{ {
Destroy(); Destroy();
m_parameters = parameters; m_parameters = parameters;
if (m_parameters.shared && !m_parameters.shareContext) if (m_parameters.shared && !m_parameters.shareContext)
m_parameters.shareContext = s_reference; m_parameters.shareContext = s_reference;
m_impl = new NzContextImpl; m_impl = new NzContextImpl;
if (!m_impl->Create(m_parameters)) if (!m_impl->Create(m_parameters))
{ {
NazaraError("Failed to create context implementation"); NazaraError("Failed to create context implementation");
delete m_impl; delete m_impl;
m_impl = nullptr; m_impl = nullptr;
return false; return false;
} }
if (!m_impl->Activate()) if (!m_impl->Activate())
{ {
NazaraError("Failed to activate context"); NazaraError("Failed to activate context");
m_impl->Destroy(); m_impl->Destroy();
delete m_impl; delete m_impl;
m_impl = nullptr; m_impl = nullptr;
return false; return false;
} }
if (m_parameters.antialiasingLevel > 0) if (m_parameters.antialiasingLevel > 0)
glEnable(GL_MULTISAMPLE); glEnable(GL_MULTISAMPLE);
if (NzOpenGL::IsSupported(NzOpenGL::DebugOutput) && m_parameters.debugMode) if (NzOpenGL::IsSupported(nzOpenGLExtension_DebugOutput) && m_parameters.debugMode)
{ {
glDebugMessageCallback(&DebugCallback, this); glDebugMessageCallback(&DebugCallback, this);
#ifdef NAZARA_DEBUG #ifdef NAZARA_DEBUG
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
#endif #endif
} }
return true; NotifyCreated();
}
return true;
void NzContext::Destroy() }
{
if (m_impl) void NzContext::Destroy()
{ {
if (currentContext == this) if (m_impl)
NzContextImpl::Desactivate(); {
NotifyDestroy();
m_impl->Destroy();
delete m_impl; if (currentContext == this)
m_impl = nullptr; NzContextImpl::Desactivate();
}
} m_impl->Destroy();
delete m_impl;
const NzContextParameters& NzContext::GetParameters() const m_impl = nullptr;
{ }
#ifdef NAZARA_RENDERER_SAFE }
if (!m_impl)
NazaraError("No context has been created"); const NzContextParameters& NzContext::GetParameters() const
#endif {
#ifdef NAZARA_RENDERER_SAFE
return m_parameters; if (!m_impl)
} NazaraError("No context has been created");
#endif
bool NzContext::IsActive() const
{ return m_parameters;
#ifdef NAZARA_RENDERER_SAFE }
if (!m_impl)
{ bool NzContext::IsActive() const
NazaraError("No context has been created"); {
return false; #ifdef NAZARA_RENDERER_SAFE
} if (!m_impl)
#endif {
NazaraError("No context has been created");
return currentContext == this; return false;
} }
#endif
bool NzContext::SetActive(bool active)
{ return currentContext == this;
#ifdef NAZARA_RENDERER_SAFE }
if (!m_impl)
{ bool NzContext::SetActive(bool active)
NazaraError("No context has been created"); {
return false; #ifdef NAZARA_RENDERER_SAFE
} if (!m_impl)
#endif {
NazaraError("No context has been created");
// Si le contexte est déjà activé/désactivé return false;
if ((currentContext == this) == active) }
return true; #endif
if (active) // Si le contexte est déjà activé/désactivé
{ if ((currentContext == this) == active)
if (!m_impl->Activate()) return true;
return false;
if (active)
currentContext = this; {
} if (!m_impl->Activate())
else return false;
{
if (!NzContextImpl::Desactivate()) currentContext = this;
return false; }
else
currentContext = nullptr; {
} if (!NzContextImpl::Desactivate())
return false;
return true;
} currentContext = nullptr;
}
void NzContext::SwapBuffers()
{ return true;
#ifdef NAZARA_RENDERER_SAFE }
if (!m_impl)
{ void NzContext::SwapBuffers()
NazaraError("No context has been created"); {
return; #ifdef NAZARA_RENDERER_SAFE
} if (!m_impl)
{
if (!m_parameters.doubleBuffered) NazaraError("No context has been created");
{ return;
NazaraError("Context is not double buffered"); }
return;
} if (!m_parameters.doubleBuffered)
#endif {
NazaraError("Context is not double buffered");
m_impl->SwapBuffers(); return;
} }
#endif
bool NzContext::EnsureContext()
{ m_impl->SwapBuffers();
if (!currentContext) }
{
if (!threadContext) bool NzContext::EnsureContext()
{ {
NzContext* context = new NzContext; if (!currentContext)
if (!context->Create()) {
{ if (!threadContext)
NazaraError("Failed to create context"); {
delete context; NzContext* context = new NzContext;
if (!context->Create())
return false; {
} NazaraError("Failed to create context");
delete context;
contexts.push_back(context);
return false;
threadContext = context; }
}
contexts.push_back(context);
if (!threadContext->SetActive(true))
{ threadContext = context;
NazaraError("Failed to active thread context"); }
return false;
} if (!threadContext->SetActive(true))
} {
NazaraError("Failed to active thread context");
return true; return false;
} }
}
NzContext* NzContext::GetCurrent()
{ return true;
return currentContext; }
}
NzContext* NzContext::GetCurrent()
const NzContext* NzContext::GetReference() {
{ return currentContext;
return s_reference; }
}
const NzContext* NzContext::GetReference()
NzContext* NzContext::GetThreadContext() {
{ return s_reference;
EnsureContext(); }
return threadContext; NzContext* NzContext::GetThreadContext()
} {
EnsureContext();
bool NzContext::Initialize()
{ return threadContext;
NzContextParameters parameters; }
// parameters.compatibilityProfile = true;
parameters.shared = false; // Difficile de partager le contexte de référence avec lui-même bool NzContext::Initialize()
{
s_reference = new NzContext; NzContextParameters parameters;
if (!s_reference->Create(parameters)) // parameters.compatibilityProfile = true;
{ parameters.shared = false; // Difficile de partager le contexte de référence avec lui-même
delete s_reference;
s_reference = nullptr; s_reference = new NzContext;
if (!s_reference->Create(parameters))
return false; {
} delete s_reference;
s_reference = nullptr;
// Le contexte de référence doit rester désactivé pour le partage
s_reference->SetActive(false); return false;
}
NzContextParameters::defaultShareContext = s_reference;
// Le contexte de référence doit rester désactivé pour le partage
return true; s_reference->SetActive(false);
}
NzContextParameters::defaultShareContext = s_reference;
void NzContext::Uninitialize()
{ return true;
for (NzContext* context : contexts) }
delete context;
void NzContext::Uninitialize()
contexts.clear(); // On supprime tous les contextes créés {
for (NzContext* context : contexts)
delete s_reference; delete context;
s_reference = nullptr;
} contexts.clear(); // On supprime tous les contextes créés
NzContext* NzContext::s_reference = nullptr; delete s_reference;
s_reference = nullptr;
}
NzContext* NzContext::s_reference = nullptr;

File diff suppressed because it is too large Load Diff

View File

@ -1,73 +1,81 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module" // This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once #pragma once
#ifndef NAZARA_GLSLSHADER_HPP #ifndef NAZARA_GLSLSHADER_HPP
#define NAZARA_GLSLSHADER_HPP #define NAZARA_GLSLSHADER_HPP
#include <Nazara/Core/String.hpp> #include <Nazara/Core/ResourceListener.hpp>
#include <Nazara/Renderer/OpenGL.hpp> #include <Nazara/Core/String.hpp>
#include <Nazara/Renderer/Shader.hpp> #include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/ShaderImpl.hpp> #include <Nazara/Renderer/Shader.hpp>
#include <map> #include <Nazara/Renderer/ShaderImpl.hpp>
#include <map>
class NzGLSLShader : public NzShaderImpl
{ class NzResource;
public:
NzGLSLShader(NzShader* parent); class NzGLSLShader : public NzShaderImpl, NzResourceListener
~NzGLSLShader(); {
public:
bool Bind(); NzGLSLShader(NzShader* parent);
bool BindTextures(); ~NzGLSLShader();
bool Compile(); bool Bind();
bool BindTextures();
bool Create();
void Destroy(); bool Compile();
NzString GetLog() const; bool Create();
nzShaderLanguage GetLanguage() const; void Destroy();
NzString GetSourceCode(nzShaderType type) const;
int GetUniformLocation(const NzString& name) const; NzString GetLog() const;
nzShaderLanguage GetLanguage() const;
bool IsLoaded(nzShaderType type) const; NzString GetSourceCode(nzShaderType type) const;
int GetUniformLocation(const NzString& name) const;
bool Load(nzShaderType type, const NzString& source);
bool Lock(); bool IsLoaded(nzShaderType type) const;
bool SendBoolean(int location, bool value); bool Load(nzShaderType type, const NzString& source);
bool SendDouble(int location, double value); bool Lock();
bool SendFloat(int location, float value);
bool SendInteger(int location, int value); bool SendBoolean(int location, bool value);
bool SendMatrix(int location, const NzMatrix4d& matrix); bool SendDouble(int location, double value);
bool SendMatrix(int location, const NzMatrix4f& matrix); bool SendFloat(int location, float value);
bool SendTexture(int location, const NzTexture* texture); bool SendInteger(int location, int value);
bool SendVector(int location, const NzVector2d& vector); bool SendMatrix(int location, const NzMatrix4d& matrix);
bool SendVector(int location, const NzVector2f& vector); bool SendMatrix(int location, const NzMatrix4f& matrix);
bool SendVector(int location, const NzVector3d& vector); bool SendTexture(int location, const NzTexture* texture);
bool SendVector(int location, const NzVector3f& vector); bool SendVector(int location, const NzVector2d& vector);
bool SendVector(int location, const NzVector4d& vector); bool SendVector(int location, const NzVector2f& vector);
bool SendVector(int location, const NzVector4f& vector); bool SendVector(int location, const NzVector3d& vector);
bool SendVector(int location, const NzVector3f& vector);
void Unbind(); bool SendVector(int location, const NzVector4d& vector);
void Unlock(); bool SendVector(int location, const NzVector4f& vector);
private: void Unbind();
struct TextureSlot void Unlock();
{
bool updated = false; private:
nzUInt8 unit; void OnResourceCreated(const NzResource* resource, int index) override;
const NzTexture* texture; void OnResourceDestroy(const NzResource* resource, int index) override;
}; void OnResourceReleased(const NzResource* resource, int index) override;
mutable std::map<NzString, GLint> m_idCache; struct TextureSlot
std::map<GLint, TextureSlot> m_textures; {
GLuint m_program; bool enabled;
GLuint m_shaders[nzShaderType_Max+1]; bool updated = false;
NzShader* m_parent; nzUInt8 unit;
NzString m_log; const NzTexture* texture;
}; };
#endif // NAZARA_GLSLSHADER_HPPs mutable std::map<NzString, GLint> m_idCache;
std::map<GLint, TextureSlot> m_textures;
GLuint m_program;
GLuint m_shaders[nzShaderType_Max+1];
NzShader* m_parent;
NzString m_log;
};
#endif // NAZARA_GLSLSHADER_HPPs

View File

@ -1,250 +1,218 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module" // This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/OpenGL.hpp> #include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/HardwareBuffer.hpp> #include <Nazara/Renderer/HardwareBuffer.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/Context.hpp> #include <Nazara/Renderer/Context.hpp>
#include <cstring> #include <cstring>
#include <stdexcept> #include <stdexcept>
#include <Nazara/Renderer/Debug.hpp> #include <Nazara/Renderer/Debug.hpp>
namespace namespace
{ {
GLenum bufferLock[] = { using LockRoutine = nzUInt8* (*)(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size);
GL_WRITE_ONLY, // nzBufferAccess_DiscardAndWrite
GL_READ_ONLY, // nzBufferAccess_ReadOnly nzUInt8* LockBuffer(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size)
GL_READ_WRITE, // nzBufferAccess_ReadWrite {
GL_WRITE_ONLY // nzBufferAccess_WriteOnly NazaraUnused(size);
};
if (access == nzBufferAccess_DiscardAndWrite)
GLenum bufferLockRange[] = { {
GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_WRITE_BIT, // nzBufferAccess_DiscardAndWrite GLint bufSize;
GL_MAP_READ_BIT, // nzBufferAccess_ReadOnly glGetBufferParameteriv(NzOpenGL::BufferTargetBinding[type], GL_BUFFER_SIZE, &bufSize);
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, // nzBufferAccess_ReadWrite
GL_MAP_WRITE_BIT // nzBufferAccess_WriteOnly GLint bufUsage;
}; glGetBufferParameteriv(NzOpenGL::BufferTargetBinding[type], GL_BUFFER_USAGE, &bufUsage);
GLenum bufferTarget[] = { // On discard le buffer
GL_ELEMENT_ARRAY_BUFFER, // nzBufferType_Index, glBufferData(NzOpenGL::BufferTargetBinding[type], bufSize, nullptr, bufUsage);
GL_ARRAY_BUFFER, // nzBufferType_Vertex }
};
void* ptr = glMapBuffer(NzOpenGL::BufferTarget[type], NzOpenGL::BufferLock[access]);
GLenum bufferTargetBinding[] = { if (ptr)
GL_ELEMENT_ARRAY_BUFFER_BINDING, // nzBufferType_Index, return reinterpret_cast<nzUInt8*>(ptr) + offset;
GL_ARRAY_BUFFER_BINDING, // nzBufferType_Vertex else
}; return nullptr;
}
GLenum bufferUsage[] = {
// J'ai choisi DYNAMIC à la place de STREAM car DYNAMIC semble plus adapté au profil "une mise à jour pour quelques rendus" nzUInt8* LockBufferRange(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size)
// Ce qui est je pense le scénario qui arrivera le plus souvent (Prévoir une option pour permettre d'utiliser le STREAM_DRAW ?) {
// Source: http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=160839 return reinterpret_cast<nzUInt8*>(glMapBufferRange(NzOpenGL::BufferTarget[type], offset, size, NzOpenGL::BufferLockRange[access]));
GL_DYNAMIC_DRAW, // nzBufferUsage_Dynamic }
GL_STATIC_DRAW // nzBufferUsage_Static
}; nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size);
using LockRoutine = nzUInt8* (*)(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size); LockRoutine mapBuffer = LockBufferFirstRun;
nzUInt8* LockBuffer(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size) nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size)
{ {
NazaraUnused(size); if (glMapBufferRange)
mapBuffer = LockBufferRange;
if (access == nzBufferAccess_DiscardAndWrite) else
{ mapBuffer = LockBuffer;
GLint bufSize;
glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_SIZE, &bufSize); return mapBuffer(type, access, offset, size);
}
GLint bufUsage; }
glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_USAGE, &bufUsage);
NzHardwareBuffer::NzHardwareBuffer(NzBuffer* parent, nzBufferType type) :
// On discard le buffer m_type(type),
glBufferData(bufferTargetBinding[type], bufSize, nullptr, bufUsage); m_parent(parent)
} {
}
void* ptr = glMapBuffer(bufferTarget[type], bufferLock[access]);
if (ptr) NzHardwareBuffer::~NzHardwareBuffer()
return reinterpret_cast<nzUInt8*>(ptr) + offset; {
else }
return nullptr;
} void NzHardwareBuffer::Bind()
{
nzUInt8* LockBufferRange(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size) #ifdef NAZARA_DEBUG
{ if (NzContext::GetCurrent() == nullptr)
return reinterpret_cast<nzUInt8*>(glMapBufferRange(bufferTarget[type], offset, size, bufferLockRange[access])); {
} NazaraError("No active context");
return;
nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size); }
#endif
LockRoutine mapBuffer = LockBufferFirstRun;
glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size) }
{
if (glMapBufferRange) bool NzHardwareBuffer::Create(unsigned int size, nzBufferUsage usage)
mapBuffer = LockBufferRange; {
else NzContext::EnsureContext();
mapBuffer = LockBuffer;
m_buffer = 0;
return mapBuffer(type, access, offset, size); glGenBuffers(1, &m_buffer);
}
} GLint previous;
glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], &previous);
NzHardwareBuffer::NzHardwareBuffer(NzBuffer* parent, nzBufferType type) :
m_type(type), glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
m_parent(parent) glBufferData(NzOpenGL::BufferTarget[m_type], size, nullptr, NzOpenGL::BufferUsage[usage]);
{
} // Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent
if (previous != 0)
NzHardwareBuffer::~NzHardwareBuffer() glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
{
} return true;
}
void NzHardwareBuffer::Bind()
{ void NzHardwareBuffer::Destroy()
#ifdef NAZARA_DEBUG {
if (NzContext::GetCurrent() == nullptr) NzContext::EnsureContext();
{
NazaraError("No active context"); glDeleteBuffers(1, &m_buffer);
return; }
}
#endif bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size)
{
glBindBuffer(bufferTarget[m_type], m_buffer); NzContext::EnsureContext();
}
GLuint previous;
bool NzHardwareBuffer::Create(unsigned int size, nzBufferUsage usage) glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
{
NzContext::EnsureContext(); if (previous != m_buffer)
glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
m_buffer = 0;
glGenBuffers(1, &m_buffer); // Il semblerait que glBuffer(Sub)Data soit plus performant que glMapBuffer(Range) en dessous d'un certain seuil
// http://www.stevestreeting.com/2007/03/17/glmapbuffer-vs-glbuffersubdata-the-return/
GLint previous; if (size < 32*1024)
glGetIntegerv(bufferTargetBinding[m_type], &previous); {
// http://www.opengl.org/wiki/Vertex_Specification_Best_Practices
glBindBuffer(bufferTarget[m_type], m_buffer); if (size == m_parent->GetSize())
glBufferData(bufferTarget[m_type], size, nullptr, bufferUsage[usage]); glBufferData(NzOpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, NzOpenGL::BufferUsage[m_parent->GetUsage()]); // Discard
// Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent glBufferSubData(NzOpenGL::BufferTarget[m_type], offset, size, data);
if (previous != 0) }
glBindBuffer(bufferTarget[m_type], previous); else
{
return true; nzUInt8* ptr = mapBuffer(m_type, (size == m_parent->GetSize()) ? nzBufferAccess_DiscardAndWrite : nzBufferAccess_WriteOnly, offset, size);
} if (!ptr)
{
void NzHardwareBuffer::Destroy() NazaraError("Failed to map buffer");
{ return false;
NzContext::EnsureContext(); }
glDeleteBuffers(1, &m_buffer); std::memcpy(ptr, data, size);
}
if (glUnmapBuffer(NzOpenGL::BufferTarget[m_type]) != GL_TRUE)
bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size) {
{ // Une erreur rare est survenue, nous devons réinitialiser le buffer
NzContext::EnsureContext(); NazaraError("Failed to unmap buffer, reinitialising content... (OpenGL error : 0x" + NzString::Number(glGetError(), 16) + ')');
GLuint previous; glBufferData(NzOpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, NzOpenGL::BufferUsage[m_parent->GetStorage()]);
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
return false;
if (previous != m_buffer) }
glBindBuffer(bufferTarget[m_type], m_buffer); }
// Il semblerait que glBuffer(Sub)Data soit plus performant que glMapBuffer(Range) en dessous d'un certain seuil // Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées)
// http://www.stevestreeting.com/2007/03/17/glmapbuffer-vs-glbuffersubdata-the-return/ if (previous != m_buffer && previous != 0)
if (size < 32*1024) glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
{
// http://www.opengl.org/wiki/Vertex_Specification_Best_Practices return true;
if (size == m_parent->GetSize()) }
glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetUsage()]); // Discard
void* NzHardwareBuffer::GetPointer()
glBufferSubData(bufferTarget[m_type], offset, size, data); {
} return nullptr;
else }
{
nzUInt8* ptr = mapBuffer(m_type, (size == m_parent->GetSize()) ? nzBufferAccess_DiscardAndWrite : nzBufferAccess_WriteOnly, offset, size); bool NzHardwareBuffer::IsHardware() const
if (!ptr) {
{ return true;
NazaraError("Failed to map buffer"); }
return false;
} void* NzHardwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size)
{
std::memcpy(ptr, data, size); NzContext::EnsureContext();
if (glUnmapBuffer(bufferTarget[m_type]) != GL_TRUE) // Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent
{ GLuint previous;
// Une erreur rare est survenue, nous devons réinitialiser le buffer glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
NazaraError("Failed to unmap buffer, reinitialising content... (OpenGL error : 0x" + NzString::Number(glGetError(), 16) + ')');
if (previous != m_buffer)
glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetStorage()]); glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
return false; 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)
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées) glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
if (previous != m_buffer && previous != 0)
glBindBuffer(bufferTarget[m_type], previous); return ptr;
}
return true;
} bool NzHardwareBuffer::Unmap()
{
void* NzHardwareBuffer::GetPointer() NzContext::EnsureContext();
{
return nullptr; GLuint previous;
} glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
bool NzHardwareBuffer::IsHardware() const if (previous != m_buffer)
{ glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
return true;
} if (glUnmapBuffer(NzOpenGL::BufferTarget[m_type]) != GL_TRUE)
{
void* NzHardwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size) // Une erreur rare est survenue, nous devons réinitialiser le buffer
{ NazaraError("Failed to unmap buffer, reinitialising content... (OpenGL error : 0x" + NzString::Number(glGetError(), 16) + ')');
NzContext::EnsureContext();
glBufferData(NzOpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, NzOpenGL::BufferUsage[m_parent->GetStorage()]);
// Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent
GLuint previous; // Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées)
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous)); if (previous != m_buffer && previous != 0)
glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
if (previous != m_buffer)
glBindBuffer(bufferTarget[m_type], m_buffer); return false;
}
void* ptr = mapBuffer(m_type, access, offset, size);
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées)
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérrations chaînées) if (previous != m_buffer && previous != 0)
if (previous != m_buffer && previous != 0) glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
glBindBuffer(bufferTarget[m_type], previous);
return true;
return ptr; }
}
bool NzHardwareBuffer::Unmap()
{
NzContext::EnsureContext();
GLuint previous;
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
if (previous != m_buffer)
glBindBuffer(bufferTarget[m_type], m_buffer);
if (glUnmapBuffer(bufferTarget[m_type]) != GL_TRUE)
{
// Une erreur rare est survenue, nous devons réinitialiser le buffer
NazaraError("Failed to unmap buffer, reinitialising content... (OpenGL error : 0x" + NzString::Number(glGetError(), 16) + ')');
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é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érations chaînées)
if (previous != m_buffer && previous != 0)
glBindBuffer(bufferTarget[m_type], previous);
return true;
}

View File

@ -1,102 +1,98 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module" // This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/OpenGL.hpp> #include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/OcclusionQuery.hpp> #include <Nazara/Renderer/OcclusionQuery.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/Config.hpp> #include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/Context.hpp> #include <Nazara/Renderer/Context.hpp>
#include <Nazara/Renderer/Renderer.hpp> #include <Nazara/Renderer/Renderer.hpp>
#include <stdexcept> #include <stdexcept>
#include <Nazara/Renderer/Debug.hpp> #include <Nazara/Renderer/Debug.hpp>
NzOcclusionQuery::NzOcclusionQuery() : NzOcclusionQuery::NzOcclusionQuery() :
m_id(0) m_id(0)
{ {
#if NAZARA_RENDERER_SAFE if (IsSupported())
if (IsSupported()) {
{ NzContext::EnsureContext();
#endif
NzContext::EnsureContext(); glGenQueries(1, reinterpret_cast<GLuint*>(&m_id));
}
glGenQueries(1, reinterpret_cast<GLuint*>(&m_id)); else
#if NAZARA_RENDERER_SAFE {
} NazaraError("Occlusion queries not supported");
else return;
{ }
NazaraError("Occlusion queries not supported");
return; #ifdef NAZARA_DEBUG
} if (!m_id)
#endif {
NazaraError("Failed to create occlusion query");
#ifdef NAZARA_DEBUG throw std::runtime_error("Constructor failed");
if (!m_id) }
{ #endif
NazaraError("Failed to create occlusion query"); }
throw std::runtime_error("Constructor failed");
} NzOcclusionQuery::~NzOcclusionQuery()
#endif {
} if (m_id)
{
NzOcclusionQuery::~NzOcclusionQuery() NzContext::EnsureContext();
{
if (m_id) GLuint query = static_cast<GLuint>(m_id);
{ glDeleteQueries(1, &query);
NzContext::EnsureContext(); }
}
GLuint query = static_cast<GLuint>(m_id);
glDeleteQueries(1, &query); void NzOcclusionQuery::Begin()
} {
} #ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr)
void NzOcclusionQuery::Begin() {
{ NazaraError("No active context");
#ifdef NAZARA_DEBUG return;
if (NzContext::GetCurrent() == nullptr) }
{ #endif
NazaraError("No active context");
return; glBeginQuery(GL_SAMPLES_PASSED, m_id);
} }
#endif
void NzOcclusionQuery::End()
glBeginQuery(GL_SAMPLES_PASSED, m_id); {
} #ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr)
void NzOcclusionQuery::End() {
{ NazaraError("No active context");
#ifdef NAZARA_DEBUG return;
if (NzContext::GetCurrent() == nullptr) }
{ #endif
NazaraError("No active context");
return; glEndQuery(GL_SAMPLES_PASSED);
} }
#endif
unsigned int NzOcclusionQuery::GetResult() const
glEndQuery(GL_SAMPLES_PASSED); {
} NzContext::EnsureContext();
unsigned int NzOcclusionQuery::GetResult() const GLuint result;
{ glGetQueryObjectuiv(m_id, GL_QUERY_RESULT, &result);
NzContext::EnsureContext();
return result;
GLuint result; }
glGetQueryObjectuiv(m_id, GL_QUERY_RESULT, &result);
bool NzOcclusionQuery::IsResultAvailable() const
return result; {
} NzContext::EnsureContext();
bool NzOcclusionQuery::IsResultAvailable() const GLint available;
{ glGetQueryObjectiv(m_id, GL_QUERY_RESULT_AVAILABLE, &available);
NzContext::EnsureContext();
return available == GL_TRUE;
GLint available; }
glGetQueryObjectiv(m_id, GL_QUERY_RESULT_AVAILABLE, &available);
bool NzOcclusionQuery::IsSupported()
return available == GL_TRUE; {
} return NzRenderer::HasCapability(nzRendererCap_OcclusionQuery);
}
bool NzOcclusionQuery::IsSupported()
{
return NzRenderer::HasCapability(nzRendererCap_OcclusionQuery);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,728 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/RenderTexture.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <vector>
#include <Nazara/Renderer/Debug.hpp>
namespace
{
struct Attachment
{
union
{
GLuint buffer;
NzTexture* texture;
};
bool isBuffer;
bool isUsed = false;
};
unsigned int attachmentIndex[nzAttachmentPoint_Max+1] =
{
2, // nzAttachmentPoint_Color
0, // nzAttachmentPoint_Depth
0, // nzAttachmentPoint_DepthStencil
1 // nzAttachmentPoint_Stencil
};
nzAttachmentPoint formatTypeToAttachment[nzPixelFormatType_Max+1] =
{
nzAttachmentPoint_Color, // nzPixelFormatType_Color
nzAttachmentPoint_Depth, // nzPixelFormatType_Depth
nzAttachmentPoint_DepthStencil, // nzPixelFormatType_DepthStencil
nzAttachmentPoint_Stencil // nzPixelFormatType_Stencil
};
GLuint lockedPrevious = 0;
nzUInt8 lockedLevel = 0;
}
struct NzRenderTextureImpl
{
GLuint fbo;
std::vector<Attachment> attachements;
std::vector<GLenum> drawBuffers;
NzContext* context;
bool checked = false;
bool complete = false;
bool drawBuffersUpdated = true;
unsigned int height;
unsigned int width;
};
NzRenderTexture::~NzRenderTexture()
{
Destroy();
}
bool NzRenderTexture::AttachBuffer(nzAttachmentPoint attachmentPoint, nzUInt8 index, nzPixelFormat format)
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Render texture not created");
return false;
}
if (attachmentPoint != nzAttachmentPoint_Color && index > 0)
{
NazaraError("Index must be 0 for non-color attachments");
return false;
}
unsigned int depthStencilIndex = attachmentIndex[nzAttachmentPoint_DepthStencil];
if (attachmentPoint == nzAttachmentPoint_Stencil && m_impl->attachements.size() > depthStencilIndex &&
m_impl->attachements[depthStencilIndex].isUsed)
{
NazaraError("Stencil target already attached by DepthStencil attachment");
return false;
}
if (formatTypeToAttachment[NzPixelFormat::GetType(format)] != attachmentPoint)
{
NazaraError("Pixel format type does not match attachment point type");
return false;
}
#endif
NzOpenGL::Format openglFormat;
if (!NzOpenGL::TranslateFormat(format, &openglFormat, NzOpenGL::FormatType_RenderBuffer))
{
NazaraError("Failed to translate pixel format into OpenGL format");
return false;
}
if (!Lock())
{
NazaraError("Failed to lock render texture");
return false;
}
// Détachement de l'attache précédente (Si il y a)
Detach(attachmentPoint, index);
GLuint renderBuffer = 0;
glGenRenderbuffers(1, &renderBuffer);
if (!renderBuffer)
{
NazaraError("Failed to create renderbuffer");
return false;
}
GLint previous;
glGetIntegerv(GL_RENDERBUFFER_BINDING, &previous);
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, openglFormat.internalFormat, m_impl->width, m_impl->height);
if (previous != 0)
glBindRenderbuffer(GL_RENDERBUFFER, previous);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, NzOpenGL::Attachment[attachmentPoint]+index, GL_RENDERBUFFER, renderBuffer);
Unlock();
unsigned int minSize = attachmentIndex[attachmentPoint]+index+1;
if (m_impl->attachements.size() < minSize)
m_impl->attachements.resize(minSize);
Attachment& attachment = m_impl->attachements[minSize-1];
attachment.isBuffer = true;
attachment.isUsed = true;
attachment.buffer = renderBuffer;
m_impl->checked = false;
m_impl->drawBuffersUpdated = false;
return true;
}
bool NzRenderTexture::AttachTexture(nzAttachmentPoint attachmentPoint, nzUInt8 index, NzTexture* texture)
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Render texture not created");
return false;
}
if (attachmentPoint != nzAttachmentPoint_Color && index > 0)
{
NazaraError("Index must be 0 for non-color attachments");
return false;
}
unsigned int depthStencilIndex = attachmentIndex[nzAttachmentPoint_DepthStencil];
if (attachmentPoint == nzAttachmentPoint_Stencil && m_impl->attachements.size() > depthStencilIndex &&
m_impl->attachements[depthStencilIndex].isUsed)
{
NazaraError("Stencil target already attached by DepthStencil attachment");
return false;
}
if (!texture || !texture->IsValid())
{
NazaraError("Invalid texture");
return false;
}
if (texture->GetWidth() < m_impl->width || texture->GetHeight() < m_impl->height)
{
NazaraError("Texture cannot be smaller than render texture");
return false;
}
if (texture->GetRenderTexture() != nullptr)
{
NazaraError("Texture already used by another render texture");
return false;
}
if (formatTypeToAttachment[NzPixelFormat::GetType(texture->GetFormat())] != attachmentPoint)
{
NazaraError("Pixel format type does not match attachment point type");
return false;
}
#endif
if (!Lock())
{
NazaraError("Failed to lock render texture");
return false;
}
// Détachement de l'attache précédente (Si il y a)
Detach(attachmentPoint, index);
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, NzOpenGL::Attachment[attachmentPoint]+index, texture->GetOpenGLID(), 0);
Unlock();
unsigned int minSize = attachmentIndex[attachmentPoint]+index+1;
if (m_impl->attachements.size() < minSize)
m_impl->attachements.resize(minSize);
Attachment& attachment = m_impl->attachements[minSize-1];
attachment.isBuffer = true;
attachment.isUsed = true;
attachment.texture = texture;
texture->AddResourceListener(this, minSize-1);
texture->SetRenderTexture(this);
m_impl->checked = false;
m_impl->drawBuffersUpdated = false;
return true;
}
bool NzRenderTexture::AttachTexture(nzAttachmentPoint attachmentPoint, nzUInt8 index, NzTexture* texture, unsigned int z)
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Render texture not created");
return false;
}
if (attachmentPoint != nzAttachmentPoint_Color && index > 0)
{
NazaraError("Index must be 0 for non-color attachments");
return false;
}
if (attachmentPoint == nzAttachmentPoint_Stencil)
{
NazaraError("Targeting stencil-only textures is not supported");
return false;
}
unsigned int depthStencilIndex = attachmentIndex[nzAttachmentPoint_DepthStencil];
if (attachmentPoint == nzAttachmentPoint_Stencil && m_impl->attachements.size() > depthStencilIndex &&
m_impl->attachements[depthStencilIndex].isUsed)
{
NazaraError("Stencil target already attached by DepthStencil attachment");
return false;
}
if (!texture || !texture->IsValid())
{
NazaraError("Invalid texture");
return false;
}
if (texture->GetWidth() < m_impl->width || texture->GetHeight() < m_impl->height)
{
NazaraError("Texture cannot be smaller than render texture");
return false;
}
unsigned int depth = (texture->GetType() == nzImageType_Cubemap) ? 6 : texture->GetDepth();
if (z >= depth)
{
NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= (" + NzString::Number(depth) + ')');
return false;
}
if (texture->GetRenderTexture() != nullptr)
{
NazaraError("Texture already used by another render texture");
return false;
}
if (formatTypeToAttachment[NzPixelFormat::GetType(texture->GetFormat())] != attachmentPoint)
{
NazaraError("Pixel format type does not match attachment point type");
return false;
}
#endif
if (!Lock())
{
NazaraError("Failed to lock render texture");
return false;
}
// Détachement de l'attache précédente (Si il y a)
Detach(attachmentPoint, index);
switch (texture->GetType())
{
case nzImageType_1D:
glFramebufferTexture1D(GL_DRAW_FRAMEBUFFER, NzOpenGL::Attachment[attachmentPoint]+index, GL_TEXTURE_1D, texture->GetOpenGLID(), 0);
break;
case nzImageType_1D_Array:
case nzImageType_2D_Array:
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, NzOpenGL::Attachment[attachmentPoint]+index, texture->GetOpenGLID(), 0, z);
break;
case nzImageType_2D:
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, NzOpenGL::Attachment[attachmentPoint]+index, NzOpenGL::TextureTarget[texture->GetType()], texture->GetOpenGLID(), 0);
break;
case nzImageType_3D:
glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, NzOpenGL::Attachment[attachmentPoint]+index, GL_TEXTURE_3D, texture->GetOpenGLID(), 0, z);
break;
case nzImageType_Cubemap:
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, NzOpenGL::Attachment[attachmentPoint]+index, NzOpenGL::CubemapFace[z], texture->GetOpenGLID(), 0);
break;
}
Unlock();
unsigned int minSize = attachmentIndex[attachmentPoint]+index+1;
if (m_impl->attachements.size() < minSize)
m_impl->attachements.resize(minSize);
Attachment& attachment = m_impl->attachements[minSize-1];
attachment.isBuffer = true;
attachment.isUsed = true;
attachment.texture = texture;
texture->AddResourceListener(this);
texture->SetRenderTexture(this);
m_impl->checked = false;
m_impl->drawBuffersUpdated = false;
return true;
}
bool NzRenderTexture::Create(unsigned int width, unsigned int height, bool lock)
{
if (!IsSupported())
{
NazaraError("Render textures not supported");
return false;
}
Destroy();
#if NAZARA_RENDERER_SAFE
if (width == 0)
{
NazaraError("Width must be at least 1 (0)");
return false;
}
if (height == 0)
{
NazaraError("Height must be at least 1 (0)");
return false;
}
if (NzContext::GetCurrent() == nullptr)
{
NazaraError("No active context");
return false;
}
#endif
NzRenderTextureImpl* impl = new NzRenderTextureImpl;
impl->width = width;
impl->height = height;
impl->context = NzContext::GetCurrent();
impl->context->AddResourceListener(this);
impl->fbo = 0;
glGenFramebuffers(1, &impl->fbo);
if (!impl->fbo)
{
NazaraError("Failed to create framebuffer");
delete impl;
return false;
}
m_impl = impl;
if (lock && !Lock())
{
NazaraError("Failed to lock render texture");
delete impl;
m_impl = nullptr;
return false;
}
return true;
}
void NzRenderTexture::Destroy()
{
if (m_impl)
{
#if NAZARA_RENDERER_SAFE
if (NzContext::GetCurrent() != m_impl->context)
{
NazaraError("RenderTexture can only be used with it's creation context");
return;
}
#endif
m_impl->context->RemoveResourceListener(this);
for (Attachment& attachment : m_impl->attachements)
{
if (attachment.isUsed)
{
if (attachment.isBuffer)
glDeleteRenderbuffers(1, &attachment.buffer);
else
{
attachment.texture->RemoveResourceListener(this);
attachment.texture->SetRenderTexture(nullptr);
}
}
}
glDeleteFramebuffers(1, &m_impl->fbo);
delete m_impl;
m_impl = nullptr;
}
}
void NzRenderTexture::Detach(nzAttachmentPoint attachmentPoint, nzUInt8 index)
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Render texture not created");
return;
}
if (attachmentPoint != nzAttachmentPoint_Color && index > 0)
{
NazaraError("Index must be 0 for non-color attachments");
return;
}
#endif
unsigned int attachIndex = attachmentIndex[attachmentPoint]+index;
if (attachIndex >= m_impl->attachements.size())
return;
Attachment& attachement = m_impl->attachements[attachIndex];
if (!attachement.isUsed)
return;
if (!Lock())
{
NazaraError("Failed to lock render texture");
return;
}
attachement.isUsed = false;
if (attachement.isBuffer)
{
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, NzOpenGL::Attachment[attachmentPoint]+index, GL_RENDERBUFFER, 0);
glDeleteRenderbuffers(1, &attachement.buffer);
}
else
{
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, NzOpenGL::Attachment[attachmentPoint]+index, 0, 0);
attachement.texture->RemoveResourceListener(this);
attachement.texture->SetRenderTexture(nullptr);
}
Unlock();
m_impl->checked = false;
m_impl->drawBuffersUpdated = false;
}
unsigned int NzRenderTexture::GetHeight() const
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Render texture not created");
return 0;
}
#endif
return m_impl->height;
}
NzRenderTargetParameters NzRenderTexture::GetParameters() const
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Render texture not created");
return NzRenderTargetParameters();
}
#endif
return NzRenderTargetParameters();
}
unsigned int NzRenderTexture::GetWidth() const
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Render texture not created");
return 0;
}
#endif
return m_impl->width;
}
bool NzRenderTexture::IsComplete() const
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Render texture not created");
return false;
}
#endif
if (!m_impl->checked)
{
if (!Lock())
{
NazaraError("Failed to lock render texture");
return false;
}
GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
Unlock();
m_impl->complete = false;
switch (status)
{
case GL_FRAMEBUFFER_COMPLETE:
m_impl->complete = true;
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
NazaraError("Incomplete attachment");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
NazaraInternalError("Incomplete draw buffer");
break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
NazaraInternalError("Incomplete read buffer");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
NazaraError("Incomplete missing attachment");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
NazaraError("Incomplete multisample");
break;
case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
NazaraError("Incomplete layer targets");
break;
case GL_FRAMEBUFFER_UNSUPPORTED:
NazaraError("Render texture has unsupported attachments");
break;
default:
NazaraInternalError("Unknown error");
}
m_impl->checked = true;
}
return m_impl->complete;
}
bool NzRenderTexture::IsRenderable() const
{
return IsComplete();
}
bool NzRenderTexture::IsValid() const
{
return m_impl != nullptr;
}
bool NzRenderTexture::Lock() const
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Render texture not created");
return false;
}
if (NzContext::GetCurrent() != m_impl->context)
{
NazaraError("RenderTexture cannot be used with this context");
return false;
}
#endif
if (lockedLevel++ == 0)
{
GLint previous;
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &previous);
lockedPrevious = previous;
if (lockedPrevious != m_impl->fbo)
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_impl->fbo);
}
return true;
}
void NzRenderTexture::Unlock() const
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Render texture not created");
return;
}
if (NzContext::GetCurrent() != m_impl->context)
{
NazaraError("RenderTexture cannot be used with this context");
return;
}
if (lockedLevel == 0)
{
NazaraWarning("Unlock called on non-locked texture");
return;
}
#endif
if (--lockedLevel == 0 && lockedPrevious != m_impl->fbo) // Ici, il est important qu'un FBO soit débindé si l'ancien était 0
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, lockedPrevious);
}
bool NzRenderTexture::HasContext() const
{
return false;
}
bool NzRenderTexture::IsSupported()
{
return NzRenderer::HasCapability(nzRendererCap_RenderTexture);
}
bool NzRenderTexture::Activate()
{
#if NAZARA_RENDERER_SAFE
if (NzContext::GetCurrent() != m_impl->context)
{
NazaraError("RenderTexture cannot be used with this context");
return false;
}
#endif
if (!m_impl->drawBuffersUpdated)
{
m_impl->drawBuffers.clear();
m_impl->drawBuffers.reserve(m_impl->attachements.size());
for (unsigned int i = attachmentIndex[nzAttachmentPoint_Color]; i < m_impl->attachements.size(); ++i)
{
if (m_impl->attachements[i].isUsed)
m_impl->drawBuffers.push_back(GL_COLOR_ATTACHMENT0 + i - attachmentIndex[nzAttachmentPoint_Color]);
}
m_impl->drawBuffersUpdated = true;
}
glDrawBuffers(m_impl->drawBuffers.size(), &m_impl->drawBuffers[0]);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_impl->fbo);
return true;
}
void NzRenderTexture::Desactivate()
{
#if NAZARA_RENDERER_SAFE
if (NzContext::GetCurrent() != m_impl->context)
{
NazaraError("RenderTexture cannot be used with this context");
return;
}
#endif
glFlush();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
void NzRenderTexture::OnResourceDestroy(const NzResource* resource, int index)
{
if (resource == m_impl->context)
// Notre context a été détruit, libérons la RenderTexture pour éviter un leak
Destroy();
else
{
// Sinon, c'est une texture
// La ressource n'est plus, du coup nous mettons à jour
Attachment& attachement = m_impl->attachements[index];
attachement.isUsed = false;
m_impl->checked = false;
m_impl->drawBuffersUpdated = false;
}
}

View File

@ -1,278 +1,276 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module" // This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/OpenGL.hpp> #include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/RenderWindow.hpp> #include <Nazara/Renderer/RenderWindow.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Thread.hpp> #include <Nazara/Core/Thread.hpp>
#include <Nazara/Renderer/Context.hpp> #include <Nazara/Renderer/Context.hpp>
#include <Nazara/Renderer/Texture.hpp> #include <Nazara/Renderer/Texture.hpp>
#include <stdexcept> #include <stdexcept>
#include <Nazara/Renderer/Debug.hpp> #include <Nazara/Renderer/Debug.hpp>
NzRenderWindow::NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters) NzRenderWindow::NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters)
{ {
Create(mode, title, style, parameters); Create(mode, title, style, parameters);
#ifdef NAZARA_DEBUG #ifdef NAZARA_DEBUG
if (!m_impl) if (!m_impl)
{ {
NazaraError("Failed to create render window"); NazaraError("Failed to create render window");
throw std::runtime_error("Constructor failed"); throw std::runtime_error("Constructor failed");
} }
#endif #endif
} }
NzRenderWindow::NzRenderWindow(NzWindowHandle handle, const NzContextParameters& parameters) NzRenderWindow::NzRenderWindow(NzWindowHandle handle, const NzContextParameters& parameters)
{ {
Create(handle, parameters); Create(handle, parameters);
#ifdef NAZARA_DEBUG #ifdef NAZARA_DEBUG
if (!m_impl) if (!m_impl)
{ {
NazaraError("Failed to create render window"); NazaraError("Failed to create render window");
throw std::runtime_error("Constructor failed"); throw std::runtime_error("Constructor failed");
} }
#endif #endif
} }
NzRenderWindow::~NzRenderWindow() NzRenderWindow::~NzRenderWindow()
{ {
// Nécessaire si NzWindow::Destroy est appelé par son destructeur // Nécessaire si NzWindow::Destroy est appelé par son destructeur
OnWindowDestroying(); OnWindowDestroy();
} }
bool NzRenderWindow::CopyToImage(NzImage* image) bool NzRenderWindow::CopyToImage(NzImage* image)
{ {
#if NAZARA_RENDERER_SAFE #if NAZARA_RENDERER_SAFE
if (!m_context) if (!m_context)
{ {
NazaraError("Window has not been created"); NazaraError("Window has not been created");
return false; return false;
} }
if (!image) if (!image)
{ {
NazaraError("Image must be valid"); NazaraError("Image must be valid");
return false; return false;
} }
#endif #endif
if (!m_context->SetActive(true)) if (!m_context->SetActive(true))
{ {
NazaraError("Failed to activate context"); NazaraError("Failed to activate context");
return false; return false;
} }
NzVector2ui size = GetSize(); NzVector2ui size = GetSize();
if (!image->Create(nzImageType_2D, nzPixelFormat_RGBA8, size.x, size.y, 1, 1)) if (!image->Create(nzImageType_2D, nzPixelFormat_RGBA8, size.x, size.y, 1, 1))
{ {
NazaraError("Failed to create image"); NazaraError("Failed to create image");
return false; return false;
} }
nzUInt8* pixels = image->GetPixels(); nzUInt8* pixels = image->GetPixels();
glReadPixels(0, 0, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glReadPixels(0, 0, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
image->FlipVertically(); image->FlipVertically();
return true; return true;
} }
bool NzRenderWindow::CopyToTexture(NzTexture* texture) bool NzRenderWindow::CopyToTexture(NzTexture* texture)
{ {
#if NAZARA_RENDERER_SAFE #if NAZARA_RENDERER_SAFE
if (!m_context) if (!m_context)
{ {
NazaraError("Window has not been created"); NazaraError("Window has not been created");
return false; return false;
} }
if (!texture) if (!texture)
{ {
NazaraError("Texture must be valid"); NazaraError("Texture must be valid");
return false; return false;
} }
#endif #endif
if (!m_context->SetActive(true)) if (!m_context->SetActive(true))
{ {
NazaraError("Failed to activate context"); NazaraError("Failed to activate context");
return false; return false;
} }
NzVector2ui size = GetSize(); NzVector2ui size = GetSize();
if (!texture->Create(nzImageType_2D, nzPixelFormat_RGBA8, size.x, size.y, 1, 1, true)) if (!texture->Create(nzImageType_2D, nzPixelFormat_RGBA8, size.x, size.y, 1, 1, true))
{ {
NazaraError("Failed to create texture"); NazaraError("Failed to create texture");
return false; return false;
} }
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, size.x, size.y); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, size.x, size.y);
texture->Unlock(); texture->Unlock();
return true; return true;
} }
bool NzRenderWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters) bool NzRenderWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters)
{ {
m_parameters = parameters; m_parameters = parameters;
return NzWindow::Create(mode, title, style); return NzWindow::Create(mode, title, style);
} }
bool NzRenderWindow::Create(NzWindowHandle handle, const NzContextParameters& parameters) bool NzRenderWindow::Create(NzWindowHandle handle, const NzContextParameters& parameters)
{ {
m_parameters = parameters; m_parameters = parameters;
return NzWindow::Create(handle); return NzWindow::Create(handle);
} }
void NzRenderWindow::Display() void NzRenderWindow::Display()
{ {
if (m_framerateLimit > 0) if (m_framerateLimit > 0)
{ {
int remainingTime = 1000/m_framerateLimit - m_clock.GetMilliseconds(); int remainingTime = 1000/m_framerateLimit - m_clock.GetMilliseconds();
if (remainingTime > 0) if (remainingTime > 0)
NzThread::Sleep(remainingTime); NzThread::Sleep(remainingTime);
m_clock.Restart(); m_clock.Restart();
} }
if (m_context && m_parameters.doubleBuffered) if (m_context && m_parameters.doubleBuffered)
m_context->SwapBuffers(); m_context->SwapBuffers();
} }
void NzRenderWindow::EnableVerticalSync(bool enabled) void NzRenderWindow::EnableVerticalSync(bool enabled)
{ {
if (m_context) if (m_context)
{ {
#if defined(NAZARA_PLATFORM_WINDOWS) #if defined(NAZARA_PLATFORM_WINDOWS)
if (!m_context->SetActive(true)) if (!m_context->SetActive(true))
{ {
NazaraError("Failed to activate context"); NazaraError("Failed to activate context");
return; return;
} }
if (wglSwapInterval) if (wglSwapInterval)
wglSwapInterval(enabled ? 1 : 0); wglSwapInterval(enabled ? 1 : 0);
else else
#elif defined(NAZARA_PLATFORM_LINUX) #elif defined(NAZARA_PLATFORM_LINUX)
if (!m_context->SetActive(true)) if (!m_context->SetActive(true))
{ {
NazaraError("Failed to activate context"); NazaraError("Failed to activate context");
return; return;
} }
if (glXSwapInterval) if (glXSwapInterval)
glXSwapInterval(enabled ? 1 : 0); glXSwapInterval(enabled ? 1 : 0);
else else
#else #else
#error Vertical Sync is not supported on this platform #error Vertical Sync is not supported on this platform
#endif #endif
NazaraError("Vertical Sync is not supported on this platform"); NazaraError("Vertical Sync is not supported on this platform");
} }
else else
NazaraError("No context"); NazaraError("No context");
} }
NzContextParameters NzRenderWindow::GetContextParameters() const unsigned int NzRenderWindow::GetHeight() const
{ {
if (m_context) return NzWindow::GetHeight();
return m_context->GetParameters(); }
else
{ NzRenderTargetParameters NzRenderWindow::GetParameters() const
NazaraError("Window not created/context not initialized"); {
return NzContextParameters(); if (m_context)
} {
} const NzContextParameters& parameters = m_context->GetParameters();
return NzRenderTargetParameters(parameters.antialiasingLevel, parameters.depthBits, parameters.stencilBits);
unsigned int NzRenderWindow::GetHeight() const }
{ else
return NzWindow::GetHeight(); {
} NazaraError("Window not created/context not initialized");
return NzRenderTargetParameters();
NzRenderTargetParameters NzRenderWindow::GetParameters() const }
{ }
if (m_context)
{ unsigned int NzRenderWindow::GetWidth() const
const NzContextParameters& parameters = m_context->GetParameters(); {
return NzRenderTargetParameters(parameters.antialiasingLevel, parameters.depthBits, parameters.stencilBits); return NzWindow::GetWidth();
} }
else
{ bool NzRenderWindow::IsRenderable() const
NazaraError("Window not created/context not initialized"); {
return NzRenderTargetParameters(); return m_impl != nullptr; // Si m_impl est valide, alors m_context l'est aussi
} }
}
void NzRenderWindow::SetFramerateLimit(unsigned int limit)
unsigned int NzRenderWindow::GetWidth() const {
{ m_framerateLimit = limit;
return NzWindow::GetWidth(); }
}
NzContextParameters NzRenderWindow::GetContextParameters() const
bool NzRenderWindow::HasContext() const {
{ if (m_context)
return true; return m_context->GetParameters();
} else
{
bool NzRenderWindow::IsValid() const NazaraError("Window not created/context not initialized");
{ return NzContextParameters();
return m_impl != nullptr && m_context != nullptr; }
} }
void NzRenderWindow::SetFramerateLimit(unsigned int limit) bool NzRenderWindow::HasContext() const
{ {
m_framerateLimit = limit; return true;
} }
bool NzRenderWindow::Activate() bool NzRenderWindow::Activate()
{ {
if (m_context->SetActive(true)) if (m_context->SetActive(true))
{ {
glDrawBuffer((m_parameters.doubleBuffered) ? GL_BACK : GL_FRONT); glDrawBuffer((m_parameters.doubleBuffered) ? GL_BACK : GL_FRONT);
return true; return true;
} }
else else
{ {
NazaraError("Failed to activate window's context"); NazaraError("Failed to activate window's context");
return false; return false;
} }
} }
void NzRenderWindow::OnWindowDestroying() bool NzRenderWindow::OnWindowCreated()
{ {
if (m_context) m_parameters.doubleBuffered = true;
{ m_parameters.window = GetHandle();
delete m_context;
m_context = nullptr; m_context = new NzContext;
} if (!m_context->Create(m_parameters))
} {
NazaraError("Failed not create context");
bool NzRenderWindow::OnWindowCreated() delete m_context;
{
m_parameters.doubleBuffered = true; return false;
m_parameters.window = GetHandle(); }
m_context = new NzContext; EnableVerticalSync(false);
if (!m_context->Create(m_parameters))
{ if (!SetActive(true)) // Les fenêtres s'activent à la création
NazaraError("Failed not create context"); NazaraWarning("Failed to activate window");
delete m_context;
m_clock.Restart();
return false;
} return true;
}
EnableVerticalSync(false);
void NzRenderWindow::OnWindowDestroy()
#if NAZARA_RENDERER_ACTIVATE_RENDERWINDOW_ON_CREATION {
if (!SetActive(true)) // Les fenêtres s'activent à la création if (m_context)
NazaraWarning("Failed to activate window"); {
#endif delete m_context;
m_context = nullptr;
m_clock.Restart(); }
}
return true;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,231 +1,234 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module" // This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
// Code inspiré de NeHe (Lesson1) et de la SFML par Laurent Gomila // Code inspiré de NeHe (Lesson1) et de la SFML par Laurent Gomila
#include <Nazara/Renderer/OpenGL.hpp> #include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/Win32/ContextImpl.hpp> #include <Nazara/Renderer/Win32/ContextImpl.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Core/LockGuard.hpp> #include <Nazara/Core/LockGuard.hpp>
#include <Nazara/Core/Mutex.hpp> #include <Nazara/Core/Mutex.hpp>
#include <Nazara/Renderer/Context.hpp> #include <Nazara/Renderer/Context.hpp>
#include <cstring> #include <cstring>
#include <Nazara/Renderer/Debug.hpp> #include <Nazara/Renderer/Debug.hpp>
NzContextImpl::NzContextImpl() NzContextImpl::NzContextImpl()
{ {
} }
bool NzContextImpl::Activate() bool NzContextImpl::Activate()
{ {
return wglMakeCurrent(m_deviceContext, m_context); return wglMakeCurrent(m_deviceContext, m_context);
} }
bool NzContextImpl::Create(NzContextParameters& parameters) bool NzContextImpl::Create(NzContextParameters& parameters)
{ {
if (parameters.window) if (parameters.window)
{ {
m_window = static_cast<HWND>(parameters.window); m_window = static_cast<HWND>(parameters.window);
m_ownsWindow = false; m_ownsWindow = false;
} }
else else
{ {
m_window = CreateWindowA("STATIC", nullptr, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, nullptr, nullptr, GetModuleHandle(nullptr), nullptr); m_window = CreateWindowA("STATIC", nullptr, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
if (!m_window) if (!m_window)
{ {
NazaraError("Failed to create window"); NazaraError("Failed to create window");
return false; return false;
} }
ShowWindow(m_window, SW_HIDE); ShowWindow(m_window, SW_HIDE);
m_ownsWindow = true; m_ownsWindow = true;
} }
m_deviceContext = GetDC(m_window); m_deviceContext = GetDC(m_window);
if (!m_deviceContext) if (!m_deviceContext)
{ {
NazaraError("Failed to get device context"); NazaraError("Failed to get device context");
Destroy(); Destroy();
return false; return false;
} }
int pixelFormat = 0; int pixelFormat = 0;
if (parameters.antialiasingLevel > 0) if (parameters.antialiasingLevel > 0)
{ {
if (wglChoosePixelFormat) if (wglChoosePixelFormat)
{ {
bool valid; bool valid;
UINT numFormats; UINT numFormats;
int attributes[] = { int attributes[] = {
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE, WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
WGL_COLOR_BITS_ARB, (parameters.bitsPerPixel == 32) ? 24 : parameters.bitsPerPixel, WGL_COLOR_BITS_ARB, (parameters.bitsPerPixel == 32) ? 24 : parameters.bitsPerPixel,
WGL_ALPHA_BITS_ARB, (parameters.bitsPerPixel == 32) ? 8 : 0, WGL_ALPHA_BITS_ARB, (parameters.bitsPerPixel == 32) ? 8 : 0,
WGL_DEPTH_BITS_ARB, parameters.depthBits, WGL_DEPTH_BITS_ARB, parameters.depthBits,
WGL_STENCIL_BITS_ARB, parameters.stencilBits, WGL_STENCIL_BITS_ARB, parameters.stencilBits,
WGL_DOUBLE_BUFFER_ARB, (parameters.doubleBuffered) ? GL_TRUE : GL_FALSE, WGL_DOUBLE_BUFFER_ARB, (parameters.doubleBuffered) ? GL_TRUE : GL_FALSE,
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE, WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
WGL_SAMPLES_ARB, parameters.antialiasingLevel, WGL_SAMPLES_ARB, parameters.antialiasingLevel,
0, 0 0, 0
}; };
do do
{ {
valid = wglChoosePixelFormat(m_deviceContext, attributes, nullptr, 1, &pixelFormat, &numFormats); valid = wglChoosePixelFormat(m_deviceContext, attributes, nullptr, 1, &pixelFormat, &numFormats);
} }
while ((!valid || numFormats == 0) && --attributes[19] > 0); while ((!valid || numFormats == 0) && --attributes[19] > 0);
if (!valid) if (!valid)
{ {
NazaraWarning("Could not find a format matching requirements, disabling antialiasing..."); NazaraWarning("Could not find a format matching requirements, disabling antialiasing...");
pixelFormat = 0; pixelFormat = 0;
} }
parameters.antialiasingLevel = attributes[19]; parameters.antialiasingLevel = attributes[19];
} }
else else
{ {
NazaraWarning("Antialiasing is not supported"); NazaraWarning("Antialiasing is not supported");
parameters.antialiasingLevel = 0; parameters.antialiasingLevel = 0;
} }
} }
PIXELFORMATDESCRIPTOR descriptor; PIXELFORMATDESCRIPTOR descriptor;
ZeroMemory(&descriptor, sizeof(PIXELFORMATDESCRIPTOR)); ZeroMemory(&descriptor, sizeof(PIXELFORMATDESCRIPTOR));
descriptor.nSize = sizeof(PIXELFORMATDESCRIPTOR); descriptor.nSize = sizeof(PIXELFORMATDESCRIPTOR);
descriptor.nVersion = 1; descriptor.nVersion = 1;
if (pixelFormat == 0) if (pixelFormat == 0)
{ {
descriptor.cColorBits = parameters.bitsPerPixel; descriptor.cColorBits = parameters.bitsPerPixel;
descriptor.cDepthBits = parameters.depthBits; descriptor.cDepthBits = parameters.depthBits;
descriptor.cStencilBits = parameters.stencilBits; descriptor.cStencilBits = parameters.stencilBits;
descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
descriptor.iPixelType = PFD_TYPE_RGBA; descriptor.iPixelType = PFD_TYPE_RGBA;
if (parameters.bitsPerPixel == 32) if (parameters.bitsPerPixel == 32)
descriptor.cAlphaBits = 8; descriptor.cAlphaBits = 8;
if (parameters.doubleBuffered) if (parameters.doubleBuffered)
descriptor.dwFlags |= PFD_DOUBLEBUFFER; descriptor.dwFlags |= PFD_DOUBLEBUFFER;
pixelFormat = ChoosePixelFormat(m_deviceContext, &descriptor); pixelFormat = ChoosePixelFormat(m_deviceContext, &descriptor);
if (pixelFormat == 0) if (pixelFormat == 0)
{ {
NazaraError("Failed to choose pixel format"); NazaraError("Failed to choose pixel format");
Destroy(); Destroy();
return false; return false;
} }
} }
if (!SetPixelFormat(m_deviceContext, pixelFormat, &descriptor)) if (!SetPixelFormat(m_deviceContext, pixelFormat, &descriptor))
{ {
NazaraError("Failed to set pixel format"); NazaraError("Failed to set pixel format");
Destroy(); Destroy();
return false; return false;
} }
// Arrivé ici, le format de pixel est choisi, nous récupérons donc les paramètres réels du futur contexte // Arrivé ici, le format de pixel est choisi, nous récupérons donc les paramètres réels du futur contexte
if (DescribePixelFormat(m_deviceContext, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &descriptor) != 0) if (DescribePixelFormat(m_deviceContext, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &descriptor) != 0)
{ {
parameters.bitsPerPixel = descriptor.cColorBits + descriptor.cAlphaBits; parameters.bitsPerPixel = descriptor.cColorBits + descriptor.cAlphaBits;
parameters.depthBits = descriptor.cDepthBits; parameters.depthBits = descriptor.cDepthBits;
parameters.stencilBits = descriptor.cDepthBits; parameters.stencilBits = descriptor.cDepthBits;
} }
else else
NazaraWarning("Failed to get context's parameters"); NazaraWarning("Failed to get context's parameters");
HGLRC shareContext = (parameters.shared) ? static_cast<NzContextImpl*>(parameters.shareContext->m_impl)->m_context : nullptr; HGLRC shareContext = (parameters.shared) ? static_cast<NzContextImpl*>(parameters.shareContext->m_impl)->m_context : nullptr;
m_context = nullptr; m_context = nullptr;
if (wglCreateContextAttribs) if (wglCreateContextAttribs)
{ {
int attributes[4*2+1]; int attributes[4*2+1];
int* attrib = attributes; int* attrib = attributes;
*attrib++ = WGL_CONTEXT_MAJOR_VERSION_ARB; *attrib++ = WGL_CONTEXT_MAJOR_VERSION_ARB;
*attrib++ = parameters.majorVersion; *attrib++ = parameters.majorVersion;
*attrib++ = WGL_CONTEXT_MINOR_VERSION_ARB; *attrib++ = WGL_CONTEXT_MINOR_VERSION_ARB;
*attrib++ = parameters.minorVersion; *attrib++ = parameters.minorVersion;
int flags = 0; if (parameters.majorVersion >= 3)
{
if (parameters.majorVersion >= 3) *attrib++ = WGL_CONTEXT_PROFILE_MASK_ARB;
{ *attrib++ = (parameters.compatibilityProfile) ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
*attrib++ = WGL_CONTEXT_PROFILE_MASK_ARB; }
if (parameters.compatibilityProfile)
*attrib++ = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; if (parameters.debugMode)
else {
{ *attrib++ = WGL_CONTEXT_FLAGS_ARB;
*attrib++ = WGL_CONTEXT_CORE_PROFILE_BIT_ARB; *attrib++ = WGL_CONTEXT_DEBUG_BIT_ARB;
flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; // Les contextes forward-compatible ne sont plus utilisés pour cette raison :
} // http://www.opengl.org/discussion_boards/showthread.php/175052-Forward-compatible-vs-Core-profile
} }
if (parameters.debugMode) *attrib++ = 0;
flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
m_context = wglCreateContextAttribs(m_deviceContext, shareContext, attributes);
if (flags) }
{
*attrib++ = WGL_CONTEXT_FLAGS_ARB; if (!m_context)
*attrib++ = flags; {
} m_context = wglCreateContext(m_deviceContext);
*attrib++ = 0; if (shareContext)
{
m_context = wglCreateContextAttribs(m_deviceContext, shareContext, attributes); // wglShareLists n'est pas thread-safe (source: SFML)
} static NzMutex mutex;
NzLockGuard lock(mutex);
if (!m_context)
{ if (!wglShareLists(shareContext, m_context))
m_context = wglCreateContext(m_deviceContext); NazaraWarning("Failed to share the context: " + NzGetLastSystemError());
}
if (shareContext) }
{
// wglShareLists n'est pas thread-safe (source: SFML) if (!m_context)
static NzMutex mutex; {
NzLockGuard lock(mutex); NazaraError("Failed to create context");
Destroy();
if (!wglShareLists(shareContext, m_context)) return false;
NazaraWarning("Failed to share the context: " + NzGetLastSystemError()); }
}
} return true;
}
if (!m_context)
{ void NzContextImpl::Destroy()
NazaraError("Failed to create context"); {
Destroy(); if (m_context)
return false; {
} if (wglGetCurrentContext() == m_context)
wglMakeCurrent(nullptr, nullptr);
return true;
} wglDeleteContext(m_context);
m_context = nullptr;
void NzContextImpl::Destroy() }
{
if (m_context) if (m_deviceContext)
wglDeleteContext(m_context); {
ReleaseDC(m_window, m_deviceContext);
if (m_deviceContext) m_deviceContext = nullptr;
ReleaseDC(m_window, m_deviceContext); }
if (m_ownsWindow) if (m_ownsWindow)
DestroyWindow(m_window); {
} DestroyWindow(m_window);
m_window = nullptr;
void NzContextImpl::SwapBuffers() }
{ }
::SwapBuffers(m_deviceContext);
} void NzContextImpl::SwapBuffers()
{
bool NzContextImpl::Desactivate() ::SwapBuffers(m_deviceContext);
{ }
return wglMakeCurrent(nullptr, nullptr);
} bool NzContextImpl::Desactivate()
{
return wglMakeCurrent(nullptr, nullptr);
}

View File

@ -1,317 +1,342 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module" // This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Animation.hpp> #include <Nazara/Utility/Animation.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Utility/Config.hpp> #include <Nazara/Utility/Config.hpp>
#include <map> #include <map>
#include <vector> #include <vector>
#include <Nazara/Utility/Debug.hpp> #include <Nazara/Utility/Debug.hpp>
struct NzAnimationImpl struct NzAnimationImpl
{ {
std::map<NzString, unsigned int> sequenceMap; std::map<NzString, unsigned int> sequenceMap;
std::vector<NzSequence> sequences; std::vector<NzSequence> sequences;
nzAnimationType type; nzAnimationType type;
unsigned int frameCount; unsigned int frameCount;
}; };
bool NzAnimationParams::IsValid() const bool NzAnimationParams::IsValid() const
{ {
if (startFrame > endFrame) if (startFrame > endFrame)
{ {
NazaraError("Start frame must be lower than end frame"); NazaraError("Start frame must be lower than end frame");
return false; return false;
} }
return true; return true;
} }
NzAnimation::~NzAnimation() NzAnimation::~NzAnimation()
{ {
Destroy(); Destroy();
} }
unsigned int NzAnimation::AddSequence(const NzSequence& sequence) bool NzAnimation::AddSequence(const NzSequence& sequence)
{ {
#if NAZARA_UTILITY_SAFE #if NAZARA_UTILITY_SAFE
if (!m_impl) if (!m_impl)
{ {
NazaraError("Animation not created"); NazaraError("Animation not created");
return 0; return false;
} }
#endif #endif
unsigned int index = m_impl->sequences.size(); unsigned int index = m_impl->sequences.size();
if (!sequence.name.IsEmpty()) if (!sequence.name.IsEmpty())
{ {
#if NAZARA_UTILITY_SAFE #if NAZARA_UTILITY_SAFE
auto it = m_impl->sequenceMap.find(sequence.name); auto it = m_impl->sequenceMap.find(sequence.name);
if (it != m_impl->sequenceMap.end()) if (it != m_impl->sequenceMap.end())
{ {
NazaraError("Sequence name \"" + sequence.name + "\" is already used"); NazaraError("Sequence name \"" + sequence.name + "\" is already used");
return 0; return false;
} }
#endif #endif
m_impl->sequenceMap[sequence.name] = index; m_impl->sequenceMap[sequence.name] = index;
} }
m_impl->sequences.push_back(sequence); m_impl->sequences.push_back(sequence);
return index; return true;
} }
bool NzAnimation::Create(nzAnimationType type, unsigned int frameCount) bool NzAnimation::Create(nzAnimationType type, unsigned int frameCount)
{ {
Destroy(); Destroy();
#if NAZARA_UTILITY_SAFE #if NAZARA_UTILITY_SAFE
if (type == nzAnimationType_Static) if (type == nzAnimationType_Static)
{ {
NazaraError("Invalid type"); NazaraError("Invalid type");
return false; return false;
} }
if (frameCount == 0) if (frameCount == 0)
{ {
NazaraError("Frame count must be over zero"); NazaraError("Frame count must be over zero");
return false; return false;
} }
#endif #endif
m_impl = new NzAnimationImpl; m_impl = new NzAnimationImpl;
m_impl->frameCount = frameCount; m_impl->frameCount = frameCount;
m_impl->type = type; m_impl->type = type;
return true; NotifyCreated();
} return true;
}
void NzAnimation::Destroy()
{ void NzAnimation::Destroy()
if (m_impl) {
{ if (m_impl)
delete m_impl; {
m_impl = nullptr; NotifyDestroy();
}
} delete m_impl;
m_impl = nullptr;
unsigned int NzAnimation::GetFrameCount() const }
{ }
#if NAZARA_UTILITY_SAFE
if (!m_impl) unsigned int NzAnimation::GetFrameCount() const
{ {
NazaraError("Animation not created"); #if NAZARA_UTILITY_SAFE
return false; if (!m_impl)
} {
#endif NazaraError("Animation not created");
return false;
return m_impl->frameCount; }
} #endif
NzSequence* NzAnimation::GetSequence(const NzString& sequenceName) return m_impl->frameCount;
{ }
#if NAZARA_UTILITY_SAFE
if (!m_impl) NzSequence* NzAnimation::GetSequence(const NzString& sequenceName)
{ {
NazaraError("Animation not created"); #if NAZARA_UTILITY_SAFE
return nullptr; if (!m_impl)
} {
NazaraError("Animation not created");
auto it = m_impl->sequenceMap.find(sequenceName); return nullptr;
if (it == m_impl->sequenceMap.end()) }
{
NazaraError("Sequence not found"); auto it = m_impl->sequenceMap.find(sequenceName);
return nullptr; if (it == m_impl->sequenceMap.end())
} {
NazaraError("Sequence not found");
return &m_impl->sequences[it->second]; return nullptr;
#else }
return &m_impl->sequences[m_impl->sequenceMap[sequenceName]];
#endif return &m_impl->sequences[it->second];
} #else
return &m_impl->sequences[m_impl->sequenceMap[sequenceName]];
NzSequence* NzAnimation::GetSequence(unsigned int index) #endif
{ }
#if NAZARA_UTILITY_SAFE
if (!m_impl) NzSequence* NzAnimation::GetSequence(unsigned int index)
{ {
NazaraError("Animation not created"); #if NAZARA_UTILITY_SAFE
return nullptr; if (!m_impl)
} {
NazaraError("Animation not created");
if (index >= m_impl->sequences.size()) return nullptr;
{ }
NazaraError("Sequence index out of range (" + NzString::Number(index) + " >= " + NzString::Number(m_impl->sequences.size()) + ')');
return nullptr; if (index >= m_impl->sequences.size())
} {
#endif NazaraError("Sequence index out of range (" + NzString::Number(index) + " >= " + NzString::Number(m_impl->sequences.size()) + ')');
return nullptr;
return &m_impl->sequences[index]; }
} #endif
const NzSequence* NzAnimation::GetSequence(const NzString& sequenceName) const return &m_impl->sequences[index];
{ }
#if NAZARA_UTILITY_SAFE
if (!m_impl) const NzSequence* NzAnimation::GetSequence(const NzString& sequenceName) const
{ {
NazaraError("Animation not created"); #if NAZARA_UTILITY_SAFE
return nullptr; if (!m_impl)
} {
NazaraError("Animation not created");
auto it = m_impl->sequenceMap.find(sequenceName); return nullptr;
if (it == m_impl->sequenceMap.end()) }
{
NazaraError("Sequence not found"); auto it = m_impl->sequenceMap.find(sequenceName);
return nullptr; if (it == m_impl->sequenceMap.end())
} {
NazaraError("Sequence not found");
return &m_impl->sequences[it->second]; return nullptr;
#else }
return &m_impl->sequences[m_impl->sequenceMap[sequenceName]];
#endif return &m_impl->sequences[it->second];
} #else
return &m_impl->sequences[m_impl->sequenceMap[sequenceName]];
const NzSequence* NzAnimation::GetSequence(unsigned int index) const #endif
{ }
#if NAZARA_UTILITY_SAFE
if (!m_impl) const NzSequence* NzAnimation::GetSequence(unsigned int index) const
{ {
NazaraError("Animation not created"); #if NAZARA_UTILITY_SAFE
return nullptr; if (!m_impl)
} {
NazaraError("Animation not created");
if (index >= m_impl->sequences.size()) return nullptr;
{ }
NazaraError("Sequence index out of range (" + NzString::Number(index) + " >= " + NzString::Number(m_impl->sequences.size()) + ')');
return nullptr; if (index >= m_impl->sequences.size())
} {
#endif NazaraError("Sequence index out of range (" + NzString::Number(index) + " >= " + NzString::Number(m_impl->sequences.size()) + ')');
return nullptr;
return &m_impl->sequences[index]; }
} #endif
unsigned int NzAnimation::GetSequenceCount() const return &m_impl->sequences[index];
{ }
#if NAZARA_UTILITY_SAFE
if (!m_impl) unsigned int NzAnimation::GetSequenceCount() const
{ {
NazaraError("Animation not created"); #if NAZARA_UTILITY_SAFE
return 0; if (!m_impl)
} {
#endif NazaraError("Animation not created");
return 0;
return m_impl->sequences.size(); }
} #endif
nzAnimationType NzAnimation::GetType() const return m_impl->sequences.size();
{ }
#if NAZARA_UTILITY_SAFE
if (!m_impl) int NzAnimation::GetSequenceIndex(const NzString& sequenceName) const
{ {
NazaraError("Animation not created"); #if NAZARA_UTILITY_SAFE
return nzAnimationType_Static; // Ce qui est une valeur invalide pour NzAnimation if (!m_impl)
} {
#endif NazaraError("Animation not created");
return -1;
return m_impl->type; }
}
auto it = m_impl->sequenceMap.find(sequenceName);
bool NzAnimation::HasSequence(const NzString& sequenceName) const if (it == m_impl->sequenceMap.end())
{ {
#if NAZARA_UTILITY_SAFE NazaraError("Sequence not found");
if (!m_impl) return -1;
{ }
NazaraError("Animation not created");
return false; return it->second;
} #else
#endif return m_impl->sequenceMap[sequenceName];
#endif
return m_impl->sequenceMap.find(sequenceName) != m_impl->sequenceMap.end(); }
}
nzAnimationType NzAnimation::GetType() const
bool NzAnimation::HasSequence(unsigned int index) const {
{ #if NAZARA_UTILITY_SAFE
#if NAZARA_UTILITY_SAFE if (!m_impl)
if (!m_impl) {
{ NazaraError("Animation not created");
NazaraError("Animation not created"); return nzAnimationType_Static; // Ce qui est une valeur invalide pour NzAnimation
return false; }
} #endif
#endif
return m_impl->type;
return index >= m_impl->sequences.size(); }
}
bool NzAnimation::HasSequence(const NzString& sequenceName) const
bool NzAnimation::IsValid() const {
{ #if NAZARA_UTILITY_SAFE
return m_impl != nullptr; if (!m_impl)
} {
NazaraError("Animation not created");
bool NzAnimation::LoadFromFile(const NzString& filePath, const NzAnimationParams& params) return false;
{ }
return NzAnimationLoader::LoadFromFile(this, filePath, params); #endif
}
return m_impl->sequenceMap.find(sequenceName) != m_impl->sequenceMap.end();
bool NzAnimation::LoadFromMemory(const void* data, std::size_t size, const NzAnimationParams& params) }
{
return NzAnimationLoader::LoadFromMemory(this, data, size, params); bool NzAnimation::HasSequence(unsigned int index) const
} {
#if NAZARA_UTILITY_SAFE
bool NzAnimation::LoadFromStream(NzInputStream& stream, const NzAnimationParams& params) if (!m_impl)
{ {
return NzAnimationLoader::LoadFromStream(this, stream, params); NazaraError("Animation not created");
} return false;
}
void NzAnimation::RemoveSequence(const NzString& identifier) #endif
{
#if NAZARA_UTILITY_SAFE return index >= m_impl->sequences.size();
if (!m_impl) }
{
NazaraError("Animation not created"); bool NzAnimation::IsValid() const
return; {
} return m_impl != nullptr;
}
auto it = m_impl->sequenceMap.find(identifier);
if (it == m_impl->sequenceMap.end()) bool NzAnimation::LoadFromFile(const NzString& filePath, const NzAnimationParams& params)
{ {
NazaraError("SubMesh not found"); return NzAnimationLoader::LoadFromFile(this, filePath, params);
return; }
}
bool NzAnimation::LoadFromMemory(const void* data, std::size_t size, const NzAnimationParams& params)
unsigned int index = it->second; {
#else return NzAnimationLoader::LoadFromMemory(this, data, size, params);
unsigned int index = m_impl->sequenceMap[identifier]; }
#endif
bool NzAnimation::LoadFromStream(NzInputStream& stream, const NzAnimationParams& params)
auto it2 = m_impl->sequences.begin(); {
std::advance(it2, index); return NzAnimationLoader::LoadFromStream(this, stream, params);
}
m_impl->sequences.erase(it2);
} void NzAnimation::RemoveSequence(const NzString& identifier)
{
void NzAnimation::RemoveSequence(unsigned int index) #if NAZARA_UTILITY_SAFE
{ if (!m_impl)
#if NAZARA_UTILITY_SAFE {
if (!m_impl) NazaraError("Animation not created");
{ return;
NazaraError("Animation not created"); }
return;
} auto it = m_impl->sequenceMap.find(identifier);
if (it == m_impl->sequenceMap.end())
if (index >= m_impl->sequences.size()) {
{ NazaraError("Sequence not found");
NazaraError("Sequence index out of range (" + NzString::Number(index) + " >= " + NzString::Number(m_impl->sequences.size()) + ')'); return;
return; }
}
#endif int index = it->second;
#else
auto it = m_impl->sequences.begin(); int index = m_impl->sequenceMap[identifier];
std::advance(it, index); #endif
m_impl->sequences.erase(it); auto it2 = m_impl->sequences.begin();
} std::advance(it2, index);
NzAnimationLoader::LoaderList NzAnimation::s_loaders; 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);
}
NzAnimationLoader::LoaderList NzAnimation::s_loaders;

View File

@ -1,337 +1,339 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module" // This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Buffer.hpp> #include <Nazara/Utility/Buffer.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Utility/BufferImpl.hpp> #include <Nazara/Utility/BufferImpl.hpp>
#include <Nazara/Utility/Config.hpp> #include <Nazara/Utility/Config.hpp>
#include <Nazara/Utility/SoftwareBuffer.hpp> #include <Nazara/Utility/SoftwareBuffer.hpp>
#include <cstring> #include <cstring>
#include <stdexcept> #include <stdexcept>
#include <Nazara/Utility/Debug.hpp> #include <Nazara/Utility/Debug.hpp>
namespace namespace
{ {
NzBufferImpl* SoftwareBufferFunction(NzBuffer* parent, nzBufferType type) NzBufferImpl* SoftwareBufferFunction(NzBuffer* parent, nzBufferType type)
{ {
return new NzSoftwareBuffer(parent, type); return new NzSoftwareBuffer(parent, type);
} }
} }
NzBuffer::NzBuffer(nzBufferType type) : NzBuffer::NzBuffer(nzBufferType type) :
m_type(type), m_type(type),
m_typeSize(0), m_typeSize(0),
m_impl(nullptr), m_impl(nullptr),
m_length(0) m_length(0)
{ {
} }
NzBuffer::NzBuffer(nzBufferType type, unsigned int length, nzUInt8 typeSize, nzBufferStorage storage, nzBufferUsage usage) : NzBuffer::NzBuffer(nzBufferType type, unsigned int length, nzUInt8 typeSize, nzBufferStorage storage, nzBufferUsage usage) :
m_type(type), m_type(type),
m_impl(nullptr) m_impl(nullptr)
{ {
Create(length, typeSize, storage, usage); Create(length, typeSize, storage, usage);
#ifdef NAZARA_DEBUG #ifdef NAZARA_DEBUG
if (!m_impl) if (!m_impl)
{ {
NazaraError("Failed to create buffer"); NazaraError("Failed to create buffer");
throw std::runtime_error("Constructor failed"); throw std::runtime_error("Constructor failed");
} }
#endif #endif
} }
NzBuffer::~NzBuffer() NzBuffer::~NzBuffer()
{ {
Destroy(); Destroy();
} }
bool NzBuffer::CopyContent(NzBuffer& buffer) bool NzBuffer::CopyContent(NzBuffer& buffer)
{ {
#if NAZARA_UTILITY_SAFE #if NAZARA_UTILITY_SAFE
if (!m_impl) if (!m_impl)
{ {
NazaraError("Buffer must be valid"); NazaraError("Buffer must be valid");
return false; return false;
} }
if (!buffer.IsValid()) if (!buffer.IsValid())
{ {
NazaraError("Source buffer must be valid"); NazaraError("Source buffer must be valid");
return false; return false;
} }
if (!buffer.GetTypeSize() != m_typeSize) if (!buffer.GetTypeSize() != m_typeSize)
{ {
NazaraError("Source buffer type size does not match buffer type size"); NazaraError("Source buffer type size does not match buffer type size");
return false; return false;
} }
#endif #endif
void* ptr = buffer.Map(nzBufferAccess_ReadOnly); void* ptr = buffer.Map(nzBufferAccess_ReadOnly);
if (!ptr) if (!ptr)
{ {
NazaraError("Failed to map source buffer"); NazaraError("Failed to map source buffer");
return false; return false;
} }
bool r = Fill(ptr, 0, buffer.GetLength()); bool r = Fill(ptr, 0, buffer.GetLength());
if (!buffer.Unmap()) if (!buffer.Unmap())
NazaraWarning("Failed to unmap source buffer"); NazaraWarning("Failed to unmap source buffer");
return r; return r;
} }
bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferStorage storage, nzBufferUsage usage) bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferStorage storage, nzBufferUsage usage)
{ {
Destroy(); Destroy();
// On tente d'abord de faire un buffer hardware, si supporté // On tente d'abord de faire un buffer hardware, si supporté
if (s_bufferFunctions[storage]) if (s_bufferFunctions[storage])
{ {
NzBufferImpl* impl = s_bufferFunctions[storage](this, m_type); NzBufferImpl* impl = s_bufferFunctions[storage](this, m_type);
if (!impl->Create(length*typeSize, usage)) if (!impl->Create(length*typeSize, usage))
{ {
NazaraError("Failed to create buffer"); NazaraError("Failed to create buffer");
delete impl; delete impl;
return false; return false;
} }
m_impl = impl; m_impl = impl;
} }
else else
{ {
NazaraError("Buffer storage not supported"); NazaraError("Buffer storage not supported");
return false; return false;
} }
m_length = length; m_length = length;
m_typeSize = typeSize; m_typeSize = typeSize;
m_storage = storage; m_storage = storage;
m_usage = usage; m_usage = usage;
// Si on arrive ici c'est que tout s'est bien passé. NotifyCreated();
return true; return true; // Si on arrive ici c'est que tout s'est bien passé.
} }
void NzBuffer::Destroy() void NzBuffer::Destroy()
{ {
if (m_impl) if (m_impl)
{ {
m_impl->Destroy(); NotifyDestroy();
delete m_impl;
m_impl = nullptr; 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 bool NzBuffer::Fill(const void* data, unsigned int offset, unsigned int length)
if (!m_impl) {
{ #if NAZARA_UTILITY_SAFE
NazaraError("Buffer not valid"); if (!m_impl)
return false; {
} NazaraError("Buffer not valid");
return false;
if (offset+length > m_length) }
{
NazaraError("Exceeding buffer size"); if (offset+length > m_length)
return false; {
} NazaraError("Exceeding buffer size");
#endif return false;
}
return m_impl->Fill(data, offset*m_typeSize, ((length == 0) ? m_length-offset : length)*m_typeSize); #endif
}
return m_impl->Fill(data, offset*m_typeSize, ((length == 0) ? m_length-offset : length)*m_typeSize);
NzBufferImpl* NzBuffer::GetImpl() const }
{
return m_impl; NzBufferImpl* NzBuffer::GetImpl() const
} {
return m_impl;
unsigned int NzBuffer::GetLength() const }
{
return m_length; unsigned int NzBuffer::GetLength() const
} {
return m_length;
void* NzBuffer::GetPointer() }
{
#if NAZARA_UTILITY_SAFE void* NzBuffer::GetPointer()
if (!m_impl) {
{ #if NAZARA_UTILITY_SAFE
NazaraError("Buffer not valid"); if (!m_impl)
return nullptr; {
} NazaraError("Buffer not valid");
#endif return nullptr;
}
return m_impl->GetPointer(); #endif
}
return m_impl->GetPointer();
const void* NzBuffer::GetPointer() const }
{
#if NAZARA_UTILITY_SAFE const void* NzBuffer::GetPointer() const
if (!m_impl) {
{ #if NAZARA_UTILITY_SAFE
NazaraError("Buffer not valid"); if (!m_impl)
return nullptr; {
} NazaraError("Buffer not valid");
#endif return nullptr;
}
return m_impl->GetPointer(); #endif
}
return m_impl->GetPointer();
unsigned int NzBuffer::GetSize() const }
{
return m_length*m_typeSize; unsigned int NzBuffer::GetSize() const
} {
return m_length*m_typeSize;
nzBufferStorage NzBuffer::GetStorage() const }
{
return m_storage; nzBufferStorage NzBuffer::GetStorage() const
} {
return m_storage;
nzBufferType NzBuffer::GetType() const }
{
return m_type; nzBufferType NzBuffer::GetType() const
} {
return m_type;
nzUInt8 NzBuffer::GetTypeSize() const }
{
return m_typeSize; nzUInt8 NzBuffer::GetTypeSize() const
} {
return m_typeSize;
nzBufferUsage NzBuffer::GetUsage() const }
{
return m_usage; nzBufferUsage NzBuffer::GetUsage() const
} {
return m_usage;
bool NzBuffer::IsHardware() const }
{
return m_storage == nzBufferStorage_Hardware; bool NzBuffer::IsHardware() const
} {
return m_storage == nzBufferStorage_Hardware;
bool NzBuffer::IsValid() const }
{
return m_impl != nullptr; bool NzBuffer::IsValid() const
} {
return m_impl != nullptr;
void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length) }
{
#if NAZARA_UTILITY_SAFE void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length)
if (!m_impl) {
{ #if NAZARA_UTILITY_SAFE
NazaraError("Buffer not valid"); if (!m_impl)
return nullptr; {
} NazaraError("Buffer not valid");
return nullptr;
if (offset+length > m_length) }
{
NazaraError("Exceeding buffer size"); if (offset+length > m_length)
return nullptr; {
} NazaraError("Exceeding buffer size");
#endif return nullptr;
}
return m_impl->Map(access, offset*m_typeSize, ((length == 0) ? m_length-offset : length)*m_typeSize); #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 bool NzBuffer::SetStorage(nzBufferStorage storage)
if (!m_impl) {
{ #if NAZARA_UTILITY_SAFE
NazaraError("Buffer not valid"); if (!m_impl)
return false; {
} NazaraError("Buffer not valid");
#endif return false;
}
if (m_storage == storage) #endif
return true;
if (m_storage == storage)
#if NAZARA_UTILITY_SAFE return true;
if (!IsSupported(storage))
{ #if NAZARA_UTILITY_SAFE
NazaraError("Storage not supported"); if (!IsSupported(storage))
return false; {
} NazaraError("Storage not supported");
#endif return false;
}
void* ptr = m_impl->Map(nzBufferAccess_ReadOnly, 0, m_length*m_typeSize); #endif
if (!ptr)
{ void* ptr = m_impl->Map(nzBufferAccess_ReadOnly, 0, m_length*m_typeSize);
NazaraError("Failed to map buffer"); if (!ptr)
return false; {
} NazaraError("Failed to map buffer");
return false;
NzBufferImpl* impl = s_bufferFunctions[storage](this, m_type); }
if (!impl->Create(m_length*m_typeSize, m_usage))
{ NzBufferImpl* impl = s_bufferFunctions[storage](this, m_type);
NazaraError("Failed to create buffer"); if (!impl->Create(m_length*m_typeSize, m_usage))
delete impl; {
NazaraError("Failed to create buffer");
if (!m_impl->Unmap()) delete impl;
NazaraWarning("Failed to unmap buffer");
if (!m_impl->Unmap())
return false; NazaraWarning("Failed to unmap buffer");
}
return false;
if (!impl->Fill(ptr, 0, m_length*m_typeSize)) }
{
NazaraError("Failed to fill buffer"); if (!impl->Fill(ptr, 0, m_length*m_typeSize))
impl->Destroy(); {
delete impl; NazaraError("Failed to fill buffer");
impl->Destroy();
if (!m_impl->Unmap()) delete impl;
NazaraWarning("Failed to unmap buffer");
if (!m_impl->Unmap())
return false; NazaraWarning("Failed to unmap buffer");
}
return false;
m_impl->Unmap(); }
m_impl->Destroy();
m_impl->Unmap();
delete m_impl; m_impl->Destroy();
m_impl = impl;
delete m_impl;
m_storage = storage; m_impl = impl;
return true; m_storage = storage;
}
return true;
bool NzBuffer::Unmap() }
{
#if NAZARA_UTILITY_SAFE bool NzBuffer::Unmap()
if (!m_impl) {
{ #if NAZARA_UTILITY_SAFE
NazaraError("Buffer not valid"); if (!m_impl)
return false; {
} NazaraError("Buffer not valid");
#endif return false;
}
return m_impl->Unmap(); #endif
}
return m_impl->Unmap();
bool NzBuffer::IsSupported(nzBufferStorage storage) }
{
return s_bufferFunctions[storage] != nullptr; bool NzBuffer::IsSupported(nzBufferStorage storage)
} {
return s_bufferFunctions[storage] != nullptr;
void NzBuffer::SetBufferFunction(nzBufferStorage storage, BufferFunction func) }
{
s_bufferFunctions[storage] = func; void NzBuffer::SetBufferFunction(nzBufferStorage storage, BufferFunction func)
} {
s_bufferFunctions[storage] = func;
bool NzBuffer::Initialize() }
{
s_bufferFunctions[nzBufferStorage_Software] = SoftwareBufferFunction; bool NzBuffer::Initialize()
{
return true; s_bufferFunctions[nzBufferStorage_Software] = SoftwareBufferFunction;
}
return true;
void NzBuffer::Uninitialize() }
{
std::memset(s_bufferFunctions, 0, (nzBufferStorage_Max+1)*sizeof(NzBuffer::BufferFunction)); void NzBuffer::Uninitialize()
} {
std::memset(s_bufferFunctions, 0, (nzBufferStorage_Max+1)*sizeof(NzBuffer::BufferFunction));
NzBuffer::BufferFunction NzBuffer::s_bufferFunctions[nzBufferStorage_Max+1] = {0}; }
NzBuffer::BufferFunction NzBuffer::s_bufferFunctions[nzBufferStorage_Max+1] = {0};

File diff suppressed because it is too large Load Diff

View File

@ -1,221 +1,200 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module" // This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Loaders/MD2.hpp> #include <Nazara/Utility/Loaders/MD2.hpp>
#include <Nazara/Core/Endianness.hpp> #include <Nazara/Core/Endianness.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Core/File.hpp> #include <Nazara/Core/File.hpp>
#include <Nazara/Core/InputStream.hpp> #include <Nazara/Core/InputStream.hpp>
#include <Nazara/Core/MemoryStream.hpp> #include <Nazara/Core/MemoryStream.hpp>
#include <Nazara/Math/Basic.hpp> #include <Nazara/Math/Basic.hpp>
#include <Nazara/Utility/Mesh.hpp> #include <Nazara/Utility/Mesh.hpp>
#include <Nazara/Utility/Loaders/MD2/Constants.hpp> #include <Nazara/Utility/Loaders/MD2/Constants.hpp>
#include <Nazara/Utility/Loaders/MD2/Mesh.hpp> #include <Nazara/Utility/Loaders/MD2/Mesh.hpp>
#include <cstddef> #include <cstddef>
#include <cstring> #include <cstring>
#include <Nazara/Utility/Debug.hpp> #include <Nazara/Utility/Debug.hpp>
namespace namespace
{ {
bool NzLoader_MD2_Check(NzInputStream& stream, const NzMeshParams& parameters) bool NzLoader_MD2_Check(NzInputStream& stream, const NzMeshParams& parameters)
{ {
NazaraUnused(parameters); NazaraUnused(parameters);
nzUInt32 magic[2]; nzUInt32 magic[2];
if (stream.Read(&magic[0], 2*sizeof(nzUInt32)) != 2*sizeof(nzUInt32)) if (stream.Read(&magic[0], 2*sizeof(nzUInt32)) != 2*sizeof(nzUInt32))
return false; return false;
#if defined(NAZARA_BIG_ENDIAN) #if defined(NAZARA_BIG_ENDIAN)
NzByteSwap(&magic[0], sizeof(nzUInt32)); NzByteSwap(&magic[0], sizeof(nzUInt32));
NzByteSwap(&magic[1], sizeof(nzUInt32)); NzByteSwap(&magic[1], sizeof(nzUInt32));
#endif #endif
return magic[0] == md2Ident && magic[1] == 8; return magic[0] == md2Ident && magic[1] == 8;
} }
bool NzLoader_MD2_Load(NzMesh* mesh, NzInputStream& stream, const NzMeshParams& parameters) bool NzLoader_MD2_Load(NzMesh* mesh, NzInputStream& stream, const NzMeshParams& parameters)
{ {
md2_header header; md2_header header;
if (stream.Read(&header, sizeof(md2_header)) != sizeof(md2_header)) if (stream.Read(&header, sizeof(md2_header)) != sizeof(md2_header))
{ {
NazaraError("Failed to read header"); NazaraError("Failed to read header");
return false; return false;
} }
// Les fichiers MD2 sont en little endian #if defined(NAZARA_BIG_ENDIAN)
#if defined(NAZARA_BIG_ENDIAN) NzByteSwap(&header.skinwidth, sizeof(nzUInt32));
NzByteSwap(&header.ident, sizeof(nzUInt32)); NzByteSwap(&header.skinheight, sizeof(nzUInt32));
#endif NzByteSwap(&header.framesize, sizeof(nzUInt32));
NzByteSwap(&header.num_skins, sizeof(nzUInt32));
if (header.ident != md2Ident) NzByteSwap(&header.num_vertices, sizeof(nzUInt32));
{ NzByteSwap(&header.num_st, sizeof(nzUInt32));
NazaraError("Invalid MD2 file"); NzByteSwap(&header.num_tris, sizeof(nzUInt32));
return false; NzByteSwap(&header.num_glcmds, sizeof(nzUInt32));
} NzByteSwap(&header.num_frames, sizeof(nzUInt32));
NzByteSwap(&header.offset_skins, sizeof(nzUInt32));
#if defined(NAZARA_BIG_ENDIAN) NzByteSwap(&header.offset_st, sizeof(nzUInt32));
NzByteSwap(&header.version, sizeof(nzUInt32)); NzByteSwap(&header.offset_tris, sizeof(nzUInt32));
#endif NzByteSwap(&header.offset_frames, sizeof(nzUInt32));
NzByteSwap(&header.offset_glcmds, sizeof(nzUInt32));
if (header.version != 8) NzByteSwap(&header.offset_end, sizeof(nzUInt32));
{ #endif
NazaraError("Bad version number (" + NzString::Number(header.version) + ')');
return false; if (stream.GetSize() < header.offset_end)
} {
NazaraError("Incomplete MD2 file");
#if defined(NAZARA_BIG_ENDIAN) return false;
NzByteSwap(&header.skinwidth, sizeof(nzUInt32)); }
NzByteSwap(&header.skinheight, sizeof(nzUInt32));
NzByteSwap(&header.framesize, sizeof(nzUInt32)); /// Création du mesh
NzByteSwap(&header.num_skins, sizeof(nzUInt32)); // Animé ou statique, c'est la question
NzByteSwap(&header.num_vertices, sizeof(nzUInt32)); bool animated;
NzByteSwap(&header.num_st, sizeof(nzUInt32)); unsigned int startFrame = NzClamp(parameters.animation.startFrame, 0U, static_cast<unsigned int>(header.num_frames-1));
NzByteSwap(&header.num_tris, sizeof(nzUInt32)); unsigned int endFrame = NzClamp(parameters.animation.endFrame, 0U, static_cast<unsigned int>(header.num_frames-1));
NzByteSwap(&header.num_glcmds, sizeof(nzUInt32));
NzByteSwap(&header.num_frames, sizeof(nzUInt32)); if (parameters.loadAnimations && startFrame != endFrame)
NzByteSwap(&header.offset_skins, sizeof(nzUInt32)); animated = true;
NzByteSwap(&header.offset_st, sizeof(nzUInt32)); else
NzByteSwap(&header.offset_tris, sizeof(nzUInt32)); animated = false;
NzByteSwap(&header.offset_frames, sizeof(nzUInt32));
NzByteSwap(&header.offset_glcmds, sizeof(nzUInt32)); if (!mesh->Create((animated) ? nzAnimationType_Keyframe : nzAnimationType_Static)) // Ne devrait jamais échouer
NzByteSwap(&header.offset_end, sizeof(nzUInt32)); {
#endif NazaraInternalError("Failed to create mesh");
return false;
if (stream.GetSize() < header.offset_end) }
{
NazaraError("Incomplete MD2 file"); /// Chargement des skins
return false; if (header.num_skins > 0)
} {
stream.SetCursorPos(header.offset_skins);
/// Création du mesh {
// Animé ou statique, c'est la question char skin[68];
bool animated; for (unsigned int i = 0; i < header.num_skins; ++i)
unsigned int startFrame = NzClamp(parameters.animation.startFrame, 0U, static_cast<unsigned int>(header.num_frames-1)); {
unsigned int endFrame = NzClamp(parameters.animation.endFrame, 0U, static_cast<unsigned int>(header.num_frames-1)); stream.Read(skin, 68*sizeof(char));
mesh->AddSkin(skin);
if (parameters.loadAnimations && startFrame != endFrame) }
animated = true; }
else }
animated = false;
/// Chargement des animmations
if (!mesh->Create((animated) ? nzAnimationType_Keyframe : nzAnimationType_Static)) // Ne devrait pas échouer if (animated)
{ {
NazaraInternalError("Failed to create mesh"); NzAnimation* animation = new NzAnimation;
return false; if (animation->Create(nzAnimationType_Keyframe, endFrame-startFrame+1))
} {
// Décodage des séquences
/// Chargement des skins NzString frameName;
if (header.num_skins > 0)
{ NzSequence sequence;
stream.SetCursorPos(header.offset_skins); sequence.framePerSecond = 10; // Par défaut pour les animations MD2
{
char skin[68]; char name[16], last[16];
for (unsigned int i = 0; i < header.num_skins; ++i) stream.SetCursorPos(header.offset_frames + startFrame*header.framesize + offsetof(md2_frame, name));
{ stream.Read(last, 16*sizeof(char));
stream.Read(skin, 68*sizeof(char));
mesh->AddSkin(skin); int pos = std::strlen(last)-1;
} for (unsigned int j = 0; j < 2; ++j)
} {
} if (!std::isdigit(last[pos]))
break;
/// Chargement des animmations
if (animated) pos--;
{ }
NzAnimation* animation = new NzAnimation; last[pos+1] = '\0';
if (animation->Create(nzAnimationType_Keyframe, endFrame-startFrame+1))
{ unsigned int numFrames = 0;
// Décodage des séquences for (unsigned int i = startFrame; i <= endFrame; ++i)
NzString frameName; {
stream.SetCursorPos(header.offset_frames + i*header.framesize + offsetof(md2_frame, name));
NzSequence sequence; stream.Read(name, 16*sizeof(char));
sequence.framePerSecond = 10; // Par défaut pour les animations MD2
pos = std::strlen(name)-1;
char name[16], last[16]; for (unsigned int j = 0; j < 2; ++j)
stream.SetCursorPos(header.offset_frames + startFrame*header.framesize + offsetof(md2_frame, name)); {
stream.Read(last, 16*sizeof(char)); if (!std::isdigit(name[pos]))
break;
int pos = std::strlen(last)-1;
for (unsigned int j = 0; j < 2; ++j) pos--;
{ }
if (!std::isdigit(last[pos])) name[pos+1] = '\0';
break;
if (std::strcmp(name, last) != 0) // Si les deux frames n'ont pas le même nom
pos--; {
} // Alors on enregistre la séquence
last[pos+1] = '\0'; sequence.firstFrame = i-numFrames;
sequence.lastFrame = i-1;
unsigned int numFrames = 0; sequence.name = last;
for (unsigned int i = startFrame; i <= endFrame; ++i) animation->AddSequence(sequence);
{
stream.SetCursorPos(header.offset_frames + i*header.framesize + offsetof(md2_frame, name)); std::strcpy(last, name);
stream.Read(name, 16*sizeof(char));
numFrames = 0;
pos = std::strlen(name)-1; }
for (unsigned int j = 0; j < 2; ++j)
{ numFrames++;
if (!std::isdigit(name[pos])) }
break;
// On ajoute la dernière frame (Qui n'a pas été traitée par la boucle)
pos--; sequence.firstFrame = endFrame-numFrames;
} sequence.lastFrame = endFrame;
name[pos+1] = '\0'; sequence.name = last;
animation->AddSequence(sequence);
if (std::strcmp(name, last) != 0) // Si les deux frames n'ont pas le même nom
{ mesh->SetAnimation(animation);
// Alors on enregistre la séquence animation->SetPersistent(false);
sequence.firstFrame = i-numFrames; }
sequence.lastFrame = i-1; else
sequence.name = last; NazaraInternalError("Failed to create animaton");
animation->AddSequence(sequence); }
std::strcpy(last, name); /// Chargement des submesh
// Actuellement le loader ne charge qu'un submesh
numFrames = 0; // TODO: Utiliser les commandes OpenGL pour accélérer le rendu
} NzMD2Mesh* subMesh = new NzMD2Mesh(mesh);
if (!subMesh->Create(header, stream, parameters))
numFrames++; {
} NazaraError("Failed to create MD2 mesh");
return false;
// On ajoute la dernière frame (Qui n'a pas été traitée par la boucle) }
sequence.firstFrame = endFrame-numFrames;
sequence.lastFrame = endFrame; mesh->AddSubMesh(subMesh);
sequence.name = last;
animation->AddSequence(sequence); return true;
}
mesh->SetAnimation(animation); }
animation->SetPersistent(false);
} void NzLoaders_MD2_Register()
else {
NazaraInternalError("Failed to create animaton"); NzMD2Mesh::Initialize();
}
NzMeshLoader::RegisterLoader("md2", NzLoader_MD2_Check, NzLoader_MD2_Load);
/// Chargement des submesh }
// Actuellement le loader ne charge qu'un submesh
// TODO: Utiliser les commandes OpenGL pour accélérer le rendu void NzLoaders_MD2_Unregister()
NzMD2Mesh* subMesh = new NzMD2Mesh(mesh); {
if (!subMesh->Create(header, stream, parameters)) NzMeshLoader::UnregisterLoader("md2", NzLoader_MD2_Check, NzLoader_MD2_Load);
{
NazaraError("Failed to create MD2 mesh"); NzMD2Mesh::Uninitialize();
return false; }
}
mesh->AddSubMesh(subMesh);
return true;
}
}
void NzLoaders_MD2_Register()
{
NzMD2Mesh::Initialize();
NzMeshLoader::RegisterLoader("md2", NzLoader_MD2_Check, NzLoader_MD2_Load);
}
void NzLoaders_MD2_Unregister()
{
NzMeshLoader::UnregisterLoader("md2", NzLoader_MD2_Check, NzLoader_MD2_Load);
NzMD2Mesh::Uninitialize();
}

View File

@ -1,287 +1,292 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module" // This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Loaders/MD2/Mesh.hpp> #include <Nazara/Utility/Loaders/MD2/Mesh.hpp>
#include <Nazara/Core/InputStream.hpp> #include <Nazara/Core/InputStream.hpp>
#include <Nazara/Math/Matrix4.hpp> #include <Nazara/Math/Matrix4.hpp>
#include <Nazara/Utility/IndexBuffer.hpp> #include <Nazara/Utility/IndexBuffer.hpp>
#include <Nazara/Utility/Mesh.hpp> #include <Nazara/Utility/Mesh.hpp>
#include <Nazara/Utility/VertexBuffer.hpp> #include <Nazara/Utility/VertexBuffer.hpp>
#include <Nazara/Utility/Debug.hpp> #include <Nazara/Utility/Debug.hpp>
NzMD2Mesh::NzMD2Mesh(const NzMesh* parent) : NzMD2Mesh::NzMD2Mesh(const NzMesh* parent) :
NzKeyframeMesh(parent), NzKeyframeMesh(parent),
m_frames(nullptr), m_frames(nullptr),
m_indexBuffer(nullptr), m_indexBuffer(nullptr),
m_vertexBuffer(nullptr) m_vertexBuffer(nullptr)
{ {
} }
NzMD2Mesh::~NzMD2Mesh() NzMD2Mesh::~NzMD2Mesh()
{ {
Destroy(); Destroy();
} }
bool NzMD2Mesh::Create(const md2_header& header, NzInputStream& stream, const NzMeshParams& parameters) bool NzMD2Mesh::Create(const md2_header& header, NzInputStream& stream, const NzMeshParams& parameters)
{ {
Destroy(); Destroy();
unsigned int startFrame = NzClamp(parameters.animation.startFrame, 0U, static_cast<unsigned int>(header.num_frames-1)); unsigned int startFrame = NzClamp(parameters.animation.startFrame, 0U, static_cast<unsigned int>(header.num_frames-1));
unsigned int endFrame = NzClamp(parameters.animation.endFrame, 0U, static_cast<unsigned int>(header.num_frames-1)); unsigned int endFrame = NzClamp(parameters.animation.endFrame, 0U, static_cast<unsigned int>(header.num_frames-1));
m_frameCount = endFrame - startFrame + 1; m_frameCount = endFrame - startFrame + 1;
m_vertexCount = header.num_tris*3; m_vertexCount = header.num_tris * 3;
/// Chargement des vertices /// Chargement des vertices
std::vector<md2_texCoord> texCoords(header.num_st); std::vector<md2_texCoord> texCoords(header.num_st);
std::vector<md2_triangle> triangles(header.num_tris); std::vector<md2_triangle> triangles(header.num_tris);
// Lecture des coordonnées de texture // Lecture des coordonnées de texture
stream.SetCursorPos(header.offset_st); stream.SetCursorPos(header.offset_st);
stream.Read(&texCoords[0], header.num_st*sizeof(md2_texCoord)); stream.Read(&texCoords[0], header.num_st*sizeof(md2_texCoord));
#if defined(NAZARA_BIG_ENDIAN) #if defined(NAZARA_BIG_ENDIAN)
for (unsigned int i = 0; i < header.num_st; ++i) for (unsigned int i = 0; i < header.num_st; ++i)
{ {
NzByteSwap(&texCoords[i].u, sizeof(nzInt16)); NzByteSwap(&texCoords[i].u, sizeof(nzInt16));
NzByteSwap(&texCoords[i].v, sizeof(nzInt16)); NzByteSwap(&texCoords[i].v, sizeof(nzInt16));
} }
#endif #endif
stream.SetCursorPos(header.offset_tris); stream.SetCursorPos(header.offset_tris);
stream.Read(&triangles[0], header.num_tris*sizeof(md2_triangle)); stream.Read(&triangles[0], header.num_tris*sizeof(md2_triangle));
#if defined(NAZARA_BIG_ENDIAN) #if defined(NAZARA_BIG_ENDIAN)
for (unsigned int i = 0; i < header.num_tris; ++i) for (unsigned int i = 0; i < header.num_tris; ++i)
{ {
NzByteSwap(&triangles[i].vertices[0], sizeof(nzUInt16)); NzByteSwap(&triangles[i].vertices[0], sizeof(nzUInt16));
NzByteSwap(&texCoords[i].texCoords[0], sizeof(nzUInt16)); NzByteSwap(&texCoords[i].texCoords[0], sizeof(nzUInt16));
NzByteSwap(&triangles[i].vertices[1], sizeof(nzUInt16)); NzByteSwap(&triangles[i].vertices[1], sizeof(nzUInt16));
NzByteSwap(&texCoords[i].texCoords[1], sizeof(nzUInt16)); NzByteSwap(&texCoords[i].texCoords[1], sizeof(nzUInt16));
NzByteSwap(&triangles[i].vertices[2], sizeof(nzUInt16)); NzByteSwap(&triangles[i].vertices[2], sizeof(nzUInt16));
NzByteSwap(&texCoords[i].texCoords[2], sizeof(nzUInt16)); NzByteSwap(&texCoords[i].texCoords[2], sizeof(nzUInt16));
} }
#endif #endif
stream.SetCursorPos(header.offset_frames + header.framesize*startFrame); stream.SetCursorPos(header.offset_frames + header.framesize*startFrame);
md2_frame frame; md2_frame frame;
frame.vertices.resize(header.num_vertices); 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 // Pour que le modèle soit correctement aligné, on génère un quaternion que nous appliquerons à chacune des vertices
NzMatrix4f rotationMatrix = NzMatrix4f::Rotate(NzEulerAnglesf(90.f, -90.f, 0.f)); NzQuaternionf rotationQuat = NzEulerAnglesf(-90.f, 90.f, 0.f);
//NzMatrix4f rotationMatrix = NzMatrix4f::Rotate(NzEulerAnglesf(-90.f, -90.f, 0.f));
unsigned int stride = s_declaration.GetStride(nzElementStream_VertexData);
unsigned int stride = s_declaration.GetStride(nzElementStream_VertexData);
m_frames = new Frame[m_frameCount];
for (unsigned int i = 0; i < m_frameCount; ++i) 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.scale, sizeof(NzVector3f));
stream.Read(&frame.name, 16*sizeof(char)); stream.Read(&frame.translate, sizeof(NzVector3f));
stream.Read(&frame.vertices[0], header.num_vertices*sizeof(md2_vertex)); stream.Read(&frame.name, 16*sizeof(char));
stream.Read(&frame.vertices[0], header.num_vertices*sizeof(md2_vertex));
#if defined(NAZARA_BIG_ENDIAN)
NzByteSwap(&frame.scale.x, sizeof(float)); #if defined(NAZARA_BIG_ENDIAN)
NzByteSwap(&frame.scale.y, sizeof(float)); NzByteSwap(&frame.scale.x, sizeof(float));
NzByteSwap(&frame.scale.z, 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.x, sizeof(float));
NzByteSwap(&frame.translate.z, sizeof(float)); NzByteSwap(&frame.translate.y, sizeof(float));
#endif 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]; m_frames[i].normal = new nzUInt8[m_vertexCount]; // Nous stockons l'indice MD2 de la normale plutôt que la normale (gain d'espace)
m_frames[i].vertices = new NzVector3f[m_vertexCount];
NzVector3f max, min;
for (unsigned int t = 0; t < header.num_tris; ++t) NzVector3f max, min;
{ for (unsigned int t = 0; t < header.num_tris; ++t)
for (unsigned int v = 0; v < 3; ++v) {
{ for (unsigned int v = 0; v < 3; ++v)
const md2_vertex& vert = frame.vertices[triangles[t].vertices[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);
max.MakeCeil(vertex); NzVector3f vertex = rotationQuat * 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);
min.MakeFloor(vertex);
// On fait en sorte d'avoir deux vertices de délimitation, définissant un rectangle dans l'espace
m_frames[i].normal[t*3+v] = vert.n; max.Maximize(vertex);
m_frames[i].vertices[t*3+v] = vertex; min.Minimize(vertex);
}
} // Le MD2 ne définit pas ses vertices dans le bon ordre, il nous faut donc les ajouter dans l'ordre inverse
unsigned int index = m_vertexCount - (t*3 + v) - 1;
m_frames[i].aabb.SetExtends(min, max); m_frames[i].normal[index] = vert.n;
} m_frames[i].vertices[index] = vertex;
}
m_indexBuffer = nullptr; // Pas d'indexbuffer pour l'instant }
m_vertexBuffer = new NzVertexBuffer(m_vertexCount, (3+3+2)*sizeof(float), parameters.storage, nzBufferUsage_Dynamic);
m_frames[i].aabb.SetExtends(min, max);
nzUInt8* ptr = reinterpret_cast<nzUInt8*>(m_vertexBuffer->Map(nzBufferAccess_WriteOnly)); }
if (!ptr)
{ m_indexBuffer = nullptr; // Pas d'indexbuffer pour l'instant
NazaraError("Failed to map vertex buffer"); m_vertexBuffer = new NzVertexBuffer(m_vertexCount, (3+3+2)*sizeof(float), parameters.storage, nzBufferUsage_Dynamic);
Destroy();
nzUInt8* ptr = reinterpret_cast<nzUInt8*>(m_vertexBuffer->Map(nzBufferAccess_WriteOnly));
return false; if (!ptr)
} {
NazaraError("Failed to map vertex buffer");
// On avance jusqu'aux premières coordonnées de texture Destroy();
ptr += s_declaration.GetElement(nzElementStream_VertexData, nzElementUsage_TexCoord)->offset;
for (unsigned int t = 0; t < header.num_tris; ++t) return false;
{ }
for (unsigned int v = 0; v < 3; ++v)
{ // On avance jusqu'aux dernières coordonnées de texture et on les définit dans l'ordre inverse
const md2_texCoord& texC = texCoords[triangles[t].texCoords[v]]; ptr += s_declaration.GetElement(nzElementStream_VertexData, nzElementUsage_TexCoord)->offset + stride * (m_vertexCount-1);
for (unsigned int t = 0; t < header.num_tris; ++t)
NzVector2f* coords = reinterpret_cast<NzVector2f*>(ptr); {
coords->x = texC.u / static_cast<float>(header.skinwidth); for (unsigned int v = 0; v < 3; ++v)
coords->y = 1.f - texC.v / static_cast<float>(header.skinheight); {
const md2_texCoord& texC = texCoords[triangles[t].texCoords[v]];
ptr += stride;
} NzVector2f* coords = reinterpret_cast<NzVector2f*>(ptr);
} coords->x = texC.u / static_cast<float>(header.skinwidth);
coords->y = 1.f - texC.v / static_cast<float>(header.skinheight);
if (!m_vertexBuffer->Unmap())
{ ptr -= stride;
NazaraError("Failed to unmap buffer"); }
Destroy(); }
return false; if (!m_vertexBuffer->Unmap())
} {
NazaraError("Failed to unmap buffer");
m_vertexBuffer->AddResourceReference(); Destroy();
m_vertexBuffer->SetPersistent(false);
return false;
AnimateImpl(0, 0, 0.f); }
return true; m_vertexBuffer->AddResourceReference();
} m_vertexBuffer->SetPersistent(false);
void NzMD2Mesh::Destroy() AnimateImpl(0, 0, 0.f);
{
if (m_frames) return true;
{ }
for (unsigned int i = 0; i < m_frameCount; ++i)
{ void NzMD2Mesh::Destroy()
delete[] m_frames[i].normal; {
delete[] m_frames[i].vertices; if (m_frames)
} {
for (unsigned int i = 0; i < m_frameCount; ++i)
delete[] m_frames; {
m_frames = nullptr; delete[] m_frames[i].normal;
} delete[] m_frames[i].vertices;
}
if (m_indexBuffer)
{ delete[] m_frames;
m_indexBuffer->RemoveResourceReference(); m_frames = nullptr;
m_indexBuffer = nullptr; }
}
if (m_indexBuffer)
if (m_vertexBuffer) {
{ m_indexBuffer->RemoveResourceReference();
m_vertexBuffer->RemoveResourceReference(); m_indexBuffer = nullptr;
m_vertexBuffer = nullptr; }
}
} if (m_vertexBuffer)
{
const NzAxisAlignedBox& NzMD2Mesh::GetAABB() const m_vertexBuffer->RemoveResourceReference();
{ m_vertexBuffer = nullptr;
return m_aabb; }
} }
nzAnimationType NzMD2Mesh::GetAnimationType() const const NzAxisAlignedBox& NzMD2Mesh::GetAABB() const
{ {
if (m_frameCount > 1) return m_aabb;
return nzAnimationType_Keyframe; }
else
return nzAnimationType_Static; nzAnimationType NzMD2Mesh::GetAnimationType() const
} {
if (m_frameCount > 1)
unsigned int NzMD2Mesh::GetFrameCount() const return nzAnimationType_Keyframe;
{ else
return m_frameCount; return nzAnimationType_Static;
} }
const NzIndexBuffer* NzMD2Mesh::GetIndexBuffer() const unsigned int NzMD2Mesh::GetFrameCount() const
{ {
return nullptr; return m_frameCount;
//return m_indexBuffer; }
}
const NzIndexBuffer* NzMD2Mesh::GetIndexBuffer() const
nzPrimitiveType NzMD2Mesh::GetPrimitiveType() const {
{ return nullptr;
return nzPrimitiveType_TriangleList; //return m_indexBuffer;
} }
const NzVertexBuffer* NzMD2Mesh::GetVertexBuffer() const nzPrimitiveType NzMD2Mesh::GetPrimitiveType() const
{ {
return m_vertexBuffer; return nzPrimitiveType_TriangleList;
} }
const NzVertexDeclaration* NzMD2Mesh::GetVertexDeclaration() const const NzVertexBuffer* NzMD2Mesh::GetVertexBuffer() const
{ {
return &s_declaration; return m_vertexBuffer;
} }
void NzMD2Mesh::Initialize() const NzVertexDeclaration* NzMD2Mesh::GetVertexDeclaration() const
{ {
NzVertexElement elements[3]; return &s_declaration;
elements[0].offset = 0; }
elements[0].type = nzElementType_Float3;
elements[0].usage = nzElementUsage_Position; void NzMD2Mesh::Initialize()
{
elements[1].offset = 3*sizeof(float); NzVertexElement elements[3];
elements[1].type = nzElementType_Float3; elements[0].offset = 0;
elements[1].usage = nzElementUsage_Normal; elements[0].type = nzElementType_Float3;
elements[0].usage = nzElementUsage_Position;
elements[2].offset = 3*sizeof(float) + 3*sizeof(float);
elements[2].type = nzElementType_Float2; elements[1].offset = 3*sizeof(float);
elements[2].usage = nzElementUsage_TexCoord; elements[1].type = nzElementType_Float3;
elements[1].usage = nzElementUsage_Normal;
s_declaration.Create(elements, 3);
} elements[2].offset = 3*sizeof(float) + 3*sizeof(float);
elements[2].type = nzElementType_Float2;
void NzMD2Mesh::Uninitialize() elements[2].usage = nzElementUsage_TexCoord;
{
s_declaration.Destroy(); s_declaration.Create(elements, 3);
} }
void NzMD2Mesh::AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation) void NzMD2Mesh::Uninitialize()
{ {
nzUInt8* ptr = reinterpret_cast<nzUInt8*>(m_vertexBuffer->Map(nzBufferAccess_WriteOnly)); s_declaration.Destroy();
if (!ptr) }
{
NazaraError("Failed to map vertex buffer"); void NzMD2Mesh::AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation)
return; {
} nzUInt8* ptr = reinterpret_cast<nzUInt8*>(m_vertexBuffer->Map(nzBufferAccess_WriteOnly));
if (!ptr)
unsigned int stride = s_declaration.GetStride(nzElementStream_VertexData); {
unsigned int positionOffset = s_declaration.GetElement(nzElementStream_VertexData, nzElementUsage_Position)->offset; NazaraError("Failed to map vertex buffer");
unsigned int normalOffset = s_declaration.GetElement(nzElementStream_VertexData, nzElementUsage_Normal)->offset; return;
}
Frame* fA = &m_frames[frameA];
Frame* fB = &m_frames[frameB]; unsigned int stride = s_declaration.GetStride(nzElementStream_VertexData);
for (unsigned int i = 0; i < m_vertexCount; ++i) unsigned int positionOffset = s_declaration.GetElement(nzElementStream_VertexData, nzElementUsage_Position)->offset;
{ unsigned int normalOffset = s_declaration.GetElement(nzElementStream_VertexData, nzElementUsage_Normal)->offset;
NzVector3f* position = reinterpret_cast<NzVector3f*>(ptr + positionOffset);
NzVector3f* normal = reinterpret_cast<NzVector3f*>(ptr + normalOffset); Frame* fA = &m_frames[frameA];
Frame* fB = &m_frames[frameB];
*position = fA->vertices[i] + interpolation * (fB->vertices[i] - fA->vertices[i]); for (unsigned int i = 0; i < m_vertexCount; ++i)
*normal = md2Normals[fA->normal[i]] + interpolation * (md2Normals[fB->normal[i]] - md2Normals[fA->normal[i]]); {
NzVector3f* position = reinterpret_cast<NzVector3f*>(ptr + positionOffset);
ptr += stride; NzVector3f* normal = reinterpret_cast<NzVector3f*>(ptr + normalOffset);
}
*position = fA->vertices[i] + interpolation * (fB->vertices[i] - fA->vertices[i]);
if (!m_vertexBuffer->Unmap()) *normal = md2Normals[fA->normal[i]] + interpolation * (md2Normals[fB->normal[i]] - md2Normals[fA->normal[i]]);
NazaraWarning("Failed to unmap vertex buffer, expect mesh corruption");
ptr += stride;
// Interpolation de l'AABB }
NzVector3f max1 = fA->aabb.GetMaximum();
NzVector3f min1 = fA->aabb.GetMinimum(); if (!m_vertexBuffer->Unmap())
m_aabb.SetExtends(min1 + interpolation * (fB->aabb.GetMinimum() - min1), max1 + interpolation * (fB->aabb.GetMaximum() - max1)); NazaraWarning("Failed to unmap vertex buffer, expect mesh corruption");
}
// Interpolation de l'AABB
NzVertexDeclaration NzMD2Mesh::s_declaration; NzVector3f max1 = fA->aabb.GetMaximum();
NzVector3f min1 = fA->aabb.GetMinimum();
m_aabb.SetExtends(min1 + interpolation * (fB->aabb.GetMinimum() - min1), max1 + interpolation * (fB->aabb.GetMaximum() - max1));
}
NzVertexDeclaration NzMD2Mesh::s_declaration;

View File

@ -1,352 +1,346 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module" // This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Loaders/PCX.hpp> #include <Nazara/Utility/Loaders/PCX.hpp>
#include <Nazara/Core/Endianness.hpp> #include <Nazara/Core/Endianness.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Core/File.hpp> #include <Nazara/Core/File.hpp>
#include <Nazara/Core/InputStream.hpp> #include <Nazara/Core/InputStream.hpp>
#include <Nazara/Core/MemoryStream.hpp> #include <Nazara/Core/MemoryStream.hpp>
#include <Nazara/Utility/Image.hpp> #include <Nazara/Utility/Image.hpp>
#include <Nazara/Utility/Debug.hpp> #include <Nazara/Utility/Debug.hpp>
// Auteur du loader original : David Henry // Auteur du loader original : David Henry
namespace namespace
{ {
struct pcx_header struct pcx_header
{ {
nzUInt8 manufacturer; nzUInt8 manufacturer;
nzUInt8 version; nzUInt8 version;
nzUInt8 encoding; nzUInt8 encoding;
nzUInt8 bitsPerPixel; nzUInt8 bitsPerPixel;
nzUInt16 xmin, ymin; nzUInt16 xmin, ymin;
nzUInt16 xmax, ymax; nzUInt16 xmax, ymax;
nzUInt16 horzRes, vertRes; nzUInt16 horzRes, vertRes;
nzUInt8 palette[48]; nzUInt8 palette[48];
nzUInt8 reserved; nzUInt8 reserved;
nzUInt8 numColorPlanes; nzUInt8 numColorPlanes;
nzUInt16 bytesPerScanLine; nzUInt16 bytesPerScanLine;
nzUInt16 paletteType; nzUInt16 paletteType;
nzUInt16 horzSize, vertSize; nzUInt16 horzSize, vertSize;
nzUInt8 padding[54]; nzUInt8 padding[54];
}; };
bool NzLoader_PCX_Check(NzInputStream& stream, const NzImageParams& parameters) bool NzLoader_PCX_Check(NzInputStream& stream, const NzImageParams& parameters)
{ {
NazaraUnused(parameters); NazaraUnused(parameters);
nzUInt8 manufacturer; nzUInt8 manufacturer;
if (stream.Read(&manufacturer, 1) != 1) if (stream.Read(&manufacturer, 1) != 1)
return false; return false;
return manufacturer == 0x0a; return manufacturer == 0x0a;
} }
bool NzLoader_PCX_Load(NzImage* image, NzInputStream& stream, const NzImageParams& parameters) bool NzLoader_PCX_Load(NzImage* image, NzInputStream& stream, const NzImageParams& parameters)
{ {
NazaraUnused(parameters); NazaraUnused(parameters);
pcx_header header; pcx_header header;
if (stream.Read(&header, sizeof(pcx_header)) != sizeof(pcx_header)) if (stream.Read(&header, sizeof(pcx_header)) != sizeof(pcx_header))
{ {
NazaraError("Failed to read header"); NazaraError("Failed to read header");
return false; return false;
} }
if (header.manufacturer != 0x0a) #if defined(NAZARA_BIG_ENDIAN)
{ // Les fichiers PCX sont en little endian
NazaraError("Bad version number (" + NzString::Number(header.manufacturer) + ')'); NzByteSwap(&header.xmin, sizeof(nzUInt16));
return false; NzByteSwap(&header.ymin, sizeof(nzUInt16));
} NzByteSwap(&header.xmax, sizeof(nzUInt16));
NzByteSwap(&header.ymax, sizeof(nzUInt16));
#if defined(NAZARA_BIG_ENDIAN) NzByteSwap(&header.horzRes, sizeof(nzUInt16));
// Les fichiers PCX sont en little endian NzByteSwap(&header.vertRes, sizeof(nzUInt16));
NzByteSwap(&header.xmin, sizeof(nzUInt16));
NzByteSwap(&header.ymin, sizeof(nzUInt16)); NzByteSwap(&header.bytesPerScanLine, sizeof(nzUInt16));
NzByteSwap(&header.xmax, sizeof(nzUInt16)); NzByteSwap(&header.paletteType, sizeof(nzUInt16));
NzByteSwap(&header.ymax, sizeof(nzUInt16)); NzByteSwap(&header.horzSize, sizeof(nzUInt16));
NzByteSwap(&header.horzRes, sizeof(nzUInt16)); NzByteSwap(&header.vertSize, sizeof(nzUInt16));
NzByteSwap(&header.vertRes, sizeof(nzUInt16)); #endif
NzByteSwap(&header.bytesPerScanLine, sizeof(nzUInt16)); unsigned int bitCount = header.bitsPerPixel * header.numColorPlanes;
NzByteSwap(&header.paletteType, sizeof(nzUInt16)); unsigned int width = header.xmax - header.xmin+1;
NzByteSwap(&header.horzSize, sizeof(nzUInt16)); unsigned int height = header.ymax - header.ymin+1;
NzByteSwap(&header.vertSize, sizeof(nzUInt16));
#endif if (!image->Create(nzImageType_2D, nzPixelFormat_RGB8, width, height, 1, (parameters.levelCount > 0) ? parameters.levelCount : 1))
{
unsigned int bitCount = header.bitsPerPixel * header.numColorPlanes; NazaraError("Failed to create image");
unsigned int width = header.xmax - header.xmin+1; return false;
unsigned int height = header.ymax - header.ymin+1; }
if (!image->Create(nzImageType_2D, nzPixelFormat_RGB8, width, height, 1, (parameters.levelCount > 0) ? parameters.levelCount : 1)) nzUInt8* pixels = image->GetPixels();
{
NazaraError("Failed to create image"); int rle_value = 0;
return false; unsigned int rle_count = 0;
}
switch (bitCount)
nzUInt8* pixels = image->GetPixels(); {
case 1:
int rle_value = 0; {
unsigned int rle_count = 0; for (unsigned int y = 0; y < height; ++y)
{
switch (bitCount) nzUInt8* ptr = &pixels[y * width * 3];
{ int bytes = header.bytesPerScanLine;
case 1:
{ /* decode line number y */
for (unsigned int y = 0; y < height; ++y) while (bytes--)
{ {
nzUInt8* ptr = &pixels[y * width * 3]; if (rle_count == 0)
int bytes = header.bytesPerScanLine; {
if (!stream.Read(&rle_value, 1))
/* decode line number y */ {
while (bytes--) NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
{ return false;
if (rle_count == 0) }
{
if (!stream.Read(&rle_value, 1)) if (rle_value < 0xc0)
{ rle_count = 1;
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')'); else
return false; {
} rle_count = rle_value - 0xc0;
if (!stream.Read(&rle_value, 1))
if (rle_value < 0xc0) {
rle_count = 1; NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
else return false;
{ }
rle_count = rle_value - 0xc0; }
if (!stream.Read(&rle_value, 1)) }
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')'); rle_count--;
return false;
} for (int i = 7; i >= 0; --i)
} {
} int colorIndex = ((rle_value & (1 << i)) > 0);
rle_count--; *ptr++ = header.palette[colorIndex * 3 + 0];
*ptr++ = header.palette[colorIndex * 3 + 1];
for (int i = 7; i >= 0; --i) *ptr++ = header.palette[colorIndex * 3 + 2];
{ }
int colorIndex = ((rle_value & (1 << i)) > 0); }
}
*ptr++ = header.palette[colorIndex * 3 + 0]; break;
*ptr++ = header.palette[colorIndex * 3 + 1]; }
*ptr++ = header.palette[colorIndex * 3 + 2];
} case 4:
} {
} nzUInt8* colorIndex = new nzUInt8[width];
break; nzUInt8* line = new nzUInt8[header.bytesPerScanLine];
}
for (unsigned int y = 0; y < height; ++y)
case 4: {
{ nzUInt8* ptr = &pixels[y * width * 3];
nzUInt8* colorIndex = new nzUInt8[width];
nzUInt8* line = new nzUInt8[header.bytesPerScanLine]; std::memset(colorIndex, 0, width);
for (unsigned int y = 0; y < height; ++y) for (unsigned int c = 0; c < 4; ++c)
{ {
nzUInt8* ptr = &pixels[y * width * 3]; nzUInt8* pLine = line;
int bytes = header.bytesPerScanLine;
std::memset(colorIndex, 0, width);
/* decode line number y */
for (unsigned int c = 0; c < 4; ++c) while (bytes--)
{ {
nzUInt8* pLine = line; if (rle_count == 0)
int bytes = header.bytesPerScanLine; {
if (!stream.Read(&rle_value, 1))
/* decode line number y */ {
while (bytes--) NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
{ delete[] colorIndex;
if (rle_count == 0) delete[] line;
{
if (!stream.Read(&rle_value, 1)) return false;
{ }
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
delete[] colorIndex; if (rle_value < 0xc0)
delete[] line; rle_count = 1;
else
return false; {
} rle_count = rle_value - 0xc0;
if (!stream.Read(&rle_value, 1))
if (rle_value < 0xc0) {
rle_count = 1; NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
else delete[] colorIndex;
{ delete[] line;
rle_count = rle_value - 0xc0;
if (!stream.Read(&rle_value, 1)) return false;
{ }
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')'); }
delete[] colorIndex; }
delete[] line;
rle_count--;
return false; *(pLine++) = rle_value;
} }
}
} /* compute line's color indexes */
for (unsigned int x = 0; x < width; ++x)
rle_count--; {
*(pLine++) = rle_value; if (line[x / 8] & (128 >> (x % 8)))
} colorIndex[x] += (1 << c);
}
/* compute line's color indexes */ }
for (unsigned int x = 0; x < width; ++x)
{ /* decode scan line. color index => rgb */
if (line[x / 8] & (128 >> (x % 8))) for (unsigned int x = 0; x < width; ++x)
colorIndex[x] += (1 << c); {
} *ptr++ = header.palette[colorIndex[x] * 3 + 0];
} *ptr++ = header.palette[colorIndex[x] * 3 + 1];
*ptr++ = header.palette[colorIndex[x] * 3 + 2];
/* decode scan line. color index => rgb */ }
for (unsigned int x = 0; x < width; ++x) }
{
*ptr++ = header.palette[colorIndex[x] * 3 + 0]; /* release memory */
*ptr++ = header.palette[colorIndex[x] * 3 + 1]; delete[] colorIndex;
*ptr++ = header.palette[colorIndex[x] * 3 + 2]; delete[] line;
} break;
} }
/* release memory */ case 8:
delete[] colorIndex; {
delete[] line; nzUInt8 palette[768];
break;
} /* the palette is contained in the last 769 bytes of the file */
unsigned int curPos = stream.GetCursorPos();
case 8: stream.SetCursorPos(stream.GetSize()-769);
{ nzUInt8 magic;
nzUInt8 palette[768]; if (!stream.Read(&magic, 1))
{
/* the palette is contained in the last 769 bytes of the file */ NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
unsigned int curPos = stream.GetCursorPos(); return false;
stream.SetCursorPos(stream.GetSize()-769); }
nzUInt8 magic;
if (!stream.Read(&magic, 1)) /* first byte must be equal to 0x0c (12) */
{ if (magic != 0x0c)
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')'); {
return false; NazaraError("Colormap's first byte must be 0x0c (0x" + NzString::Number(magic, 16) + ')');
} return false;
}
/* first byte must be equal to 0x0c (12) */
if (magic != 0x0c) /* read palette */
{ if (stream.Read(palette, 768) != 768)
NazaraError("Colormap's first byte must be 0x0c (0x" + NzString::Number(magic, 16) + ')'); {
return false; NazaraError("Failed to read palette");
} return false;
}
/* read palette */
if (stream.Read(palette, 768) != 768) stream.SetCursorPos(curPos);
{
NazaraError("Failed to read palette"); /* read pixel data */
return false; for (unsigned int y = 0; y < height; ++y)
} {
nzUInt8* ptr = &pixels[y * width * 3];
stream.SetCursorPos(curPos); int bytes = header.bytesPerScanLine;
/* read pixel data */ /* decode line number y */
for (unsigned int y = 0; y < height; ++y) while (bytes--)
{ {
nzUInt8* ptr = &pixels[y * width * 3]; if (rle_count == 0)
int bytes = header.bytesPerScanLine; {
if (!stream.Read(&rle_value, 1))
/* decode line number y */ {
while (bytes--) NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
{ return false;
if (rle_count == 0) }
{
if (!stream.Read(&rle_value, 1)) if (rle_value < 0xc0)
{ rle_count = 1;
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')'); else
return false; {
} rle_count = rle_value - 0xc0;
if (!stream.Read(&rle_value, 1))
if (rle_value < 0xc0) {
rle_count = 1; NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
else return false;
{ }
rle_count = rle_value - 0xc0; }
if (!stream.Read(&rle_value, 1)) }
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')'); rle_count--;
return false;
} *ptr++ = palette[rle_value * 3 + 0];
} *ptr++ = palette[rle_value * 3 + 1];
} *ptr++ = palette[rle_value * 3 + 2];
}
rle_count--; }
break;
*ptr++ = palette[rle_value * 3 + 0]; }
*ptr++ = palette[rle_value * 3 + 1];
*ptr++ = palette[rle_value * 3 + 2]; case 24:
} {
} for (unsigned int y = 0; y < height; ++y)
break; {
} /* for each color plane */
for (int c = 0; c < 3; ++c)
case 24: {
{ nzUInt8* ptr = &pixels[y * width * 4];
for (unsigned int y = 0; y < height; ++y) int bytes = header.bytesPerScanLine;
{
/* for each color plane */ /* decode line number y */
for (int c = 0; c < 3; ++c) while (bytes--)
{ {
nzUInt8* ptr = &pixels[y * width * 4]; if (rle_count == 0)
int bytes = header.bytesPerScanLine; {
if (!stream.Read(&rle_value, 1))
/* decode line number y */ {
while (bytes--) NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
{ return false;
if (rle_count == 0) }
{
if (!stream.Read(&rle_value, 1)) if (rle_value < 0xc0)
{ rle_count = 1;
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')'); else
return false; {
} rle_count = rle_value - 0xc0;
if (!stream.Read(&rle_value, 1))
if (rle_value < 0xc0) {
rle_count = 1; NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
else return false;
{ }
rle_count = rle_value - 0xc0; }
if (!stream.Read(&rle_value, 1)) }
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')'); rle_count--;
return false; ptr[c] = static_cast<nzUInt8>(rle_value);
} ptr += 3;
} }
} }
}
rle_count--; break;
ptr[c] = static_cast<nzUInt8>(rle_value); }
ptr += 3;
} default:
} NazaraError("Failed to load " + NzString::Number(bitCount) + " bitcount pcx files");
} return false;
break; }
}
if (parameters.loadFormat != nzPixelFormat_Undefined)
default: image->Convert(parameters.loadFormat);
NazaraError("Failed to load " + NzString::Number(bitCount) + " bitcount pcx files");
return false; return true;
} }
}
if (parameters.loadFormat != nzPixelFormat_Undefined)
image->Convert(parameters.loadFormat); void NzLoaders_PCX_Register()
{
return true; NzImageLoader::RegisterLoader("pcx", NzLoader_PCX_Check, NzLoader_PCX_Load);
} }
}
void NzLoaders_PCX_Unregister()
void NzLoaders_PCX_Register() {
{ NzImageLoader::UnregisterLoader("pcx", NzLoader_PCX_Check, NzLoader_PCX_Load);
NzImageLoader::RegisterLoader("pcx", NzLoader_PCX_Check, NzLoader_PCX_Load); }
}
void NzLoaders_PCX_Unregister()
{
NzImageLoader::UnregisterLoader("pcx", NzLoader_PCX_Check, NzLoader_PCX_Load);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,186 +1,199 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module" // This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/StaticMesh.hpp> #include <Nazara/Utility/StaticMesh.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <stdexcept> #include <stdexcept>
#include <Nazara/Utility/Debug.hpp> #include <Nazara/Utility/Debug.hpp>
NzStaticMesh::NzStaticMesh(const NzMesh* parent) : NzStaticMesh::NzStaticMesh(const NzMesh* parent) :
NzSubMesh(parent) NzSubMesh(parent)
{ {
} }
NzStaticMesh::NzStaticMesh(const NzMesh* parent, const NzVertexDeclaration* vertexDeclaration, NzVertexBuffer* vertexBuffer, NzIndexBuffer* indexBuffer) : NzStaticMesh::NzStaticMesh(const NzMesh* parent, const NzVertexDeclaration* vertexDeclaration, NzVertexBuffer* vertexBuffer, NzIndexBuffer* indexBuffer) :
NzSubMesh(parent) NzSubMesh(parent)
{ {
#ifdef NAZARA_DEBUG #ifdef NAZARA_DEBUG
if (!Create(vertexDeclaration, vertexBuffer, indexBuffer)) if (!Create(vertexDeclaration, vertexBuffer, indexBuffer))
{ {
NazaraError("Failed to create mesh"); NazaraError("Failed to create mesh");
throw std::runtime_error("Constructor failed"); throw std::runtime_error("Constructor failed");
} }
#else #else
Create(vertexDeclaration, vertexBuffer, indexBuffer); Create(vertexDeclaration, vertexBuffer, indexBuffer);
#endif #endif
} }
NzStaticMesh::~NzStaticMesh() NzStaticMesh::~NzStaticMesh()
{ {
Destroy(); Destroy();
} }
bool NzStaticMesh::Create(const NzVertexDeclaration* vertexDeclaration, NzVertexBuffer* vertexBuffer, NzIndexBuffer* indexBuffer) bool NzStaticMesh::Create(const NzVertexDeclaration* vertexDeclaration, NzVertexBuffer* vertexBuffer, NzIndexBuffer* indexBuffer)
{ {
Destroy(); Destroy();
#if NAZARA_UTILITY_SAFE #if NAZARA_UTILITY_SAFE
if (!vertexDeclaration) if (!vertexDeclaration)
{ {
NazaraError("Vertex declaration is null"); NazaraError("Invalid vertex declaration");
return false; return false;
} }
if (!vertexBuffer) if (!vertexBuffer)
{ {
NazaraError("Vertex buffer is null"); NazaraError("Invalid vertex buffer");
return false; return false;
} }
#endif #endif
if (indexBuffer) if (indexBuffer)
{ indexBuffer->AddResourceListener(this);
m_indexBuffer = indexBuffer;
m_indexBuffer->AddResourceReference(); m_indexBuffer = indexBuffer;
}
m_vertexBuffer = vertexBuffer;
m_vertexBuffer = vertexBuffer; m_vertexBuffer->AddResourceListener(this);
m_vertexBuffer->AddResourceReference();
m_vertexDeclaration = vertexDeclaration;
m_vertexDeclaration = vertexDeclaration; m_vertexDeclaration->AddResourceListener(this);
m_vertexDeclaration->AddResourceReference();
return true;
return true; }
}
void NzStaticMesh::Destroy()
void NzStaticMesh::Destroy() {
{ m_aabb.SetNull();
m_aabb.SetNull();
if (m_indexBuffer)
if (m_indexBuffer) {
{ m_indexBuffer->RemoveResourceListener(this);
m_indexBuffer->RemoveResourceReference(); m_indexBuffer = nullptr;
m_indexBuffer = nullptr; }
}
if (m_vertexBuffer)
if (m_vertexBuffer) {
{ m_vertexBuffer->RemoveResourceListener(this);
m_vertexBuffer->RemoveResourceReference(); m_vertexBuffer = nullptr;
m_vertexBuffer = nullptr; }
}
if (m_vertexDeclaration)
if (m_vertexDeclaration) {
{ m_vertexDeclaration->RemoveResourceListener(this);
m_vertexDeclaration->RemoveResourceReference(); m_vertexDeclaration = nullptr;
m_vertexDeclaration = nullptr; }
} }
}
bool NzStaticMesh::GenerateAABB()
bool NzStaticMesh::GenerateAABB() {
{ if (!m_aabb.IsNull())
if (!m_aabb.IsNull()) return true;
return true;
const NzVertexElement* position = m_vertexDeclaration->GetElement(nzElementStream_VertexData, nzElementUsage_Position);
const NzVertexElement* position = m_vertexDeclaration->GetElement(nzElementStream_VertexData, nzElementUsage_Position); if (position && position->type == nzElementType_Float3) // Si nous avons des positions du type Vec3
if (position && position->type == nzElementType_Float3) // Si nous avons des positions du type Vec3 {
{ // On lock le buffer pour itérer sur toutes les positions et composer notre AABB
// On lock le buffer pour itérer sur toutes les positions et composer notre AABB nzUInt8* buffer = reinterpret_cast<nzUInt8*>(m_vertexBuffer->Map(nzBufferAccess_ReadOnly));
nzUInt8* buffer = reinterpret_cast<nzUInt8*>(m_vertexBuffer->Map(nzBufferAccess_ReadOnly)); if (!buffer)
if (!buffer) {
{ NazaraWarning("Failed to lock vertex buffer");
NazaraWarning("Failed to lock vertex buffer"); return false;
return false; }
}
buffer += position->offset;
buffer += position->offset; unsigned int stride = m_vertexDeclaration->GetStride(nzElementStream_VertexData);
unsigned int stride = m_vertexDeclaration->GetStride(nzElementStream_VertexData); unsigned int vertexCount = m_vertexBuffer->GetVertexCount();
unsigned int vertexCount = m_vertexBuffer->GetVertexCount(); for (unsigned int i = 0; i < vertexCount; ++i)
for (unsigned int i = 0; i < vertexCount; ++i) {
{ m_aabb.ExtendTo(*reinterpret_cast<NzVector3f*>(buffer));
m_aabb.ExtendTo(*reinterpret_cast<NzVector3f*>(buffer));
buffer += stride;
buffer += stride; }
}
if (!m_vertexBuffer->Unmap())
if (!m_vertexBuffer->Unmap()) NazaraWarning("Failed to unmap vertex buffer");
NazaraWarning("Failed to unmap vertex buffer"); }
}
return true;
return true; }
}
const NzAxisAlignedBox& NzStaticMesh::GetAABB() const
const NzAxisAlignedBox& NzStaticMesh::GetAABB() const {
{ return m_aabb;
return m_aabb; }
}
nzAnimationType NzStaticMesh::GetAnimationType() const
nzAnimationType NzStaticMesh::GetAnimationType() const {
{ return nzAnimationType_Static;
return nzAnimationType_Static; }
}
unsigned int NzStaticMesh::GetFrameCount() const
unsigned int NzStaticMesh::GetFrameCount() const {
{ return 1;
return 1; }
}
const NzIndexBuffer* NzStaticMesh::GetIndexBuffer() const
const NzIndexBuffer* NzStaticMesh::GetIndexBuffer() const {
{ return m_indexBuffer;
return m_indexBuffer; }
}
nzPrimitiveType NzStaticMesh::GetPrimitiveType() const
nzPrimitiveType NzStaticMesh::GetPrimitiveType() const {
{ return m_primitiveType;
return m_primitiveType; }
}
const NzVertexBuffer* NzStaticMesh::GetVertexBuffer() const
const NzVertexBuffer* NzStaticMesh::GetVertexBuffer() const {
{ return m_vertexBuffer;
return m_vertexBuffer; }
}
const NzVertexDeclaration* NzStaticMesh::GetVertexDeclaration() const
const NzVertexDeclaration* NzStaticMesh::GetVertexDeclaration() const {
{ return m_vertexDeclaration;
return m_vertexDeclaration; }
}
bool NzStaticMesh::IsAnimated() const
bool NzStaticMesh::IsAnimated() const {
{ return false;
return false; }
}
bool NzStaticMesh::IsValid() const
bool NzStaticMesh::IsValid() const {
{ return m_vertexBuffer != nullptr && m_vertexDeclaration != nullptr;
return m_vertexBuffer != nullptr && m_vertexDeclaration != nullptr; }
}
void NzStaticMesh::SetAABB(const NzAxisAlignedBox& aabb)
void NzStaticMesh::SetAABB(const NzAxisAlignedBox& aabb) {
{ m_aabb = aabb;
m_aabb = aabb; }
}
void NzStaticMesh::SetPrimitiveType(nzPrimitiveType primitiveType)
void NzStaticMesh::SetPrimitiveType(nzPrimitiveType primitiveType) {
{ m_primitiveType = primitiveType;
m_primitiveType = primitiveType; }
}
void NzStaticMesh::AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation)
void NzStaticMesh::AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation) {
{ NazaraUnused(frameA);
NazaraUnused(frameA); NazaraUnused(frameB);
NazaraUnused(frameB); NazaraUnused(interpolation);
NazaraUnused(interpolation);
// Le safe mode est censé nous protéger de cet appel
// Le safe mode est censé nous protéger de cet appel NazaraError("Static mesh have no animation, please enable safe mode");
NazaraError("Static mesh have no animation, please enable safe mode"); }
}
void NzStaticMesh::OnResourceReleased(const NzResource* resource, int index)
{
NazaraUnused(index);
if (resource == m_indexBuffer)
m_indexBuffer = nullptr;
else if (resource == m_vertexBuffer)
m_vertexBuffer = nullptr;
else if (resource == m_vertexDeclaration)
m_vertexDeclaration = nullptr;
else
NazaraInternalError("Not listening to " + NzString::Pointer(resource));
}

View File

@ -1,346 +1,372 @@
// Copyright (C) 2012 Jérôme Leclercq // Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module" // This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/VertexDeclaration.hpp> #include <Nazara/Utility/VertexDeclaration.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Utility/Config.hpp> #include <Nazara/Utility/Config.hpp>
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
#if NAZARA_UTILITY_THREADSAFE && NAZARA_THREADSAFETY_VERTEXDECLARATION #if NAZARA_UTILITY_THREADSAFE && NAZARA_THREADSAFETY_VERTEXDECLARATION
#include <Nazara/Core/ThreadSafety.hpp> #include <Nazara/Core/ThreadSafety.hpp>
#else #else
#include <Nazara/Core/ThreadSafetyOff.hpp> #include <Nazara/Core/ThreadSafetyOff.hpp>
#endif #endif
#include <Nazara/Utility/Debug.hpp> #include <Nazara/Utility/Debug.hpp>
namespace namespace
{ {
const unsigned int size[] = const unsigned int elementCount[] =
{ {
sizeof(nzUInt32), // nzElementType_Color 4, // nzElementType_Color
1*sizeof(double), // nzElementType_Double1 1, // nzElementType_Double1
2*sizeof(double), // nzElementType_Double2 2, // nzElementType_Double2
3*sizeof(double), // nzElementType_Double3 3, // nzElementType_Double3
4*sizeof(double), // nzElementType_Double4 4, // nzElementType_Double4
1*sizeof(float), // nzElementType_Float1 1, // nzElementType_Float1
2*sizeof(float), // nzElementType_Float2 2, // nzElementType_Float2
3*sizeof(float), // nzElementType_Float3 3, // nzElementType_Float3
4*sizeof(float) // nzElementType_Float4 4 // nzElementType_Float4
}; };
bool VertexElementCompare(const NzVertexElement& elementA, const NzVertexElement& elementB) const unsigned int elementSize[] =
{ {
// Nous classons d'abord par stream 4*sizeof(nzUInt8), // nzElementType_Color
if (elementA.stream == elementB.stream) 1*sizeof(double), // nzElementType_Double1
{ 2*sizeof(double), // nzElementType_Double2
// Ensuite par usage 3*sizeof(double), // nzElementType_Double3
if (elementA.usage == elementB.usage) 4*sizeof(double), // nzElementType_Double4
// Et finalement par usageIndex 1*sizeof(float), // nzElementType_Float1
return elementA.usageIndex < elementB.usageIndex; 2*sizeof(float), // nzElementType_Float2
else 3*sizeof(float), // nzElementType_Float3
return elementA.usage < elementB.usage; 4*sizeof(float) // nzElementType_Float4
} };
else
return elementA.stream < elementB.stream; bool VertexElementCompare(const NzVertexElement& elementA, const NzVertexElement& elementB)
} {
} // Nous classons d'abord par stream
if (elementA.stream == elementB.stream)
struct NzVertexDeclarationImpl {
{ // Ensuite par usage
std::vector<NzVertexElement> elements; if (elementA.usage == elementB.usage)
int elementPos[nzElementStream_Max+1][nzElementUsage_Max+1]; // Et finalement par usageIndex
int streamPos[nzElementStream_Max+1]; return elementA.usageIndex < elementB.usageIndex;
unsigned int stride[nzElementStream_Max+1] = {0}; else
return elementA.usage < elementB.usage;
unsigned short refCount = 1; }
NazaraMutex(mutex) else
}; return elementA.stream < elementB.stream;
}
NzVertexDeclaration::NzVertexDeclaration(const NzVertexElement* elements, unsigned int elementCount) }
{
#ifdef NAZARA_DEBUG struct NzVertexDeclarationImpl
if (!Create(elements, elementCount)) {
{ std::vector<NzVertexElement> elements;
NazaraError("Failed to create declaration"); int elementPos[nzElementStream_Max+1][nzElementUsage_Max+1];
throw std::runtime_error("Constructor failed"); int streamPos[nzElementStream_Max+1];
} unsigned int stride[nzElementStream_Max+1] = {0};
#else
Create(elements, elementCount); unsigned short refCount = 1;
#endif NazaraMutex(mutex)
} };
NzVertexDeclaration::NzVertexDeclaration(const NzVertexDeclaration& declaration) : NzVertexDeclaration::NzVertexDeclaration(const NzVertexElement* elements, unsigned int elementCount)
NzResource(), {
m_sharedImpl(declaration.m_sharedImpl) #ifdef NAZARA_DEBUG
{ if (!Create(elements, elementCount))
if (m_sharedImpl) {
{ NazaraError("Failed to create declaration");
NazaraMutexLock(m_sharedImpl->mutex); throw std::runtime_error("Constructor failed");
m_sharedImpl->refCount++; }
NazaraMutexUnlock(m_sharedImpl->mutex); #else
} Create(elements, elementCount);
} #endif
}
NzVertexDeclaration::NzVertexDeclaration(NzVertexDeclaration&& declaration) noexcept :
m_sharedImpl(declaration.m_sharedImpl) NzVertexDeclaration::NzVertexDeclaration(const NzVertexDeclaration& declaration) :
{ NzResource(),
declaration.m_sharedImpl = nullptr; m_sharedImpl(declaration.m_sharedImpl)
} {
if (m_sharedImpl)
NzVertexDeclaration::~NzVertexDeclaration() {
{ NazaraMutexLock(m_sharedImpl->mutex);
Destroy(); m_sharedImpl->refCount++;
} NazaraMutexUnlock(m_sharedImpl->mutex);
}
bool NzVertexDeclaration::Create(const NzVertexElement* elements, unsigned int elementCount) }
{
Destroy(); NzVertexDeclaration::NzVertexDeclaration(NzVertexDeclaration&& declaration) noexcept :
m_sharedImpl(declaration.m_sharedImpl)
#if NAZARA_UTILITY_SAFE {
if (!elements || elementCount == 0) declaration.m_sharedImpl = nullptr;
{ }
NazaraError("No element");
return false; NzVertexDeclaration::~NzVertexDeclaration()
} {
#endif Destroy();
}
NzVertexDeclarationImpl* impl = new NzVertexDeclarationImpl;
std::memset(&impl->elementPos, -1, (nzElementStream_Max+1)*(nzElementUsage_Max+1)*sizeof(int)); bool NzVertexDeclaration::Create(const NzVertexElement* elements, unsigned int elementCount)
std::memset(&impl->streamPos, -1, (nzElementStream_Max+1)*sizeof(int)); {
Destroy();
// On copie et trie les éléments
impl->elements.resize(elementCount); #if NAZARA_UTILITY_SAFE
std::memcpy(&impl->elements[0], elements, elementCount*sizeof(NzVertexElement)); if (!elements || elementCount == 0)
std::sort(impl->elements.begin(), impl->elements.end(), VertexElementCompare); {
NazaraError("No element");
for (unsigned int i = 0; i < elementCount; ++i) return false;
{ }
NzVertexElement& current = impl->elements[i]; #endif
#if NAZARA_UTILITY_SAFE
// Notre tableau étant trié, s'il y a collision, les deux éléments identiques se suivent... NzVertexDeclarationImpl* impl = new NzVertexDeclarationImpl;
if (i > 0) std::memset(&impl->elementPos, -1, (nzElementStream_Max+1)*(nzElementUsage_Max+1)*sizeof(int));
{ std::memset(&impl->streamPos, -1, (nzElementStream_Max+1)*sizeof(int));
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) // On copie et trie les éléments
{ impl->elements.resize(elementCount);
// Les deux éléments sont identiques là où ils ne devraient pas, nous avons une collision... std::memcpy(&impl->elements[0], elements, elementCount*sizeof(NzVertexElement));
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)); std::sort(impl->elements.begin(), impl->elements.end(), VertexElementCompare);
delete impl;
for (unsigned int i = 0; i < elementCount; ++i)
return false; {
} NzVertexElement& current = impl->elements[i];
} #if NAZARA_UTILITY_SAFE
#endif // Notre tableau étant trié, s'il y a collision, les deux éléments identiques se suivent...
if (i > 0)
if (current.usageIndex == 0) {
impl->elementPos[current.stream][current.usage] = i; NzVertexElement& previous = impl->elements[i-1]; // On accède à l'élément précédent
if (previous.usage == current.usage && previous.usageIndex == current.usageIndex && previous.stream == current.stream)
if (impl->streamPos[current.stream] == -1) {
impl->streamPos[current.stream] = i; // Premier élément du stream (via le triage) // 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));
impl->stride[current.stream] += size[current.type]; delete impl;
}
return false;
#if NAZARA_UTILITY_FORCE_DECLARATION_STRIDE_MULTIPLE_OF_32 }
for (unsigned int& stride : impl->stride) }
stride = ((static_cast<int>(stride)-1)/32+1)*32; #endif
#endif
if (current.usageIndex == 0)
m_sharedImpl = impl; impl->elementPos[current.stream][current.usage] = i;
return true; if (impl->streamPos[current.stream] == -1)
} impl->streamPos[current.stream] = i; // Premier élément du stream (via le triage)
void NzVertexDeclaration::Destroy() impl->stride[current.stream] += elementSize[current.type];
{ }
if (!m_sharedImpl)
return; #if NAZARA_UTILITY_FORCE_DECLARATION_STRIDE_MULTIPLE_OF_32
for (unsigned int& stride : impl->stride)
NazaraMutexLock(m_sharedImpl->mutex); stride = ((static_cast<int>(stride)-1)/32+1)*32;
bool freeSharedImpl = (--m_sharedImpl->refCount == 0); #endif
NazaraMutexUnlock(m_sharedImpl->mutex);
m_sharedImpl = impl;
if (freeSharedImpl)
delete m_sharedImpl; NotifyCreated();
return true;
m_sharedImpl = nullptr; }
}
void NzVertexDeclaration::Destroy()
const NzVertexElement* NzVertexDeclaration::GetElement(unsigned int i) const {
{ if (!m_sharedImpl)
#if NAZARA_UTILITY_SAFE return;
if (!m_sharedImpl)
{ NotifyDestroy();
NazaraError("Declaration not created");
return nullptr; NazaraMutexLock(m_sharedImpl->mutex);
} bool freeSharedImpl = (--m_sharedImpl->refCount == 0);
NazaraMutexUnlock(m_sharedImpl->mutex);
if (i >= m_sharedImpl->elements.size())
{ if (freeSharedImpl)
NazaraError("Element index out of range (" + NzString::Number(i) + " >= " + NzString::Number(m_sharedImpl->elements.size()) + ')'); delete m_sharedImpl;
return nullptr;
} m_sharedImpl = nullptr;
#endif }
return &m_sharedImpl->elements[i]; const NzVertexElement* NzVertexDeclaration::GetElement(unsigned int i) const
} {
#if NAZARA_UTILITY_SAFE
const NzVertexElement* NzVertexDeclaration::GetElement(nzElementStream stream, unsigned int i) const if (!m_sharedImpl)
{ {
#if NAZARA_UTILITY_SAFE NazaraError("Declaration not created");
if (!m_sharedImpl) return nullptr;
{ }
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()) + ')');
int streamPos = m_sharedImpl->streamPos[stream]; return nullptr;
if (streamPos == -1) }
{ #endif
NazaraError("Declaration has no stream 0x" + NzString::Number(stream, 16));
return nullptr; return &m_sharedImpl->elements[i];
} }
unsigned int upperLimit = GetElementCount(stream); const NzVertexElement* NzVertexDeclaration::GetElement(nzElementStream stream, unsigned int i) const
if (i >= upperLimit) {
{ #if NAZARA_UTILITY_SAFE
NazaraError("Element index out of range (" + NzString::Number(i) + " >= " + NzString::Number(upperLimit) + ')'); if (!m_sharedImpl)
return nullptr; {
} NazaraError("Declaration not created");
#endif return nullptr;
}
return &m_sharedImpl->elements[m_sharedImpl->streamPos[stream]+i];
} int streamPos = m_sharedImpl->streamPos[stream];
if (streamPos == -1)
const NzVertexElement* NzVertexDeclaration::GetElement(nzElementStream stream, nzElementUsage usage, unsigned int usageIndex) const {
{ NazaraError("Declaration has no stream 0x" + NzString::Number(stream, 16));
#if NAZARA_UTILITY_SAFE return nullptr;
if (!m_sharedImpl) }
{
NazaraError("Declaration not created"); unsigned int upperLimit = GetElementCount(stream);
return nullptr; if (i >= upperLimit)
} {
#endif NazaraError("Element index out of range (" + NzString::Number(i) + " >= " + NzString::Number(upperLimit) + ')');
return nullptr;
int elementPos = m_sharedImpl->elementPos[stream][usage]; }
if (elementPos == -1) #endif
return nullptr;
return &m_sharedImpl->elements[m_sharedImpl->streamPos[stream]+i];
elementPos += usageIndex; }
if (static_cast<unsigned int>(elementPos) >= m_sharedImpl->elements.size())
return nullptr; const NzVertexElement* NzVertexDeclaration::GetElement(nzElementStream stream, nzElementUsage usage, unsigned int usageIndex) const
{
NzVertexElement& element = m_sharedImpl->elements[elementPos]; #if NAZARA_UTILITY_SAFE
if (element.stream != stream || element.usage != usage || element.usageIndex != usageIndex) if (!m_sharedImpl)
return nullptr; {
NazaraError("Declaration not created");
return &element; return nullptr;
} }
#endif
unsigned int NzVertexDeclaration::GetElementCount() const
{ int elementPos = m_sharedImpl->elementPos[stream][usage];
#if NAZARA_UTILITY_SAFE if (elementPos == -1)
if (!m_sharedImpl) return nullptr;
{
NazaraError("Declaration not created"); elementPos += usageIndex;
return 0; if (static_cast<unsigned int>(elementPos) >= m_sharedImpl->elements.size())
} return nullptr;
#endif
NzVertexElement& element = m_sharedImpl->elements[elementPos];
return m_sharedImpl->elements.size(); if (element.stream != stream || element.usage != usage || element.usageIndex != usageIndex)
} return nullptr;
unsigned int NzVertexDeclaration::GetElementCount(nzElementStream stream) const return &element;
{ }
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl) unsigned int NzVertexDeclaration::GetElementCount() const
{ {
NazaraError("Declaration not created"); #if NAZARA_UTILITY_SAFE
return 0; if (!m_sharedImpl)
} {
#endif NazaraError("Declaration not created");
return 0;
int streamPos = m_sharedImpl->streamPos[stream]; }
if (streamPos == -1) #endif
return 0;
return m_sharedImpl->elements.size();
unsigned int upperLimit = 0; }
if (stream == nzElementStream_Max)
upperLimit = m_sharedImpl->elements.size(); unsigned int NzVertexDeclaration::GetElementCount(nzElementStream stream) const
else {
{ #if NAZARA_UTILITY_SAFE
for (unsigned int upperStream = stream+1; upperStream <= nzElementStream_Max; ++upperStream) if (!m_sharedImpl)
{ {
if (m_sharedImpl->streamPos[upperStream] != -1) NazaraError("Declaration not created");
{ return 0;
upperLimit = m_sharedImpl->streamPos[upperStream]; }
break; #endif
}
else if (upperStream == nzElementStream_Max) // Dernier stream, toujours pas de limite int streamPos = m_sharedImpl->streamPos[stream];
upperLimit = m_sharedImpl->elements.size(); if (streamPos == -1)
} return 0;
}
unsigned int upperLimit = 0;
return upperLimit-streamPos; if (stream == nzElementStream_Max)
} upperLimit = m_sharedImpl->elements.size();
else
unsigned int NzVertexDeclaration::GetStride(nzElementStream stream) const {
{ for (unsigned int upperStream = stream+1; upperStream <= nzElementStream_Max; ++upperStream)
#if NAZARA_UTILITY_SAFE {
if (!m_sharedImpl) if (m_sharedImpl->streamPos[upperStream] != -1)
{ {
NazaraError("Declaration not created"); upperLimit = m_sharedImpl->streamPos[upperStream];
return 0; break;
} }
#endif else if (upperStream == nzElementStream_Max) // Dernier stream, toujours pas de limite
upperLimit = m_sharedImpl->elements.size();
return m_sharedImpl->stride[stream]; }
} }
bool NzVertexDeclaration::HasStream(nzElementStream stream) const return upperLimit-streamPos;
{ }
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl) unsigned int NzVertexDeclaration::GetStride(nzElementStream stream) const
{ {
NazaraError("Declaration not created"); #if NAZARA_UTILITY_SAFE
return false; if (!m_sharedImpl)
} {
#endif NazaraError("Declaration not created");
return 0;
return m_sharedImpl->streamPos[stream] != -1; }
} #endif
bool NzVertexDeclaration::IsValid() const return m_sharedImpl->stride[stream];
{ }
return m_sharedImpl != nullptr;
} bool NzVertexDeclaration::HasStream(nzElementStream stream) const
{
NzVertexDeclaration& NzVertexDeclaration::operator=(const NzVertexDeclaration& declaration) #if NAZARA_UTILITY_SAFE
{ if (!m_sharedImpl)
Destroy(); {
NazaraError("Declaration not created");
m_sharedImpl = declaration.m_sharedImpl; return false;
if (m_sharedImpl) }
{ #endif
NazaraMutexLock(m_sharedImpl->mutex);
m_sharedImpl->refCount++; return m_sharedImpl->streamPos[stream] != -1;
NazaraMutexUnlock(m_sharedImpl->mutex); }
}
bool NzVertexDeclaration::IsValid() const
return *this; {
} return m_sharedImpl != nullptr;
}
NzVertexDeclaration& NzVertexDeclaration::operator=(NzVertexDeclaration&& declaration) noexcept
{ NzVertexDeclaration& NzVertexDeclaration::operator=(const NzVertexDeclaration& declaration)
Destroy(); {
Destroy();
m_sharedImpl = declaration.m_sharedImpl;
declaration.m_sharedImpl = nullptr; m_sharedImpl = declaration.m_sharedImpl;
if (m_sharedImpl)
return *this; {
} NazaraMutexLock(m_sharedImpl->mutex);
m_sharedImpl->refCount++;
NazaraMutexUnlock(m_sharedImpl->mutex);
}
return *this;
}
NzVertexDeclaration& NzVertexDeclaration::operator=(NzVertexDeclaration&& declaration) noexcept
{
Destroy();
m_sharedImpl = declaration.m_sharedImpl;
declaration.m_sharedImpl = nullptr;
return *this;
}
unsigned int NzVertexDeclaration::GetElementCount(nzElementType type)
{
return elementCount[type];
}
unsigned int NzVertexDeclaration::GetElementSize(nzElementType type)
{
return elementSize[type];
}

File diff suppressed because it is too large Load Diff