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
project "NazaraRenderer"
end
files
{
"../include/Nazara/Renderer/**.hpp",
"../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"
links "opengl32"
links "winmm"
else
excludes { "../src/Nazara/Renderer/Win32/*.hpp", "../src/Nazara/Renderer/Win32/*.cpp" }
end
if (_OPTIONS["one-library"]) then
excludes "../src/Nazara/Renderer/Debug/Leaks.cpp"
else
configuration "DebugStatic"
links "NazaraCore-s-d"
links "NazaraUtility-s-d"
configuration "ReleaseStatic"
links "NazaraCore-s"
links "NazaraUtility-s"
configuration "DebugDLL"
links "NazaraCore-d"
links "NazaraUtility-d"
configuration "ReleaseDLL"
links "NazaraCore"
links "NazaraUtility"
if (not _OPTIONS["one-library"]) then
project "NazaraRenderer"
end
defines "NAZARA_RENDERER_OPENGL"
files
{
"../include/Nazara/Renderer/**.hpp",
"../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"
links "opengl32"
links "winmm"
else
excludes { "../src/Nazara/Renderer/Win32/*.hpp", "../src/Nazara/Renderer/Win32/*.cpp" }
end
if (_OPTIONS["one-library"]) then
excludes "../src/Nazara/Renderer/Debug/Leaks.cpp"
else
configuration "DebugStatic"
links "NazaraCore-s-d"
links "NazaraUtility-s-d"
configuration "ReleaseStatic"
links "NazaraCore-s"
links "NazaraUtility-s"
configuration "DebugDLL"
links "NazaraCore-d"
links "NazaraUtility-d"
configuration "ReleaseDLL"
links "NazaraCore"
links "NazaraUtility"
end

File diff suppressed because it is too large Load Diff

View File

@ -1,61 +1,62 @@
// This file was automatically generated by Nazara
/*
Nazara Engine - Core module
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
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
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
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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
SOFTWARE.
*/
#pragma once
#include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/Clock.hpp>
#include <Nazara/Core/Color.hpp>
#include <Nazara/Core/ConditionVariable.hpp>
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Core.hpp>
#include <Nazara/Core/Directory.hpp>
#include <Nazara/Core/DynLib.hpp>
#include <Nazara/Core/Endianness.hpp>
#include <Nazara/Core/Enums.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/File.hpp>
#include <Nazara/Core/Format.hpp>
#include <Nazara/Core/Functor.hpp>
#include <Nazara/Core/Hash.hpp>
#include <Nazara/Core/Hashable.hpp>
#include <Nazara/Core/HashDigest.hpp>
#include <Nazara/Core/HashImpl.hpp>
#include <Nazara/Core/Initializer.hpp>
#include <Nazara/Core/InputStream.hpp>
#include <Nazara/Core/LockGuard.hpp>
#include <Nazara/Core/Log.hpp>
#include <Nazara/Core/MemoryStream.hpp>
#include <Nazara/Core/Mutex.hpp>
#include <Nazara/Core/NonCopyable.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/Semaphore.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <Nazara/Core/Thread.hpp>
#include <Nazara/Core/Tuple.hpp>
#include <Nazara/Core/Unicode.hpp>
// This file was automatically generated by Nazara
/*
Nazara Engine - Core module
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
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
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
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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
SOFTWARE.
*/
#pragma once
#include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/Clock.hpp>
#include <Nazara/Core/Color.hpp>
#include <Nazara/Core/ConditionVariable.hpp>
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Core.hpp>
#include <Nazara/Core/Directory.hpp>
#include <Nazara/Core/DynLib.hpp>
#include <Nazara/Core/Endianness.hpp>
#include <Nazara/Core/Enums.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/File.hpp>
#include <Nazara/Core/Format.hpp>
#include <Nazara/Core/Functor.hpp>
#include <Nazara/Core/Hash.hpp>
#include <Nazara/Core/Hashable.hpp>
#include <Nazara/Core/HashDigest.hpp>
#include <Nazara/Core/HashImpl.hpp>
#include <Nazara/Core/Initializer.hpp>
#include <Nazara/Core/InputStream.hpp>
#include <Nazara/Core/LockGuard.hpp>
#include <Nazara/Core/Log.hpp>
#include <Nazara/Core/MemoryStream.hpp>
#include <Nazara/Core/Mutex.hpp>
#include <Nazara/Core/NonCopyable.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceListener.hpp>
#include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/Semaphore.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <Nazara/Core/Thread.hpp>
#include <Nazara/Core/Tuple.hpp>
#include <Nazara/Core/Unicode.hpp>

View File

@ -1,84 +1,85 @@
/*
Nazara Engine - Core module
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
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
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
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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
SOFTWARE.
*/
#pragma once
#ifndef NAZARA_CONFIG_CORE_HPP
#define NAZARA_CONFIG_CORE_HPP
/// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci
// Appelle exit dès qu'une assertion est invalide
#define NAZARA_CORE_EXIT_ON_ASSERT_FAILURE 1
// Teste les assertions
#define NAZARA_CORE_ENABLE_ASSERTS 0
// Taille du buffer lors d'une lecture complète d'un fichier (ex: Hash)
#define NAZARA_CORE_FILE_BUFFERSIZE 4096
// Le moteur doit-il incorporer les Unicode Character Data (Nécessaires pour faire fonctionner le flag NzString::HandleUTF8)
#define NAZARA_CORE_INCLUDE_UNICODEDATA 0
// Utilise un tracker pour repérer les éventuels leaks (Ralentit l'exécution)
#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)
#define NAZARA_CORE_NORMALIZE_DIRECTORY_SEPARATORS 1
// Précision des réels lors de la transformation en texte (Max. chiffres après la virgule)
#define NAZARA_CORE_REAL_PRECISION 6
// Duplique la sortie du log sur le flux de sortie standard (cout)
#define NAZARA_CORE_DUPLICATE_TO_COUT 0
// Active les tests de sécurité basés sur le code (Conseillé pour le développement)
#define NAZARA_CORE_SAFE 1
// Protège les classes des accès concurrentiels
#define NAZARA_CORE_THREADSAFE 1
// Les classes à protéger des accès concurrentiels
#define NAZARA_THREADSAFETY_BYTEARRAY 1 // NzByteArray (COW)
#define NAZARA_THREADSAFETY_CLOCK 0 // NzClock
#define NAZARA_THREADSAFETY_DIRECTORY 1 // NzDirectory
#define NAZARA_THREADSAFETY_DYNLIB 1 // NzDynLib
#define NAZARA_THREADSAFETY_FILE 1 // NzFile
#define NAZARA_THREADSAFETY_HASHDIGEST 0 // NzHashDigest
#define NAZARA_THREADSAFETY_LOG 1 // NzLog
#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
// 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
*/
#endif // NAZARA_CONFIG_CORE_HPP
/*
Nazara Engine - Core module
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
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
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
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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
SOFTWARE.
*/
#pragma once
#ifndef NAZARA_CONFIG_CORE_HPP
#define NAZARA_CONFIG_CORE_HPP
/// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci
// Appelle exit dès qu'une assertion est invalide
#define NAZARA_CORE_EXIT_ON_ASSERT_FAILURE 1
// Teste les assertions
#define NAZARA_CORE_ENABLE_ASSERTS 0
// Taille du buffer lors d'une lecture complète d'un fichier (ex: Hash)
#define NAZARA_CORE_FILE_BUFFERSIZE 4096
// Le moteur doit-il incorporer les Unicode Character Data (Nécessaires pour faire fonctionner le flag NzString::HandleUTF8)
#define NAZARA_CORE_INCLUDE_UNICODEDATA 0
// Utilise un tracker pour repérer les éventuels leaks (Ralentit l'exécution)
#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)
#define NAZARA_CORE_NORMALIZE_DIRECTORY_SEPARATORS 1
// Précision des réels lors de la transformation en texte (Max. chiffres après la virgule)
#define NAZARA_CORE_REAL_PRECISION 6
// Duplique la sortie du log sur le flux de sortie standard (cout)
#define NAZARA_CORE_DUPLICATE_TO_COUT 0
// Active les tests de sécurité basés sur le code (Conseillé pour le développement)
#define NAZARA_CORE_SAFE 1
// Protège les classes des accès concurrentiels
#define NAZARA_CORE_THREADSAFE 1
// Les classes à protéger des accès concurrentiels
#define NAZARA_THREADSAFETY_BYTEARRAY 1 // NzByteArray (COW)
#define NAZARA_THREADSAFETY_CLOCK 0 // NzClock
#define NAZARA_THREADSAFETY_DIRECTORY 1 // NzDirectory
#define NAZARA_THREADSAFETY_DYNLIB 1 // NzDynLib
#define NAZARA_THREADSAFETY_FILE 1 // NzFile
#define NAZARA_THREADSAFETY_HASHDIGEST 0 // NzHashDigest
#define NAZARA_THREADSAFETY_LOG 1 // NzLog
#define NAZARA_THREADSAFETY_RESOURCE 1 // NzResource
#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
// 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
*/
#endif // NAZARA_CONFIG_CORE_HPP

View File

@ -1,26 +1,30 @@
// 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_ENUMS_CORE_HPP
#define NAZARA_ENUMS_CORE_HPP
enum nzEndianness
{
nzEndianness_Unknown = -1,
nzEndianness_BigEndian,
nzEndianness_LittleEndian
};
enum nzErrorType
{
nzErrorType_AssertFailed,
nzErrorType_Internal,
nzErrorType_Normal,
nzErrorType_Warning
};
#endif // NAZARA_ENUMS_CORE_HPP
// 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_ENUMS_CORE_HPP
#define NAZARA_ENUMS_CORE_HPP
enum nzEndianness
{
nzEndianness_Unknown = -1,
nzEndianness_BigEndian,
nzEndianness_LittleEndian,
nzEndianness_Max = nzEndianness_LittleEndian
};
enum nzErrorType
{
nzErrorType_AssertFailed,
nzErrorType_Internal,
nzErrorType_Normal,
nzErrorType_Warning,
nzErrorType_Max = nzErrorType_Warning
};
#endif // NAZARA_ENUMS_CORE_HPP

View File

@ -1,30 +1,72 @@
// 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_RESOURCE_HPP
#define NAZARA_RESOURCE_HPP
#include <Nazara/Prerequesites.hpp>
class NAZARA_API NzResource
{
public:
NzResource(bool persistent = true);
NzResource(const NzResource& resource);
virtual ~NzResource();
void AddResourceReference() const;
bool IsPersistent() const;
void RemoveResourceReference() const;
void SetPersistent(bool persistent = true);
private:
// Je fais précéder le nom par 'resource' pour éviter les éventuels conflits de noms
mutable bool m_resourcePersistent;
mutable unsigned int m_resourceReferenceCount;
};
#endif // NAZARA_RESOURCE_HPP
// 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_RESOURCE_HPP
#define NAZARA_RESOURCE_HPP
#include <Nazara/Prerequesites.hpp>
#include <set>
#if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_RESOURCE
#include <Nazara/Core/ThreadSafety.hpp>
#else
#include <Nazara/Core/ThreadSafetyOff.hpp>
#endif
class NzResourceListener;
struct NzResourceEntry
{
NzResourceEntry(NzResourceListener* resourceListener, int i = 0) :
listener(resourceListener),
index(i)
{
}
bool operator<(const NzResourceEntry& rhs) const
{
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
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/File.hpp>
#include <Nazara/Core/InputStream.hpp>
#include <Nazara/Core/MemoryStream.hpp>
#include <Nazara/Core/Debug.hpp>
template<typename Type, typename Parameters>
bool NzResourceLoader<Type, Parameters>::LoadFromFile(Type* resource, const NzString& filePath, const Parameters& parameters)
{
#if NAZARA_CORE_SAFE
if (!parameters.IsValid())
{
NazaraError("Invalid Parameters");
return false;
}
#endif
NzString path = NzFile::NormalizePath(filePath);
NzString ext = path.SubstrFrom('.', -1, true);
if (ext.IsEmpty())
{
NazaraError("Failed to get file extension");
return false;
}
NzFile file(path, NzFile::ReadOnly);
if (!file.IsOpen())
{
NazaraError("Failed to open file");
return false;
}
for (auto loader = Type::s_loaders.begin(); loader != Type::s_loaders.end(); ++loader)
{
for (const NzString& loaderExt : std::get<0>(*loader))
{
int cmp = NzString::Compare(loaderExt, ext);
if (cmp == 0)
{
if (!std::get<1>(*loader)(file, parameters))
continue;
file.SetCursorPos(0);
// Chargement de la ressource
if (std::get<2>(*loader)(resource, file, parameters))
return true;
NazaraWarning("Loader failed");
file.SetCursorPos(0);
}
else if (cmp < 0) // S'il est encore possible que l'extension se situe après
continue;
break;
}
}
NazaraError("Failed to load file: no loader");
return false;
}
template<typename Type, typename Parameters>
bool NzResourceLoader<Type, Parameters>::LoadFromMemory(Type* resource, const void* data, unsigned int size, const Parameters& parameters)
{
NzMemoryStream stream(data, size);
return LoadFromStream(resource, stream, parameters);
}
template<typename Type, typename Parameters>
bool NzResourceLoader<Type, Parameters>::LoadFromStream(Type* resource, NzInputStream& stream, const Parameters& parameters)
{
#if NAZARA_CORE_SAFE
if (!parameters.IsValid())
{
NazaraError("Invalid Parameters");
return false;
}
if (stream.GetSize() == 0 || stream.GetCursorPos() >= stream.GetSize())
{
NazaraError("No data to load");
return false;
}
#endif
nzUInt64 streamPos = stream.GetCursorPos();
for (auto loader = Type::s_loaders.begin(); loader != Type::s_loaders.end(); ++loader)
{
// Le loader supporte-t-il les données ?
if (!std::get<1>(*loader)(stream, parameters))
continue;
// On repositionne le stream au début
stream.SetCursorPos(streamPos);
// Chargement de la ressource
if (std::get<2>(*loader)(resource, stream, parameters))
return true;
NazaraWarning("Loader failed");
stream.SetCursorPos(streamPos); // On repositionne au début
}
NazaraError("Failed to load file: no loader");
return false;
}
template<typename Type, typename Parameters>
void NzResourceLoader<Type, Parameters>::RegisterLoader(const NzString& fileExtensions, CheckFunction checkFunc, LoadFunction loadFunc)
{
/// Trouver une alternative à ce code monstrueux
std::vector<NzString> exts;
fileExtensions.SplitAny(exts, " /\\.,;|-_");
std::set<NzString> extensions;
std::copy(exts.begin(), exts.end(), std::inserter(extensions, extensions.begin()));
Type::s_loaders.insert(std::make_tuple(std::move(extensions), checkFunc, loadFunc));
}
template<typename Type, typename Parameters>
void NzResourceLoader<Type, Parameters>::UnregisterLoader(const NzString& fileExtensions, CheckFunction checkFunc, LoadFunction loadFunc)
{
std::vector<NzString> exts;
fileExtensions.SplitAny(exts, " /\\.,;|-_");
std::set<NzString> extensions;
std::copy(exts.begin(), exts.end(), std::inserter(extensions, extensions.begin()));
Type::s_loaders.erase(std::make_tuple(std::move(extensions), checkFunc, loadFunc));
}
#include <Nazara/Core/DebugOff.hpp>
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/File.hpp>
#include <Nazara/Core/InputStream.hpp>
#include <Nazara/Core/MemoryStream.hpp>
#include <Nazara/Core/Debug.hpp>
template<typename Type, typename Parameters>
bool NzResourceLoader<Type, Parameters>::LoadFromFile(Type* resource, const NzString& filePath, const Parameters& parameters)
{
#if NAZARA_CORE_SAFE
if (!parameters.IsValid())
{
NazaraError("Invalid parameters");
return false;
}
#endif
NzString path = NzFile::NormalizePath(filePath);
NzString ext = path.SubstrFrom('.', -1, true);
if (ext.IsEmpty())
{
NazaraError("Failed to get file extension");
return false;
}
NzFile file(path, NzFile::ReadOnly);
if (!file.IsOpen())
{
NazaraError("Failed to open file");
return false;
}
for (auto loader = Type::s_loaders.begin(); loader != Type::s_loaders.end(); ++loader)
{
for (const NzString& loaderExt : std::get<0>(*loader))
{
int cmp = NzString::Compare(loaderExt, ext);
if (cmp == 0)
{
if (!std::get<1>(*loader)(file, parameters))
continue;
file.SetCursorPos(0);
// Chargement de la ressource
if (std::get<2>(*loader)(resource, file, parameters))
return true;
NazaraWarning("Loader failed");
file.SetCursorPos(0);
}
else if (cmp < 0) // S'il est encore possible que l'extension se situe après
continue;
break;
}
}
NazaraError("Failed to load file: no loader");
return false;
}
template<typename Type, typename Parameters>
bool NzResourceLoader<Type, Parameters>::LoadFromMemory(Type* resource, const void* data, unsigned int size, const Parameters& parameters)
{
NzMemoryStream stream(data, size);
return LoadFromStream(resource, stream, parameters);
}
template<typename Type, typename Parameters>
bool NzResourceLoader<Type, Parameters>::LoadFromStream(Type* resource, NzInputStream& stream, const Parameters& parameters)
{
#if NAZARA_CORE_SAFE
if (!parameters.IsValid())
{
NazaraError("Invalid parameters");
return false;
}
if (stream.GetSize() == 0 || stream.GetCursorPos() >= stream.GetSize())
{
NazaraError("No data to load");
return false;
}
#endif
nzUInt64 streamPos = stream.GetCursorPos();
for (auto loader = Type::s_loaders.begin(); loader != Type::s_loaders.end(); ++loader)
{
// Le loader supporte-t-il les données ?
if (!std::get<1>(*loader)(stream, parameters))
continue;
// On repositionne le stream au début
stream.SetCursorPos(streamPos);
// Chargement de la ressource
if (std::get<2>(*loader)(resource, stream, parameters))
return true;
NazaraWarning("Loader failed");
stream.SetCursorPos(streamPos); // On repositionne au début
}
NazaraError("Failed to load file: no loader");
return false;
}
template<typename Type, typename Parameters>
void NzResourceLoader<Type, Parameters>::RegisterLoader(const NzString& fileExtensions, CheckFunction checkFunc, LoadFunction loadFunc)
{
///FIXME: Trouver une alternative à ce code monstrueux
std::vector<NzString> exts;
fileExtensions.SplitAny(exts, " /\\.,;|-_");
std::set<NzString> extensions;
std::copy(exts.begin(), exts.end(), std::inserter(extensions, extensions.begin()));
Type::s_loaders.insert(std::make_tuple(std::move(extensions), checkFunc, loadFunc));
}
template<typename Type, typename Parameters>
void NzResourceLoader<Type, Parameters>::UnregisterLoader(const NzString& fileExtensions, CheckFunction checkFunc, LoadFunction loadFunc)
{
std::vector<NzString> exts;
fileExtensions.SplitAny(exts, " /\\.,;|-_");
std::set<NzString> extensions;
std::copy(exts.begin(), exts.end(), std::inserter(extensions, extensions.begin()));
Type::s_loaders.erase(std::make_tuple(std::move(extensions), checkFunc, loadFunc));
}
#include <Nazara/Core/DebugOff.hpp>

View File

@ -1,321 +1,321 @@
// 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_STRING_HPP
#define NAZARA_STRING_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Hashable.hpp>
#include <iosfwd>
#include <string>
#include <vector>
#if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_STRING
#include <Nazara/Core/ThreadSafety.hpp>
#else
#include <Nazara/Core/ThreadSafetyOff.hpp>
#endif
class NzAbstractHash;
class NzHashDigest;
class NAZARA_API NzString : public NzHashable
{
public:
enum Flags
{
None = 0x00, // Mode par défaut
CaseInsensitive = 0x01, // Insensible à la casse
HandleUtf8 = 0x02, // Traite les octets comme une suite de caractères UTF-8
TrimOnlyLeft = 0x04, // Trim(med), ne coupe que la partie gauche de la chaîne
TrimOnlyRight = 0x08 // Trim(med), ne coupe que la partie droite de la chaîne
};
struct SharedString;
NzString();
NzString(char character);
NzString(const char* string);
NzString(const std::string& string);
NzString(const NzString& string);
NzString(NzString&& string) noexcept;
NzString(SharedString* sharedString);
~NzString();
NzString& Append(char character);
NzString& Append(const char* string);
NzString& Append(const NzString& string);
void Clear(bool keepBuffer = false);
bool Contains(char character, int start = 0, nzUInt32 flags = None) const;
bool Contains(const char* string, int start = 0, nzUInt32 flags = None) const;
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(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 CountAny(const char* 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(const char* 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(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 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 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 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 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 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 NzString& string, int start = 0, nzUInt32 flags = None) const;
char* GetBuffer();
unsigned int GetCapacity() const;
const char* GetConstBuffer() const;
unsigned int GetLength() const;
unsigned int GetSize() const;
char* GetUtf8Buffer(unsigned int* size = nullptr) const;
char16_t* GetUtf16Buffer(unsigned int* size = nullptr) const;
char32_t* GetUtf32Buffer(unsigned int* size = nullptr) const;
wchar_t* GetWideBuffer(unsigned int* size = nullptr) const;
NzString GetWord(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, const char* string);
NzString& Insert(int pos, const NzString& string);
bool IsEmpty() const;
bool IsNull() const;
bool IsNumber(nzUInt8 radix = 10, nzUInt32 flags = CaseInsensitive) const;
bool Match(const char* pattern) const;
bool Match(const NzString& pattern) const;
NzString& Prepend(char character);
NzString& Prepend(const char* string);
NzString& Prepend(const NzString& string);
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 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, const char* 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);
NzString& Resize(int size, char character = ' ');
NzString Resized(int size, char character = ' ') const;
NzString& Reverse();
NzString Reversed() const;
NzString Simplified(nzUInt32 flags = None) const;
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, 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 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;
bool StartsWith(char character, nzUInt32 flags = None) const;
bool StartsWith(const char* string, nzUInt32 flags = None) const;
bool StartsWith(const NzString& string, nzUInt32 flags = None) 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(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 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 NzString& string, int startPos = 0, bool toLast = false, bool include = false, nzUInt32 flags = None) const;
void Swap(NzString& str);
bool ToBool(bool* value, nzUInt32 flags = None) const;
bool ToDouble(double* value) const;
bool ToInteger(long long* value, nzUInt8 radix = 10) const;
NzString ToLower(nzUInt32 flags = None) const;
NzString ToUpper(nzUInt32 flags = None) const;
NzString& Trim(nzUInt32 flags = None);
NzString& Trim(char character, nzUInt32 flags = None);
NzString Trimmed(nzUInt32 flags = None) const;
NzString Trimmed(char character, nzUInt32 flags = None) const;
// Méthodes STD
char* begin();
const char* begin() const;
char* end();
const char* end() const;
void push_front(char c);
void push_back(char c);
/*char* rbegin();
const char* rbegin() const;
char* rend();
const char* rend() const;*/
typedef const char& const_reference;
typedef char* iterator;
//typedef char* reverse_iterator;
typedef char value_type;
// Méthodes STD
operator std::string() const;
char& operator[](unsigned int pos);
char operator[](unsigned int pos) const;
NzString& operator=(char character);
NzString& operator=(const char* string);
NzString& operator=(const std::string& string);
NzString& operator=(const NzString& string);
NzString& operator=(NzString&& string) noexcept;
NzString operator+(char character) const;
NzString operator+(const char* string) const;
NzString operator+(const std::string& string) const;
NzString operator+(const NzString& string) const;
NzString& operator+=(char character);
NzString& operator+=(const char* string);
NzString& operator+=(const std::string& string);
NzString& operator+=(const NzString& string);
bool operator==(char character) const;
bool operator==(const char* string) const;
bool operator==(const std::string& string) const;
bool operator!=(char character) const;
bool operator!=(const char* string) const;
bool operator!=(const std::string& string) const;
bool operator<(char character) const;
bool operator<(const char* string) const;
bool operator<(const std::string& string) const;
bool operator<=(char character) const;
bool operator<=(const char* string) const;
bool operator<=(const std::string& string) const;
bool operator>(char character) const;
bool operator>(const char* string) const;
bool operator>(const std::string& string) const;
bool operator>=(char character) const;
bool operator>=(const char* string) const;
bool operator>=(const std::string& string) const;
static NzString Boolean(bool boolean);
static int Compare(const NzString& first, const NzString& second);
static NzString Number(float number);
static NzString Number(double number);
static NzString Number(long double number);
static NzString Number(signed 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(unsigned short number, nzUInt8 radix = 10);
static NzString Number(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(unsigned 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 Pointer(const void* ptr);
static NzString Unicode(char32_t character);
static NzString Unicode(const char* u8String);
static NzString Unicode(const char16_t* u16String);
static NzString Unicode(const char32_t* u32String);
static NzString Unicode(const wchar_t* wString);
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 NzString operator+(char character, const NzString& string);
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 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==(const char* 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!=(const char* 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<(const char* 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<=(const char* 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>(const char* 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>=(const char* string, const NzString& nstring);
NAZARA_API friend bool operator>=(const std::string& string, const NzString& nstring);
struct NAZARA_API SharedString
{
SharedString() = default;
SharedString(unsigned short referenceCount, unsigned int bufferSize, unsigned int stringSize, char* str) :
capacity(bufferSize),
size(stringSize),
string(str),
refCount(referenceCount)
{
}
unsigned int capacity;
unsigned int size;
char* string;
unsigned short refCount = 1;
NazaraMutex(mutex)
};
static SharedString emptyString;
static unsigned int npos;
private:
void EnsureOwnership();
bool FillHash(NzHashImpl* hash) const;
void ReleaseString();
SharedString* m_sharedString;
};
namespace std
{
NAZARA_API istream& getline(istream& is, NzString& str);
NAZARA_API istream& getline(istream& is, NzString& str, char delim);
NAZARA_API void swap(NzString& lhs, NzString& rhs);
}
#endif // NAZARA_STRING_HPP
// 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_STRING_HPP
#define NAZARA_STRING_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Hashable.hpp>
#include <iosfwd>
#include <string>
#include <vector>
#if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_STRING
#include <Nazara/Core/ThreadSafety.hpp>
#else
#include <Nazara/Core/ThreadSafetyOff.hpp>
#endif
class NzAbstractHash;
class NzHashDigest;
class NAZARA_API NzString : public NzHashable
{
public:
enum Flags
{
None = 0x00, // Mode par défaut
CaseInsensitive = 0x01, // Insensible à la casse
HandleUtf8 = 0x02, // Traite les octets comme une suite de caractères UTF-8
TrimOnlyLeft = 0x04, // Trim(med), ne coupe que la partie gauche de la chaîne
TrimOnlyRight = 0x08 // Trim(med), ne coupe que la partie droite de la chaîne
};
struct SharedString;
NzString();
NzString(char character);
NzString(const char* string);
NzString(const std::string& string);
NzString(const NzString& string);
NzString(NzString&& string) noexcept;
NzString(SharedString* sharedString);
~NzString();
NzString& Append(char character);
NzString& Append(const char* string);
NzString& Append(const NzString& string);
void Clear(bool keepBuffer = false);
bool Contains(char character, int start = 0, nzUInt32 flags = None) const;
bool Contains(const char* string, int start = 0, nzUInt32 flags = None) const;
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(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 CountAny(const char* 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(const char* 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(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 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 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 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 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 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 NzString& string, int start = 0, nzUInt32 flags = None) const;
char* GetBuffer();
unsigned int GetCapacity() const;
const char* GetConstBuffer() const;
unsigned int GetLength() const;
unsigned int GetSize() const;
char* GetUtf8Buffer(unsigned int* size = nullptr) const;
char16_t* GetUtf16Buffer(unsigned int* size = nullptr) const;
char32_t* GetUtf32Buffer(unsigned int* size = nullptr) const;
wchar_t* GetWideBuffer(unsigned int* size = nullptr) const;
NzString GetWord(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, const char* string);
NzString& Insert(int pos, const NzString& string);
bool IsEmpty() const;
bool IsNull() const;
bool IsNumber(nzUInt8 radix = 10, nzUInt32 flags = CaseInsensitive) const;
bool Match(const char* pattern) const;
bool Match(const NzString& pattern) const;
NzString& Prepend(char character);
NzString& Prepend(const char* string);
NzString& Prepend(const NzString& string);
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 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, const char* 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);
NzString& Resize(int size, char character = ' ');
NzString Resized(int size, char character = ' ') const;
NzString& Reverse();
NzString Reversed() const;
NzString Simplified(nzUInt32 flags = None) const;
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, 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 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;
bool StartsWith(char character, nzUInt32 flags = None) const;
bool StartsWith(const char* string, nzUInt32 flags = None) const;
bool StartsWith(const NzString& string, nzUInt32 flags = None) 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(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 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 NzString& string, int startPos = 0, bool toLast = false, bool include = false, nzUInt32 flags = None) const;
void Swap(NzString& str);
bool ToBool(bool* value, nzUInt32 flags = None) const;
bool ToDouble(double* value) const;
bool ToInteger(long long* value, nzUInt8 radix = 10) const;
NzString ToLower(nzUInt32 flags = None) const;
NzString ToUpper(nzUInt32 flags = None) const;
NzString& Trim(nzUInt32 flags = None);
NzString& Trim(char character, nzUInt32 flags = None);
NzString Trimmed(nzUInt32 flags = None) const;
NzString Trimmed(char character, nzUInt32 flags = None) const;
// Méthodes STD
char* begin();
const char* begin() const;
char* end();
const char* end() const;
void push_front(char c);
void push_back(char c);
/*char* rbegin();
const char* rbegin() const;
char* rend();
const char* rend() const;*/
typedef const char& const_reference;
typedef char* iterator;
//typedef char* reverse_iterator;
typedef char value_type;
// Méthodes STD
operator std::string() const;
char& operator[](unsigned int pos);
char operator[](unsigned int pos) const;
NzString& operator=(char character);
NzString& operator=(const char* string);
NzString& operator=(const std::string& string);
NzString& operator=(const NzString& string);
NzString& operator=(NzString&& string) noexcept;
NzString operator+(char character) const;
NzString operator+(const char* string) const;
NzString operator+(const std::string& string) const;
NzString operator+(const NzString& string) const;
NzString& operator+=(char character);
NzString& operator+=(const char* string);
NzString& operator+=(const std::string& string);
NzString& operator+=(const NzString& string);
bool operator==(char character) const;
bool operator==(const char* string) const;
bool operator==(const std::string& string) const;
bool operator!=(char character) const;
bool operator!=(const char* string) const;
bool operator!=(const std::string& string) const;
bool operator<(char character) const;
bool operator<(const char* string) const;
bool operator<(const std::string& string) const;
bool operator<=(char character) const;
bool operator<=(const char* string) const;
bool operator<=(const std::string& string) const;
bool operator>(char character) const;
bool operator>(const char* string) const;
bool operator>(const std::string& string) const;
bool operator>=(char character) const;
bool operator>=(const char* string) const;
bool operator>=(const std::string& string) const;
static NzString Boolean(bool boolean);
static int Compare(const NzString& first, const NzString& second);
static NzString Number(float number);
static NzString Number(double number);
static NzString Number(long double number);
static NzString Number(signed 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(unsigned short number, nzUInt8 radix = 10);
static NzString Number(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(unsigned 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 Pointer(const void* ptr);
static NzString Unicode(char32_t character);
static NzString Unicode(const char* u8String);
static NzString Unicode(const char16_t* u16String);
static NzString Unicode(const char32_t* u32String);
static NzString Unicode(const wchar_t* wString);
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 NzString operator+(char character, const NzString& string);
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 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==(const char* 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!=(const char* 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<(const char* 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<=(const char* 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>(const char* 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>=(const char* string, const NzString& nstring);
NAZARA_API friend bool operator>=(const std::string& string, const NzString& nstring);
struct NAZARA_API SharedString
{
SharedString() = default;
SharedString(unsigned short referenceCount, unsigned int bufferSize, unsigned int stringSize, char* str) :
capacity(bufferSize),
size(stringSize),
string(str),
refCount(referenceCount)
{
}
unsigned int capacity;
unsigned int size;
char* string;
unsigned short refCount = 1;
NazaraMutex(mutex)
};
static SharedString emptyString;
static const unsigned int npos;
private:
void EnsureOwnership();
bool FillHash(NzHashImpl* hash) const;
void ReleaseString();
SharedString* m_sharedString;
};
namespace std
{
NAZARA_API istream& getline(istream& is, NzString& str);
NAZARA_API istream& getline(istream& is, NzString& str, char delim);
NAZARA_API void swap(NzString& lhs, NzString& rhs);
}
#endif // NAZARA_STRING_HPP

View File

@ -1,52 +1,49 @@
/*
Nazara Engine - Mathematics module
Copyright (C) 2012 Jérôme "Lynix" Leclercq (Lynix680@gmail.com)
Rémi "overdrivr" Bèges (remi.beges@laposte.net)
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
the Software without restriction, including without limitation the rights to
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
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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
SOFTWARE.
*/
#pragma once
#ifndef NAZARA_CONFIG_MATH_HPP
#define NAZARA_CONFIG_MATH_HPP
/// 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
#define NAZARA_MATH_ANGLE_RADIAN 0
// Définit la disposition des matrices en colonnes (Façon OpenGL)
#define NAZARA_MATH_MATRIX_COLUMN_MAJOR 1
// Optimise les opérations entre matrices affines (Demande plusieurs comparaisons pour déterminer si une matrice est affine)
#define NAZARA_MATH_MATRIX4_CHECK_AFFINE 0
// Active les tests de sécurité basés sur le code (Conseillé pour le développement)
#define NAZARA_MATH_SAFE 1
// Protège les classes des accès concurrentiels
#define NAZARA_MATH_THREADSAFE 1
// Les classes à protéger des accès concurrentiels
#define NAZARA_THREADSAFETY_MATRIX3 1 // NzMatrix3 (COW)
#define NAZARA_THREADSAFETY_MATRIX4 1 // NzMatrix4 (COW)
#endif // NAZARA_CONFIG_MATH_HPP
/*
Nazara Engine - Mathematics module
Copyright (C) 2012 Jérôme "Lynix" Leclercq (Lynix680@gmail.com)
Rémi "overdrivr" Bèges (remi.beges@laposte.net)
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
the Software without restriction, including without limitation the rights to
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
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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
SOFTWARE.
*/
#pragma once
#ifndef NAZARA_CONFIG_MATH_HPP
#define NAZARA_CONFIG_MATH_HPP
/// 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
#define NAZARA_MATH_ANGLE_RADIAN 0
// Optimise les opérations entre matrices affines (Demande plusieurs comparaisons pour déterminer si une matrice est affine)
#define NAZARA_MATH_MATRIX4_CHECK_AFFINE 0
// Active les tests de sécurité basés sur le code (Conseillé pour le développement)
#define NAZARA_MATH_SAFE 1
// Protège les classes des accès concurrentiels
#define NAZARA_MATH_THREADSAFE 1
// Les classes à protéger des accès concurrentiels
#define NAZARA_THREADSAFETY_MATRIX3 1 // NzMatrix3 (COW)
#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
// This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_MATRIX4_HPP
#define NAZARA_MATRIX4_HPP
#include <Nazara/Core/String.hpp>
#include <Nazara/Math/Config.hpp>
#if NAZARA_MATH_THREADSAFE && NAZARA_THREADSAFETY_MATRIX4
#include <Nazara/Core/ThreadSafety.hpp>
#else
#include <Nazara/Core/ThreadSafetyOff.hpp>
#endif
template<typename T> class NzEulerAngles;
template<typename T> class NzQuaternion;
template<typename T> class NzVector2;
template<typename T> class NzVector3;
template<typename T> class NzVector4;
template<typename T> class NzMatrix4
{
public:
NzMatrix4();
NzMatrix4(T r11, T r12, T r13, T r14,
T r21, T r22, T r23, T r24,
T r31, T r32, T r33, T r34,
T r41, T r42, T r43, T r44);
NzMatrix4(const T matrix[16]);
//NzMatrix4(const NzMatrix3<T>& matrix);
template<typename U> explicit NzMatrix4(const NzMatrix4<U>& matrix);
NzMatrix4(const NzMatrix4& matrix);
NzMatrix4(NzMatrix4&& matrix) noexcept;
~NzMatrix4();
NzMatrix4 Concatenate(const NzMatrix4& matrix) const;
T GetDeterminant() const;
NzMatrix4 GetInverse() const;
NzQuaternion<T> GetRotation() const;
//NzMatrix3 GetRotationMatrix() const;
NzVector3<T> GetScale() const;
NzVector3<T> GetTranslation() const;
NzMatrix4 GetTransposed() const;
bool HasNegativeScale() const;
bool HasScale() const;
bool IsAffine() const;
bool IsDefined() const;
void MakeIdentity();
void MakeLookAt(const NzVector3<T>& eye, const NzVector3<T>& center, const NzVector3<T>& up);
void MakeOrtho(T left, T top, T width, T height, T zNear = -1.0, T zFar = 1.0);
void MakePerspective(T angle, T ratio, T zNear, T zFar);
void MakeRotation(const NzQuaternion<T>& rotation);
void MakeScale(const NzVector3<T>& scale);
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,
T r31, T r32, T r33, T r34,
T r41, T r42, T r43, T r44);
void Set(const T matrix[16]);
//NzMatrix4(const NzMatrix3<T>& matrix);
void Set(const NzMatrix4& matrix);
void Set(NzMatrix4&& matrix);
template<typename U> void Set(const NzMatrix4<U>& matrix);
void SetRotation(const NzQuaternion<T>& rotation);
void SetScale(const NzVector3<T>& scale);
void SetTranslation(const NzVector3<T>& translation);
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;
NzVector4<T> Transform(const NzVector4<T>& vector) const;
NzMatrix4& Transpose();
operator NzString() 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;
NzMatrix4& operator=(const NzMatrix4& matrix);
NzMatrix4& operator=(NzMatrix4&& matrix) noexcept;
NzMatrix4 operator*(const NzMatrix4& matrix) const;
NzVector2<T> operator*(const NzVector2<T>& vector) const;
NzVector3<T> operator*(const NzVector3<T>& vector) const;
NzVector4<T> operator*(const NzVector4<T>& vector) const;
NzMatrix4 operator*(T scalar) const;
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 Identity();
static NzMatrix4 LookAt(const NzVector3<T>& eye, const NzVector3<T>& center, const NzVector3<T>& up);
static NzMatrix4 Ortho(T left, T top, T width, T height, T zNear = -1.0, T zFar = 1.0);
static NzMatrix4 Perspective(T angle, T ratio, T zNear, T zFar);
static NzMatrix4 Rotate(const NzQuaternion<T>& rotation);
static NzMatrix4 Scale(const NzVector3<T>& scale);
static NzMatrix4 Translate(const NzVector3<T>& translation);
static NzMatrix4 Zero();
struct SharedMatrix
{
T m11, m12, m13, m14,
m21, m22, m23, m24,
m31, m32, m33, m34,
m41, m42, m43, m44;
unsigned short refCount = 1;
NazaraMutex(mutex)
};
private:
void EnsureOwnership();
void ReleaseMatrix();
SharedMatrix* m_sharedMatrix = nullptr;
};
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);
typedef NzMatrix4<double> NzMatrix4d;
typedef NzMatrix4<float> NzMatrix4f;
#include <Nazara/Math/Matrix4.inl>
#endif // NAZARA_MATRIX4_HPP
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_MATRIX4_HPP
#define NAZARA_MATRIX4_HPP
#include <Nazara/Core/String.hpp>
#include <Nazara/Math/Config.hpp>
#if NAZARA_MATH_THREADSAFE && NAZARA_THREADSAFETY_MATRIX4
#include <Nazara/Core/ThreadSafety.hpp>
#else
#include <Nazara/Core/ThreadSafetyOff.hpp>
#endif
template<typename T> class NzEulerAngles;
template<typename T> class NzQuaternion;
template<typename T> class NzVector2;
template<typename T> class NzVector3;
template<typename T> class NzVector4;
template<typename T> class NzMatrix4
{
public:
NzMatrix4();
NzMatrix4(T r11, T r12, T r13, T r14,
T r21, T r22, T r23, T r24,
T r31, T r32, T r33, T r34,
T r41, T r42, T r43, T r44);
NzMatrix4(const T matrix[16]);
//NzMatrix4(const NzMatrix3<T>& matrix);
template<typename U> explicit NzMatrix4(const NzMatrix4<U>& matrix);
NzMatrix4(const NzMatrix4& matrix);
NzMatrix4(NzMatrix4&& matrix) noexcept;
~NzMatrix4();
NzMatrix4 Concatenate(const NzMatrix4& matrix) const;
NzMatrix4 ConcatenateAffine(const NzMatrix4& matrix) const;
T GetDeterminant() const;
NzMatrix4 GetInverse() const;
NzQuaternion<T> GetRotation() const;
//NzMatrix3 GetRotationMatrix() const;
NzVector3<T> GetScale() const;
NzVector3<T> GetTranslation() const;
NzMatrix4 GetTransposed() const;
bool HasNegativeScale() const;
bool HasScale() const;
bool IsAffine() const;
bool IsDefined() const;
void MakeIdentity();
void MakeLookAt(const NzVector3<T>& eye, const NzVector3<T>& target, const NzVector3<T>& up = NzVector3<T>::Up());
void MakeOrtho(T left, T top, T width, T height, T zNear = -1.0, T zFar = 1.0);
void MakePerspective(T angle, T ratio, T zNear, T zFar);
void MakeRotation(const NzQuaternion<T>& rotation);
void MakeScale(const NzVector3<T>& scale);
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,
T r31, T r32, T r33, T r34,
T r41, T r42, T r43, T r44);
void Set(const T matrix[16]);
//NzMatrix4(const NzMatrix3<T>& matrix);
void Set(const NzMatrix4& matrix);
void Set(NzMatrix4&& matrix);
template<typename U> void Set(const NzMatrix4<U>& matrix);
void SetRotation(const NzQuaternion<T>& rotation);
void SetScale(const NzVector3<T>& scale);
void SetTranslation(const NzVector3<T>& translation);
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;
NzVector4<T> Transform(const NzVector4<T>& vector) const;
NzMatrix4& Transpose();
operator NzString() 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;
NzMatrix4& operator=(const NzMatrix4& matrix);
NzMatrix4& operator=(NzMatrix4&& matrix) noexcept;
NzMatrix4 operator*(const NzMatrix4& matrix) const;
NzVector2<T> operator*(const NzVector2<T>& vector) const;
NzVector3<T> operator*(const NzVector3<T>& vector) const;
NzVector4<T> operator*(const NzVector4<T>& vector) const;
NzMatrix4 operator*(T scalar) const;
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 Identity();
static NzMatrix4 LookAt(const NzVector3<T>& eye, const NzVector3<T>& target, const NzVector3<T>& up = NzVector3<T>::Up());
static NzMatrix4 Ortho(T left, T top, T width, T height, T zNear = -1.0, T zFar = 1.0);
static NzMatrix4 Perspective(T angle, T ratio, T zNear, T zFar);
static NzMatrix4 Rotate(const NzQuaternion<T>& rotation);
static NzMatrix4 Scale(const NzVector3<T>& scale);
static NzMatrix4 Translate(const NzVector3<T>& translation);
static NzMatrix4 Zero();
struct SharedMatrix
{
T m11, m12, m13, m14,
m21, m22, m23, m24,
m31, m32, m33, m34,
m41, m42, m43, m44;
unsigned short refCount = 1;
NazaraMutex(mutex)
};
private:
void EnsureOwnership();
void ReleaseMatrix();
SharedMatrix* m_sharedMatrix = nullptr;
};
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);
typedef NzMatrix4<double> NzMatrix4d;
typedef NzMatrix4<float> NzMatrix4f;
#include <Nazara/Math/Matrix4.inl>
#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
// This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_QUATERNION_HPP
#define NAZARA_QUATERNION_HPP
#include <Nazara/Core/String.hpp>
template<typename T> class NzEulerAngles;
template<typename T> class NzVector3;
template<typename T> class NzQuaternion
{
public:
NzQuaternion();
NzQuaternion(T W, T X, T Y, T Z);
NzQuaternion(T quat[4]);
NzQuaternion(T angle, const NzVector3<T>& axis);
NzQuaternion(const NzEulerAngles<T>& angles);
//NzQuaternion(const NzMatrix3<T>& mat);
template<typename U> explicit NzQuaternion(const NzQuaternion<U>& quat);
NzQuaternion(const NzQuaternion& quat) = default;
~NzQuaternion() = default;
T DotProduct(const NzQuaternion& vec) const;
NzQuaternion GetConjugate() const;
NzQuaternion GetNormalized() const;
void MakeIdentity();
void MakeZero();
T Magnitude() const;
T Normalize();
void Set(T W, T X, T Y, T Z);
void Set(T quat[4]);
void Set(T angle, const NzVector3<T>& normalizedAxis);
void Set(const NzEulerAngles<T>& angles);
//void Set(const NzMatrix3<T>& mat);
void Set(const NzQuaternion& quat);
template<typename U> void Set(const NzQuaternion<U>& quat);
T SquaredMagnitude() const;
NzEulerAngles<T> ToEulerAngles() const;
//NzMatrix3<T> ToRotationMatrix() const;
NzString ToString() const;
operator NzString() const;
NzQuaternion& operator=(const NzQuaternion& quat);
NzQuaternion operator+(const NzQuaternion& quat) const;
NzQuaternion operator*(const NzQuaternion& quat) const;
NzVector3<T> operator*(const NzVector3<T>& vec) const;
NzQuaternion operator*(T scale) const;
NzQuaternion operator/(const NzQuaternion& quat) const;
NzQuaternion& operator+=(const NzQuaternion& quat);
NzQuaternion& operator*=(const NzQuaternion& quat);
NzQuaternion& operator*=(T scale);
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;
static NzQuaternion Identity();
static NzQuaternion Slerp(const NzQuaternion& quatA, const NzQuaternion& quatB, T interp);
static NzQuaternion Zero();
T w, x, y, z;
};
template<typename T> std::ostream& operator<<(std::ostream& out, const NzQuaternion<T>& quat);
typedef NzQuaternion<double> NzQuaterniond;
typedef NzQuaternion<float> NzQuaternionf;
#include <Nazara/Math/Quaternion.inl>
#endif // NAZARA_QUATERNION_HPP
// Copyright (C) 2012 Rémi Bèges - Jérôme Leclercq
// This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_QUATERNION_HPP
#define NAZARA_QUATERNION_HPP
#include <Nazara/Core/String.hpp>
template<typename T> class NzEulerAngles;
template<typename T> class NzVector3;
template<typename T> class NzQuaternion
{
public:
NzQuaternion();
NzQuaternion(T W, T X, T Y, T Z);
NzQuaternion(T quat[4]);
NzQuaternion(T angle, const NzVector3<T>& axis);
NzQuaternion(const NzEulerAngles<T>& angles);
//NzQuaternion(const NzMatrix3<T>& mat);
template<typename U> explicit NzQuaternion(const NzQuaternion<U>& quat);
NzQuaternion(const NzQuaternion& quat) = default;
~NzQuaternion() = default;
T DotProduct(const NzQuaternion& vec) const;
NzQuaternion GetConjugate() const;
NzQuaternion GetInverse() const;
NzQuaternion GetNormal() const;
void Inverse();
void MakeIdentity();
void MakeZero();
T Magnitude() const;
T Normalize();
void Set(T W, T X, T Y, T Z);
void Set(T quat[4]);
void Set(T angle, const NzVector3<T>& normalizedAxis);
void Set(const NzEulerAngles<T>& angles);
//void Set(const NzMatrix3<T>& mat);
void Set(const NzQuaternion& quat);
template<typename U> void Set(const NzQuaternion<U>& quat);
T SquaredMagnitude() const;
NzEulerAngles<T> ToEulerAngles() const;
//NzMatrix3<T> ToRotationMatrix() const;
NzString ToString() const;
operator NzString() const;
NzQuaternion& operator=(const NzQuaternion& quat);
NzQuaternion operator+(const NzQuaternion& quat) const;
NzQuaternion operator*(const NzQuaternion& quat) const;
NzVector3<T> operator*(const NzVector3<T>& vec) const;
NzQuaternion operator*(T scale) const;
NzQuaternion operator/(const NzQuaternion& quat) const;
NzQuaternion& operator+=(const NzQuaternion& quat);
NzQuaternion& operator*=(const NzQuaternion& quat);
NzQuaternion& operator*=(T scale);
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;
static NzQuaternion Identity();
static NzQuaternion Slerp(const NzQuaternion& quatA, const NzQuaternion& quatB, T interp);
static NzQuaternion Zero();
T w, x, y, z;
};
template<typename T> std::ostream& operator<<(std::ostream& out, const NzQuaternion<T>& quat);
typedef NzQuaternion<double> NzQuaterniond;
typedef NzQuaternion<float> NzQuaternionf;
#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
// This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/StringStream.hpp>
#include <Nazara/Math/Basic.hpp>
#include <Nazara/Math/Config.hpp>
#include <Nazara/Math/EulerAngles.hpp>
#include <Nazara/Math/Vector3.hpp>
#include <limits>
#include <Nazara/Core/Debug.hpp>
#define F(a) static_cast<T>(a)
template<typename T>
NzQuaternion<T>::NzQuaternion()
{
}
template<typename T>
NzQuaternion<T>::NzQuaternion(T W, T X, T Y, T Z)
{
Set(W, X, Y, Z);
}
template<typename T>
NzQuaternion<T>::NzQuaternion(T quat[4])
{
Set(quat);
}
template<typename T>
NzQuaternion<T>::NzQuaternion(T angle, const NzVector3<T>& axis)
{
Set(angle, axis);
}
template<typename T>
NzQuaternion<T>::NzQuaternion(const NzEulerAngles<T>& angles)
{
Set(angles);
}
/*
template<typename T>
NzQuaternion<T>::NzQuaternion(const NzMatrix3<T>& mat)
{
Set(mat);
}
*/
template<typename T>
template<typename U>
NzQuaternion<T>::NzQuaternion(const NzQuaternion<U>& quat)
{
Set(quat);
}
template<typename T>
T NzQuaternion<T>::DotProduct(const NzQuaternion& quat) const
{
return w*quat.w + x*quat.x + y*quat.y + z*quat.z;
}
template<typename T>
NzQuaternion<T> NzQuaternion<T>::GetConjugate() const
{
return NzQuaternion(w, -x, -y, -z);
}
template<typename T>
NzQuaternion<T> NzQuaternion<T>::GetNormalized() const
{
NzQuaternion<T> quat(*this);
quat.Normalize();
return quat;
}
template<typename T>
void NzQuaternion<T>::MakeIdentity()
{
Set(1.0, 0.0, 0.0, 0.0);
}
template<typename T>
void NzQuaternion<T>::MakeZero()
{
Set(0.0, 0.0, 0.0, 0.0);
}
template<typename T>
T NzQuaternion<T>::Magnitude() const
{
return std::sqrt(SquaredMagnitude());
}
template<typename T>
T NzQuaternion<T>::Normalize()
{
T squaredMagnitude = SquaredMagnitude();
if (squaredMagnitude-F(1.0) > std::numeric_limits<T>::epsilon())
{
T magnitude = std::sqrt(squaredMagnitude);
w /= magnitude;
x /= magnitude;
y /= magnitude;
z /= magnitude;
return magnitude;
}
else
return F(1.0); // Le quaternion est déjà normalisé
}
template<typename T>
void NzQuaternion<T>::Set(T W, T X, T Y, T Z)
{
w = W;
x = X;
y = Y;
z = Z;
}
template<typename T>
void NzQuaternion<T>::Set(T quat[4])
{
w = quat[0];
x = quat[1];
y = quat[2];
z = quat[3];
}
template<typename T>
void NzQuaternion<T>::Set(T angle, const NzVector3<T>& normalizedAxis)
{
#if !NAZARA_MATH_ANGLE_RADIAN
angle = NzDegreeToRadian(angle);
#endif
angle /= 2;
auto sinAngle = std::sin(angle);
w = std::cos(angle);
x = normalizedAxis.x * sinAngle;
y = normalizedAxis.y * sinAngle;
z = normalizedAxis.z * sinAngle;
}
template<typename T>
void NzQuaternion<T>::Set(const NzEulerAngles<T>& angles)
{
Set(angles.ToQuaternion());
}
template<typename T>
template<typename U>
void NzQuaternion<T>::Set(const NzQuaternion<U>& quat)
{
w = static_cast<T>(quat.w);
x = static_cast<T>(quat.x);
y = static_cast<T>(quat.y);
z = static_cast<T>(quat.z);
}
template<typename T>
void NzQuaternion<T>::Set(const NzQuaternion& quat)
{
w = quat.w;
x = quat.x;
y = quat.y;
z = quat.z;
}
template<typename T>
T NzQuaternion<T>::SquaredMagnitude() const
{
return w*w + x*x + y*y + z*z;
}
template<typename T>
NzEulerAngles<T> NzQuaternion<T>::ToEulerAngles() const
{
T test = x*y + z*w;
if (test > F(0.499))
// singularity at north pole
return NzEulerAngles<T>(NzDegrees(F(90.0)), NzRadians(F(2.0) * std::atan2(x, w)), F(0.0));
if (test < F(-0.499))
return NzEulerAngles<T>(NzDegrees(F(-90.0)), NzRadians(F(-2.0) * std::atan2(x, w)), F(0.0));
T xx = x*x;
T yy = y*y;
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)),
NzRadians(std::atan2(F(2.0)*y*w - F(2.0)*x*z, F(1.0) - F(2.0)*yy - F(2.0)*zz)),
NzRadians(std::asin(F(2.0)*test)));
}
template<typename T>
NzString NzQuaternion<T>::ToString() const
{
NzStringStream ss;
return ss << "Quaternion(" << w << " | " << x << ", " << y << ", " << z << ')';
}
template<typename T>
NzQuaternion<T>::operator NzString() const
{
return ToString();
}
template<typename T>
NzQuaternion<T>& NzQuaternion<T>::operator=(const NzQuaternion& quat)
{
Set(quat);
return *this;
}
template<typename T>
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>
NzQuaternion<T> NzQuaternion<T>::operator*(const NzQuaternion& quat) const
{
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,
w*quat.y + y*quat.w + z*quat.x - x*quat.z,
w*quat.z + z*quat.w + x*quat.y - y*quat.x);
}
template<typename T>
NzVector3<T> NzQuaternion<T>::operator*(const NzVector3<T>& vec) const
{
NzVector3<T> normal(vec);
normal.Normalize();
NzQuaternion qvec(0.0, normal.x, normal.y, normal.z);
NzQuaternion result(operator*(qvec * GetConjugate()));
return NzVector3<T>(result.x, result.y, result.z);
}
template<typename T>
NzQuaternion<T> NzQuaternion<T>::operator*(T scale) const
{
return NzQuaternion(w * scale,
x * scale,
y * scale,
z * scale);
}
template<typename T>
NzQuaternion<T> NzQuaternion<T>::operator/(const NzQuaternion& quat) const
{
return GetConjugate(quat) * (*this);
}
template<typename T>
NzQuaternion<T>& NzQuaternion<T>::operator+=(const NzQuaternion& quat)
{
return operator=(operator+(quat));
}
template<typename T>
NzQuaternion<T>& NzQuaternion<T>::operator*=(const NzQuaternion& quat)
{
return operator=(operator*(quat));
}
template<typename T>
NzQuaternion<T>& NzQuaternion<T>::operator*=(T scale)
{
return operator=(operator*(scale));
}
template<typename T>
NzQuaternion<T>& NzQuaternion<T>::operator/=(const NzQuaternion& quat)
{
return operator=(operator/(quat));
}
template<typename T>
bool NzQuaternion<T>::operator==(const NzQuaternion& quat) const
{
return NzNumberEquals(w, quat.w) &&
NzNumberEquals(x, quat.x) &&
NzNumberEquals(y, quat.y) &&
NzNumberEquals(z, quat.z);
}
template<typename T>
bool NzQuaternion<T>::operator!=(const NzQuaternion& quat) const
{
return !operator==(quat);
}
template<typename T>
bool NzQuaternion<T>::operator<(const NzQuaternion& quat) const
{
return w < quat.w && x < quat.x && y < quat.y && z < quat.z;
}
template<typename T>
bool NzQuaternion<T>::operator<=(const NzQuaternion& quat) const
{
return operator<(quat) || operator==(quat);
}
template<typename T>
bool NzQuaternion<T>::operator>(const NzQuaternion& quat) const
{
return !operator<=(quat);
}
template<typename T>
bool NzQuaternion<T>::operator>=(const NzQuaternion& quat) const
{
return !operator<(quat);
}
template<typename T>
NzQuaternion<T> NzQuaternion<T>::Identity()
{
NzQuaternion quaternion;
quaternion.MakeIdentity();
return quaternion;
}
template<typename T>
NzQuaternion<T> NzQuaternion<T>::Slerp(const NzQuaternion& quatA, const NzQuaternion& quatB, T interp)
{
if (interp <= F(0.0))
return quatA;
if (interp >= F(1.0))
return quatB;
NzQuaternion q;
T cosOmega = quatA.DotProduct(quatB);
if (cosOmega < F(0.0))
{
// On inverse tout
q.Set(-quatB.w, -quatB.x, -quatB.y, -quatB.z);
cosOmega = -cosOmega;
}
else
q.Set(quatB);
T k0, k1;
if (cosOmega > F(0.9999))
{
// Interpolation linéaire pour éviter une division par zéro
k0 = F(1.0) - interp;
k1 = interp;
}
else
{
T sinOmega = std::sqrt(F(1.0) - cosOmega*cosOmega);
T omega = std::atan2(sinOmega, cosOmega);
// Pour éviter deux divisions
sinOmega = F(1.0)/sinOmega;
k0 = std::sin((F(1.0) - 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>
// Copyright (C) 2012 Rémi Bèges - Jérôme Leclercq
// This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/StringStream.hpp>
#include <Nazara/Math/Basic.hpp>
#include <Nazara/Math/Config.hpp>
#include <Nazara/Math/EulerAngles.hpp>
#include <Nazara/Math/Vector3.hpp>
#include <limits>
#include <Nazara/Core/Debug.hpp>
#define F(a) static_cast<T>(a)
template<typename T>
NzQuaternion<T>::NzQuaternion()
{
}
template<typename T>
NzQuaternion<T>::NzQuaternion(T W, T X, T Y, T Z)
{
Set(W, X, Y, Z);
}
template<typename T>
NzQuaternion<T>::NzQuaternion(T quat[4])
{
Set(quat);
}
template<typename T>
NzQuaternion<T>::NzQuaternion(T angle, const NzVector3<T>& axis)
{
Set(angle, axis);
}
template<typename T>
NzQuaternion<T>::NzQuaternion(const NzEulerAngles<T>& angles)
{
Set(angles);
}
/*
template<typename T>
NzQuaternion<T>::NzQuaternion(const NzMatrix3<T>& mat)
{
Set(mat);
}
*/
template<typename T>
template<typename U>
NzQuaternion<T>::NzQuaternion(const NzQuaternion<U>& quat)
{
Set(quat);
}
template<typename T>
T NzQuaternion<T>::DotProduct(const NzQuaternion& quat) const
{
return w*quat.w + x*quat.x + y*quat.y + z*quat.z;
}
template<typename T>
NzQuaternion<T> NzQuaternion<T>::GetConjugate() const
{
return NzQuaternion(w, -x, -y, -z);
}
template<typename T>
NzQuaternion<T> NzQuaternion<T>::GetInverse() const
{
NzQuaternion<T> quat(*this);
quat.Inverse();
return quat;
}
template<typename T>
NzQuaternion<T> NzQuaternion<T>::GetNormal() const
{
NzQuaternion<T> quat(*this);
quat.Normalize();
return quat;
}
template<typename T>
void NzQuaternion<T>::Inverse()
{
T norm = SquaredMagnitude();
if (norm > F(0.0))
{
T invNorm = F(1.0) / norm;
w *= invNorm;
x *= -invNorm;
y *= -invNorm;
z *= -invNorm;
}
}
template<typename T>
void NzQuaternion<T>::MakeIdentity()
{
Set(F(1.0), F(0.0), F(0.0), F(0.0));
}
template<typename T>
void NzQuaternion<T>::MakeZero()
{
Set(F(0.0), F(0.0), F(0.0), F(0.0));
}
template<typename T>
T NzQuaternion<T>::Magnitude() const
{
return std::sqrt(SquaredMagnitude());
}
template<typename T>
T NzQuaternion<T>::Normalize()
{
T squaredMagnitude = SquaredMagnitude();
// Inutile de vérifier si la magnitude au carrée est négative (Elle ne peut pas l'être)
if (!NzNumberEquals(squaredMagnitude, F(1.0)))
{
T norm = std::sqrt(squaredMagnitude);
T invNorm = F(1.0) / norm;
w *= invNorm;
x *= invNorm;
y *= invNorm;
z *= invNorm;
return norm;
}
else
return F(1.0); // Le quaternion est déjà normalisé
}
template<typename T>
void NzQuaternion<T>::Set(T W, T X, T Y, T Z)
{
w = W;
x = X;
y = Y;
z = Z;
}
template<typename T>
void NzQuaternion<T>::Set(T quat[4])
{
w = quat[0];
x = quat[1];
y = quat[2];
z = quat[3];
}
template<typename T>
void NzQuaternion<T>::Set(T angle, const NzVector3<T>& axis)
{
angle /= F(2.0);
#if !NAZARA_MATH_ANGLE_RADIAN
angle = NzDegreeToRadian(angle);
#endif
NzVector3<T> normalizedAxis = axis.GetNormal();
T sinAngle = std::sin(angle);
w = std::cos(angle);
x = normalizedAxis.x * sinAngle;
y = normalizedAxis.y * sinAngle;
z = normalizedAxis.z * sinAngle;
Normalize();
}
template<typename T>
void NzQuaternion<T>::Set(const NzEulerAngles<T>& angles)
{
Set(angles.ToQuaternion());
}
template<typename T>
template<typename U>
void NzQuaternion<T>::Set(const NzQuaternion<U>& quat)
{
w = static_cast<T>(quat.w);
x = static_cast<T>(quat.x);
y = static_cast<T>(quat.y);
z = static_cast<T>(quat.z);
}
template<typename T>
void NzQuaternion<T>::Set(const NzQuaternion& quat)
{
w = quat.w;
x = quat.x;
y = quat.y;
z = quat.z;
}
template<typename T>
T NzQuaternion<T>::SquaredMagnitude() const
{
return w*w + x*x + y*y + z*z;
}
template<typename T>
NzEulerAngles<T> NzQuaternion<T>::ToEulerAngles() const
{
T test = x*y + z*w;
if (test > F(0.499))
// singularity at north pole
return NzEulerAngles<T>(NzDegrees(F(90.0)), NzRadians(F(2.0) * std::atan2(x, w)), F(0.0));
if (test < F(-0.499))
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)),
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)),
NzRadians(std::asin(F(2.0)*test)));
}
template<typename T>
NzString NzQuaternion<T>::ToString() const
{
NzStringStream ss;
return ss << "Quaternion(" << w << " | " << x << ", " << y << ", " << z << ')';
}
template<typename T>
NzQuaternion<T>::operator NzString() const
{
return ToString();
}
template<typename T>
NzQuaternion<T>& NzQuaternion<T>::operator=(const NzQuaternion& quat)
{
Set(quat);
return *this;
}
template<typename T>
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>
NzQuaternion<T> NzQuaternion<T>::operator*(const NzQuaternion& quat) const
{
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,
w*quat.y + y*quat.w + z*quat.x - x*quat.z,
w*quat.z + z*quat.w + x*quat.y - y*quat.x);
}
template<typename T>
NzVector3<T> NzQuaternion<T>::operator*(const NzVector3<T>& vec) const
{
NzVector3f quatVec(x, y, z);
NzVector3f uv = quatVec.CrossProduct(vec);
NzVector3f uuv = quatVec.CrossProduct(uv);
uv *= F(2.0) * w;
uuv *= F(2.0);
return vec + uv + uuv;
}
template<typename T>
NzQuaternion<T> NzQuaternion<T>::operator*(T scale) const
{
return NzQuaternion(w * scale,
x * scale,
y * scale,
z * scale);
}
template<typename T>
NzQuaternion<T> NzQuaternion<T>::operator/(const NzQuaternion& quat) const
{
return GetConjugate(quat) * (*this);
}
template<typename T>
NzQuaternion<T>& NzQuaternion<T>::operator+=(const NzQuaternion& quat)
{
return operator=(operator+(quat));
}
template<typename T>
NzQuaternion<T>& NzQuaternion<T>::operator*=(const NzQuaternion& quat)
{
return operator=(operator*(quat));
}
template<typename T>
NzQuaternion<T>& NzQuaternion<T>::operator*=(T scale)
{
return operator=(operator*(scale));
}
template<typename T>
NzQuaternion<T>& NzQuaternion<T>::operator/=(const NzQuaternion& quat)
{
return operator=(operator/(quat));
}
template<typename T>
bool NzQuaternion<T>::operator==(const NzQuaternion& quat) const
{
return NzNumberEquals(w, quat.w) &&
NzNumberEquals(x, quat.x) &&
NzNumberEquals(y, quat.y) &&
NzNumberEquals(z, quat.z);
}
template<typename T>
bool NzQuaternion<T>::operator!=(const NzQuaternion& quat) const
{
return !operator==(quat);
}
template<typename T>
bool NzQuaternion<T>::operator<(const NzQuaternion& quat) const
{
return w < quat.w && x < quat.x && y < quat.y && z < quat.z;
}
template<typename T>
bool NzQuaternion<T>::operator<=(const NzQuaternion& quat) const
{
return operator<(quat) || operator==(quat);
}
template<typename T>
bool NzQuaternion<T>::operator>(const NzQuaternion& quat) const
{
return !operator<=(quat);
}
template<typename T>
bool NzQuaternion<T>::operator>=(const NzQuaternion& quat) const
{
return !operator<(quat);
}
template<typename T>
NzQuaternion<T> NzQuaternion<T>::Identity()
{
NzQuaternion quaternion;
quaternion.MakeIdentity();
return quaternion;
}
template<typename T>
NzQuaternion<T> NzQuaternion<T>::Slerp(const NzQuaternion& quatA, const NzQuaternion& quatB, T interp)
{
if (interp <= F(0.0))
return quatA;
if (interp >= F(1.0))
return quatB;
NzQuaternion q;
T cosOmega = quatA.DotProduct(quatB);
if (cosOmega < F(0.0))
{
// On inverse tout
q.Set(-quatB.w, -quatB.x, -quatB.y, -quatB.z);
cosOmega = -cosOmega;
}
else
q.Set(quatB);
T k0, k1;
if (cosOmega > F(0.9999))
{
// Interpolation linéaire pour éviter une division par zéro
k0 = F(1.0) - interp;
k1 = interp;
}
else
{
T sinOmega = std::sqrt(F(1.0) - cosOmega*cosOmega);
T omega = std::atan2(sinOmega, cosOmega);
// Pour éviter deux divisions
sinOmega = F(1.0)/sinOmega;
k0 = std::sin((F(1.0) - 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
// This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_VECTOR2_HPP
#define NAZARA_VECTOR2_HPP
#include <Nazara/Core/String.hpp>
template<typename T> class NzVector2
{
public:
NzVector2();
NzVector2(T X, T Y);
explicit NzVector2(T scale);
NzVector2(T vec[2]);
template<typename U> explicit NzVector2(const NzVector2<U>& vec);
NzVector2(const NzVector2& vec) = default;
~NzVector2() = default;
T AbsDotProduct(const NzVector2& vec) const;
T Distance(const NzVector2& vec) const;
float Distancef(const NzVector2& vec) const;
T DotProduct(const NzVector2& vec) const;
NzVector2 GetNormal() const;
void MakeCeil(const NzVector2& vec);
void MakeFloor(const NzVector2& vec);
void MakeUnitX();
void MakeUnitY();
void MakeZero();
T Length() const;
float Lengthf() const;
void Normalize();
void Set(T X, T Y);
void Set(T scale);
void Set(T vec[2]);
template<typename U> void Set(const NzVector2<U>& vec);
T SquaredDistance(const NzVector2& vec) const;
T SquaredLength() const;
NzString ToString() const;
operator NzString() const;
operator T*();
operator const T*() const;
T& operator[](unsigned int i);
T operator[](unsigned int i) 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*(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*=(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;
static NzVector2 UnitX();
static NzVector2 UnitY();
static NzVector2 Zero();
T x, y;
};
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);
typedef NzVector2<double> NzVector2d;
typedef NzVector2<float> NzVector2f;
typedef NzVector2<int> NzVector2i;
typedef NzVector2<unsigned int> NzVector2ui;
#include <Nazara/Math/Vector2.inl>
#endif // NAZARA_VECTOR2_HPP
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_VECTOR2_HPP
#define NAZARA_VECTOR2_HPP
#include <Nazara/Core/String.hpp>
template<typename T> class NzVector2
{
public:
NzVector2();
NzVector2(T X, T Y);
explicit NzVector2(T scale);
NzVector2(T vec[2]);
template<typename U> explicit NzVector2(const NzVector2<U>& vec);
NzVector2(const NzVector2& vec) = default;
~NzVector2() = default;
T AbsDotProduct(const NzVector2& vec) const;
T Distance(const NzVector2& vec) const;
float Distancef(const NzVector2& vec) const;
T DotProduct(const NzVector2& vec) const;
NzVector2 GetNormal() const;
T Length() const;
float Lengthf() const;
void MakeUnitX();
void MakeUnitY();
void MakeZero();
void Maximize(const NzVector2& vec);
void Minimize(const NzVector2& vec);
void Normalize();
void Set(T X, T Y);
void Set(T scale);
void Set(T vec[2]);
template<typename U> void Set(const NzVector2<U>& vec);
T SquaredDistance(const NzVector2& vec) const;
T SquaredLength() const;
NzString ToString() const;
operator NzString() const;
operator T*();
operator const T*() const;
T& operator[](unsigned int i);
T operator[](unsigned int i) 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*(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*=(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;
static NzVector2 UnitX();
static NzVector2 UnitY();
static NzVector2 Zero();
T x, y;
};
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);
typedef NzVector2<double> NzVector2d;
typedef NzVector2<float> NzVector2f;
typedef NzVector2<int> NzVector2i;
typedef NzVector2<unsigned int> NzVector2ui;
#include <Nazara/Math/Vector2.inl>
#endif // NAZARA_VECTOR2_HPP

View File

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

View File

@ -1,111 +1,121 @@
// Copyright (C) 2012 Rémi Bèges - Jérôme Leclercq
// This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_VECTOR3_HPP
#define NAZARA_VECTOR3_HPP
#include <Nazara/Core/String.hpp>
#include <Nazara/Math/Vector2.hpp>
template<typename T> class NzVector3
{
public:
NzVector3();
NzVector3(T X, T Y, T Z);
explicit NzVector3(T scale);
NzVector3(T vec[3]);
NzVector3(const NzVector2<T>& vec, T Z = 0.0);
template<typename U> explicit NzVector3(const NzVector3<U>& vec);
NzVector3(const NzVector3& vec) = default;
~NzVector3() = default;
T AbsDotProduct(const NzVector3& vec) const;
NzVector3 CrossProduct(const NzVector3& vec) const;
T Distance(const NzVector3& vec) const;
float Distancef(const NzVector3& vec) const;
T DotProduct(const NzVector3& vec) const;
NzVector3 GetNormal() const;
T Length() const;
float Lengthf() const;
void MakeCeil(const NzVector3& vec);
void MakeFloor(const NzVector3& vec);
void MakeUnitX();
void MakeUnitY();
void MakeUnitZ();
void MakeZero();
void Normalize();
void Set(T X, T Y, T Z);
void Set(T scale);
void Set(T vec[3]);
void Set(const NzVector2<T>& vec, T Z = 0.0);
template<typename U> void Set(const NzVector3<U>& vec);
T SquaredDistance(const NzVector3& vec) const;
T SquaredLength() const;
NzString ToString() const;
operator NzString() const;
operator T*();
operator const T*() const;
T& operator[](unsigned int i);
T operator[](unsigned int i) const;
const NzVector3& operator+() const;
NzVector3 operator-() const;
NzVector3 operator+(const NzVector3& vec) 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/(T scale) const;
NzVector3& operator+=(const NzVector3& vec);
NzVector3& operator-=(const NzVector3& vec);
NzVector3& operator*=(const NzVector3& vec);
NzVector3& operator*=(T scale);
NzVector3& operator/=(const NzVector3& vec);
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();
static NzVector3 UnitY();
static NzVector3 UnitZ();
static NzVector3 Zero();
T x, y, z;
};
template<typename T> std::ostream& operator<<(std::ostream& out, const NzVector3<T>& vec);
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
// Copyright (C) 2012 Rémi Bèges - Jérôme Leclercq
// This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_VECTOR3_HPP
#define NAZARA_VECTOR3_HPP
#include <Nazara/Core/String.hpp>
#include <Nazara/Math/Vector2.hpp>
template<typename T> class NzVector3
{
public:
NzVector3();
NzVector3(T X, T Y, T Z);
explicit NzVector3(T scale);
NzVector3(T vec[3]);
NzVector3(const NzVector2<T>& vec, T Z = 0.0);
template<typename U> explicit NzVector3(const NzVector3<U>& vec);
NzVector3(const NzVector3& vec) = default;
~NzVector3() = default;
T AbsDotProduct(const NzVector3& vec) const;
NzVector3 CrossProduct(const NzVector3& vec) const;
T Distance(const NzVector3& vec) const;
float Distancef(const NzVector3& vec) const;
T DotProduct(const NzVector3& vec) const;
NzVector3 GetNormal() const;
T Length() const;
float Lengthf() const;
void MakeForward();
void MakeLeft();
void MakeUnitX();
void MakeUnitY();
void MakeUnitZ();
void MakeUp();
void MakeZero();
void Maximize(const NzVector3& vec);
void Minimize(const NzVector3& vec);
void Normalize();
void Set(T X, T Y, T Z);
void Set(T scale);
void Set(T vec[3]);
void Set(const NzVector2<T>& vec, T Z = 0.0);
template<typename U> void Set(const NzVector3<U>& vec);
T SquaredDistance(const NzVector3& vec) const;
T SquaredLength() const;
NzString ToString() const;
operator NzString() const;
operator T*();
operator const T*() const;
T& operator[](unsigned int i);
T operator[](unsigned int i) const;
const NzVector3& operator+() const;
NzVector3 operator-() const;
NzVector3 operator+(const NzVector3& vec) 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/(T scale) const;
NzVector3& operator+=(const NzVector3& vec);
NzVector3& operator-=(const NzVector3& vec);
NzVector3& operator*=(const NzVector3& vec);
NzVector3& operator*=(T scale);
NzVector3& operator/=(const NzVector3& vec);
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 CrossProduct(const NzVector3& vec1, const NzVector3& vec2);
static T DotProduct(const NzVector3& vec1, const NzVector3& vec2);
static NzVector3 Forward();
static NzVector3 Left();
static NzVector3 Normalize(const NzVector3& vec);
static NzVector3 UnitX();
static NzVector3 UnitY();
static NzVector3 UnitZ();
static NzVector3 Up();
static NzVector3 Zero();
T x, y, z;
};
template<typename T> std::ostream& operator<<(std::ostream& out, const NzVector3<T>& vec);
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
// This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_VECTOR4_HPP
#define NAZARA_VECTOR4_HPP
#include <Nazara/Core/String.hpp>
#include <Nazara/Math/Vector3.hpp>
template<typename T> class NzVector4
{
public:
NzVector4();
NzVector4(T X, T Y, T Z, T W = 1.0);
explicit NzVector4(T scale);
NzVector4(T vec[4]);
NzVector4(const NzVector3<T>& vec, T W = 1.0);
template<typename U> explicit NzVector4(const NzVector4<U>& vec);
NzVector4(const NzVector4& vec) = default;
~NzVector4() = default;
T AbsDotProduct(const NzVector4& vec) const;
T DotProduct(const NzVector4& vec) const;
void MakeCeil(const NzVector4& vec);
void MakeFloor(const NzVector4& vec);
void MakeUnitX();
void MakeUnitY();
void MakeUnitZ();
void MakeZero();
void Normalize();
void Set(T X, T Y, T Z, T W = 1.0);
void Set(T scale);
void Set(T vec[4]);
void Set(const NzVector3<T>& vec, T W = 1.0);
template<typename U> void Set(const NzVector4<U>& vec);
NzString ToString() const;
operator NzString() const;
operator T*();
operator const T*() const;
T& operator[](unsigned int i);
T operator[](unsigned int i) 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*(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*=(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;
static NzVector4 UnitX();
static NzVector4 UnitY();
static NzVector4 UnitZ();
static NzVector4 Zero();
T x, y, z, w;
};
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);
typedef NzVector4<double> NzVector4d;
typedef NzVector4<float> NzVector4f;
typedef NzVector4<int> NzVector4i;
#include <Nazara/Math/Vector4.inl>
#endif // NAZARA_VECTOR4_HPP
// Copyright (C) 2012 Rémi Bèges - Jérôme Leclercq
// This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_VECTOR4_HPP
#define NAZARA_VECTOR4_HPP
#include <Nazara/Core/String.hpp>
#include <Nazara/Math/Vector3.hpp>
template<typename T> class NzVector4
{
public:
NzVector4();
NzVector4(T X, T Y, T Z, T W = 1.0);
explicit NzVector4(T scale);
NzVector4(T vec[4]);
NzVector4(const NzVector3<T>& vec, T W = 1.0);
template<typename U> explicit NzVector4(const NzVector4<U>& vec);
NzVector4(const NzVector4& vec) = default;
~NzVector4() = default;
T AbsDotProduct(const NzVector4& vec) const;
T DotProduct(const NzVector4& vec) const;
void MakeUnitX();
void MakeUnitY();
void MakeUnitZ();
void MakeZero();
void Maximize(const NzVector4& vec);
void Minimize(const NzVector4& vec);
void Normalize();
void Set(T X, T Y, T Z, T W = 1.0);
void Set(T scale);
void Set(T vec[4]);
void Set(const NzVector3<T>& vec, T W = 1.0);
template<typename U> void Set(const NzVector4<U>& vec);
NzString ToString() const;
operator NzString() const;
operator T*();
operator const T*() const;
T& operator[](unsigned int i);
T operator[](unsigned int i) 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*(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*=(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;
static NzVector4 UnitX();
static NzVector4 UnitY();
static NzVector4 UnitZ();
static NzVector4 Zero();
T x, y, z, w;
};
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);
typedef NzVector4<double> NzVector4d;
typedef NzVector4<float> NzVector4f;
typedef NzVector4<int> NzVector4i;
#include <Nazara/Math/Vector4.inl>
#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
/*
Nazara Engine - Renderer module
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
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
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
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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
SOFTWARE.
*/
#pragma once
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <Nazara/Renderer/ContextParameters.hpp>
#include <Nazara/Renderer/Enums.hpp>
#include <Nazara/Renderer/OcclusionQuery.hpp>
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/RenderTarget.hpp>
#include <Nazara/Renderer/RenderTargetParameters.hpp>
#include <Nazara/Renderer/RenderWindow.hpp>
#include <Nazara/Renderer/Shader.hpp>
#include <Nazara/Renderer/Texture.hpp>
// This file was automatically generated by Nazara
/*
Nazara Engine - Renderer module
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
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
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
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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
SOFTWARE.
*/
#pragma once
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <Nazara/Renderer/ContextParameters.hpp>
#include <Nazara/Renderer/Enums.hpp>
#include <Nazara/Renderer/OcclusionQuery.hpp>
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/RenderTarget.hpp>
#include <Nazara/Renderer/RenderTargetParameters.hpp>
#include <Nazara/Renderer/RenderTexture.hpp>
#include <Nazara/Renderer/RenderWindow.hpp>
#include <Nazara/Renderer/Shader.hpp>
#include <Nazara/Renderer/Texture.hpp>

View File

@ -1,44 +1,41 @@
/*
Nazara Engine - Renderer module
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
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
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
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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
SOFTWARE.
*/
#pragma once
#ifndef NAZARA_CONFIG_RENDERER_HPP
#define NAZARA_CONFIG_RENDERER_HPP
/// 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
#define NAZARA_RENDERER_ACTIVATE_RENDERWINDOW_ON_CREATION 1
// Utilise un tracker pour repérer les éventuels leaks (Ralentit l'exécution)
#define NAZARA_RENDERER_MEMORYLEAKTRACKER 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)
#define NAZARA_RENDERER_OPENGL_DEBUG 0
// Active les tests de sécurité basés sur le code (Conseillé pour le développement)
#define NAZARA_RENDERER_SAFE 1
#endif // NAZARA_CONFIG_MODULENAME_HPP
/*
Nazara Engine - Renderer module
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
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
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
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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
SOFTWARE.
*/
#pragma once
#ifndef NAZARA_CONFIG_RENDERER_HPP
#define NAZARA_CONFIG_RENDERER_HPP
/// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci
// Utilise un tracker pour repérer les éventuels leaks (Ralentit l'exécution)
#define NAZARA_RENDERER_MEMORYLEAKTRACKER 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)
#define NAZARA_RENDERER_OPENGL_DEBUG 0
// Active les tests de sécurité basés sur le code (Conseillé pour le développement)
#define NAZARA_RENDERER_SAFE 1
#endif // NAZARA_CONFIG_MODULENAME_HPP

View File

@ -1,47 +1,49 @@
// 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
#ifdef NAZARA_RENDERER_COMMON
#error This file is not part of the common renderer interface, you must undefine NAZARA_RENDERER_COMMON to use it
#endif
#pragma once
#ifndef NAZARA_CONTEXT_HPP
#define NAZARA_CONTEXT_HPP
#include <Nazara/Renderer/ContextParameters.hpp>
class NzContextImpl;
class NAZARA_API NzContext
{
friend NzContextImpl;
public:
NzContext();
~NzContext();
bool Create(const NzContextParameters& parameters = NzContextParameters());
void Destroy();
const NzContextParameters& GetParameters() const;
bool IsActive() const;
bool SetActive(bool active);
void SwapBuffers();
static bool EnsureContext();
static NzContext* GetCurrent();
static const NzContext* GetReference();
static NzContext* GetThreadContext();
static bool Initialize();
static void Uninitialize();
private:
NzContextParameters m_parameters;
NzContextImpl* m_impl;
static NzContext* s_reference;
};
#endif // NAZARA_CONTEXT_HPP
// 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_CONTEXT_HPP
#define NAZARA_CONTEXT_HPP
#ifdef NAZARA_RENDERER_OPENGL
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Renderer/ContextParameters.hpp>
class NzContextImpl;
class NAZARA_API NzContext : public NzResource
{
friend NzContextImpl;
public:
NzContext();
~NzContext();
bool Create(const NzContextParameters& parameters = NzContextParameters());
void Destroy();
const NzContextParameters& GetParameters() const;
bool IsActive() const;
bool SetActive(bool active);
void SwapBuffers();
static bool EnsureContext();
static NzContext* GetCurrent();
static const NzContext* GetReference();
static NzContext* GetThreadContext();
static bool Initialize();
static void Uninitialize();
private:
NzContextParameters m_parameters;
NzContextImpl* m_impl;
static NzContext* s_reference;
};
#endif // NAZARA_RENDERER_OPENGL
#endif // NAZARA_CONTEXT_HPP

View File

@ -1,141 +1,174 @@
// 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_ENUMS_RENDERER_HPP
#define NAZARA_ENUMS_RENDERER_HPP
enum nzBlendFunc
{
nzBlendFunc_DestAlpha,
nzBlendFunc_DestColor,
nzBlendFunc_SrcAlpha,
nzBlendFunc_SrcColor,
nzBlendFunc_InvDestAlpha,
nzBlendFunc_InvDestColor,
nzBlendFunc_InvSrcAlpha,
nzBlendFunc_InvSrcColor,
nzBlendFunc_One,
nzBlendFunc_Zero
};
enum nzFaceCulling
{
nzFaceCulling_Back,
nzFaceCulling_Front,
nzFaceCulling_FrontAndBack
};
enum nzFaceFilling
{
nzFaceFilling_Point,
nzFaceFilling_Line,
nzFaceFilling_Fill
};
enum nzMatrixType
{
nzMatrixType_Projection,
nzMatrixType_View,
nzMatrixType_World,
nzMatrixType_Max = nzMatrixType_World
};
enum nzPixelBufferType
{
nzPixelBufferType_Pack,
nzPixelBufferType_Unpack
};
enum nzRendererCap
{
nzRendererCap_AnisotropicFilter,
nzRendererCap_FP64,
nzRendererCap_HardwareBuffer,
nzRendererCap_MultipleRenderTargets,
nzRendererCap_OcclusionQuery,
nzRendererCap_PixelBufferObject,
nzRendererCap_Texture3D,
nzRendererCap_TextureCubemap,
nzRendererCap_TextureMulti,
nzRendererCap_TextureNPOT,
nzRendererCap_Max = nzRendererCap_TextureNPOT
};
enum nzRendererClear
{
nzRendererClear_Color = 0x01,
nzRendererClear_Depth = 0x02,
nzRendererClear_Stencil = 0x04
};
enum nzRendererComparison
{
nzRendererComparison_Always,
nzRendererComparison_Equal,
nzRendererComparison_Greater,
nzRendererComparison_GreaterOrEqual,
nzRendererComparison_Less,
nzRendererComparison_LessOrEqual,
nzRendererComparison_Never
};
enum nzRendererParameter
{
nzRendererParameter_Blend,
nzRendererParameter_ColorWrite,
nzRendererParameter_DepthTest,
nzRendererParameter_DepthWrite,
nzRendererParameter_FaceCulling,
nzRendererParameter_Stencil
};
enum nzShaderLanguage
{
nzShaderLanguage_Unknown,
nzShaderLanguage_Cg,
nzShaderLanguage_GLSL
};
enum nzShaderType
{
nzShaderType_Fragment,
nzShaderType_Geometry,
nzShaderType_Vertex,
nzShaderType_Max = nzShaderType_Vertex
};
enum nzStencilOperation
{
nzStencilOperation_Decrement,
nzStencilOperation_DecrementToSaturation,
nzStencilOperation_Increment,
nzStencilOperation_IncrementToSaturation,
nzStencilOperation_Invert,
nzStencilOperation_Keep,
nzStencilOperation_Replace,
nzStencilOperation_Zero
};
enum nzTextureFilter
{
nzTextureFilter_Bilinear,
nzTextureFilter_Nearest,
nzTextureFilter_Trilinear,
nzTextureFilter_Unknown
};
enum nzTextureWrap
{
nzTextureWrap_Clamp,
nzTextureWrap_Repeat,
nzTextureWrap_Unknown
};
#endif // NAZARA_ENUMS_RENDERER_HPP
// 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_ENUMS_RENDERER_HPP
#define NAZARA_ENUMS_RENDERER_HPP
enum nzAttachmentPoint
{
nzAttachmentPoint_Color,
nzAttachmentPoint_Depth,
nzAttachmentPoint_DepthStencil,
nzAttachmentPoint_Stencil,
nzAttachmentPoint_Max = nzAttachmentPoint_Stencil
};
enum nzBlendFunc
{
nzBlendFunc_DestAlpha,
nzBlendFunc_DestColor,
nzBlendFunc_SrcAlpha,
nzBlendFunc_SrcColor,
nzBlendFunc_InvDestAlpha,
nzBlendFunc_InvDestColor,
nzBlendFunc_InvSrcAlpha,
nzBlendFunc_InvSrcColor,
nzBlendFunc_One,
nzBlendFunc_Zero,
nzBlendFunc_Max = nzBlendFunc_Zero
};
enum nzFaceCulling
{
nzFaceCulling_Back,
nzFaceCulling_Front,
nzFaceCulling_FrontAndBack,
nzFaceCulling_Max = nzFaceCulling_FrontAndBack
};
enum nzFaceFilling
{
nzFaceFilling_Point,
nzFaceFilling_Line,
nzFaceFilling_Fill,
nzFaceFilling_Max = nzFaceFilling_Fill
};
enum nzMatrixType
{
nzMatrixType_Projection,
nzMatrixType_View,
nzMatrixType_World,
nzMatrixType_Max = nzMatrixType_World
};
enum nzPixelBufferType
{
nzPixelBufferType_Pack,
nzPixelBufferType_Unpack,
nzPixelBufferType_Max = nzPixelBufferType_Unpack
};
enum nzRendererCap
{
nzRendererCap_AnisotropicFilter,
nzRendererCap_FP64,
nzRendererCap_HardwareBuffer,
nzRendererCap_MultipleRenderTargets,
nzRendererCap_OcclusionQuery,
nzRendererCap_PixelBufferObject,
nzRendererCap_RenderTexture,
nzRendererCap_Texture3D,
nzRendererCap_TextureCubemap,
nzRendererCap_TextureMulti,
nzRendererCap_TextureNPOT,
nzRendererCap_Max = nzRendererCap_TextureNPOT
};
enum nzRendererClearFlags
{
nzRendererClear_Color = 0x01,
nzRendererClear_Depth = 0x02,
nzRendererClear_Stencil = 0x04
};
enum nzRendererComparison
{
nzRendererComparison_Always,
nzRendererComparison_Equal,
nzRendererComparison_Greater,
nzRendererComparison_GreaterOrEqual,
nzRendererComparison_Less,
nzRendererComparison_LessOrEqual,
nzRendererComparison_Never,
nzRendererComparison_Max = nzRendererComparison_Never
};
enum nzRendererParameter
{
nzRendererParameter_Blend,
nzRendererParameter_ColorWrite,
nzRendererParameter_DepthTest,
nzRendererParameter_DepthWrite,
nzRendererParameter_FaceCulling,
nzRendererParameter_Stencil,
nzRendererParameter_Max = nzRendererParameter_Stencil
};
enum nzShaderLanguage
{
nzShaderLanguage_Unknown = -1,
nzShaderLanguage_Cg,
nzShaderLanguage_GLSL,
nzShaderLanguage_Max = nzShaderLanguage_GLSL
};
enum nzShaderType
{
nzShaderType_Fragment,
nzShaderType_Geometry,
nzShaderType_Vertex,
nzShaderType_Max = nzShaderType_Vertex
};
enum nzStencilOperation
{
nzStencilOperation_Decrement,
nzStencilOperation_DecrementToSaturation,
nzStencilOperation_Increment,
nzStencilOperation_IncrementToSaturation,
nzStencilOperation_Invert,
nzStencilOperation_Keep,
nzStencilOperation_Replace,
nzStencilOperation_Zero,
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
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#ifdef NAZARA_RENDERER_COMMON
#error This file is not part of the common renderer interface, you must undefine NAZARA_RENDERER_COMMON to use it
#endif
#pragma once
#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>
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/String.hpp>
// Inclusion des extensions
#include <GL3/glext.h>
#if defined(NAZARA_PLATFORM_WINDOWS)
#include <GL3/wglext.h>
#elif defined(NAZARA_PLATFORM_LINUX)
#include <GL3/glxext.h>
#endif
using NzOpenGLFunc = void (*)();
class NAZARA_API NzOpenGL
{
public:
enum Extension
{
AnisotropicFilter,
DebugOutput,
FP64,
FrameBufferObject,
PixelBufferObject,
SeparateShaderObjects,
Texture3D,
TextureArray,
TextureCompression_s3tc,
TextureStorage,
VertexArrayObject,
Max = VertexArrayObject
};
static NzOpenGLFunc GetEntry(const NzString& entryPoint);
static unsigned int GetVersion();
static bool Initialize();
static bool IsSupported(Extension extension);
static bool IsSupported(const NzString& string);
static void Uninitialize();
};
NAZARA_API extern PFNGLACTIVETEXTUREPROC glActiveTexture;
NAZARA_API extern PFNGLATTACHSHADERPROC glAttachShader;
NAZARA_API extern PFNGLBEGINQUERYPROC glBeginQuery;
NAZARA_API extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
NAZARA_API extern PFNGLBINDBUFFERPROC glBindBuffer;
NAZARA_API extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
NAZARA_API extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
NAZARA_API extern PFNGLBINDTEXTUREPROC glBindTexture;
NAZARA_API extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
NAZARA_API extern PFNGLBLENDFUNCPROC glBlendFunc;
NAZARA_API extern PFNGLBUFFERDATAPROC glBufferData;
NAZARA_API extern PFNGLBUFFERSUBDATAPROC glBufferSubData;
NAZARA_API extern PFNGLCLEARPROC glClear;
NAZARA_API extern PFNGLCLEARCOLORPROC glClearColor;
NAZARA_API extern PFNGLCLEARDEPTHPROC glClearDepth;
NAZARA_API extern PFNGLCLEARSTENCILPROC glClearStencil;
NAZARA_API extern PFNGLCREATEPROGRAMPROC glCreateProgram;
NAZARA_API extern PFNGLCREATESHADERPROC glCreateShader;
NAZARA_API extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
NAZARA_API extern PFNGLCOLORMASKPROC glColorMask;
NAZARA_API extern PFNGLCULLFACEPROC glCullFace;
NAZARA_API extern PFNGLCOMPILESHADERPROC glCompileShader;
NAZARA_API extern PFNGLCOPYTEXSUBIMAGE2DPROC glCopyTexSubImage2D;
NAZARA_API extern PFNGLDEBUGMESSAGECALLBACKPROC glDebugMessageCallback;
NAZARA_API extern PFNGLDEBUGMESSAGECONTROLPROC glDebugMessageControl;
NAZARA_API extern PFNGLDEBUGMESSAGEINSERTPROC glDebugMessageInsert;
NAZARA_API extern PFNGLDELETEBUFFERSPROC glDeleteBuffers;
NAZARA_API extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
NAZARA_API extern PFNGLDELETEPROGRAMPROC glDeleteProgram;
NAZARA_API extern PFNGLDELETEQUERIESPROC glDeleteQueries;
NAZARA_API extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers;
NAZARA_API extern PFNGLDELETESHADERPROC glDeleteShader;
NAZARA_API extern PFNGLDELETETEXTURESPROC glDeleteTextures;
NAZARA_API extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
NAZARA_API extern PFNGLDEPTHFUNCPROC glDepthFunc;
NAZARA_API extern PFNGLDEPTHMASKPROC glDepthMask;
NAZARA_API extern PFNGLDISABLEPROC glDisable;
NAZARA_API extern PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
NAZARA_API extern PFNGLDRAWARRAYSPROC glDrawArrays;
NAZARA_API extern PFNGLDRAWBUFFERPROC glDrawBuffer;
NAZARA_API extern PFNGLDRAWBUFFERSPROC glDrawBuffers;
NAZARA_API extern PFNGLDRAWELEMENTSPROC glDrawElements;
NAZARA_API extern PFNGLENDQUERYPROC glEndQuery;
NAZARA_API extern PFNGLFLUSHPROC glFlush;
NAZARA_API extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
NAZARA_API extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
NAZARA_API extern PFNGLENABLEPROC glEnable;
NAZARA_API extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
NAZARA_API extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
NAZARA_API extern PFNGLGENBUFFERSPROC glGenBuffers;
NAZARA_API extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
NAZARA_API extern PFNGLGENQUERIESPROC glGenQueries;
NAZARA_API extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
NAZARA_API extern PFNGLGENTEXTURESPROC glGenTextures;
NAZARA_API extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
NAZARA_API extern PFNGLGETBUFFERPARAMETERIVPROC glGetBufferParameteriv;
NAZARA_API extern PFNGLGETDEBUGMESSAGELOGPROC glGetDebugMessageLog;
NAZARA_API extern PFNGLGETERRORPROC glGetError;
NAZARA_API extern PFNGLGETINTEGERVPROC glGetIntegerv;
NAZARA_API extern PFNGLGETPROGRAMIVPROC glGetProgramiv;
NAZARA_API extern PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
NAZARA_API extern PFNGLGETQUERYIVPROC glGetQueryiv;
NAZARA_API extern PFNGLGETQUERYOBJECTIVPROC glGetQueryObjectiv;
NAZARA_API extern PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectuiv;
NAZARA_API extern PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
NAZARA_API extern PFNGLGETSHADERIVPROC glGetShaderiv;
NAZARA_API extern PFNGLGETSHADERSOURCEPROC glGetShaderSource;
NAZARA_API extern PFNGLGETSTRINGPROC glGetString;
NAZARA_API extern PFNGLGETSTRINGIPROC glGetStringi;
NAZARA_API extern PFNGLGETTEXIMAGEPROC glGetTexImage;
NAZARA_API extern PFNGLGETTEXLEVELPARAMETERFVPROC glGetTexLevelParameterfv;
NAZARA_API extern PFNGLGETTEXLEVELPARAMETERIVPROC glGetTexLevelParameteriv;
NAZARA_API extern PFNGLGETTEXPARAMETERFVPROC glGetTexParameterfv;
NAZARA_API extern PFNGLGETTEXPARAMETERIVPROC glGetTexParameteriv;
NAZARA_API extern PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
NAZARA_API extern PFNGLLINKPROGRAMPROC glLinkProgram;
NAZARA_API extern PFNGLMAPBUFFERPROC glMapBuffer;
NAZARA_API extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
NAZARA_API extern PFNGLPIXELSTOREIPROC glPixelStorei;
NAZARA_API extern PFNGLPOLYGONMODEPROC glPolygonMode;
NAZARA_API extern PFNGLPROGRAMUNIFORM1DPROC glProgramUniform1d;
NAZARA_API extern PFNGLPROGRAMUNIFORM1FPROC glProgramUniform1f;
NAZARA_API extern PFNGLPROGRAMUNIFORM1IPROC glProgramUniform1i;
NAZARA_API extern PFNGLPROGRAMUNIFORM2DVPROC glProgramUniform2dv;
NAZARA_API extern PFNGLPROGRAMUNIFORM2FVPROC glProgramUniform2fv;
NAZARA_API extern PFNGLPROGRAMUNIFORM3DVPROC glProgramUniform3dv;
NAZARA_API extern PFNGLPROGRAMUNIFORM3FVPROC glProgramUniform3fv;
NAZARA_API extern PFNGLPROGRAMUNIFORM4DVPROC glProgramUniform4dv;
NAZARA_API extern PFNGLPROGRAMUNIFORM4FVPROC glProgramUniform4fv;
NAZARA_API extern PFNGLPROGRAMUNIFORMMATRIX4DVPROC glProgramUniformMatrix4dv;
NAZARA_API extern PFNGLPROGRAMUNIFORMMATRIX4FVPROC glProgramUniformMatrix4fv;
NAZARA_API extern PFNGLREADPIXELSPROC glReadPixels;
NAZARA_API extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
NAZARA_API extern PFNGLSCISSORPROC glScissor;
NAZARA_API extern PFNGLSHADERSOURCEPROC glShaderSource;
NAZARA_API extern PFNGLSTENCILFUNCPROC glStencilFunc;
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_OPENGL_HPP
// 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_OPENGL_HPP
#define NAZARA_OPENGL_HPP
#ifdef NAZARA_RENDERER_OPENGL
// 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>
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Utility/Enums.hpp>
#include <Nazara/Renderer/Enums.hpp>
// Inclusion des extensions
#include <GL3/glext.h>
#if defined(NAZARA_PLATFORM_WINDOWS)
#include <GL3/wglext.h>
#elif defined(NAZARA_PLATFORM_LINUX)
#include <GL3/glxext.h>
#endif
enum nzOpenGLExtension
{
nzOpenGLExtension_AnisotropicFilter,
nzOpenGLExtension_DebugOutput,
nzOpenGLExtension_FP64,
nzOpenGLExtension_FrameBufferObject,
nzOpenGLExtension_PixelBufferObject,
nzOpenGLExtension_SeparateShaderObjects,
nzOpenGLExtension_TextureArray,
nzOpenGLExtension_TextureCompression_s3tc,
nzOpenGLExtension_TextureStorage,
nzOpenGLExtension_VertexArrayObject,
nzOpenGLExtension_Max = nzOpenGLExtension_VertexArrayObject
};
using NzOpenGLFunc = void (*)();
namespace NzOpenGL
{
enum FormatType
{
FormatType_RenderBuffer,
// FormatType_MultisampleTexture,
FormatType_Texture
};
struct Format
{
GLenum dataFormat;
GLenum dataType;
GLint internalFormat;
};
NzOpenGLFunc GetEntry(const NzString& entryPoint);
unsigned int GetVersion();
bool Initialize();
bool IsSupported(nzOpenGLExtension extension);
bool IsSupported(const NzString& string);
bool TranslateFormat(nzPixelFormat pixelFormat, Format* format, FormatType target);
void Uninitialize();
extern GLenum Attachment[nzAttachmentPoint_Max+1];
extern nzUInt8 AttributeIndex[nzElementUsage_Max+1];
extern GLenum BlendFunc[nzBlendFunc_Max+1];
extern GLenum BufferLock[nzBufferAccess_Max+1];
extern GLenum BufferLockRange[nzBufferAccess_Max+1];
extern GLenum BufferTarget[nzBufferType_Max+1];
extern GLenum BufferTargetBinding[nzBufferType_Max+1];
extern GLenum BufferUsage[nzBufferUsage_Max+1];
extern GLenum CubemapFace[6]; // Un cube possède six faces et ça n'est pas prêt de changer
extern GLenum ElementType[nzElementType_Max+1];
extern GLenum FaceCulling[nzFaceCulling_Max+1];
extern GLenum FaceFilling[nzFaceFilling_Max+1];
extern GLenum PrimitiveType[nzPrimitiveType_Max+1];
extern GLenum RendererComparison[nzRendererComparison_Max+1];
extern GLenum RendererParameter[nzRendererParameter_Max+1];
extern GLenum ShaderType[nzShaderType_Max+1];
extern GLenum StencilOperation[nzStencilOperation_Max+1];
extern GLenum TextureTarget[nzImageType_Max+1];
extern GLenum TextureTargetBinding[nzImageType_Max+1];
extern GLenum TextureTargetProxy[nzImageType_Max+1];
}
NAZARA_API extern PFNGLACTIVETEXTUREPROC glActiveTexture;
NAZARA_API extern PFNGLATTACHSHADERPROC glAttachShader;
NAZARA_API extern PFNGLBEGINQUERYPROC glBeginQuery;
NAZARA_API extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
NAZARA_API extern PFNGLBINDBUFFERPROC glBindBuffer;
NAZARA_API extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
NAZARA_API extern PFNGLBINDFRAGDATALOCATIONPROC glBindFragDataLocation;
NAZARA_API extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
NAZARA_API extern PFNGLBINDTEXTUREPROC glBindTexture;
NAZARA_API extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
NAZARA_API extern PFNGLBLENDFUNCPROC glBlendFunc;
NAZARA_API extern PFNGLBUFFERDATAPROC glBufferData;
NAZARA_API extern PFNGLBUFFERSUBDATAPROC glBufferSubData;
NAZARA_API extern PFNGLCLEARPROC glClear;
NAZARA_API extern PFNGLCLEARCOLORPROC glClearColor;
NAZARA_API extern PFNGLCLEARDEPTHPROC glClearDepth;
NAZARA_API extern PFNGLCLEARSTENCILPROC glClearStencil;
NAZARA_API extern PFNGLCREATEPROGRAMPROC glCreateProgram;
NAZARA_API extern PFNGLCREATESHADERPROC glCreateShader;
NAZARA_API extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
NAZARA_API extern PFNGLCOLORMASKPROC glColorMask;
NAZARA_API extern PFNGLCULLFACEPROC glCullFace;
NAZARA_API extern PFNGLCOMPILESHADERPROC glCompileShader;
NAZARA_API extern PFNGLCOPYTEXSUBIMAGE2DPROC glCopyTexSubImage2D;
NAZARA_API extern PFNGLDEBUGMESSAGECALLBACKPROC glDebugMessageCallback;
NAZARA_API extern PFNGLDEBUGMESSAGECONTROLPROC glDebugMessageControl;
NAZARA_API extern PFNGLDEBUGMESSAGEINSERTPROC glDebugMessageInsert;
NAZARA_API extern PFNGLDELETEBUFFERSPROC glDeleteBuffers;
NAZARA_API extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
NAZARA_API extern PFNGLDELETEPROGRAMPROC glDeleteProgram;
NAZARA_API extern PFNGLDELETEQUERIESPROC glDeleteQueries;
NAZARA_API extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers;
NAZARA_API extern PFNGLDELETESHADERPROC glDeleteShader;
NAZARA_API extern PFNGLDELETETEXTURESPROC glDeleteTextures;
NAZARA_API extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
NAZARA_API extern PFNGLDEPTHFUNCPROC glDepthFunc;
NAZARA_API extern PFNGLDEPTHMASKPROC glDepthMask;
NAZARA_API extern PFNGLDISABLEPROC glDisable;
NAZARA_API extern PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
NAZARA_API extern PFNGLDRAWARRAYSPROC glDrawArrays;
NAZARA_API extern PFNGLDRAWBUFFERPROC glDrawBuffer;
NAZARA_API extern PFNGLDRAWBUFFERSPROC glDrawBuffers;
NAZARA_API extern PFNGLDRAWELEMENTSPROC glDrawElements;
NAZARA_API extern PFNGLENDQUERYPROC glEndQuery;
NAZARA_API extern PFNGLFLUSHPROC glFlush;
NAZARA_API extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
NAZARA_API extern PFNGLFRAMEBUFFERTEXTUREPROC glFramebufferTexture;
NAZARA_API extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D;
NAZARA_API extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
NAZARA_API extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D;
NAZARA_API extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
NAZARA_API extern PFNGLENABLEPROC glEnable;
NAZARA_API extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
NAZARA_API extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
NAZARA_API extern PFNGLGENBUFFERSPROC glGenBuffers;
NAZARA_API extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
NAZARA_API extern PFNGLGENQUERIESPROC glGenQueries;
NAZARA_API extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
NAZARA_API extern PFNGLGENTEXTURESPROC glGenTextures;
NAZARA_API extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
NAZARA_API extern PFNGLGETBUFFERPARAMETERIVPROC glGetBufferParameteriv;
NAZARA_API extern PFNGLGETDEBUGMESSAGELOGPROC glGetDebugMessageLog;
NAZARA_API extern PFNGLGETERRORPROC glGetError;
NAZARA_API extern PFNGLGETINTEGERVPROC glGetIntegerv;
NAZARA_API extern PFNGLGETPROGRAMIVPROC glGetProgramiv;
NAZARA_API extern PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
NAZARA_API extern PFNGLGETQUERYIVPROC glGetQueryiv;
NAZARA_API extern PFNGLGETQUERYOBJECTIVPROC glGetQueryObjectiv;
NAZARA_API extern PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectuiv;
NAZARA_API extern PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
NAZARA_API extern PFNGLGETSHADERIVPROC glGetShaderiv;
NAZARA_API extern PFNGLGETSHADERSOURCEPROC glGetShaderSource;
NAZARA_API extern PFNGLGETSTRINGPROC glGetString;
NAZARA_API extern PFNGLGETSTRINGIPROC glGetStringi;
NAZARA_API extern PFNGLGETTEXIMAGEPROC glGetTexImage;
NAZARA_API extern PFNGLGETTEXLEVELPARAMETERFVPROC glGetTexLevelParameterfv;
NAZARA_API extern PFNGLGETTEXLEVELPARAMETERIVPROC glGetTexLevelParameteriv;
NAZARA_API extern PFNGLGETTEXPARAMETERFVPROC glGetTexParameterfv;
NAZARA_API extern PFNGLGETTEXPARAMETERIVPROC glGetTexParameteriv;
NAZARA_API extern PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
NAZARA_API extern PFNGLLINKPROGRAMPROC glLinkProgram;
NAZARA_API extern PFNGLMAPBUFFERPROC glMapBuffer;
NAZARA_API extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
NAZARA_API extern PFNGLPIXELSTOREIPROC glPixelStorei;
NAZARA_API extern PFNGLPOLYGONMODEPROC glPolygonMode;
NAZARA_API extern PFNGLPROGRAMUNIFORM1DPROC glProgramUniform1d;
NAZARA_API extern PFNGLPROGRAMUNIFORM1FPROC glProgramUniform1f;
NAZARA_API extern PFNGLPROGRAMUNIFORM1IPROC glProgramUniform1i;
NAZARA_API extern PFNGLPROGRAMUNIFORM2DVPROC glProgramUniform2dv;
NAZARA_API extern PFNGLPROGRAMUNIFORM2FVPROC glProgramUniform2fv;
NAZARA_API extern PFNGLPROGRAMUNIFORM3DVPROC glProgramUniform3dv;
NAZARA_API extern PFNGLPROGRAMUNIFORM3FVPROC glProgramUniform3fv;
NAZARA_API extern PFNGLPROGRAMUNIFORM4DVPROC glProgramUniform4dv;
NAZARA_API extern PFNGLPROGRAMUNIFORM4FVPROC glProgramUniform4fv;
NAZARA_API extern PFNGLPROGRAMUNIFORMMATRIX4DVPROC glProgramUniformMatrix4dv;
NAZARA_API extern PFNGLPROGRAMUNIFORMMATRIX4FVPROC glProgramUniformMatrix4fv;
NAZARA_API extern PFNGLREADPIXELSPROC glReadPixels;
NAZARA_API extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
NAZARA_API extern PFNGLSCISSORPROC glScissor;
NAZARA_API extern PFNGLSHADERSOURCEPROC glShaderSource;
NAZARA_API extern PFNGLSTENCILFUNCPROC glStencilFunc;
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
// 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_RENDERTARGET_HPP
#define NAZARA_RENDERTARGET_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/RenderTargetParameters.hpp>
class NzRenderer;
class NAZARA_API NzRenderTarget
{
friend class NzRenderer;
public:
NzRenderTarget() = default;
virtual ~NzRenderTarget();
#ifndef NAZARA_RENDERER_COMMON
virtual bool HasContext() const = 0;
#endif
virtual unsigned int GetHeight() const = 0;
virtual NzRenderTargetParameters GetParameters() const = 0;
virtual unsigned int GetWidth() const = 0;
bool IsActive() const;
virtual bool IsValid() const = 0;
bool SetActive(bool active);
protected:
virtual bool Activate() = 0;
virtual void Desactivate();
};
#endif // NAZARA_RENDERTARGET_HPP
// 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_RENDERTARGET_HPP
#define NAZARA_RENDERTARGET_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/RenderTargetParameters.hpp>
class NzRenderer;
class NAZARA_API NzRenderTarget
{
friend class NzRenderer;
public:
NzRenderTarget() = default;
virtual ~NzRenderTarget();
virtual unsigned int GetHeight() const = 0;
virtual NzRenderTargetParameters GetParameters() const = 0;
virtual unsigned int GetWidth() const = 0;
bool IsActive() const;
virtual bool IsRenderable() const = 0;
bool SetActive(bool active);
// Fonctions OpenGL
virtual bool HasContext() const = 0;
protected:
virtual bool Activate() = 0;
virtual void Desactivate();
};
#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
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
// Interface inspirée de la SFML par Laurent Gomila
#pragma once
#ifndef NAZARA_RENDERWINDOW_HPP
#define NAZARA_RENDERWINDOW_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Clock.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/ContextParameters.hpp>
#include <Nazara/Renderer/RenderTarget.hpp>
#include <Nazara/Utility/Window.hpp>
class NzContext;
class NzImage;
class NzTexture;
struct NzContextParameters;
class NAZARA_API NzRenderWindow : public NzRenderTarget, public NzWindow
{
public:
NzRenderWindow() = default;
NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style = nzWindowStyle_Default, const NzContextParameters& parameters = NzContextParameters());
NzRenderWindow(NzWindowHandle handle, const NzContextParameters& parameters = NzContextParameters());
virtual ~NzRenderWindow();
bool CopyToImage(NzImage* image); ///TODO: Const
bool CopyToTexture(NzTexture* texture); ///TODO: Const
bool Create(NzVideoMode mode, const NzString& title, nzUInt32 style = nzWindowStyle_Default, const NzContextParameters& parameters = NzContextParameters());
bool Create(NzWindowHandle handle, const NzContextParameters& parameters = NzContextParameters());
void Display();
void EnableVerticalSync(bool enabled);
#ifndef NAZARA_RENDERER_COMMON
NzContextParameters GetContextParameters() const;
#endif
unsigned int GetHeight() const;
NzRenderTargetParameters GetParameters() const;
unsigned int GetWidth() const;
#ifndef NAZARA_RENDERER_COMMON
bool HasContext() const;
#endif
bool IsValid() const;
void SetFramerateLimit(unsigned int limit);
protected:
virtual bool Activate() override;
private:
virtual void OnWindowDestroying() override;
virtual bool OnWindowCreated() override;
NzClock m_clock;
NzContextParameters m_parameters;
NzContext* m_context = nullptr;
unsigned int m_framerateLimit = 0;
};
#endif // NAZARA_RENDERWINDOW_HPP
// 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
// Interface inspirée de la SFML par Laurent Gomila
#pragma once
#ifndef NAZARA_RENDERWINDOW_HPP
#define NAZARA_RENDERWINDOW_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Clock.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/ContextParameters.hpp>
#include <Nazara/Renderer/RenderTarget.hpp>
#include <Nazara/Utility/Window.hpp>
class NzContext;
class NzImage;
class NzTexture;
struct NzContextParameters;
class NAZARA_API NzRenderWindow : public NzRenderTarget, public NzWindow
{
public:
NzRenderWindow() = default;
NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style = nzWindowStyle_Default, const NzContextParameters& parameters = NzContextParameters());
NzRenderWindow(NzWindowHandle handle, const NzContextParameters& parameters = NzContextParameters());
virtual ~NzRenderWindow();
bool CopyToImage(NzImage* image); ///TODO: Const
bool CopyToTexture(NzTexture* texture); ///TODO: Const
bool Create(NzVideoMode mode, const NzString& title, nzUInt32 style = nzWindowStyle_Default, const NzContextParameters& parameters = NzContextParameters());
bool Create(NzWindowHandle handle, const NzContextParameters& parameters = NzContextParameters());
void Display();
void EnableVerticalSync(bool enabled);
unsigned int GetHeight() const;
NzRenderTargetParameters GetParameters() const;
unsigned int GetWidth() const;
bool IsRenderable() const;
bool IsValid() const;
void SetFramerateLimit(unsigned int limit);
// Fonctions OpenGL
NzContextParameters GetContextParameters() const;
bool HasContext() const;
protected:
bool Activate() override;
private:
bool OnWindowCreated() override;
void OnWindowDestroy() override;
NzClock m_clock;
NzContextParameters m_parameters;
NzContext* m_context = nullptr;
unsigned int m_framerateLimit = 0;
};
#endif // NAZARA_RENDERWINDOW_HPP

View File

@ -1,89 +1,92 @@
// 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_TEXTURE_HPP
#define NAZARA_TEXTURE_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/NonCopyable.hpp>
#include <Nazara/Renderer/Enums.hpp>
#include <Nazara/Utility/Image.hpp>
#include <Nazara/Utility/PixelFormat.hpp>
struct NzTextureImpl;
class NAZARA_API NzTexture : public NzResource, NzNonCopyable
{
friend class NzShader;
public:
NzTexture();
explicit NzTexture(const NzImage& image);
~NzTexture();
#ifndef NAZARA_RENDERER_COMMON
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 Download(NzImage* image) const;
bool EnableMipmapping(bool enable);
unsigned int GetAnisotropyLevel() const;
nzUInt8 GetBPP() const;
unsigned int GetDepth() const;
nzTextureFilter GetFilterMode() const;
nzPixelFormat GetFormat() const;
unsigned int GetHeight() const;
nzImageType GetType() const;
unsigned int GetWidth() const;
nzTextureWrap GetWrapMode() const;
bool IsCompressed() const;
bool IsCubemap() const;
bool IsTarget() const;
bool IsValid() const;
bool LoadFromFile(const NzString& filePath, const NzImageParams& params = NzImageParams());
bool LoadFromImage(const NzImage& image);
bool LoadFromMemory(const void* data, std::size_t size, const NzImageParams& params = NzImageParams());
bool LoadFromStream(NzInputStream& stream, const NzImageParams& params = NzImageParams());
bool Lock();
bool SetAnisotropyLevel(unsigned int anistropyLevel);
bool SetFilterMode(nzTextureFilter filter);
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, const NzCubeui& cube, nzUInt8 level = 0);
bool Update(const nzUInt8* pixels, nzUInt8 level = 0);
bool Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z = 0, nzUInt8 level = 0);
bool Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 level = 0);
bool UpdateFace(nzCubemapFace face, const NzImage& image, nzUInt8 level = 0);
bool UpdateFace(nzCubemapFace face, const NzImage& image, 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();
static unsigned int GetValidSize(unsigned int size);
static bool IsFormatSupported(nzPixelFormat format);
static bool IsMipmappingSupported();
static bool IsTypeSupported(nzImageType type);
private:
void SetTarget(bool isTarget);
NzTextureImpl* m_impl;
};
#endif // NAZARA_TEXTURE_HPP
// 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_TEXTURE_HPP
#define NAZARA_TEXTURE_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/NonCopyable.hpp>
#include <Nazara/Renderer/Enums.hpp>
#include <Nazara/Utility/Image.hpp>
#include <Nazara/Utility/PixelFormat.hpp>
class NzRenderTexture;
struct NzTextureImpl;
class NAZARA_API NzTexture : public NzResource, NzNonCopyable
{
friend NzRenderTexture;
friend class NzShader;
public:
NzTexture();
explicit NzTexture(const NzImage& image);
~NzTexture();
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 EnableMipmapping(bool enable);
unsigned int GetAnisotropyLevel() const;
nzUInt8 GetBPP() const;
unsigned int GetDepth() const;
nzTextureFilter GetFilterMode() const;
nzPixelFormat GetFormat() const;
unsigned int GetHeight() const;
nzImageType GetType() const;
unsigned int GetWidth() const;
nzTextureWrap GetWrapMode() const;
bool IsCompressed() const;
bool IsCubemap() const;
bool IsTarget() const;
bool IsValid() const;
bool LoadFromFile(const NzString& filePath, const NzImageParams& params = NzImageParams());
bool LoadFromImage(const NzImage& image);
bool LoadFromMemory(const void* data, std::size_t size, const NzImageParams& params = NzImageParams());
bool LoadFromStream(NzInputStream& stream, const NzImageParams& params = NzImageParams());
bool Lock();
bool SetAnisotropyLevel(unsigned int anistropyLevel);
bool SetFilterMode(nzTextureFilter filter);
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, const NzCubeui& cube, nzUInt8 level = 0);
bool Update(const nzUInt8* pixels, nzUInt8 level = 0);
bool Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z = 0, nzUInt8 level = 0);
bool Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 level = 0);
bool UpdateFace(nzCubemapFace face, const NzImage& image, nzUInt8 level = 0);
bool UpdateFace(nzCubemapFace face, const NzImage& image, 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();
// Fonctions OpenGL
unsigned int GetOpenGLID() const;
bool Prepare() const;
static unsigned int GetValidSize(unsigned int size);
static bool IsFormatSupported(nzPixelFormat format);
static bool IsMipmappingSupported();
static bool IsTypeSupported(nzImageType type);
private:
NzRenderTexture* GetRenderTexture() const;
void SetRenderTexture(NzRenderTexture* renderTexture);
NzTextureImpl* m_impl;
};
#endif // NAZARA_TEXTURE_HPP

View File

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

View File

@ -1,220 +1,250 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_ENUMS_UTILITY_HPP
#define NAZARA_ENUMS_UTILITY_HPP
enum nzAnimationType
{
nzAnimationType_Keyframe,
nzAnimationType_Skeletal,
nzAnimationType_Static
};
enum nzBufferAccess
{
nzBufferAccess_DiscardAndWrite,
nzBufferAccess_ReadOnly,
nzBufferAccess_ReadWrite,
nzBufferAccess_WriteOnly
};
enum nzBufferStorage
{
//nzBufferStorage_Both,
nzBufferStorage_Hardware,
nzBufferStorage_Software,
nzBufferStorage_Max = nzBufferStorage_Software
};
enum nzBufferType
{
nzBufferType_Index,
nzBufferType_Vertex
};
enum nzBufferUsage
{
nzBufferUsage_Dynamic,
nzBufferUsage_Static
};
enum nzCubemapFace
{
// 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
nzCubemapFace_PositiveX = 0,
nzCubemapFace_PositiveY = 2,
nzCubemapFace_PositiveZ = 4,
nzCubemapFace_NegativeX = 1,
nzCubemapFace_NegativeY = 3,
nzCubemapFace_NegativeZ = 5
};
enum nzElementStream
{
nzElementStream_VertexData,
nzElementStream_InstancedData,
nzElementStream_Max = nzElementStream_InstancedData
};
enum nzElementType
{
nzElementType_Color,
nzElementType_Double1,
nzElementType_Double2,
nzElementType_Double3,
nzElementType_Double4,
nzElementType_Float1,
nzElementType_Float2,
nzElementType_Float3,
nzElementType_Float4
};
enum nzElementUsage
{
nzElementUsage_Diffuse,
nzElementUsage_Normal,
nzElementUsage_Position,
nzElementUsage_Tangent,
nzElementUsage_TexCoord,
nzElementUsage_Max = nzElementUsage_TexCoord
};
enum nzEventType
{
nzEventType_GainedFocus,
nzEventType_LostFocus,
nzEventType_KeyPressed,
nzEventType_KeyReleased,
nzEventType_MouseButtonDoubleClicked,
nzEventType_MouseButtonPressed,
nzEventType_MouseButtonReleased,
nzEventType_MouseEntered,
nzEventType_MouseLeft,
nzEventType_MouseMoved,
nzEventType_MouseWheelMoved,
nzEventType_Moved,
nzEventType_Quit,
nzEventType_Resized,
nzEventType_TextEntered
};
enum nzExtend
{
nzExtend_Finite,
nzExtend_Infinite,
nzExtend_Null
};
enum nzImageType
{
nzImageType_1D,
nzImageType_1D_Array,
nzImageType_2D,
nzImageType_2D_Array,
nzImageType_3D,
nzImageType_Cubemap,
nzImageType_Max = nzImageType_Cubemap
};
enum nzPixelFormat
{
nzPixelFormat_Undefined = -1,
nzPixelFormat_BGR8, // 3*nzUInt8
nzPixelFormat_BGRA8, // 4*nzUInt8
nzPixelFormat_DXT1,
nzPixelFormat_DXT3,
nzPixelFormat_DXT5,
nzPixelFormat_L8, // 1*nzUInt8
nzPixelFormat_LA8, // 2*nzUInt8
/*
nzPixelFormat_RGB16F,
nzPixelFormat_RGB16I, // 4*nzUInt16
nzPixelFormat_RGB32F,
nzPixelFormat_RGB32I, // 4*nzUInt32
nzPixelFormat_RGBA16F,
nzPixelFormat_RGBA16I, // 4*nzUInt16
nzPixelFormat_RGBA32F,
nzPixelFormat_RGBA32I, // 4*nzUInt32
*/
nzPixelFormat_RGBA4, // 1*nzUInt16
nzPixelFormat_RGB5A1, // 1*nzUInt16
nzPixelFormat_RGB8, // 3*nzUInt8
nzPixelFormat_RGBA8, // 4*nzUInt8
/*
nzPixelFormat_Depth16,
nzPixelFormat_Depth24,
nzPixelFormat_Depth24Stencil8,
nzPixelFormat_Depth32,
nzPixelFormat_Stencil1,
nzPixelFormat_Stencil4,
nzPixelFormat_Stencil8,
nzPixelFormat_Stencil16,
*/
nzPixelFormat_Max = nzPixelFormat_RGBA8
};
enum nzPixelFlipping
{
nzPixelFlipping_Horizontally,
nzPixelFlipping_Vertically,
nzPixelFlipping_Max = nzPixelFlipping_Vertically
};
enum nzPrimitiveType
{
nzPrimitiveType_LineList,
nzPrimitiveType_LineStrip,
nzPrimitiveType_PointList,
nzPrimitiveType_TriangleList,
nzPrimitiveType_TriangleStrip,
nzPrimitiveType_TriangleFan
};
enum nzWindowCursor
{
nzWindowCursor_None,
nzWindowCursor_Default,
nzWindowCursor_Crosshair,
nzWindowCursor_Hand,
nzWindowCursor_Help,
nzWindowCursor_Move,
nzWindowCursor_Pointer,
nzWindowCursor_Progress,
nzWindowCursor_ResizeE,
nzWindowCursor_ResizeN,
nzWindowCursor_ResizeNE,
nzWindowCursor_ResizeNW,
nzWindowCursor_ResizeS,
nzWindowCursor_ResizeSE,
nzWindowCursor_ResizeSW,
nzWindowCursor_ResizeW,
nzWindowCursor_Text,
nzWindowCursor_Wait
};
enum nzWindowStyle
{
nzWindowStyle_None = 0x0,
nzWindowStyle_Fullscreen = 0x1,
nzWindowStyle_Closable = 0x2,
nzWindowStyle_Resizable = 0x4,
nzWindowStyle_Titlebar = 0x4,
nzWindowStyle_Default = nzWindowStyle_Closable | nzWindowStyle_Resizable | nzWindowStyle_Titlebar
};
#endif // NAZARA_ENUMS_UTILITY_HPP
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_ENUMS_UTILITY_HPP
#define NAZARA_ENUMS_UTILITY_HPP
enum nzAnimationType
{
nzAnimationType_Keyframe,
nzAnimationType_Skeletal,
nzAnimationType_Static,
nzAnimationType_Max = nzAnimationType_Static
};
enum nzBufferAccess
{
nzBufferAccess_DiscardAndWrite,
nzBufferAccess_ReadOnly,
nzBufferAccess_ReadWrite,
nzBufferAccess_WriteOnly,
nzBufferAccess_Max = nzBufferAccess_WriteOnly
};
enum nzBufferStorage
{
//nzBufferStorage_Both,
nzBufferStorage_Hardware,
nzBufferStorage_Software,
nzBufferStorage_Max = nzBufferStorage_Software
};
enum nzBufferType
{
nzBufferType_Index,
nzBufferType_Vertex,
nzBufferType_Max = nzBufferType_Vertex
};
enum nzBufferUsage
{
nzBufferUsage_Dynamic,
nzBufferUsage_Static,
nzBufferUsage_Max = nzBufferUsage_Static
};
enum nzCubemapFace
{
// 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
nzCubemapFace_PositiveX = 0,
nzCubemapFace_PositiveY = 2,
nzCubemapFace_PositiveZ = 4,
nzCubemapFace_NegativeX = 1,
nzCubemapFace_NegativeY = 3,
nzCubemapFace_NegativeZ = 5,
nzCubemapFace_Max = nzCubemapFace_NegativeZ
};
enum nzElementStream
{
nzElementStream_VertexData,
nzElementStream_InstancedData,
nzElementStream_Max = nzElementStream_InstancedData
};
enum nzElementType
{
nzElementType_Color,
nzElementType_Double1,
nzElementType_Double2,
nzElementType_Double3,
nzElementType_Double4,
nzElementType_Float1,
nzElementType_Float2,
nzElementType_Float3,
nzElementType_Float4,
nzElementType_Max = nzElementType_Float4
};
enum nzElementUsage
{
nzElementUsage_Diffuse,
nzElementUsage_Normal,
nzElementUsage_Position,
nzElementUsage_Tangent,
nzElementUsage_TexCoord,
nzElementUsage_Max = nzElementUsage_TexCoord
};
enum nzEventType
{
nzEventType_GainedFocus,
nzEventType_LostFocus,
nzEventType_KeyPressed,
nzEventType_KeyReleased,
nzEventType_MouseButtonDoubleClicked,
nzEventType_MouseButtonPressed,
nzEventType_MouseButtonReleased,
nzEventType_MouseEntered,
nzEventType_MouseLeft,
nzEventType_MouseMoved,
nzEventType_MouseWheelMoved,
nzEventType_Moved,
nzEventType_Quit,
nzEventType_Resized,
nzEventType_TextEntered,
nzEventType_Max = nzEventType_TextEntered
};
enum nzExtend
{
nzExtend_Finite,
nzExtend_Infinite,
nzExtend_Null,
nzExtend_Max = nzExtend_Null
};
enum nzImageType
{
nzImageType_1D,
nzImageType_1D_Array,
nzImageType_2D,
nzImageType_2D_Array,
nzImageType_3D,
nzImageType_Cubemap,
nzImageType_Max = nzImageType_Cubemap
};
enum nzPixelFormat
{
nzPixelFormat_Undefined = -1,
nzPixelFormat_BGR8, // 3*nzUInt8
nzPixelFormat_BGRA8, // 4*nzUInt8
nzPixelFormat_DXT1,
nzPixelFormat_DXT3,
nzPixelFormat_DXT5,
nzPixelFormat_L8, // 1*nzUInt8
nzPixelFormat_LA8, // 2*nzUInt8
/*
nzPixelFormat_RGB16F,
nzPixelFormat_RGB16I, // 4*nzUInt16
nzPixelFormat_RGB32F,
nzPixelFormat_RGB32I, // 4*nzUInt32
nzPixelFormat_RGBA16F,
nzPixelFormat_RGBA16I, // 4*nzUInt16
nzPixelFormat_RGBA32F,
nzPixelFormat_RGBA32I, // 4*nzUInt32
*/
nzPixelFormat_RGBA4, // 1*nzUInt16
nzPixelFormat_RGB5A1, // 1*nzUInt16
nzPixelFormat_RGB8, // 3*nzUInt8
nzPixelFormat_RGBA8, // 4*nzUInt8
nzPixelFormat_Depth16,
nzPixelFormat_Depth24,
nzPixelFormat_Depth24Stencil8,
nzPixelFormat_Depth32,
nzPixelFormat_Stencil1,
nzPixelFormat_Stencil4,
nzPixelFormat_Stencil8,
nzPixelFormat_Stencil16,
nzPixelFormat_Max = nzPixelFormat_Stencil16
};
enum nzPixelFormatType
{
nzPixelFormatType_Undefined = -1,
nzPixelFormatType_Color,
nzPixelFormatType_Depth,
nzPixelFormatType_DepthStencil,
nzPixelFormatType_Stencil,
nzPixelFormatType_Max = nzPixelFormatType_Stencil
};
enum nzPixelFlipping
{
nzPixelFlipping_Horizontally,
nzPixelFlipping_Vertically,
nzPixelFlipping_Max = nzPixelFlipping_Vertically
};
enum nzPrimitiveType
{
nzPrimitiveType_LineList,
nzPrimitiveType_LineStrip,
nzPrimitiveType_PointList,
nzPrimitiveType_TriangleList,
nzPrimitiveType_TriangleStrip,
nzPrimitiveType_TriangleFan,
nzPrimitiveType_Max = nzPrimitiveType_TriangleFan
};
enum nzWindowCursor
{
nzWindowCursor_None,
nzWindowCursor_Default,
nzWindowCursor_Crosshair,
nzWindowCursor_Hand,
nzWindowCursor_Help,
nzWindowCursor_Move,
nzWindowCursor_Pointer,
nzWindowCursor_Progress,
nzWindowCursor_ResizeE,
nzWindowCursor_ResizeN,
nzWindowCursor_ResizeNE,
nzWindowCursor_ResizeNW,
nzWindowCursor_ResizeS,
nzWindowCursor_ResizeSE,
nzWindowCursor_ResizeSW,
nzWindowCursor_ResizeW,
nzWindowCursor_Text,
nzWindowCursor_Wait,
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
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_MESH_HPP
#define NAZARA_MESH_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/InputStream.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Utility/Animation.hpp>
#include <Nazara/Utility/AxisAlignedBox.hpp>
#include <Nazara/Utility/SubMesh.hpp>
class NzVertexDeclaration;
struct NzMeshParams
{
NzAnimationParams animation;
//const NzVertexDeclaration* declaration = nullptr;
nzBufferStorage storage = nzBufferStorage_Hardware;
bool loadAnimations = true;
bool IsValid() const;
};
class NzMesh;
using NzMeshLoader = NzResourceLoader<NzMesh, NzMeshParams>;
struct NzMeshImpl;
class NAZARA_API NzMesh : public NzResource
{
friend NzMeshLoader;
public:
NzMesh() = default;
~NzMesh();
unsigned int AddSkin(const NzString& skin, bool setDefault = false);
nzUInt8 AddSubMesh(NzSubMesh* subMesh);
nzUInt8 AddSubMesh(const NzString& identifier, NzSubMesh* subMesh);
void Animate(unsigned int frameA, unsigned int frameB, float interpolation);
bool Create(nzAnimationType type);
void Destroy();
const NzAxisAlignedBox& GetAABB() const;
const NzAnimation* GetAnimation() const;
nzAnimationType GetAnimationType() const;
unsigned int GetFrameCount() const;
NzString GetSkin(unsigned int index = 0) const;
unsigned int GetSkinCount() const;
NzSubMesh* GetSubMesh(const NzString& identifier);
NzSubMesh* GetSubMesh(nzUInt8 index);
const NzSubMesh* GetSubMesh(const NzString& identifier) const;
const NzSubMesh* GetSubMesh(nzUInt8 index) const;
nzUInt8 GetSubMeshCount() const;
unsigned int GetVertexCount() const;
bool HasAnimation() const;
bool HasSkin(unsigned int index = 0) const;
bool HasSubMesh(const NzString& identifier) const;
bool HasSubMesh(nzUInt8 index = 0) const;
void InvalidateAABB() const;
bool IsAnimable() const;
bool IsValid() const;
bool LoadFromFile(const NzString& filePath, const NzMeshParams& params = NzMeshParams());
bool LoadFromMemory(const void* data, std::size_t size, const NzMeshParams& params = NzMeshParams());
bool LoadFromStream(NzInputStream& stream, const NzMeshParams& params = NzMeshParams());
void RemoveSkin(unsigned int index = 0);
void RemoveSubMesh(const NzString& identifier);
void RemoveSubMesh(nzUInt8 index = 0);
bool SetAnimation(const NzAnimation* animation);
private:
NzMeshImpl* m_impl = nullptr;
static NzMeshLoader::LoaderList s_loaders;
};
#endif // NAZARA_MESH_HPP
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_MESH_HPP
#define NAZARA_MESH_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/InputStream.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceListener.hpp>
#include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Utility/Animation.hpp>
#include <Nazara/Utility/AxisAlignedBox.hpp>
#include <Nazara/Utility/SubMesh.hpp>
class NzVertexDeclaration;
struct NzMeshParams
{
NzAnimationParams animation;
//const NzVertexDeclaration* declaration = nullptr;
nzBufferStorage storage = nzBufferStorage_Hardware;
bool loadAnimations = true;
bool IsValid() const;
};
class NzMesh;
using NzMeshLoader = NzResourceLoader<NzMesh, NzMeshParams>;
struct NzMeshImpl;
class NAZARA_API NzMesh : public NzResource, NzResourceListener
{
friend NzMeshLoader;
public:
NzMesh() = default;
~NzMesh();
bool AddSkin(const NzString& skin, bool setDefault = false);
bool AddSubMesh(NzSubMesh* subMesh);
bool AddSubMesh(const NzString& identifier, NzSubMesh* subMesh);
void Animate(unsigned int frameA, unsigned int frameB, float interpolation);
bool Create(nzAnimationType type);
void Destroy();
const NzAxisAlignedBox& GetAABB() const;
const NzAnimation* GetAnimation() const;
nzAnimationType GetAnimationType() const;
unsigned int GetFrameCount() const;
NzString GetSkin(unsigned int index = 0) const;
unsigned int GetSkinCount() const;
NzSubMesh* GetSubMesh(const NzString& identifier);
NzSubMesh* GetSubMesh(unsigned int index);
const NzSubMesh* GetSubMesh(const NzString& identifier) const;
const NzSubMesh* GetSubMesh(unsigned int index) const;
unsigned int GetSubMeshCount() const;
int GetSubMeshIndex(const NzString& identifier) const;
unsigned int GetVertexCount() const;
bool HasAnimation() const;
bool HasSkin(unsigned int index = 0) const;
bool HasSubMesh(const NzString& identifier) const;
bool HasSubMesh(unsigned int index = 0) const;
void InvalidateAABB() const;
bool IsAnimable() const;
bool IsValid() const;
bool LoadFromFile(const NzString& filePath, const NzMeshParams& params = NzMeshParams());
bool LoadFromMemory(const void* data, std::size_t size, const NzMeshParams& params = NzMeshParams());
bool LoadFromStream(NzInputStream& stream, const NzMeshParams& params = NzMeshParams());
void RemoveSkin(unsigned int index = 0);
void RemoveSubMesh(const NzString& identifier);
void RemoveSubMesh(unsigned int index = 0);
bool SetAnimation(const NzAnimation* animation);
private:
void OnResourceCreated(const NzResource* resource, int index) override;
void OnResourceReleased(const NzResource* resource, int index) override;
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
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PIXELFORMAT_HPP
#define NAZARA_PIXELFORMAT_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Utility/Enums.hpp>
#include <map>
class NzUtility;
class NzPixelFormat
{
friend class NzUtility;
public:
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);
static bool Convert(nzPixelFormat srcFormat, nzPixelFormat dstFormat, const void* src, void* dst);
static bool Convert(nzPixelFormat srcFormat, nzPixelFormat dstFormat, const void* start, const void* end, void* dst);
static bool Flip(nzPixelFlipping flipping, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, const void* src, void* dst);
static nzUInt8 GetBPP(nzPixelFormat format);
static bool HasAlpha(nzPixelFormat format);
static bool IsCompressed(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 NzString ToString(nzPixelFormat format);
private:
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];
};
#include <Nazara/Utility/PixelFormat.inl>
#endif // NAZARA_PIXELFORMAT_HPP
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PIXELFORMAT_HPP
#define NAZARA_PIXELFORMAT_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Utility/Enums.hpp>
#include <map>
class NzUtility;
class NzPixelFormat
{
friend class NzUtility;
public:
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);
static bool Convert(nzPixelFormat srcFormat, nzPixelFormat dstFormat, const void* src, void* dst);
static bool Convert(nzPixelFormat srcFormat, nzPixelFormat dstFormat, const void* start, const void* end, void* dst);
static bool Flip(nzPixelFlipping flipping, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, const void* src, void* dst);
static nzUInt8 GetBPP(nzPixelFormat format);
static nzPixelFormatType GetType(nzPixelFormat format);
static bool HasAlpha(nzPixelFormat format);
static bool IsCompressed(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 NzString ToString(nzPixelFormat format);
private:
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];
};
#include <Nazara/Utility/PixelFormat.inl>
#endif // NAZARA_PIXELFORMAT_HPP

View File

@ -1,371 +1,487 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Error.hpp>
#include <cstring>
#include <Nazara/Utility/Debug.hpp>
inline bool NzPixelFormat::Convert(nzPixelFormat srcFormat, nzPixelFormat dstFormat, const void* src, void* dst)
{
if (srcFormat == dstFormat)
{
std::memcpy(dst, src, GetBPP(srcFormat));
return true;
}
#if NAZARA_UTILITY_SAFE
if (IsCompressed(srcFormat))
{
NazaraError("Cannot convert single pixel from compressed format");
return false;
}
if (IsCompressed(dstFormat))
{
NazaraError("Cannot convert single pixel to compressed format");
return false;
}
#endif
ConvertFunction func = s_convertFunctions[srcFormat][dstFormat];
if (!func)
{
NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " is not supported");
return false;
}
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");
return false;
}
return true;
}
inline bool NzPixelFormat::Convert(nzPixelFormat srcFormat, nzPixelFormat dstFormat, const void* start, const void* end, void* dst)
{
if (srcFormat == dstFormat)
{
std::memcpy(dst, start, reinterpret_cast<const nzUInt8*>(end)-reinterpret_cast<const nzUInt8*>(start));
return true;
}
ConvertFunction func = s_convertFunctions[srcFormat][dstFormat];
if (!func)
{
NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " is not supported");
return false;
}
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");
return false;
}
return true;
}
inline bool NzPixelFormat::Flip(nzPixelFlipping flipping, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, const void* src, void* dst)
{
#if NAZARA_UTILITY_SAFE
if (!IsValid(format))
{
NazaraError("Invalid pixel format");
return false;
}
#endif
auto it = s_flipFunctions[flipping].find(format);
if (it != s_flipFunctions[flipping].end())
it->second(width, height, depth, reinterpret_cast<const nzUInt8*>(src), reinterpret_cast<nzUInt8*>(dst));
else
{
// Flipping générique
#if NAZARA_UTILITY_SAFE
if (IsCompressed(format))
{
NazaraError("No function to flip compressed format");
return false;
}
#endif
nzUInt8 bpp = GetBPP(format);
unsigned int lineStride = width*bpp;
switch (flipping)
{
case nzPixelFlipping_Horizontally:
{
if (src == dst)
{
for (unsigned int z = 0; z < depth; ++z)
{
nzUInt8* ptr = reinterpret_cast<nzUInt8*>(dst) + width*height*z;
for (unsigned int y = 0; y < height; ++y)
{
for (unsigned int x = 0; x < width/2; ++x)
std::swap_ranges(&ptr[x*bpp], &ptr[(x+1)*bpp], &ptr[(width-x)*bpp]);
ptr += lineStride;
}
}
}
else
{
for (unsigned int z = 0; z < depth; ++z)
{
nzUInt8* ptr = reinterpret_cast<nzUInt8*>(dst) + width*height*z;
for (unsigned int y = 0; y < height; ++y)
{
for (unsigned int x = 0; x < width; ++x)
std::memcpy(&ptr[x*bpp], &ptr[(width-x)*bpp], bpp);
ptr += lineStride;
}
}
}
break;
}
case nzPixelFlipping_Vertically:
{
if (src == dst)
{
for (unsigned int z = 0; z < depth; ++z)
{
nzUInt8* ptr = reinterpret_cast<nzUInt8*>(dst) + width*height*z;
for (unsigned int y = 0; y < height/2; ++y)
std::swap_ranges(&ptr[y*lineStride], &ptr[(y+1)*lineStride-1], &ptr[(height-y-1)*lineStride]);
}
}
else
{
for (unsigned int z = 0; z < depth; ++z)
{
const nzUInt8* srcPtr = reinterpret_cast<const nzUInt8*>(src);
nzUInt8* dstPtr = reinterpret_cast<nzUInt8*>(dst) + (width-1)*height*depth*bpp;
for (unsigned int y = 0; y < height; ++y)
{
std::memcpy(dstPtr, srcPtr, lineStride);
srcPtr += lineStride;
dstPtr -= lineStride;
}
}
}
break;
}
}
}
return true;
}
inline nzUInt8 NzPixelFormat::GetBPP(nzPixelFormat format)
{
switch (format)
{
case nzPixelFormat_BGR8:
return 3;
case nzPixelFormat_BGRA8:
return 4;
case nzPixelFormat_DXT1:
return 1;
case nzPixelFormat_DXT3:
return 2;
case nzPixelFormat_DXT5:
return 2;
case nzPixelFormat_L8:
return 1;
case nzPixelFormat_LA8:
return 2;
/*
case nzPixelFormat_RGB16F:
return 6;
case nzPixelFormat_RGB16I:
return 6;
case nzPixelFormat_RGB32F:
return 12;
case nzPixelFormat_RGB32I:
return 12;
case nzPixelFormat_RGBA16F:
return 8;
case nzPixelFormat_RGBA16I:
return 8;
case nzPixelFormat_RGBA32F:
return 16;
case nzPixelFormat_RGBA32I:
return 16;
*/
case nzPixelFormat_RGBA4:
return 2;
case nzPixelFormat_RGB5A1:
return 2;
case nzPixelFormat_RGB8:
return 3;
case nzPixelFormat_RGBA8:
return 4;
case nzPixelFormat_Undefined:
NazaraError("Invalid pixel format");
return 0;
}
NazaraInternalError("Invalid pixel format");
return 0;
}
inline bool NzPixelFormat::HasAlpha(nzPixelFormat format)
{
switch (format)
{
case nzPixelFormat_BGRA8:
case nzPixelFormat_DXT3:
case nzPixelFormat_DXT5:
case nzPixelFormat_LA8:
case nzPixelFormat_RGB5A1:
case nzPixelFormat_RGBA4:
case nzPixelFormat_RGBA8:
return true;
case nzPixelFormat_BGR8:
case nzPixelFormat_DXT1:
case nzPixelFormat_L8:
case nzPixelFormat_RGB8:
return false;
case nzPixelFormat_Undefined:
break;
}
NazaraError("Invalid pixel format");
return false;
}
inline bool NzPixelFormat::IsCompressed(nzPixelFormat format)
{
switch (format)
{
case nzPixelFormat_DXT1:
case nzPixelFormat_DXT3:
case nzPixelFormat_DXT5:
return true;
default:
return false;
}
}
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_Undefined:
return "Undefined";
}
NazaraError("Invalid pixel format");
return "Invalid format";
}
#include <Nazara/Utility/DebugOff.hpp>
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Error.hpp>
#include <cstring>
#include <Nazara/Utility/Debug.hpp>
inline bool NzPixelFormat::Convert(nzPixelFormat srcFormat, nzPixelFormat dstFormat, const void* src, void* dst)
{
if (srcFormat == dstFormat)
{
std::memcpy(dst, src, GetBPP(srcFormat));
return true;
}
#if NAZARA_UTILITY_SAFE
if (IsCompressed(srcFormat))
{
NazaraError("Cannot convert single pixel from compressed format");
return false;
}
if (IsCompressed(dstFormat))
{
NazaraError("Cannot convert single pixel to compressed format");
return false;
}
#endif
ConvertFunction func = s_convertFunctions[srcFormat][dstFormat];
if (!func)
{
NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " is not supported");
return false;
}
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");
return false;
}
return true;
}
inline bool NzPixelFormat::Convert(nzPixelFormat srcFormat, nzPixelFormat dstFormat, const void* start, const void* end, void* dst)
{
if (srcFormat == dstFormat)
{
std::memcpy(dst, start, reinterpret_cast<const nzUInt8*>(end)-reinterpret_cast<const nzUInt8*>(start));
return true;
}
ConvertFunction func = s_convertFunctions[srcFormat][dstFormat];
if (!func)
{
NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " is not supported");
return false;
}
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");
return false;
}
return true;
}
inline bool NzPixelFormat::Flip(nzPixelFlipping flipping, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, const void* src, void* dst)
{
#if NAZARA_UTILITY_SAFE
if (!IsValid(format))
{
NazaraError("Invalid pixel format");
return false;
}
#endif
auto it = s_flipFunctions[flipping].find(format);
if (it != s_flipFunctions[flipping].end())
it->second(width, height, depth, reinterpret_cast<const nzUInt8*>(src), reinterpret_cast<nzUInt8*>(dst));
else
{
// Flipping générique
#if NAZARA_UTILITY_SAFE
if (IsCompressed(format))
{
NazaraError("No function to flip compressed format");
return false;
}
#endif
nzUInt8 bpp = GetBPP(format);
unsigned int lineStride = width*bpp;
switch (flipping)
{
case nzPixelFlipping_Horizontally:
{
if (src == dst)
{
for (unsigned int z = 0; z < depth; ++z)
{
nzUInt8* ptr = reinterpret_cast<nzUInt8*>(dst) + width*height*z;
for (unsigned int y = 0; y < height; ++y)
{
for (unsigned int x = 0; x < width/2; ++x)
std::swap_ranges(&ptr[x*bpp], &ptr[(x+1)*bpp], &ptr[(width-x)*bpp]);
ptr += lineStride;
}
}
}
else
{
for (unsigned int z = 0; z < depth; ++z)
{
nzUInt8* ptr = reinterpret_cast<nzUInt8*>(dst) + width*height*z;
for (unsigned int y = 0; y < height; ++y)
{
for (unsigned int x = 0; x < width; ++x)
std::memcpy(&ptr[x*bpp], &ptr[(width-x)*bpp], bpp);
ptr += lineStride;
}
}
}
break;
}
case nzPixelFlipping_Vertically:
{
if (src == dst)
{
for (unsigned int z = 0; z < depth; ++z)
{
nzUInt8* ptr = reinterpret_cast<nzUInt8*>(dst) + width*height*z;
for (unsigned int y = 0; y < height/2; ++y)
std::swap_ranges(&ptr[y*lineStride], &ptr[(y+1)*lineStride-1], &ptr[(height-y-1)*lineStride]);
}
}
else
{
for (unsigned int z = 0; z < depth; ++z)
{
const nzUInt8* srcPtr = reinterpret_cast<const nzUInt8*>(src);
nzUInt8* dstPtr = reinterpret_cast<nzUInt8*>(dst) + (width-1)*height*depth*bpp;
for (unsigned int y = 0; y < height; ++y)
{
std::memcpy(dstPtr, srcPtr, lineStride);
srcPtr += lineStride;
dstPtr -= lineStride;
}
}
}
break;
}
}
}
return true;
}
inline nzUInt8 NzPixelFormat::GetBPP(nzPixelFormat format)
{
switch (format)
{
case nzPixelFormat_BGR8:
return 3;
case nzPixelFormat_BGRA8:
return 4;
case nzPixelFormat_DXT1:
return 1;
case nzPixelFormat_DXT3:
return 2;
case nzPixelFormat_DXT5:
return 2;
case nzPixelFormat_L8:
return 1;
case nzPixelFormat_LA8:
return 2;
/*
case nzPixelFormat_RGB16F:
return 6;
case nzPixelFormat_RGB16I:
return 6;
case nzPixelFormat_RGB32F:
return 12;
case nzPixelFormat_RGB32I:
return 12;
case nzPixelFormat_RGBA16F:
return 8;
case nzPixelFormat_RGBA16I:
return 8;
case nzPixelFormat_RGBA32F:
return 16;
case nzPixelFormat_RGBA32I:
return 16;
*/
case nzPixelFormat_RGBA4:
return 2;
case nzPixelFormat_RGB5A1:
return 2;
case nzPixelFormat_RGB8:
return 3;
case nzPixelFormat_RGBA8:
return 4;
case nzPixelFormat_Depth16:
return 2;
case nzPixelFormat_Depth24:
return 3;
case nzPixelFormat_Depth24Stencil8:
return 4;
case nzPixelFormat_Depth32:
return 4;
case nzPixelFormat_Stencil1:
NazaraWarning("This format uses less than one byte per pixel");
return 0;
case nzPixelFormat_Stencil4:
NazaraWarning("This format uses less than one byte per pixel");
return 0;
case nzPixelFormat_Stencil8:
return 1;
case nzPixelFormat_Stencil16:
return 2;
case nzPixelFormat_Undefined:
break;
}
NazaraError("Invalid pixel format");
return 0;
}
inline nzPixelFormatType NzPixelFormat::GetType(nzPixelFormat format)
{
switch (format)
{
case nzPixelFormat_BGR8:
case nzPixelFormat_BGRA8:
case nzPixelFormat_DXT1:
case nzPixelFormat_DXT3:
case nzPixelFormat_DXT5:
case nzPixelFormat_L8:
case nzPixelFormat_LA8:
case nzPixelFormat_RGB5A1:
case nzPixelFormat_RGB8:
case nzPixelFormat_RGBA4:
case nzPixelFormat_RGBA8:
return nzPixelFormatType_Color;
case nzPixelFormat_Depth16:
case nzPixelFormat_Depth24:
case nzPixelFormat_Depth32:
return nzPixelFormatType_Depth;
case nzPixelFormat_Depth24Stencil8:
return nzPixelFormatType_DepthStencil;
case nzPixelFormat_Stencil1:
case nzPixelFormat_Stencil4:
case nzPixelFormat_Stencil8:
case nzPixelFormat_Stencil16:
return nzPixelFormatType_Stencil;
case nzPixelFormat_Undefined:
break;
}
NazaraError("Invalid pixel format");
return nzPixelFormatType_Undefined;
}
inline bool NzPixelFormat::HasAlpha(nzPixelFormat format)
{
switch (format)
{
case nzPixelFormat_BGRA8:
case nzPixelFormat_DXT3:
case nzPixelFormat_DXT5:
case nzPixelFormat_LA8:
case nzPixelFormat_RGB5A1:
case nzPixelFormat_RGBA4:
case nzPixelFormat_RGBA8:
return true;
case nzPixelFormat_BGR8:
case nzPixelFormat_DXT1:
case nzPixelFormat_L8:
case nzPixelFormat_RGB8:
case nzPixelFormat_Depth16:
case nzPixelFormat_Depth24:
case nzPixelFormat_Depth24Stencil8:
case nzPixelFormat_Depth32:
case nzPixelFormat_Stencil1:
case nzPixelFormat_Stencil4:
case nzPixelFormat_Stencil8:
case nzPixelFormat_Stencil16:
return false;
case nzPixelFormat_Undefined:
break;
}
NazaraError("Invalid pixel format");
return false;
}
inline bool NzPixelFormat::IsCompressed(nzPixelFormat format)
{
switch (format)
{
case nzPixelFormat_DXT1:
case nzPixelFormat_DXT3:
case nzPixelFormat_DXT5:
return true;
case nzPixelFormat_BGRA8:
case nzPixelFormat_LA8:
case nzPixelFormat_RGB5A1:
case nzPixelFormat_RGBA4:
case nzPixelFormat_RGBA8:
case nzPixelFormat_BGR8:
case nzPixelFormat_L8:
case nzPixelFormat_RGB8:
case nzPixelFormat_Depth16:
case nzPixelFormat_Depth24:
case nzPixelFormat_Depth24Stencil8:
case nzPixelFormat_Depth32:
case nzPixelFormat_Stencil1:
case nzPixelFormat_Stencil4:
case nzPixelFormat_Stencil8:
case nzPixelFormat_Stencil16:
return false;
case nzPixelFormat_Undefined:
break;
}
NazaraError("Invalid pixel format");
return false;
}
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
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_STATICMESH_HPP
#define NAZARA_STATICMESH_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Utility/SubMesh.hpp>
class NAZARA_API NzStaticMesh final : public NzSubMesh
{
public:
NzStaticMesh(const NzMesh* parent);
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 GenerateAABB();
const NzAxisAlignedBox& GetAABB() const;
nzAnimationType GetAnimationType() const;
unsigned int GetFrameCount() const;
const NzIndexBuffer* GetIndexBuffer() const;
nzPrimitiveType GetPrimitiveType() const;
const NzVertexBuffer* GetVertexBuffer() const;
const NzVertexDeclaration* GetVertexDeclaration() const;
bool IsAnimated() const;
bool IsValid() const;
void SetAABB(const NzAxisAlignedBox& aabb);
void SetPrimitiveType(nzPrimitiveType primitiveType);
private:
void AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation);
nzPrimitiveType m_primitiveType = nzPrimitiveType_TriangleList;
NzAxisAlignedBox m_aabb;
NzIndexBuffer* m_indexBuffer = nullptr;
NzVertexBuffer* m_vertexBuffer = nullptr;
const NzVertexDeclaration* m_vertexDeclaration = nullptr;
};
#endif // NAZARA_STATICMESH_HPP
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_STATICMESH_HPP
#define NAZARA_STATICMESH_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/ResourceListener.hpp>
#include <Nazara/Utility/SubMesh.hpp>
class NAZARA_API NzStaticMesh final : public NzSubMesh, NzResourceListener
{
public:
NzStaticMesh(const NzMesh* parent);
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 GenerateAABB();
const NzAxisAlignedBox& GetAABB() const;
nzAnimationType GetAnimationType() const;
unsigned int GetFrameCount() const;
const NzIndexBuffer* GetIndexBuffer() const;
nzPrimitiveType GetPrimitiveType() const;
const NzVertexBuffer* GetVertexBuffer() const;
const NzVertexDeclaration* GetVertexDeclaration() const;
bool IsAnimated() const;
bool IsValid() const;
void SetAABB(const NzAxisAlignedBox& aabb);
void SetPrimitiveType(nzPrimitiveType primitiveType);
private:
void AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation);
void OnResourceReleased(const NzResource* resource, int index) override;
nzPrimitiveType m_primitiveType = nzPrimitiveType_TriangleList;
NzAxisAlignedBox m_aabb;
NzIndexBuffer* m_indexBuffer = nullptr;
NzVertexBuffer* m_vertexBuffer = nullptr;
const NzVertexDeclaration* m_vertexDeclaration = nullptr;
};
#endif // NAZARA_STATICMESH_HPP

View File

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

View File

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

View File

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

View File

@ -1,265 +1,265 @@
/*
// 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/ByteArray.hpp>
#include <algorithm>
#include <cstring>
#include <Nazara/Core/Debug.hpp>
inline unsigned int nzPow2(unsigned int n)
{
unsigned int x = 1;
while(x <= n)
x <<= 1;
return x;
}
// Cet algorithme est inspiré de la documentation de Qt
inline unsigned int nzGetNewSize(unsigned int newSize)
{
if (newSize < 20)
return newSize+4;
else
{
if (newSize < (1 << 12)-12)
return nzPow2(newSize << 1)-12;
else
return newSize + (1 << 11);
}
}
NzByteArray::NzByteArray() :
m_sharedArray(&emptyArray)
{
}
NzByteArray::NzByteArray(const nzUInt8* buffer, unsigned int bufferLength)
{
if (bufferLength > 0)
{
m_sharedArray = new SharedArray;
m_sharedArray->buffer = new nzUInt8[bufferLength];
m_sharedArray->capacity = bufferLength;
m_sharedArray->size = bufferLength;
std::memcpy(m_sharedArray->buffer, buffer, bufferLength);
}
else
m_sharedArray = &emptyArray;
}
NzByteArray::NzByteArray(const NzByteArray& buffer) :
m_sharedArray(buffer.m_sharedArray)
{
if (m_sharedArray != &emptyArray)
{
NazaraMutexLock(m_sharedArray->mutex);
m_sharedArray->refCount++;
NazaraMutexUnlock(m_sharedArray->mutex);
}
}
NzByteArray::NzByteArray(NzByteArray&& buffer) :
m_sharedArray(buffer.m_sharedArray)
{
buffer.m_sharedArray = &emptyArray;
}
NzByteArray::NzByteArray(SharedArray* sharedArray) :
m_sharedArray(sharedArray)
{
}
NzByteArray::~NzByteArray()
{
ReleaseArray();
}
NzByteArray& NzByteArray::Append(const NzByteArray& byteArray)
{
if (byteArray.m_sharedArray->size == 0)
return *this;
if (m_sharedArray->size == 0 && m_sharedArray->capacity < byteArray.m_sharedArray->size)
return operator=(byteArray);
if (m_sharedArray->capacity >= m_sharedArray->size + byteArray.m_sharedArray->size)
{
EnsureOwnership();
std::memcpy(&m_sharedArray->buffer[m_sharedArray->size], byteArray.m_sharedArray->buffer, byteArray.m_sharedArray->size);
m_sharedArray->size += byteArray.m_sharedArray->size;
}
else
{
unsigned int newSize = m_sharedArray->size + byteArray.m_sharedArray->size;
unsigned int bufferSize = nzGetNewSize(newSize);
nzUInt8* buffer = new nzUInt8[bufferSize+1];
std::memcpy(buffer, m_sharedArray->buffer, m_sharedArray->size);
std::memcpy(&buffer[m_sharedArray->size], byteArray.m_sharedArray->buffer, byteArray.m_sharedArray->size);
ReleaseArray();
m_sharedArray = new SharedArray;
m_sharedArray->buffer = buffer;
m_sharedArray->capacity = bufferSize;
m_sharedArray->size = newSize;
}
return *this;
}
void NzByteArray::Clear()
{
ReleaseArray();
}
nzUInt8* NzByteArray::GetBuffer()
{
EnsureOwnership();
return m_sharedArray->buffer;
}
unsigned int NzByteArray::GetCapacity() const
{
return m_sharedArray->capacity;
}
const nzUInt8* NzByteArray::GetConstBuffer() const
{
return m_sharedArray->buffer;
}
unsigned int NzByteArray::GetSize() const
{
return m_sharedArray->size;
}
NzByteArray& NzByteArray::Insert(int pos, const nzUInt8* buffer, unsigned int bufferLength)
{
if (bufferLength == 0)
return *this;
if (m_sharedArray->size == 0)
return operator=(string);
if (pos < 0)
pos = std::max(static_cast<int>(m_sharedArray->size + pos), 0);
unsigned int start = std::min(static_cast<unsigned int>(pos), m_sharedArray->size);
// Si le buffer est déjà suffisamment grand
if (m_sharedArray->capacity >= m_sharedArray->size + bufferLength)
{
EnsureOwnership();
std::memmove(&m_sharedArray->buffer[start+bufferLength], &m_sharedArray->buffer[start], m_sharedArray->size);
std::memcpy(&m_sharedArray->buffer[start], buffer, bufferLength);
m_sharedArray->size += bufferLength;
}
else
{
unsigned int newSize = m_sharedArray->size+bufferLength;
nzUInt8* newBuffer = new nzUInt8[newSize+1];
nzUInt8* ptr = newBuffer;
const nzUInt8* s = m_sharedArray->buffer;
while (ptr != &newBuffer[start])
*ptr++ = *s++;
while (ptr != &newBuffer[start+bufferLength])
*ptr++ = *buffer++;
std::strcpy(ptr, s);
ReleaseString();
m_sharedArray = new SharedString;
m_sharedArray->allocatedSize = newSize;
m_sharedArray->buffer = newBuffer;
m_sharedArray->size = newSize;
}
return *this;
}
NzByteArray& NzByteArray::Insert(int pos, const NzByteArray& byteArray)
{
if (string.m_sharedArray->size == 0)
return *this;
if (m_sharedArray->size == 0 && m_sharedArray->capacity < string.m_sharedArray->size)
return operator=(string);
if (pos < 0)
pos = std::max(static_cast<int>(m_sharedArray->size + pos), 0);
unsigned int start = std::min(static_cast<unsigned int>(pos), m_sharedArray->size);
// Si le buffer est déjà suffisamment grand
if (m_sharedArray->capacity >= m_sharedArray->size + string.m_sharedArray->size)
{
EnsureOwnership();
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));
m_sharedArray->size += string.m_sharedArray->size;
}
else
{
unsigned int newSize = m_sharedArray->size+string.m_sharedArray->size;
char* newString = new char[newSize+1];
char* ptr = newString;
const char* s = m_sharedArray->string;
while (ptr != &newString[start])
*ptr++ = *s++;
const char* p = string.m_sharedArray->string;
while (ptr != &newString[start+string.m_sharedArray->size])
*ptr++ = *p++;
std::strcpy(ptr, s);
ReleaseString();
m_sharedArray = new SharedString;
m_sharedArray->capacity = newSize;
m_sharedArray->size = newSize;
m_sharedArray->string = newString;
}
return *this;
}
bool NzByteArray::IsEmpty() const
{
return m_sharedArray->size == 0;
}
void NzByteArray::Reserve(unsigned int bufferSize)
{
if (m_sharedArray->allocatedSize >= bufferSize)
return;
nzUInt8* ptr = new nzUInt8[bufferSize+1];
if (m_sharedArray->size > 0)
std::memcpy(ptr, m_sharedArray->buffer, m_sharedArray->size);
unsigned int size = m_sharedArray->size;
ReleaseArray();
m_sharedArray = new SharedString;
m_sharedArray->allocatedSize = bufferSize;
m_sharedArray->buffer = ptr;
m_sharedArray->size = size;
}
NzByteArray::SharedString NzByteArray::emptyArray(0, 0, 0, nullptr);
unsigned int NzByteArray::npos(static_cast<unsigned int>(-1));
*/
// 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/ByteArray.hpp>
#include <algorithm>
#include <cstring>
#include <Nazara/Core/Debug.hpp>
inline unsigned int nzPow2(unsigned int n)
{
unsigned int x = 1;
while(x <= n)
x <<= 1;
return x;
}
// Cet algorithme est inspiré de la documentation de Qt
inline unsigned int nzGetNewSize(unsigned int newSize)
{
if (newSize < 20)
return newSize+4;
else
{
if (newSize < (1 << 12)-12)
return nzPow2(newSize << 1)-12;
else
return newSize + (1 << 11);
}
}
NzByteArray::NzByteArray() :
m_sharedArray(&emptyArray)
{
}
NzByteArray::NzByteArray(const nzUInt8* buffer, unsigned int bufferLength)
{
if (bufferLength > 0)
{
m_sharedArray = new SharedArray;
m_sharedArray->buffer = new nzUInt8[bufferLength];
m_sharedArray->capacity = bufferLength;
m_sharedArray->size = bufferLength;
std::memcpy(m_sharedArray->buffer, buffer, bufferLength);
}
else
m_sharedArray = &emptyArray;
}
NzByteArray::NzByteArray(const NzByteArray& buffer) :
m_sharedArray(buffer.m_sharedArray)
{
if (m_sharedArray != &emptyArray)
{
NazaraMutexLock(m_sharedArray->mutex);
m_sharedArray->refCount++;
NazaraMutexUnlock(m_sharedArray->mutex);
}
}
NzByteArray::NzByteArray(NzByteArray&& buffer) noexcept :
m_sharedArray(buffer.m_sharedArray)
{
buffer.m_sharedArray = &emptyArray;
}
NzByteArray::NzByteArray(SharedArray* sharedArray) :
m_sharedArray(sharedArray)
{
}
NzByteArray::~NzByteArray()
{
ReleaseArray();
}
NzByteArray& NzByteArray::Append(const NzByteArray& byteArray)
{
if (byteArray.m_sharedArray->size == 0)
return *this;
if (m_sharedArray->size == 0 && m_sharedArray->capacity < byteArray.m_sharedArray->size)
return operator=(byteArray);
if (m_sharedArray->capacity >= m_sharedArray->size + byteArray.m_sharedArray->size)
{
EnsureOwnership();
std::memcpy(&m_sharedArray->buffer[m_sharedArray->size], byteArray.m_sharedArray->buffer, byteArray.m_sharedArray->size);
m_sharedArray->size += byteArray.m_sharedArray->size;
}
else
{
unsigned int newSize = m_sharedArray->size + byteArray.m_sharedArray->size;
unsigned int bufferSize = nzGetNewSize(newSize);
nzUInt8* buffer = new nzUInt8[bufferSize+1];
std::memcpy(buffer, m_sharedArray->buffer, m_sharedArray->size);
std::memcpy(&buffer[m_sharedArray->size], byteArray.m_sharedArray->buffer, byteArray.m_sharedArray->size);
ReleaseArray();
m_sharedArray = new SharedArray;
m_sharedArray->buffer = buffer;
m_sharedArray->capacity = bufferSize;
m_sharedArray->size = newSize;
}
return *this;
}
void NzByteArray::Clear()
{
ReleaseArray();
}
nzUInt8* NzByteArray::GetBuffer()
{
EnsureOwnership();
return m_sharedArray->buffer;
}
unsigned int NzByteArray::GetCapacity() const
{
return m_sharedArray->capacity;
}
const nzUInt8* NzByteArray::GetConstBuffer() const
{
return m_sharedArray->buffer;
}
unsigned int NzByteArray::GetSize() const
{
return m_sharedArray->size;
}
NzByteArray& NzByteArray::Insert(int pos, const nzUInt8* buffer, unsigned int bufferLength)
{
if (bufferLength == 0)
return *this;
if (m_sharedArray->size == 0)
return operator=(string);
if (pos < 0)
pos = std::max(static_cast<int>(m_sharedArray->size + pos), 0);
unsigned int start = std::min(static_cast<unsigned int>(pos), m_sharedArray->size);
// Si le buffer est déjà suffisamment grand
if (m_sharedArray->capacity >= m_sharedArray->size + bufferLength)
{
EnsureOwnership();
std::memmove(&m_sharedArray->buffer[start+bufferLength], &m_sharedArray->buffer[start], m_sharedArray->size);
std::memcpy(&m_sharedArray->buffer[start], buffer, bufferLength);
m_sharedArray->size += bufferLength;
}
else
{
unsigned int newSize = m_sharedArray->size+bufferLength;
nzUInt8* newBuffer = new nzUInt8[newSize+1];
nzUInt8* ptr = newBuffer;
const nzUInt8* s = m_sharedArray->buffer;
while (ptr != &newBuffer[start])
*ptr++ = *s++;
while (ptr != &newBuffer[start+bufferLength])
*ptr++ = *buffer++;
std::strcpy(ptr, s);
ReleaseString();
m_sharedArray = new SharedString;
m_sharedArray->allocatedSize = newSize;
m_sharedArray->buffer = newBuffer;
m_sharedArray->size = newSize;
}
return *this;
}
NzByteArray& NzByteArray::Insert(int pos, const NzByteArray& byteArray)
{
if (string.m_sharedArray->size == 0)
return *this;
if (m_sharedArray->size == 0 && m_sharedArray->capacity < string.m_sharedArray->size)
return operator=(string);
if (pos < 0)
pos = std::max(static_cast<int>(m_sharedArray->size + pos), 0);
unsigned int start = std::min(static_cast<unsigned int>(pos), m_sharedArray->size);
// Si le buffer est déjà suffisamment grand
if (m_sharedArray->capacity >= m_sharedArray->size + string.m_sharedArray->size)
{
EnsureOwnership();
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));
m_sharedArray->size += string.m_sharedArray->size;
}
else
{
unsigned int newSize = m_sharedArray->size+string.m_sharedArray->size;
char* newString = new char[newSize+1];
char* ptr = newString;
const char* s = m_sharedArray->string;
while (ptr != &newString[start])
*ptr++ = *s++;
const char* p = string.m_sharedArray->string;
while (ptr != &newString[start+string.m_sharedArray->size])
*ptr++ = *p++;
std::strcpy(ptr, s);
ReleaseString();
m_sharedArray = new SharedString;
m_sharedArray->capacity = newSize;
m_sharedArray->size = newSize;
m_sharedArray->string = newString;
}
return *this;
}
bool NzByteArray::IsEmpty() const
{
return m_sharedArray->size == 0;
}
void NzByteArray::Reserve(unsigned int bufferSize)
{
if (m_sharedArray->allocatedSize >= bufferSize)
return;
nzUInt8* ptr = new nzUInt8[bufferSize+1];
if (m_sharedArray->size > 0)
std::memcpy(ptr, m_sharedArray->buffer, m_sharedArray->size);
unsigned int size = m_sharedArray->size;
ReleaseArray();
m_sharedArray = new SharedString;
m_sharedArray->allocatedSize = bufferSize;
m_sharedArray->buffer = ptr;
m_sharedArray->size = size;
}
NzByteArray::SharedString NzByteArray::emptyArray(0, 0, 0, nullptr);
unsigned int NzByteArray::npos(static_cast<unsigned int>(-1));
*/

View File

@ -1,264 +1,271 @@
// 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/Debug/MemoryLeakTracker.hpp>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <stdexcept>
#if defined(NAZARA_PLATFORM_WINDOWS)
#include <windows.h>
#elif defined(NAZARA_PLATFORM_POSIX)
#include <pthread.h>
#endif
namespace
{
struct Block
{
std::size_t size;
const char* file;
Block* prev;
Block* next;
bool array;
unsigned int line;
unsigned int magic;
};
bool initialized = false;
const unsigned int magic = 0x51429EE;
const char* MLTFileName = "NazaraLeaks.log";
const char* nextFreeFile = "Internal error";
unsigned int nextFreeLine = 0;
Block ptrList =
{
0,
nullptr,
&ptrList,
&ptrList,
false,
0,
magic
};
#if defined(NAZARA_PLATFORM_WINDOWS)
CRITICAL_SECTION mutex;
#elif defined(NAZARA_PLATFORM_POSIX)
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
}
NzMemoryManager::NzMemoryManager()
{
}
NzMemoryManager::~NzMemoryManager()
{
Uninitialize();
}
void* NzMemoryManager::Allocate(std::size_t size, bool multi, const char* file, unsigned int line)
{
if (!initialized)
Initialize();
#if defined(NAZARA_PLATFORM_WINDOWS)
EnterCriticalSection(&mutex);
#elif defined(NAZARA_PLATFORM_POSIX)
pthread_mutex_lock(&mutex);
#endif
Block* ptr = reinterpret_cast<Block*>(std::malloc(size+sizeof(Block)));
if (!ptr)
return nullptr; // Impossible d'envoyer une exception car cela allouerait de la mémoire avec new (boucle infinie)
ptr->array = multi;
ptr->file = file;
ptr->line = line;
ptr->size = size;
ptr->magic = magic;
ptr->prev = ptrList.prev;
ptr->next = &ptrList;
ptrList.prev->next = ptr;
ptrList.prev = ptr;
#if defined(NAZARA_PLATFORM_WINDOWS)
LeaveCriticalSection(&mutex);
#elif defined(NAZARA_PLATFORM_POSIX)
pthread_mutex_unlock(&mutex);
#endif
return reinterpret_cast<char*>(ptr)+sizeof(Block);
}
void NzMemoryManager::Free(void* pointer, bool multi)
{
if (!pointer)
return;
Block* ptr = reinterpret_cast<Block*>(reinterpret_cast<char*>(pointer)-sizeof(Block));
if (ptr->magic != magic)
return;
#if defined(NAZARA_PLATFORM_WINDOWS)
EnterCriticalSection(&mutex);
#elif defined(NAZARA_PLATFORM_POSIX)
pthread_mutex_lock(&mutex);
#endif
if (ptr->array != multi)
{
char* time = TimeInfo();
FILE* log = std::fopen(MLTFileName, "a");
if (nextFreeFile)
{
if (multi)
std::fprintf(log, "%s Warning: delete[] after new at %s:%d\n", time, nextFreeFile, nextFreeLine);
else
std::fprintf(log, "%s Warning: delete after new[] at %s:%d\n", time, nextFreeFile, nextFreeLine);
}
else
{
if (multi)
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);
}
std::fclose(log);
std::free(time);
}
ptr->magic = 0;
ptr->prev->next = ptr->next;
ptr->next->prev = ptr->prev;
std::free(ptr);
nextFreeFile = nullptr;
nextFreeLine = 0;
#if defined(NAZARA_PLATFORM_WINDOWS)
LeaveCriticalSection(&mutex);
#elif defined(NAZARA_PLATFORM_POSIX)
pthread_mutex_unlock(&mutex);
#endif
}
void NzMemoryManager::NextFree(const char* file, unsigned int line)
{
nextFreeFile = file;
nextFreeLine = line;
}
void NzMemoryManager::Initialize()
{
char* time = TimeInfo();
FILE* file = std::fopen(MLTFileName, "w");
std::fprintf(file, "%s ==============================\n", time);
std::fprintf(file, "%s Nazara Memory Leak Tracker \n", time);
std::fprintf(file, "%s ==============================\n", time);
std::fclose(file);
std::free(time);
if (std::atexit(Uninitialize) != 0)
{
static NzMemoryManager manager;
}
#ifdef NAZARA_PLATFORM_WINDOWS
InitializeCriticalSection(&mutex);
#endif
initialized = true;
}
char* NzMemoryManager::TimeInfo()
{
char* buffer = reinterpret_cast<char*>(std::malloc(23*sizeof(char)));
time_t currentTime = std::time(nullptr);
std::strftime(buffer, 23, "%d/%m/%Y - %H:%M:%S:", std::localtime(&currentTime));
return buffer;
}
void NzMemoryManager::Uninitialize()
{
#ifdef NAZARA_PLATFORM_WINDOWS
DeleteCriticalSection(&mutex);
#endif
FILE* log = std::fopen(MLTFileName, "a");
char* time = TimeInfo();
std::fprintf(log, "%s Application finished, checking leaks...\n", time);
if (ptrList.next == &ptrList)
{
std::fprintf(log, "%s ==============================\n", time);
std::fprintf(log, "%s No leak detected \n", time);
std::fprintf(log, "%s ==============================", time);
}
else
{
std::fprintf(log, "%s ==============================\n", time);
std::fprintf(log, "%s Leaks have been detected \n", time);
std::fprintf(log, "%s ==============================\n\n", time);
std::fputs("Leak list:\n", log);
Block* ptr = ptrList.next;
unsigned int count = 0;
unsigned int totalSize = 0;
while (ptr != &ptrList)
{
count++;
totalSize += ptr->size;
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, "-0x%p -> %d bytes allocated at unknown position\n", reinterpret_cast<char*>(ptr)+sizeof(Block), ptr->size);
void* pointer = ptr;
ptr = ptr->next;
std::free(pointer);
}
std::fprintf(log, "\n%d blocks leaked (%d bytes)", count, totalSize);
}
std::free(time);
std::fclose(log);
}
void* operator new(std::size_t size, const char* file, unsigned int line)
{
return NzMemoryManager::Allocate(size, false, file, line);
}
void* operator new[](std::size_t size, const char* file, unsigned int line)
{
return NzMemoryManager::Allocate(size, true, file, line);
}
void operator delete(void* ptr, const char* file, unsigned int line) throw()
{
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);
}
// 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/Debug/MemoryLeakTracker.hpp>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <stdexcept>
#if defined(NAZARA_PLATFORM_WINDOWS)
#include <windows.h>
#elif defined(NAZARA_PLATFORM_POSIX)
#include <pthread.h>
#endif
namespace
{
struct Block
{
std::size_t size;
const char* file;
Block* prev;
Block* next;
bool array;
unsigned int line;
unsigned int magic;
};
bool initialized = false;
const unsigned int magic = 0x51429EE;
const char* MLTFileName = "NazaraLeaks.log";
const char* nextFreeFile = "Internal error";
unsigned int nextFreeLine = 0;
Block ptrList =
{
0,
nullptr,
&ptrList,
&ptrList,
false,
0,
magic
};
#if defined(NAZARA_PLATFORM_WINDOWS)
CRITICAL_SECTION mutex;
#elif defined(NAZARA_PLATFORM_POSIX)
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
}
NzMemoryManager::NzMemoryManager()
{
}
NzMemoryManager::~NzMemoryManager()
{
Uninitialize();
}
void* NzMemoryManager::Allocate(std::size_t size, bool multi, const char* file, unsigned int line)
{
if (!initialized)
Initialize();
#if defined(NAZARA_PLATFORM_WINDOWS)
EnterCriticalSection(&mutex);
#elif defined(NAZARA_PLATFORM_POSIX)
pthread_mutex_lock(&mutex);
#endif
Block* ptr = reinterpret_cast<Block*>(std::malloc(size+sizeof(Block)));
if (!ptr)
{
// Pas d'information de temps (Car nécessitant une allocation)
FILE* log = std::fopen(MLTFileName, "a");
std::fprintf(log, "Failed to allocate memory (%d bytes)\n", size);
std::fclose(log);
return nullptr; // Impossible d'envoyer une exception car cela allouerait de la mémoire avec new (boucle infinie)
}
ptr->array = multi;
ptr->file = file;
ptr->line = line;
ptr->size = size;
ptr->magic = magic;
ptr->prev = ptrList.prev;
ptr->next = &ptrList;
ptrList.prev->next = ptr;
ptrList.prev = ptr;
#if defined(NAZARA_PLATFORM_WINDOWS)
LeaveCriticalSection(&mutex);
#elif defined(NAZARA_PLATFORM_POSIX)
pthread_mutex_unlock(&mutex);
#endif
return reinterpret_cast<char*>(ptr)+sizeof(Block);
}
void NzMemoryManager::Free(void* pointer, bool multi)
{
if (!pointer)
return;
Block* ptr = reinterpret_cast<Block*>(reinterpret_cast<char*>(pointer)-sizeof(Block));
if (ptr->magic != magic)
return;
#if defined(NAZARA_PLATFORM_WINDOWS)
EnterCriticalSection(&mutex);
#elif defined(NAZARA_PLATFORM_POSIX)
pthread_mutex_lock(&mutex);
#endif
if (ptr->array != multi)
{
char* time = TimeInfo();
FILE* log = std::fopen(MLTFileName, "a");
if (nextFreeFile)
{
if (multi)
std::fprintf(log, "%s Warning: delete[] after new at %s:%d\n", time, nextFreeFile, nextFreeLine);
else
std::fprintf(log, "%s Warning: delete after new[] at %s:%d\n", time, nextFreeFile, nextFreeLine);
}
else
{
if (multi)
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);
}
std::fclose(log);
std::free(time);
}
ptr->magic = 0;
ptr->prev->next = ptr->next;
ptr->next->prev = ptr->prev;
std::free(ptr);
nextFreeFile = nullptr;
nextFreeLine = 0;
#if defined(NAZARA_PLATFORM_WINDOWS)
LeaveCriticalSection(&mutex);
#elif defined(NAZARA_PLATFORM_POSIX)
pthread_mutex_unlock(&mutex);
#endif
}
void NzMemoryManager::NextFree(const char* file, unsigned int line)
{
nextFreeFile = file;
nextFreeLine = line;
}
void NzMemoryManager::Initialize()
{
char* time = TimeInfo();
FILE* file = std::fopen(MLTFileName, "w");
std::fprintf(file, "%s ==============================\n", time);
std::fprintf(file, "%s Nazara Memory Leak Tracker \n", time);
std::fprintf(file, "%s ==============================\n", time);
std::fclose(file);
std::free(time);
if (std::atexit(Uninitialize) != 0)
{
static NzMemoryManager manager;
}
#ifdef NAZARA_PLATFORM_WINDOWS
InitializeCriticalSection(&mutex);
#endif
initialized = true;
}
char* NzMemoryManager::TimeInfo()
{
char* buffer = reinterpret_cast<char*>(std::malloc(23*sizeof(char)));
time_t currentTime = std::time(nullptr);
std::strftime(buffer, 23, "%d/%m/%Y - %H:%M:%S:", std::localtime(&currentTime));
return buffer;
}
void NzMemoryManager::Uninitialize()
{
#ifdef NAZARA_PLATFORM_WINDOWS
DeleteCriticalSection(&mutex);
#endif
FILE* log = std::fopen(MLTFileName, "a");
char* time = TimeInfo();
std::fprintf(log, "%s Application finished, checking leaks...\n", time);
if (ptrList.next == &ptrList)
{
std::fprintf(log, "%s ==============================\n", time);
std::fprintf(log, "%s No leak detected \n", time);
std::fprintf(log, "%s ==============================", time);
}
else
{
std::fprintf(log, "%s ==============================\n", time);
std::fprintf(log, "%s Leaks have been detected \n", time);
std::fprintf(log, "%s ==============================\n\n", time);
std::fputs("Leak list:\n", log);
Block* ptr = ptrList.next;
unsigned int count = 0;
unsigned int totalSize = 0;
while (ptr != &ptrList)
{
count++;
totalSize += ptr->size;
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, "-0x%p -> %d bytes allocated at unknown position\n", reinterpret_cast<char*>(ptr)+sizeof(Block), ptr->size);
void* pointer = ptr;
ptr = ptr->next;
std::free(pointer);
}
std::fprintf(log, "\n%d blocks leaked (%d bytes)", count, totalSize);
}
std::free(time);
std::fclose(log);
}
void* operator new(std::size_t size, const char* file, unsigned int line)
{
return NzMemoryManager::Allocate(size, false, file, line);
}
void* operator new[](std::size_t size, const char* file, unsigned int line)
{
return NzMemoryManager::Allocate(size, true, file, line);
}
void operator delete(void* ptr, const char* file, unsigned int line) throw()
{
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
// 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/Resource.hpp>
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Debug.hpp>
NzResource::NzResource(bool persistent) :
m_resourcePersistent(persistent),
m_resourceReferenceCount(0)
{
}
NzResource::NzResource(const NzResource& resource) :
m_resourcePersistent(resource.m_resourcePersistent),
m_resourceReferenceCount(0)
{
}
NzResource::~NzResource() = default;
void NzResource::AddResourceReference() const
{
m_resourceReferenceCount++;
}
bool NzResource::IsPersistent() const
{
return m_resourcePersistent;
}
void NzResource::RemoveResourceReference() const
{
#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)
delete this;
}
void NzResource::SetPersistent(bool persistent)
{
m_resourcePersistent = persistent;
if (!persistent && m_resourceReferenceCount == 0)
delete this;
}
// 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/Resource.hpp>
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/ResourceListener.hpp>
#include <Nazara/Core/Debug.hpp>
NzResource::NzResource(bool persistent) :
m_resourcePersistent(persistent),
m_resourceReferenceCount(0)
{
}
NzResource::NzResource(const NzResource& resource) :
m_resourcePersistent(resource.m_resourcePersistent),
m_resourceReferenceCount(0)
{
}
NzResource::~NzResource()
{
EnsureResourceListenerUpdate();
for (auto it = m_resourceListenersCache.begin(); it != m_resourceListenersCache.end(); ++it)
(*it).listener->OnResourceReleased(this, (*it).index);
}
void NzResource::AddResourceListener(NzResourceListener* listener, int index) const
{
NazaraLock(m_mutex)
if (m_resourceListeners.insert(NzResourceEntry(listener, index)).second)
{
m_resourceListenerUpdated = false;
// AddResourceReference()
m_resourceReferenceCount++;
}
}
void NzResource::AddResourceReference() const
{
NazaraLock(m_mutex)
m_resourceReferenceCount++;
}
bool NzResource::IsPersistent() const
{
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
// 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/Context.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Log.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <vector>
#if defined(NAZARA_PLATFORM_WINDOWS)
#include <Nazara/Renderer/Win32/ContextImpl.hpp>
#elif defined(NAZARA_PLATFORM_LINUX)
#include <Nazara/Renderer/Linux/ContextImpl.hpp>
#else
#error Lack of implementation: Context
#endif
#include <Nazara/Renderer/Debug.hpp>
namespace
{
NAZARA_THREADLOCAL NzContext* currentContext = nullptr;
NAZARA_THREADLOCAL NzContext* threadContext = nullptr;
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)
{
NazaraUnused(length);
NzStringStream ss;
ss << "OpenGL debug message (ID: 0x" << NzString::Number(id, 16) << "):\n";
ss << "Sent by context: " << userParam;
ss << "\n-Source: ";
switch (source)
{
case GL_DEBUG_SOURCE_API_ARB:
ss << "OpenGL";
break;
case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
ss << "Operating system";
break;
case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
ss << "Shader compiler";
break;
case GL_DEBUG_SOURCE_THIRD_PARTY_ARB:
ss << "Shader compiler";
break;
case GL_DEBUG_SOURCE_APPLICATION_ARB:
ss << "Application";
break;
case GL_DEBUG_SOURCE_OTHER_ARB:
ss << "Other";
break;
default:
// Peut être rajouté par une extension
ss << "Unknown";
break;
}
ss << '\n';
ss << "-Type: ";
switch (type)
{
case GL_DEBUG_TYPE_ERROR_ARB:
ss << "Error";
break;
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
ss << "Deprecated behavior";
break;
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
ss << "Undefined behavior";
break;
case GL_DEBUG_TYPE_PORTABILITY_ARB:
ss << "Portability";
break;
case GL_DEBUG_TYPE_PERFORMANCE_ARB:
ss << "Performance";
break;
case GL_DEBUG_TYPE_OTHER_ARB:
ss << "Other";
break;
default:
// Peut être rajouté par une extension
ss << "Unknown";
break;
}
ss << '\n';
ss << "-Severity: ";
switch (severity)
{
case GL_DEBUG_SEVERITY_HIGH_ARB:
ss << "High";
break;
case GL_DEBUG_SEVERITY_MEDIUM_ARB:
ss << "Medium";
break;
case GL_DEBUG_SEVERITY_LOW_ARB:
ss << "Low";
break;
default:
// Peut être rajouté par une extension
ss << "Unknown";
break;
}
ss << '\n';
ss << "Message: " << message << '\n';
NazaraNotice(ss);
}
}
NzContext::NzContext() :
m_impl(nullptr)
{
}
NzContext::~NzContext()
{
Destroy();
}
bool NzContext::Create(const NzContextParameters& parameters)
{
Destroy();
m_parameters = parameters;
if (m_parameters.shared && !m_parameters.shareContext)
m_parameters.shareContext = s_reference;
m_impl = new NzContextImpl;
if (!m_impl->Create(m_parameters))
{
NazaraError("Failed to create context implementation");
delete m_impl;
m_impl = nullptr;
return false;
}
if (!m_impl->Activate())
{
NazaraError("Failed to activate context");
m_impl->Destroy();
delete m_impl;
m_impl = nullptr;
return false;
}
if (m_parameters.antialiasingLevel > 0)
glEnable(GL_MULTISAMPLE);
if (NzOpenGL::IsSupported(NzOpenGL::DebugOutput) && m_parameters.debugMode)
{
glDebugMessageCallback(&DebugCallback, this);
#ifdef NAZARA_DEBUG
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
#endif
}
return true;
}
void NzContext::Destroy()
{
if (m_impl)
{
if (currentContext == this)
NzContextImpl::Desactivate();
m_impl->Destroy();
delete m_impl;
m_impl = nullptr;
}
}
const NzContextParameters& NzContext::GetParameters() const
{
#ifdef NAZARA_RENDERER_SAFE
if (!m_impl)
NazaraError("No context has been created");
#endif
return m_parameters;
}
bool NzContext::IsActive() const
{
#ifdef NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("No context has been created");
return false;
}
#endif
return currentContext == this;
}
bool NzContext::SetActive(bool active)
{
#ifdef NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("No context has been created");
return false;
}
#endif
// Si le contexte est déjà activé/désactivé
if ((currentContext == this) == active)
return true;
if (active)
{
if (!m_impl->Activate())
return false;
currentContext = this;
}
else
{
if (!NzContextImpl::Desactivate())
return false;
currentContext = nullptr;
}
return true;
}
void NzContext::SwapBuffers()
{
#ifdef NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("No context has been created");
return;
}
if (!m_parameters.doubleBuffered)
{
NazaraError("Context is not double buffered");
return;
}
#endif
m_impl->SwapBuffers();
}
bool NzContext::EnsureContext()
{
if (!currentContext)
{
if (!threadContext)
{
NzContext* context = new NzContext;
if (!context->Create())
{
NazaraError("Failed to create context");
delete context;
return false;
}
contexts.push_back(context);
threadContext = context;
}
if (!threadContext->SetActive(true))
{
NazaraError("Failed to active thread context");
return false;
}
}
return true;
}
NzContext* NzContext::GetCurrent()
{
return currentContext;
}
const NzContext* NzContext::GetReference()
{
return s_reference;
}
NzContext* NzContext::GetThreadContext()
{
EnsureContext();
return threadContext;
}
bool NzContext::Initialize()
{
NzContextParameters parameters;
// parameters.compatibilityProfile = true;
parameters.shared = false; // Difficile de partager le contexte de référence avec lui-même
s_reference = new NzContext;
if (!s_reference->Create(parameters))
{
delete s_reference;
s_reference = nullptr;
return false;
}
// Le contexte de référence doit rester désactivé pour le partage
s_reference->SetActive(false);
NzContextParameters::defaultShareContext = s_reference;
return true;
}
void NzContext::Uninitialize()
{
for (NzContext* context : contexts)
delete context;
contexts.clear(); // On supprime tous les contextes créés
delete s_reference;
s_reference = nullptr;
}
NzContext* NzContext::s_reference = nullptr;
// 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/Context.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Log.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <vector>
#if defined(NAZARA_PLATFORM_WINDOWS)
#include <Nazara/Renderer/Win32/ContextImpl.hpp>
#elif defined(NAZARA_PLATFORM_LINUX)
#include <Nazara/Renderer/Linux/ContextImpl.hpp>
#else
#error Lack of implementation: Context
#endif
#include <Nazara/Renderer/Debug.hpp>
namespace
{
NAZARA_THREADLOCAL NzContext* currentContext = nullptr;
NAZARA_THREADLOCAL NzContext* threadContext = nullptr;
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)
{
NazaraUnused(length);
NzStringStream ss;
ss << "OpenGL debug message (ID: 0x" << NzString::Number(id, 16) << "):\n";
ss << "Sent by context: " << userParam;
ss << "\n-Source: ";
switch (source)
{
case GL_DEBUG_SOURCE_API_ARB:
ss << "OpenGL";
break;
case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
ss << "Operating system";
break;
case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
ss << "Shader compiler";
break;
case GL_DEBUG_SOURCE_THIRD_PARTY_ARB:
ss << "Shader compiler";
break;
case GL_DEBUG_SOURCE_APPLICATION_ARB:
ss << "Application";
break;
case GL_DEBUG_SOURCE_OTHER_ARB:
ss << "Other";
break;
default:
// Peut être rajouté par une extension
ss << "Unknown";
break;
}
ss << '\n';
ss << "-Type: ";
switch (type)
{
case GL_DEBUG_TYPE_ERROR_ARB:
ss << "Error";
break;
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
ss << "Deprecated behavior";
break;
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
ss << "Undefined behavior";
break;
case GL_DEBUG_TYPE_PORTABILITY_ARB:
ss << "Portability";
break;
case GL_DEBUG_TYPE_PERFORMANCE_ARB:
ss << "Performance";
break;
case GL_DEBUG_TYPE_OTHER_ARB:
ss << "Other";
break;
default:
// Peut être rajouté par une extension
ss << "Unknown";
break;
}
ss << '\n';
ss << "-Severity: ";
switch (severity)
{
case GL_DEBUG_SEVERITY_HIGH_ARB:
ss << "High";
break;
case GL_DEBUG_SEVERITY_MEDIUM_ARB:
ss << "Medium";
break;
case GL_DEBUG_SEVERITY_LOW_ARB:
ss << "Low";
break;
default:
// Peut être rajouté par une extension
ss << "Unknown";
break;
}
ss << '\n';
ss << "Message: " << message << '\n';
NazaraNotice(ss);
}
}
NzContext::NzContext() :
m_impl(nullptr)
{
}
NzContext::~NzContext()
{
Destroy();
}
bool NzContext::Create(const NzContextParameters& parameters)
{
Destroy();
m_parameters = parameters;
if (m_parameters.shared && !m_parameters.shareContext)
m_parameters.shareContext = s_reference;
m_impl = new NzContextImpl;
if (!m_impl->Create(m_parameters))
{
NazaraError("Failed to create context implementation");
delete m_impl;
m_impl = nullptr;
return false;
}
if (!m_impl->Activate())
{
NazaraError("Failed to activate context");
m_impl->Destroy();
delete m_impl;
m_impl = nullptr;
return false;
}
if (m_parameters.antialiasingLevel > 0)
glEnable(GL_MULTISAMPLE);
if (NzOpenGL::IsSupported(nzOpenGLExtension_DebugOutput) && m_parameters.debugMode)
{
glDebugMessageCallback(&DebugCallback, this);
#ifdef NAZARA_DEBUG
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
#endif
}
NotifyCreated();
return true;
}
void NzContext::Destroy()
{
if (m_impl)
{
NotifyDestroy();
if (currentContext == this)
NzContextImpl::Desactivate();
m_impl->Destroy();
delete m_impl;
m_impl = nullptr;
}
}
const NzContextParameters& NzContext::GetParameters() const
{
#ifdef NAZARA_RENDERER_SAFE
if (!m_impl)
NazaraError("No context has been created");
#endif
return m_parameters;
}
bool NzContext::IsActive() const
{
#ifdef NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("No context has been created");
return false;
}
#endif
return currentContext == this;
}
bool NzContext::SetActive(bool active)
{
#ifdef NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("No context has been created");
return false;
}
#endif
// Si le contexte est déjà activé/désactivé
if ((currentContext == this) == active)
return true;
if (active)
{
if (!m_impl->Activate())
return false;
currentContext = this;
}
else
{
if (!NzContextImpl::Desactivate())
return false;
currentContext = nullptr;
}
return true;
}
void NzContext::SwapBuffers()
{
#ifdef NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("No context has been created");
return;
}
if (!m_parameters.doubleBuffered)
{
NazaraError("Context is not double buffered");
return;
}
#endif
m_impl->SwapBuffers();
}
bool NzContext::EnsureContext()
{
if (!currentContext)
{
if (!threadContext)
{
NzContext* context = new NzContext;
if (!context->Create())
{
NazaraError("Failed to create context");
delete context;
return false;
}
contexts.push_back(context);
threadContext = context;
}
if (!threadContext->SetActive(true))
{
NazaraError("Failed to active thread context");
return false;
}
}
return true;
}
NzContext* NzContext::GetCurrent()
{
return currentContext;
}
const NzContext* NzContext::GetReference()
{
return s_reference;
}
NzContext* NzContext::GetThreadContext()
{
EnsureContext();
return threadContext;
}
bool NzContext::Initialize()
{
NzContextParameters parameters;
// parameters.compatibilityProfile = true;
parameters.shared = false; // Difficile de partager le contexte de référence avec lui-même
s_reference = new NzContext;
if (!s_reference->Create(parameters))
{
delete s_reference;
s_reference = nullptr;
return false;
}
// Le contexte de référence doit rester désactivé pour le partage
s_reference->SetActive(false);
NzContextParameters::defaultShareContext = s_reference;
return true;
}
void NzContext::Uninitialize()
{
for (NzContext* context : contexts)
delete context;
contexts.clear(); // On supprime tous les contextes créés
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
// 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_GLSLSHADER_HPP
#define NAZARA_GLSLSHADER_HPP
#include <Nazara/Core/String.hpp>
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/Shader.hpp>
#include <Nazara/Renderer/ShaderImpl.hpp>
#include <map>
class NzGLSLShader : public NzShaderImpl
{
public:
NzGLSLShader(NzShader* parent);
~NzGLSLShader();
bool Bind();
bool BindTextures();
bool Compile();
bool Create();
void Destroy();
NzString GetLog() const;
nzShaderLanguage GetLanguage() const;
NzString GetSourceCode(nzShaderType type) const;
int GetUniformLocation(const NzString& name) const;
bool IsLoaded(nzShaderType type) const;
bool Load(nzShaderType type, const NzString& source);
bool Lock();
bool SendBoolean(int location, bool value);
bool SendDouble(int location, double value);
bool SendFloat(int location, float value);
bool SendInteger(int location, int value);
bool SendMatrix(int location, const NzMatrix4d& matrix);
bool SendMatrix(int location, const NzMatrix4f& matrix);
bool SendTexture(int location, const NzTexture* texture);
bool SendVector(int location, const NzVector2d& vector);
bool SendVector(int location, const NzVector2f& vector);
bool SendVector(int location, const NzVector3d& vector);
bool SendVector(int location, const NzVector3f& vector);
bool SendVector(int location, const NzVector4d& vector);
bool SendVector(int location, const NzVector4f& vector);
void Unbind();
void Unlock();
private:
struct TextureSlot
{
bool updated = false;
nzUInt8 unit;
const NzTexture* texture;
};
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
// 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_GLSLSHADER_HPP
#define NAZARA_GLSLSHADER_HPP
#include <Nazara/Core/ResourceListener.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/Shader.hpp>
#include <Nazara/Renderer/ShaderImpl.hpp>
#include <map>
class NzResource;
class NzGLSLShader : public NzShaderImpl, NzResourceListener
{
public:
NzGLSLShader(NzShader* parent);
~NzGLSLShader();
bool Bind();
bool BindTextures();
bool Compile();
bool Create();
void Destroy();
NzString GetLog() const;
nzShaderLanguage GetLanguage() const;
NzString GetSourceCode(nzShaderType type) const;
int GetUniformLocation(const NzString& name) const;
bool IsLoaded(nzShaderType type) const;
bool Load(nzShaderType type, const NzString& source);
bool Lock();
bool SendBoolean(int location, bool value);
bool SendDouble(int location, double value);
bool SendFloat(int location, float value);
bool SendInteger(int location, int value);
bool SendMatrix(int location, const NzMatrix4d& matrix);
bool SendMatrix(int location, const NzMatrix4f& matrix);
bool SendTexture(int location, const NzTexture* texture);
bool SendVector(int location, const NzVector2d& vector);
bool SendVector(int location, const NzVector2f& vector);
bool SendVector(int location, const NzVector3d& vector);
bool SendVector(int location, const NzVector3f& vector);
bool SendVector(int location, const NzVector4d& vector);
bool SendVector(int location, const NzVector4f& vector);
void Unbind();
void Unlock();
private:
void OnResourceCreated(const NzResource* resource, int index) override;
void OnResourceDestroy(const NzResource* resource, int index) override;
void OnResourceReleased(const NzResource* resource, int index) override;
struct TextureSlot
{
bool enabled;
bool updated = false;
nzUInt8 unit;
const NzTexture* texture;
};
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
// 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/HardwareBuffer.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <cstring>
#include <stdexcept>
#include <Nazara/Renderer/Debug.hpp>
namespace
{
GLenum bufferLock[] = {
GL_WRITE_ONLY, // nzBufferAccess_DiscardAndWrite
GL_READ_ONLY, // nzBufferAccess_ReadOnly
GL_READ_WRITE, // nzBufferAccess_ReadWrite
GL_WRITE_ONLY // nzBufferAccess_WriteOnly
};
GLenum bufferLockRange[] = {
GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_WRITE_BIT, // nzBufferAccess_DiscardAndWrite
GL_MAP_READ_BIT, // nzBufferAccess_ReadOnly
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, // nzBufferAccess_ReadWrite
GL_MAP_WRITE_BIT // nzBufferAccess_WriteOnly
};
GLenum bufferTarget[] = {
GL_ELEMENT_ARRAY_BUFFER, // nzBufferType_Index,
GL_ARRAY_BUFFER, // nzBufferType_Vertex
};
GLenum bufferTargetBinding[] = {
GL_ELEMENT_ARRAY_BUFFER_BINDING, // nzBufferType_Index,
GL_ARRAY_BUFFER_BINDING, // nzBufferType_Vertex
};
GLenum bufferUsage[] = {
// J'ai choisi DYNAMIC à la place de STREAM car DYNAMIC semble plus adapté au profil "une mise à jour pour quelques rendus"
// 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
GL_DYNAMIC_DRAW, // nzBufferUsage_Dynamic
GL_STATIC_DRAW // nzBufferUsage_Static
};
using LockRoutine = nzUInt8* (*)(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size);
nzUInt8* LockBuffer(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size)
{
NazaraUnused(size);
if (access == nzBufferAccess_DiscardAndWrite)
{
GLint bufSize;
glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_SIZE, &bufSize);
GLint bufUsage;
glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_USAGE, &bufUsage);
// On discard le buffer
glBufferData(bufferTargetBinding[type], bufSize, nullptr, bufUsage);
}
void* ptr = glMapBuffer(bufferTarget[type], bufferLock[access]);
if (ptr)
return reinterpret_cast<nzUInt8*>(ptr) + offset;
else
return nullptr;
}
nzUInt8* LockBufferRange(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size)
{
return reinterpret_cast<nzUInt8*>(glMapBufferRange(bufferTarget[type], offset, size, bufferLockRange[access]));
}
nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size);
LockRoutine mapBuffer = LockBufferFirstRun;
nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size)
{
if (glMapBufferRange)
mapBuffer = LockBufferRange;
else
mapBuffer = LockBuffer;
return mapBuffer(type, access, offset, size);
}
}
NzHardwareBuffer::NzHardwareBuffer(NzBuffer* parent, nzBufferType type) :
m_type(type),
m_parent(parent)
{
}
NzHardwareBuffer::~NzHardwareBuffer()
{
}
void NzHardwareBuffer::Bind()
{
#ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr)
{
NazaraError("No active context");
return;
}
#endif
glBindBuffer(bufferTarget[m_type], m_buffer);
}
bool NzHardwareBuffer::Create(unsigned int size, nzBufferUsage usage)
{
NzContext::EnsureContext();
m_buffer = 0;
glGenBuffers(1, &m_buffer);
GLint previous;
glGetIntegerv(bufferTargetBinding[m_type], &previous);
glBindBuffer(bufferTarget[m_type], m_buffer);
glBufferData(bufferTarget[m_type], size, nullptr, bufferUsage[usage]);
// Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent
if (previous != 0)
glBindBuffer(bufferTarget[m_type], previous);
return true;
}
void NzHardwareBuffer::Destroy()
{
NzContext::EnsureContext();
glDeleteBuffers(1, &m_buffer);
}
bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size)
{
NzContext::EnsureContext();
GLuint previous;
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
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
// http://www.stevestreeting.com/2007/03/17/glmapbuffer-vs-glbuffersubdata-the-return/
if (size < 32*1024)
{
// http://www.opengl.org/wiki/Vertex_Specification_Best_Practices
if (size == m_parent->GetSize())
glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetUsage()]); // Discard
glBufferSubData(bufferTarget[m_type], offset, size, data);
}
else
{
nzUInt8* ptr = mapBuffer(m_type, (size == m_parent->GetSize()) ? nzBufferAccess_DiscardAndWrite : nzBufferAccess_WriteOnly, offset, size);
if (!ptr)
{
NazaraError("Failed to map buffer");
return false;
}
std::memcpy(ptr, data, size);
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()]);
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;
}
void* NzHardwareBuffer::GetPointer()
{
return nullptr;
}
bool NzHardwareBuffer::IsHardware() const
{
return true;
}
void* NzHardwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size)
{
NzContext::EnsureContext();
// Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent
GLuint previous;
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
if (previous != m_buffer)
glBindBuffer(bufferTarget[m_type], m_buffer);
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)
glBindBuffer(bufferTarget[m_type], previous);
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;
}
// 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/HardwareBuffer.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <cstring>
#include <stdexcept>
#include <Nazara/Renderer/Debug.hpp>
namespace
{
using LockRoutine = nzUInt8* (*)(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size);
nzUInt8* LockBuffer(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size)
{
NazaraUnused(size);
if (access == nzBufferAccess_DiscardAndWrite)
{
GLint bufSize;
glGetBufferParameteriv(NzOpenGL::BufferTargetBinding[type], GL_BUFFER_SIZE, &bufSize);
GLint bufUsage;
glGetBufferParameteriv(NzOpenGL::BufferTargetBinding[type], GL_BUFFER_USAGE, &bufUsage);
// On discard le buffer
glBufferData(NzOpenGL::BufferTargetBinding[type], bufSize, nullptr, bufUsage);
}
void* ptr = glMapBuffer(NzOpenGL::BufferTarget[type], NzOpenGL::BufferLock[access]);
if (ptr)
return reinterpret_cast<nzUInt8*>(ptr) + offset;
else
return nullptr;
}
nzUInt8* LockBufferRange(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size)
{
return reinterpret_cast<nzUInt8*>(glMapBufferRange(NzOpenGL::BufferTarget[type], offset, size, NzOpenGL::BufferLockRange[access]));
}
nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size);
LockRoutine mapBuffer = LockBufferFirstRun;
nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size)
{
if (glMapBufferRange)
mapBuffer = LockBufferRange;
else
mapBuffer = LockBuffer;
return mapBuffer(type, access, offset, size);
}
}
NzHardwareBuffer::NzHardwareBuffer(NzBuffer* parent, nzBufferType type) :
m_type(type),
m_parent(parent)
{
}
NzHardwareBuffer::~NzHardwareBuffer()
{
}
void NzHardwareBuffer::Bind()
{
#ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr)
{
NazaraError("No active context");
return;
}
#endif
glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
}
bool NzHardwareBuffer::Create(unsigned int size, nzBufferUsage usage)
{
NzContext::EnsureContext();
m_buffer = 0;
glGenBuffers(1, &m_buffer);
GLint previous;
glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], &previous);
glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
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)
glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
return true;
}
void NzHardwareBuffer::Destroy()
{
NzContext::EnsureContext();
glDeleteBuffers(1, &m_buffer);
}
bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size)
{
NzContext::EnsureContext();
GLuint previous;
glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
if (previous != m_buffer)
glBindBuffer(NzOpenGL::BufferTarget[m_type], 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/
if (size < 32*1024)
{
// http://www.opengl.org/wiki/Vertex_Specification_Best_Practices
if (size == m_parent->GetSize())
glBufferData(NzOpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, NzOpenGL::BufferUsage[m_parent->GetUsage()]); // Discard
glBufferSubData(NzOpenGL::BufferTarget[m_type], offset, size, data);
}
else
{
nzUInt8* ptr = mapBuffer(m_type, (size == m_parent->GetSize()) ? nzBufferAccess_DiscardAndWrite : nzBufferAccess_WriteOnly, offset, size);
if (!ptr)
{
NazaraError("Failed to map buffer");
return false;
}
std::memcpy(ptr, data, size);
if (glUnmapBuffer(NzOpenGL::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(NzOpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, NzOpenGL::BufferUsage[m_parent->GetStorage()]);
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(NzOpenGL::BufferTarget[m_type], previous);
return true;
}
void* NzHardwareBuffer::GetPointer()
{
return nullptr;
}
bool NzHardwareBuffer::IsHardware() const
{
return true;
}
void* NzHardwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size)
{
NzContext::EnsureContext();
// Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent
GLuint previous;
glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
if (previous != m_buffer)
glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
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)
glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
return ptr;
}
bool NzHardwareBuffer::Unmap()
{
NzContext::EnsureContext();
GLuint previous;
glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
if (previous != m_buffer)
glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
if (glUnmapBuffer(NzOpenGL::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(NzOpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, NzOpenGL::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(NzOpenGL::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(NzOpenGL::BufferTarget[m_type], previous);
return true;
}

View File

@ -1,102 +1,98 @@
// 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/OcclusionQuery.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <stdexcept>
#include <Nazara/Renderer/Debug.hpp>
NzOcclusionQuery::NzOcclusionQuery() :
m_id(0)
{
#if NAZARA_RENDERER_SAFE
if (IsSupported())
{
#endif
NzContext::EnsureContext();
glGenQueries(1, reinterpret_cast<GLuint*>(&m_id));
#if NAZARA_RENDERER_SAFE
}
else
{
NazaraError("Occlusion queries not supported");
return;
}
#endif
#ifdef NAZARA_DEBUG
if (!m_id)
{
NazaraError("Failed to create occlusion query");
throw std::runtime_error("Constructor failed");
}
#endif
}
NzOcclusionQuery::~NzOcclusionQuery()
{
if (m_id)
{
NzContext::EnsureContext();
GLuint query = static_cast<GLuint>(m_id);
glDeleteQueries(1, &query);
}
}
void NzOcclusionQuery::Begin()
{
#ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr)
{
NazaraError("No active context");
return;
}
#endif
glBeginQuery(GL_SAMPLES_PASSED, m_id);
}
void NzOcclusionQuery::End()
{
#ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr)
{
NazaraError("No active context");
return;
}
#endif
glEndQuery(GL_SAMPLES_PASSED);
}
unsigned int NzOcclusionQuery::GetResult() const
{
NzContext::EnsureContext();
GLuint result;
glGetQueryObjectuiv(m_id, GL_QUERY_RESULT, &result);
return result;
}
bool NzOcclusionQuery::IsResultAvailable() const
{
NzContext::EnsureContext();
GLint available;
glGetQueryObjectiv(m_id, GL_QUERY_RESULT_AVAILABLE, &available);
return available == GL_TRUE;
}
bool NzOcclusionQuery::IsSupported()
{
return NzRenderer::HasCapability(nzRendererCap_OcclusionQuery);
}
// 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/OcclusionQuery.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <stdexcept>
#include <Nazara/Renderer/Debug.hpp>
NzOcclusionQuery::NzOcclusionQuery() :
m_id(0)
{
if (IsSupported())
{
NzContext::EnsureContext();
glGenQueries(1, reinterpret_cast<GLuint*>(&m_id));
}
else
{
NazaraError("Occlusion queries not supported");
return;
}
#ifdef NAZARA_DEBUG
if (!m_id)
{
NazaraError("Failed to create occlusion query");
throw std::runtime_error("Constructor failed");
}
#endif
}
NzOcclusionQuery::~NzOcclusionQuery()
{
if (m_id)
{
NzContext::EnsureContext();
GLuint query = static_cast<GLuint>(m_id);
glDeleteQueries(1, &query);
}
}
void NzOcclusionQuery::Begin()
{
#ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr)
{
NazaraError("No active context");
return;
}
#endif
glBeginQuery(GL_SAMPLES_PASSED, m_id);
}
void NzOcclusionQuery::End()
{
#ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr)
{
NazaraError("No active context");
return;
}
#endif
glEndQuery(GL_SAMPLES_PASSED);
}
unsigned int NzOcclusionQuery::GetResult() const
{
NzContext::EnsureContext();
GLuint result;
glGetQueryObjectuiv(m_id, GL_QUERY_RESULT, &result);
return result;
}
bool NzOcclusionQuery::IsResultAvailable() const
{
NzContext::EnsureContext();
GLint available;
glGetQueryObjectiv(m_id, GL_QUERY_RESULT_AVAILABLE, &available);
return available == GL_TRUE;
}
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
// 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/RenderWindow.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Thread.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <Nazara/Renderer/Texture.hpp>
#include <stdexcept>
#include <Nazara/Renderer/Debug.hpp>
NzRenderWindow::NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters)
{
Create(mode, title, style, parameters);
#ifdef NAZARA_DEBUG
if (!m_impl)
{
NazaraError("Failed to create render window");
throw std::runtime_error("Constructor failed");
}
#endif
}
NzRenderWindow::NzRenderWindow(NzWindowHandle handle, const NzContextParameters& parameters)
{
Create(handle, parameters);
#ifdef NAZARA_DEBUG
if (!m_impl)
{
NazaraError("Failed to create render window");
throw std::runtime_error("Constructor failed");
}
#endif
}
NzRenderWindow::~NzRenderWindow()
{
// Nécessaire si NzWindow::Destroy est appelé par son destructeur
OnWindowDestroying();
}
bool NzRenderWindow::CopyToImage(NzImage* image)
{
#if NAZARA_RENDERER_SAFE
if (!m_context)
{
NazaraError("Window has not been created");
return false;
}
if (!image)
{
NazaraError("Image must be valid");
return false;
}
#endif
if (!m_context->SetActive(true))
{
NazaraError("Failed to activate context");
return false;
}
NzVector2ui size = GetSize();
if (!image->Create(nzImageType_2D, nzPixelFormat_RGBA8, size.x, size.y, 1, 1))
{
NazaraError("Failed to create image");
return false;
}
nzUInt8* pixels = image->GetPixels();
glReadPixels(0, 0, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
image->FlipVertically();
return true;
}
bool NzRenderWindow::CopyToTexture(NzTexture* texture)
{
#if NAZARA_RENDERER_SAFE
if (!m_context)
{
NazaraError("Window has not been created");
return false;
}
if (!texture)
{
NazaraError("Texture must be valid");
return false;
}
#endif
if (!m_context->SetActive(true))
{
NazaraError("Failed to activate context");
return false;
}
NzVector2ui size = GetSize();
if (!texture->Create(nzImageType_2D, nzPixelFormat_RGBA8, size.x, size.y, 1, 1, true))
{
NazaraError("Failed to create texture");
return false;
}
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, size.x, size.y);
texture->Unlock();
return true;
}
bool NzRenderWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters)
{
m_parameters = parameters;
return NzWindow::Create(mode, title, style);
}
bool NzRenderWindow::Create(NzWindowHandle handle, const NzContextParameters& parameters)
{
m_parameters = parameters;
return NzWindow::Create(handle);
}
void NzRenderWindow::Display()
{
if (m_framerateLimit > 0)
{
int remainingTime = 1000/m_framerateLimit - m_clock.GetMilliseconds();
if (remainingTime > 0)
NzThread::Sleep(remainingTime);
m_clock.Restart();
}
if (m_context && m_parameters.doubleBuffered)
m_context->SwapBuffers();
}
void NzRenderWindow::EnableVerticalSync(bool enabled)
{
if (m_context)
{
#if defined(NAZARA_PLATFORM_WINDOWS)
if (!m_context->SetActive(true))
{
NazaraError("Failed to activate context");
return;
}
if (wglSwapInterval)
wglSwapInterval(enabled ? 1 : 0);
else
#elif defined(NAZARA_PLATFORM_LINUX)
if (!m_context->SetActive(true))
{
NazaraError("Failed to activate context");
return;
}
if (glXSwapInterval)
glXSwapInterval(enabled ? 1 : 0);
else
#else
#error Vertical Sync is not supported on this platform
#endif
NazaraError("Vertical Sync is not supported on this platform");
}
else
NazaraError("No context");
}
NzContextParameters NzRenderWindow::GetContextParameters() const
{
if (m_context)
return m_context->GetParameters();
else
{
NazaraError("Window not created/context not initialized");
return NzContextParameters();
}
}
unsigned int NzRenderWindow::GetHeight() const
{
return NzWindow::GetHeight();
}
NzRenderTargetParameters NzRenderWindow::GetParameters() const
{
if (m_context)
{
const NzContextParameters& parameters = m_context->GetParameters();
return NzRenderTargetParameters(parameters.antialiasingLevel, parameters.depthBits, parameters.stencilBits);
}
else
{
NazaraError("Window not created/context not initialized");
return NzRenderTargetParameters();
}
}
unsigned int NzRenderWindow::GetWidth() const
{
return NzWindow::GetWidth();
}
bool NzRenderWindow::HasContext() const
{
return true;
}
bool NzRenderWindow::IsValid() const
{
return m_impl != nullptr && m_context != nullptr;
}
void NzRenderWindow::SetFramerateLimit(unsigned int limit)
{
m_framerateLimit = limit;
}
bool NzRenderWindow::Activate()
{
if (m_context->SetActive(true))
{
glDrawBuffer((m_parameters.doubleBuffered) ? GL_BACK : GL_FRONT);
return true;
}
else
{
NazaraError("Failed to activate window's context");
return false;
}
}
void NzRenderWindow::OnWindowDestroying()
{
if (m_context)
{
delete m_context;
m_context = nullptr;
}
}
bool NzRenderWindow::OnWindowCreated()
{
m_parameters.doubleBuffered = true;
m_parameters.window = GetHandle();
m_context = new NzContext;
if (!m_context->Create(m_parameters))
{
NazaraError("Failed not create context");
delete m_context;
return false;
}
EnableVerticalSync(false);
#if NAZARA_RENDERER_ACTIVATE_RENDERWINDOW_ON_CREATION
if (!SetActive(true)) // Les fenêtres s'activent à la création
NazaraWarning("Failed to activate window");
#endif
m_clock.Restart();
return true;
}
// 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/RenderWindow.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Thread.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <Nazara/Renderer/Texture.hpp>
#include <stdexcept>
#include <Nazara/Renderer/Debug.hpp>
NzRenderWindow::NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters)
{
Create(mode, title, style, parameters);
#ifdef NAZARA_DEBUG
if (!m_impl)
{
NazaraError("Failed to create render window");
throw std::runtime_error("Constructor failed");
}
#endif
}
NzRenderWindow::NzRenderWindow(NzWindowHandle handle, const NzContextParameters& parameters)
{
Create(handle, parameters);
#ifdef NAZARA_DEBUG
if (!m_impl)
{
NazaraError("Failed to create render window");
throw std::runtime_error("Constructor failed");
}
#endif
}
NzRenderWindow::~NzRenderWindow()
{
// Nécessaire si NzWindow::Destroy est appelé par son destructeur
OnWindowDestroy();
}
bool NzRenderWindow::CopyToImage(NzImage* image)
{
#if NAZARA_RENDERER_SAFE
if (!m_context)
{
NazaraError("Window has not been created");
return false;
}
if (!image)
{
NazaraError("Image must be valid");
return false;
}
#endif
if (!m_context->SetActive(true))
{
NazaraError("Failed to activate context");
return false;
}
NzVector2ui size = GetSize();
if (!image->Create(nzImageType_2D, nzPixelFormat_RGBA8, size.x, size.y, 1, 1))
{
NazaraError("Failed to create image");
return false;
}
nzUInt8* pixels = image->GetPixels();
glReadPixels(0, 0, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
image->FlipVertically();
return true;
}
bool NzRenderWindow::CopyToTexture(NzTexture* texture)
{
#if NAZARA_RENDERER_SAFE
if (!m_context)
{
NazaraError("Window has not been created");
return false;
}
if (!texture)
{
NazaraError("Texture must be valid");
return false;
}
#endif
if (!m_context->SetActive(true))
{
NazaraError("Failed to activate context");
return false;
}
NzVector2ui size = GetSize();
if (!texture->Create(nzImageType_2D, nzPixelFormat_RGBA8, size.x, size.y, 1, 1, true))
{
NazaraError("Failed to create texture");
return false;
}
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, size.x, size.y);
texture->Unlock();
return true;
}
bool NzRenderWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters)
{
m_parameters = parameters;
return NzWindow::Create(mode, title, style);
}
bool NzRenderWindow::Create(NzWindowHandle handle, const NzContextParameters& parameters)
{
m_parameters = parameters;
return NzWindow::Create(handle);
}
void NzRenderWindow::Display()
{
if (m_framerateLimit > 0)
{
int remainingTime = 1000/m_framerateLimit - m_clock.GetMilliseconds();
if (remainingTime > 0)
NzThread::Sleep(remainingTime);
m_clock.Restart();
}
if (m_context && m_parameters.doubleBuffered)
m_context->SwapBuffers();
}
void NzRenderWindow::EnableVerticalSync(bool enabled)
{
if (m_context)
{
#if defined(NAZARA_PLATFORM_WINDOWS)
if (!m_context->SetActive(true))
{
NazaraError("Failed to activate context");
return;
}
if (wglSwapInterval)
wglSwapInterval(enabled ? 1 : 0);
else
#elif defined(NAZARA_PLATFORM_LINUX)
if (!m_context->SetActive(true))
{
NazaraError("Failed to activate context");
return;
}
if (glXSwapInterval)
glXSwapInterval(enabled ? 1 : 0);
else
#else
#error Vertical Sync is not supported on this platform
#endif
NazaraError("Vertical Sync is not supported on this platform");
}
else
NazaraError("No context");
}
unsigned int NzRenderWindow::GetHeight() const
{
return NzWindow::GetHeight();
}
NzRenderTargetParameters NzRenderWindow::GetParameters() const
{
if (m_context)
{
const NzContextParameters& parameters = m_context->GetParameters();
return NzRenderTargetParameters(parameters.antialiasingLevel, parameters.depthBits, parameters.stencilBits);
}
else
{
NazaraError("Window not created/context not initialized");
return NzRenderTargetParameters();
}
}
unsigned int NzRenderWindow::GetWidth() const
{
return NzWindow::GetWidth();
}
bool NzRenderWindow::IsRenderable() const
{
return m_impl != nullptr; // Si m_impl est valide, alors m_context l'est aussi
}
void NzRenderWindow::SetFramerateLimit(unsigned int limit)
{
m_framerateLimit = limit;
}
NzContextParameters NzRenderWindow::GetContextParameters() const
{
if (m_context)
return m_context->GetParameters();
else
{
NazaraError("Window not created/context not initialized");
return NzContextParameters();
}
}
bool NzRenderWindow::HasContext() const
{
return true;
}
bool NzRenderWindow::Activate()
{
if (m_context->SetActive(true))
{
glDrawBuffer((m_parameters.doubleBuffered) ? GL_BACK : GL_FRONT);
return true;
}
else
{
NazaraError("Failed to activate window's context");
return false;
}
}
bool NzRenderWindow::OnWindowCreated()
{
m_parameters.doubleBuffered = true;
m_parameters.window = GetHandle();
m_context = new NzContext;
if (!m_context->Create(m_parameters))
{
NazaraError("Failed not create context");
delete m_context;
return false;
}
EnableVerticalSync(false);
if (!SetActive(true)) // Les fenêtres s'activent à la création
NazaraWarning("Failed to activate window");
m_clock.Restart();
return true;
}
void NzRenderWindow::OnWindowDestroy()
{
if (m_context)
{
delete m_context;
m_context = nullptr;
}
}

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
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
// Code inspiré de NeHe (Lesson1) et de la SFML par Laurent Gomila
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/Win32/ContextImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/LockGuard.hpp>
#include <Nazara/Core/Mutex.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <cstring>
#include <Nazara/Renderer/Debug.hpp>
NzContextImpl::NzContextImpl()
{
}
bool NzContextImpl::Activate()
{
return wglMakeCurrent(m_deviceContext, m_context);
}
bool NzContextImpl::Create(NzContextParameters& parameters)
{
if (parameters.window)
{
m_window = static_cast<HWND>(parameters.window);
m_ownsWindow = false;
}
else
{
m_window = CreateWindowA("STATIC", nullptr, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
if (!m_window)
{
NazaraError("Failed to create window");
return false;
}
ShowWindow(m_window, SW_HIDE);
m_ownsWindow = true;
}
m_deviceContext = GetDC(m_window);
if (!m_deviceContext)
{
NazaraError("Failed to get device context");
Destroy();
return false;
}
int pixelFormat = 0;
if (parameters.antialiasingLevel > 0)
{
if (wglChoosePixelFormat)
{
bool valid;
UINT numFormats;
int attributes[] = {
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
WGL_COLOR_BITS_ARB, (parameters.bitsPerPixel == 32) ? 24 : parameters.bitsPerPixel,
WGL_ALPHA_BITS_ARB, (parameters.bitsPerPixel == 32) ? 8 : 0,
WGL_DEPTH_BITS_ARB, parameters.depthBits,
WGL_STENCIL_BITS_ARB, parameters.stencilBits,
WGL_DOUBLE_BUFFER_ARB, (parameters.doubleBuffered) ? GL_TRUE : GL_FALSE,
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
WGL_SAMPLES_ARB, parameters.antialiasingLevel,
0, 0
};
do
{
valid = wglChoosePixelFormat(m_deviceContext, attributes, nullptr, 1, &pixelFormat, &numFormats);
}
while ((!valid || numFormats == 0) && --attributes[19] > 0);
if (!valid)
{
NazaraWarning("Could not find a format matching requirements, disabling antialiasing...");
pixelFormat = 0;
}
parameters.antialiasingLevel = attributes[19];
}
else
{
NazaraWarning("Antialiasing is not supported");
parameters.antialiasingLevel = 0;
}
}
PIXELFORMATDESCRIPTOR descriptor;
ZeroMemory(&descriptor, sizeof(PIXELFORMATDESCRIPTOR));
descriptor.nSize = sizeof(PIXELFORMATDESCRIPTOR);
descriptor.nVersion = 1;
if (pixelFormat == 0)
{
descriptor.cColorBits = parameters.bitsPerPixel;
descriptor.cDepthBits = parameters.depthBits;
descriptor.cStencilBits = parameters.stencilBits;
descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
descriptor.iPixelType = PFD_TYPE_RGBA;
if (parameters.bitsPerPixel == 32)
descriptor.cAlphaBits = 8;
if (parameters.doubleBuffered)
descriptor.dwFlags |= PFD_DOUBLEBUFFER;
pixelFormat = ChoosePixelFormat(m_deviceContext, &descriptor);
if (pixelFormat == 0)
{
NazaraError("Failed to choose pixel format");
Destroy();
return false;
}
}
if (!SetPixelFormat(m_deviceContext, pixelFormat, &descriptor))
{
NazaraError("Failed to set pixel format");
Destroy();
return false;
}
// 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)
{
parameters.bitsPerPixel = descriptor.cColorBits + descriptor.cAlphaBits;
parameters.depthBits = descriptor.cDepthBits;
parameters.stencilBits = descriptor.cDepthBits;
}
else
NazaraWarning("Failed to get context's parameters");
HGLRC shareContext = (parameters.shared) ? static_cast<NzContextImpl*>(parameters.shareContext->m_impl)->m_context : nullptr;
m_context = nullptr;
if (wglCreateContextAttribs)
{
int attributes[4*2+1];
int* attrib = attributes;
*attrib++ = WGL_CONTEXT_MAJOR_VERSION_ARB;
*attrib++ = parameters.majorVersion;
*attrib++ = WGL_CONTEXT_MINOR_VERSION_ARB;
*attrib++ = parameters.minorVersion;
int flags = 0;
if (parameters.majorVersion >= 3)
{
*attrib++ = WGL_CONTEXT_PROFILE_MASK_ARB;
if (parameters.compatibilityProfile)
*attrib++ = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
else
{
*attrib++ = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
}
}
if (parameters.debugMode)
flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
if (flags)
{
*attrib++ = WGL_CONTEXT_FLAGS_ARB;
*attrib++ = flags;
}
*attrib++ = 0;
m_context = wglCreateContextAttribs(m_deviceContext, shareContext, attributes);
}
if (!m_context)
{
m_context = wglCreateContext(m_deviceContext);
if (shareContext)
{
// wglShareLists n'est pas thread-safe (source: SFML)
static NzMutex mutex;
NzLockGuard lock(mutex);
if (!wglShareLists(shareContext, m_context))
NazaraWarning("Failed to share the context: " + NzGetLastSystemError());
}
}
if (!m_context)
{
NazaraError("Failed to create context");
Destroy();
return false;
}
return true;
}
void NzContextImpl::Destroy()
{
if (m_context)
wglDeleteContext(m_context);
if (m_deviceContext)
ReleaseDC(m_window, m_deviceContext);
if (m_ownsWindow)
DestroyWindow(m_window);
}
void NzContextImpl::SwapBuffers()
{
::SwapBuffers(m_deviceContext);
}
bool NzContextImpl::Desactivate()
{
return wglMakeCurrent(nullptr, nullptr);
}
// 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
// Code inspiré de NeHe (Lesson1) et de la SFML par Laurent Gomila
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/Win32/ContextImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/LockGuard.hpp>
#include <Nazara/Core/Mutex.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <cstring>
#include <Nazara/Renderer/Debug.hpp>
NzContextImpl::NzContextImpl()
{
}
bool NzContextImpl::Activate()
{
return wglMakeCurrent(m_deviceContext, m_context);
}
bool NzContextImpl::Create(NzContextParameters& parameters)
{
if (parameters.window)
{
m_window = static_cast<HWND>(parameters.window);
m_ownsWindow = false;
}
else
{
m_window = CreateWindowA("STATIC", nullptr, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
if (!m_window)
{
NazaraError("Failed to create window");
return false;
}
ShowWindow(m_window, SW_HIDE);
m_ownsWindow = true;
}
m_deviceContext = GetDC(m_window);
if (!m_deviceContext)
{
NazaraError("Failed to get device context");
Destroy();
return false;
}
int pixelFormat = 0;
if (parameters.antialiasingLevel > 0)
{
if (wglChoosePixelFormat)
{
bool valid;
UINT numFormats;
int attributes[] = {
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
WGL_COLOR_BITS_ARB, (parameters.bitsPerPixel == 32) ? 24 : parameters.bitsPerPixel,
WGL_ALPHA_BITS_ARB, (parameters.bitsPerPixel == 32) ? 8 : 0,
WGL_DEPTH_BITS_ARB, parameters.depthBits,
WGL_STENCIL_BITS_ARB, parameters.stencilBits,
WGL_DOUBLE_BUFFER_ARB, (parameters.doubleBuffered) ? GL_TRUE : GL_FALSE,
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
WGL_SAMPLES_ARB, parameters.antialiasingLevel,
0, 0
};
do
{
valid = wglChoosePixelFormat(m_deviceContext, attributes, nullptr, 1, &pixelFormat, &numFormats);
}
while ((!valid || numFormats == 0) && --attributes[19] > 0);
if (!valid)
{
NazaraWarning("Could not find a format matching requirements, disabling antialiasing...");
pixelFormat = 0;
}
parameters.antialiasingLevel = attributes[19];
}
else
{
NazaraWarning("Antialiasing is not supported");
parameters.antialiasingLevel = 0;
}
}
PIXELFORMATDESCRIPTOR descriptor;
ZeroMemory(&descriptor, sizeof(PIXELFORMATDESCRIPTOR));
descriptor.nSize = sizeof(PIXELFORMATDESCRIPTOR);
descriptor.nVersion = 1;
if (pixelFormat == 0)
{
descriptor.cColorBits = parameters.bitsPerPixel;
descriptor.cDepthBits = parameters.depthBits;
descriptor.cStencilBits = parameters.stencilBits;
descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
descriptor.iPixelType = PFD_TYPE_RGBA;
if (parameters.bitsPerPixel == 32)
descriptor.cAlphaBits = 8;
if (parameters.doubleBuffered)
descriptor.dwFlags |= PFD_DOUBLEBUFFER;
pixelFormat = ChoosePixelFormat(m_deviceContext, &descriptor);
if (pixelFormat == 0)
{
NazaraError("Failed to choose pixel format");
Destroy();
return false;
}
}
if (!SetPixelFormat(m_deviceContext, pixelFormat, &descriptor))
{
NazaraError("Failed to set pixel format");
Destroy();
return false;
}
// 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)
{
parameters.bitsPerPixel = descriptor.cColorBits + descriptor.cAlphaBits;
parameters.depthBits = descriptor.cDepthBits;
parameters.stencilBits = descriptor.cDepthBits;
}
else
NazaraWarning("Failed to get context's parameters");
HGLRC shareContext = (parameters.shared) ? static_cast<NzContextImpl*>(parameters.shareContext->m_impl)->m_context : nullptr;
m_context = nullptr;
if (wglCreateContextAttribs)
{
int attributes[4*2+1];
int* attrib = attributes;
*attrib++ = WGL_CONTEXT_MAJOR_VERSION_ARB;
*attrib++ = parameters.majorVersion;
*attrib++ = WGL_CONTEXT_MINOR_VERSION_ARB;
*attrib++ = parameters.minorVersion;
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;
}
if (parameters.debugMode)
{
*attrib++ = WGL_CONTEXT_FLAGS_ARB;
*attrib++ = WGL_CONTEXT_DEBUG_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
}
*attrib++ = 0;
m_context = wglCreateContextAttribs(m_deviceContext, shareContext, attributes);
}
if (!m_context)
{
m_context = wglCreateContext(m_deviceContext);
if (shareContext)
{
// wglShareLists n'est pas thread-safe (source: SFML)
static NzMutex mutex;
NzLockGuard lock(mutex);
if (!wglShareLists(shareContext, m_context))
NazaraWarning("Failed to share the context: " + NzGetLastSystemError());
}
}
if (!m_context)
{
NazaraError("Failed to create context");
Destroy();
return false;
}
return true;
}
void NzContextImpl::Destroy()
{
if (m_context)
{
if (wglGetCurrentContext() == m_context)
wglMakeCurrent(nullptr, nullptr);
wglDeleteContext(m_context);
m_context = nullptr;
}
if (m_deviceContext)
{
ReleaseDC(m_window, m_deviceContext);
m_deviceContext = nullptr;
}
if (m_ownsWindow)
{
DestroyWindow(m_window);
m_window = nullptr;
}
}
void NzContextImpl::SwapBuffers()
{
::SwapBuffers(m_deviceContext);
}
bool NzContextImpl::Desactivate()
{
return wglMakeCurrent(nullptr, nullptr);
}

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -1,221 +1,200 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Loaders/MD2.hpp>
#include <Nazara/Core/Endianness.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/File.hpp>
#include <Nazara/Core/InputStream.hpp>
#include <Nazara/Core/MemoryStream.hpp>
#include <Nazara/Math/Basic.hpp>
#include <Nazara/Utility/Mesh.hpp>
#include <Nazara/Utility/Loaders/MD2/Constants.hpp>
#include <Nazara/Utility/Loaders/MD2/Mesh.hpp>
#include <cstddef>
#include <cstring>
#include <Nazara/Utility/Debug.hpp>
namespace
{
bool NzLoader_MD2_Check(NzInputStream& stream, const NzMeshParams& parameters)
{
NazaraUnused(parameters);
nzUInt32 magic[2];
if (stream.Read(&magic[0], 2*sizeof(nzUInt32)) != 2*sizeof(nzUInt32))
return false;
#if defined(NAZARA_BIG_ENDIAN)
NzByteSwap(&magic[0], sizeof(nzUInt32));
NzByteSwap(&magic[1], sizeof(nzUInt32));
#endif
return magic[0] == md2Ident && magic[1] == 8;
}
bool NzLoader_MD2_Load(NzMesh* mesh, NzInputStream& stream, const NzMeshParams& parameters)
{
md2_header header;
if (stream.Read(&header, sizeof(md2_header)) != sizeof(md2_header))
{
NazaraError("Failed to read header");
return false;
}
// Les fichiers MD2 sont en little endian
#if defined(NAZARA_BIG_ENDIAN)
NzByteSwap(&header.ident, sizeof(nzUInt32));
#endif
if (header.ident != md2Ident)
{
NazaraError("Invalid MD2 file");
return false;
}
#if defined(NAZARA_BIG_ENDIAN)
NzByteSwap(&header.version, sizeof(nzUInt32));
#endif
if (header.version != 8)
{
NazaraError("Bad version number (" + NzString::Number(header.version) + ')');
return false;
}
#if defined(NAZARA_BIG_ENDIAN)
NzByteSwap(&header.skinwidth, sizeof(nzUInt32));
NzByteSwap(&header.skinheight, sizeof(nzUInt32));
NzByteSwap(&header.framesize, sizeof(nzUInt32));
NzByteSwap(&header.num_skins, sizeof(nzUInt32));
NzByteSwap(&header.num_vertices, sizeof(nzUInt32));
NzByteSwap(&header.num_st, sizeof(nzUInt32));
NzByteSwap(&header.num_tris, sizeof(nzUInt32));
NzByteSwap(&header.num_glcmds, sizeof(nzUInt32));
NzByteSwap(&header.num_frames, sizeof(nzUInt32));
NzByteSwap(&header.offset_skins, sizeof(nzUInt32));
NzByteSwap(&header.offset_st, sizeof(nzUInt32));
NzByteSwap(&header.offset_tris, sizeof(nzUInt32));
NzByteSwap(&header.offset_frames, sizeof(nzUInt32));
NzByteSwap(&header.offset_glcmds, sizeof(nzUInt32));
NzByteSwap(&header.offset_end, sizeof(nzUInt32));
#endif
if (stream.GetSize() < header.offset_end)
{
NazaraError("Incomplete MD2 file");
return false;
}
/// Création du mesh
// Animé ou statique, c'est la question
bool animated;
unsigned int startFrame = NzClamp(parameters.animation.startFrame, 0U, static_cast<unsigned int>(header.num_frames-1));
unsigned int endFrame = NzClamp(parameters.animation.endFrame, 0U, static_cast<unsigned int>(header.num_frames-1));
if (parameters.loadAnimations && startFrame != endFrame)
animated = true;
else
animated = false;
if (!mesh->Create((animated) ? nzAnimationType_Keyframe : nzAnimationType_Static)) // Ne devrait pas échouer
{
NazaraInternalError("Failed to create mesh");
return false;
}
/// Chargement des skins
if (header.num_skins > 0)
{
stream.SetCursorPos(header.offset_skins);
{
char skin[68];
for (unsigned int i = 0; i < header.num_skins; ++i)
{
stream.Read(skin, 68*sizeof(char));
mesh->AddSkin(skin);
}
}
}
/// Chargement des animmations
if (animated)
{
NzAnimation* animation = new NzAnimation;
if (animation->Create(nzAnimationType_Keyframe, endFrame-startFrame+1))
{
// Décodage des séquences
NzString frameName;
NzSequence sequence;
sequence.framePerSecond = 10; // Par défaut pour les animations MD2
char name[16], last[16];
stream.SetCursorPos(header.offset_frames + startFrame*header.framesize + offsetof(md2_frame, name));
stream.Read(last, 16*sizeof(char));
int pos = std::strlen(last)-1;
for (unsigned int j = 0; j < 2; ++j)
{
if (!std::isdigit(last[pos]))
break;
pos--;
}
last[pos+1] = '\0';
unsigned int numFrames = 0;
for (unsigned int i = startFrame; i <= endFrame; ++i)
{
stream.SetCursorPos(header.offset_frames + i*header.framesize + offsetof(md2_frame, name));
stream.Read(name, 16*sizeof(char));
pos = std::strlen(name)-1;
for (unsigned int j = 0; j < 2; ++j)
{
if (!std::isdigit(name[pos]))
break;
pos--;
}
name[pos+1] = '\0';
if (std::strcmp(name, last) != 0) // Si les deux frames n'ont pas le même nom
{
// Alors on enregistre la séquence
sequence.firstFrame = i-numFrames;
sequence.lastFrame = i-1;
sequence.name = last;
animation->AddSequence(sequence);
std::strcpy(last, name);
numFrames = 0;
}
numFrames++;
}
// On ajoute la dernière frame (Qui n'a pas été traitée par la boucle)
sequence.firstFrame = endFrame-numFrames;
sequence.lastFrame = endFrame;
sequence.name = last;
animation->AddSequence(sequence);
mesh->SetAnimation(animation);
animation->SetPersistent(false);
}
else
NazaraInternalError("Failed to create animaton");
}
/// Chargement des submesh
// Actuellement le loader ne charge qu'un submesh
// TODO: Utiliser les commandes OpenGL pour accélérer le rendu
NzMD2Mesh* subMesh = new NzMD2Mesh(mesh);
if (!subMesh->Create(header, stream, parameters))
{
NazaraError("Failed to create MD2 mesh");
return false;
}
mesh->AddSubMesh(subMesh);
return true;
}
}
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();
}
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Loaders/MD2.hpp>
#include <Nazara/Core/Endianness.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/File.hpp>
#include <Nazara/Core/InputStream.hpp>
#include <Nazara/Core/MemoryStream.hpp>
#include <Nazara/Math/Basic.hpp>
#include <Nazara/Utility/Mesh.hpp>
#include <Nazara/Utility/Loaders/MD2/Constants.hpp>
#include <Nazara/Utility/Loaders/MD2/Mesh.hpp>
#include <cstddef>
#include <cstring>
#include <Nazara/Utility/Debug.hpp>
namespace
{
bool NzLoader_MD2_Check(NzInputStream& stream, const NzMeshParams& parameters)
{
NazaraUnused(parameters);
nzUInt32 magic[2];
if (stream.Read(&magic[0], 2*sizeof(nzUInt32)) != 2*sizeof(nzUInt32))
return false;
#if defined(NAZARA_BIG_ENDIAN)
NzByteSwap(&magic[0], sizeof(nzUInt32));
NzByteSwap(&magic[1], sizeof(nzUInt32));
#endif
return magic[0] == md2Ident && magic[1] == 8;
}
bool NzLoader_MD2_Load(NzMesh* mesh, NzInputStream& stream, const NzMeshParams& parameters)
{
md2_header header;
if (stream.Read(&header, sizeof(md2_header)) != sizeof(md2_header))
{
NazaraError("Failed to read header");
return false;
}
#if defined(NAZARA_BIG_ENDIAN)
NzByteSwap(&header.skinwidth, sizeof(nzUInt32));
NzByteSwap(&header.skinheight, sizeof(nzUInt32));
NzByteSwap(&header.framesize, sizeof(nzUInt32));
NzByteSwap(&header.num_skins, sizeof(nzUInt32));
NzByteSwap(&header.num_vertices, sizeof(nzUInt32));
NzByteSwap(&header.num_st, sizeof(nzUInt32));
NzByteSwap(&header.num_tris, sizeof(nzUInt32));
NzByteSwap(&header.num_glcmds, sizeof(nzUInt32));
NzByteSwap(&header.num_frames, sizeof(nzUInt32));
NzByteSwap(&header.offset_skins, sizeof(nzUInt32));
NzByteSwap(&header.offset_st, sizeof(nzUInt32));
NzByteSwap(&header.offset_tris, sizeof(nzUInt32));
NzByteSwap(&header.offset_frames, sizeof(nzUInt32));
NzByteSwap(&header.offset_glcmds, sizeof(nzUInt32));
NzByteSwap(&header.offset_end, sizeof(nzUInt32));
#endif
if (stream.GetSize() < header.offset_end)
{
NazaraError("Incomplete MD2 file");
return false;
}
/// Création du mesh
// Animé ou statique, c'est la question
bool animated;
unsigned int startFrame = NzClamp(parameters.animation.startFrame, 0U, static_cast<unsigned int>(header.num_frames-1));
unsigned int endFrame = NzClamp(parameters.animation.endFrame, 0U, static_cast<unsigned int>(header.num_frames-1));
if (parameters.loadAnimations && startFrame != endFrame)
animated = true;
else
animated = false;
if (!mesh->Create((animated) ? nzAnimationType_Keyframe : nzAnimationType_Static)) // Ne devrait jamais échouer
{
NazaraInternalError("Failed to create mesh");
return false;
}
/// Chargement des skins
if (header.num_skins > 0)
{
stream.SetCursorPos(header.offset_skins);
{
char skin[68];
for (unsigned int i = 0; i < header.num_skins; ++i)
{
stream.Read(skin, 68*sizeof(char));
mesh->AddSkin(skin);
}
}
}
/// Chargement des animmations
if (animated)
{
NzAnimation* animation = new NzAnimation;
if (animation->Create(nzAnimationType_Keyframe, endFrame-startFrame+1))
{
// Décodage des séquences
NzString frameName;
NzSequence sequence;
sequence.framePerSecond = 10; // Par défaut pour les animations MD2
char name[16], last[16];
stream.SetCursorPos(header.offset_frames + startFrame*header.framesize + offsetof(md2_frame, name));
stream.Read(last, 16*sizeof(char));
int pos = std::strlen(last)-1;
for (unsigned int j = 0; j < 2; ++j)
{
if (!std::isdigit(last[pos]))
break;
pos--;
}
last[pos+1] = '\0';
unsigned int numFrames = 0;
for (unsigned int i = startFrame; i <= endFrame; ++i)
{
stream.SetCursorPos(header.offset_frames + i*header.framesize + offsetof(md2_frame, name));
stream.Read(name, 16*sizeof(char));
pos = std::strlen(name)-1;
for (unsigned int j = 0; j < 2; ++j)
{
if (!std::isdigit(name[pos]))
break;
pos--;
}
name[pos+1] = '\0';
if (std::strcmp(name, last) != 0) // Si les deux frames n'ont pas le même nom
{
// Alors on enregistre la séquence
sequence.firstFrame = i-numFrames;
sequence.lastFrame = i-1;
sequence.name = last;
animation->AddSequence(sequence);
std::strcpy(last, name);
numFrames = 0;
}
numFrames++;
}
// On ajoute la dernière frame (Qui n'a pas été traitée par la boucle)
sequence.firstFrame = endFrame-numFrames;
sequence.lastFrame = endFrame;
sequence.name = last;
animation->AddSequence(sequence);
mesh->SetAnimation(animation);
animation->SetPersistent(false);
}
else
NazaraInternalError("Failed to create animaton");
}
/// Chargement des submesh
// Actuellement le loader ne charge qu'un submesh
// TODO: Utiliser les commandes OpenGL pour accélérer le rendu
NzMD2Mesh* subMesh = new NzMD2Mesh(mesh);
if (!subMesh->Create(header, stream, parameters))
{
NazaraError("Failed to create MD2 mesh");
return false;
}
mesh->AddSubMesh(subMesh);
return true;
}
}
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
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Loaders/MD2/Mesh.hpp>
#include <Nazara/Core/InputStream.hpp>
#include <Nazara/Math/Matrix4.hpp>
#include <Nazara/Utility/IndexBuffer.hpp>
#include <Nazara/Utility/Mesh.hpp>
#include <Nazara/Utility/VertexBuffer.hpp>
#include <Nazara/Utility/Debug.hpp>
NzMD2Mesh::NzMD2Mesh(const NzMesh* parent) :
NzKeyframeMesh(parent),
m_frames(nullptr),
m_indexBuffer(nullptr),
m_vertexBuffer(nullptr)
{
}
NzMD2Mesh::~NzMD2Mesh()
{
Destroy();
}
bool NzMD2Mesh::Create(const md2_header& header, NzInputStream& stream, const NzMeshParams& parameters)
{
Destroy();
unsigned int startFrame = NzClamp(parameters.animation.startFrame, 0U, static_cast<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_vertexCount = header.num_tris*3;
/// Chargement des vertices
std::vector<md2_texCoord> texCoords(header.num_st);
std::vector<md2_triangle> triangles(header.num_tris);
// Lecture des coordonnées de texture
stream.SetCursorPos(header.offset_st);
stream.Read(&texCoords[0], header.num_st*sizeof(md2_texCoord));
#if defined(NAZARA_BIG_ENDIAN)
for (unsigned int i = 0; i < header.num_st; ++i)
{
NzByteSwap(&texCoords[i].u, sizeof(nzInt16));
NzByteSwap(&texCoords[i].v, sizeof(nzInt16));
}
#endif
stream.SetCursorPos(header.offset_tris);
stream.Read(&triangles[0], header.num_tris*sizeof(md2_triangle));
#if defined(NAZARA_BIG_ENDIAN)
for (unsigned int i = 0; i < header.num_tris; ++i)
{
NzByteSwap(&triangles[i].vertices[0], sizeof(nzUInt16));
NzByteSwap(&texCoords[i].texCoords[0], sizeof(nzUInt16));
NzByteSwap(&triangles[i].vertices[1], sizeof(nzUInt16));
NzByteSwap(&texCoords[i].texCoords[1], sizeof(nzUInt16));
NzByteSwap(&triangles[i].vertices[2], sizeof(nzUInt16));
NzByteSwap(&texCoords[i].texCoords[2], sizeof(nzUInt16));
}
#endif
stream.SetCursorPos(header.offset_frames + header.framesize*startFrame);
md2_frame frame;
frame.vertices.resize(header.num_vertices);
// Pour que le modèle soit correctement aligné, on génère une matrice de rotation que nous appliquerons à chacune des vertices
NzMatrix4f rotationMatrix = NzMatrix4f::Rotate(NzEulerAnglesf(90.f, -90.f, 0.f));
unsigned int stride = s_declaration.GetStride(nzElementStream_VertexData);
m_frames = new Frame[m_frameCount];
for (unsigned int i = 0; i < m_frameCount; ++i)
{
stream.Read(&frame.scale, sizeof(NzVector3f));
stream.Read(&frame.translate, sizeof(NzVector3f));
stream.Read(&frame.name, 16*sizeof(char));
stream.Read(&frame.vertices[0], header.num_vertices*sizeof(md2_vertex));
#if defined(NAZARA_BIG_ENDIAN)
NzByteSwap(&frame.scale.x, sizeof(float));
NzByteSwap(&frame.scale.y, sizeof(float));
NzByteSwap(&frame.scale.z, sizeof(float));
NzByteSwap(&frame.translate.x, sizeof(float));
NzByteSwap(&frame.translate.y, sizeof(float));
NzByteSwap(&frame.translate.z, sizeof(float));
#endif
m_frames[i].normal = new nzUInt8[m_vertexCount]; // Nous stockons l'indice de la normale plutôt que la normale (gain d'espace)
m_frames[i].vertices = new NzVector3f[m_vertexCount];
NzVector3f max, min;
for (unsigned int t = 0; t < header.num_tris; ++t)
{
for (unsigned int v = 0; v < 3; ++v)
{
const md2_vertex& vert = frame.vertices[triangles[t].vertices[v]];
NzVector3f vertex = rotationMatrix * NzVector3f(vert.x * frame.scale.x + frame.translate.x, vert.y * frame.scale.y + frame.translate.y, vert.z * frame.scale.z + frame.translate.z);
max.MakeCeil(vertex);
min.MakeFloor(vertex);
m_frames[i].normal[t*3+v] = vert.n;
m_frames[i].vertices[t*3+v] = vertex;
}
}
m_frames[i].aabb.SetExtends(min, max);
}
m_indexBuffer = nullptr; // Pas d'indexbuffer pour l'instant
m_vertexBuffer = new NzVertexBuffer(m_vertexCount, (3+3+2)*sizeof(float), parameters.storage, nzBufferUsage_Dynamic);
nzUInt8* ptr = reinterpret_cast<nzUInt8*>(m_vertexBuffer->Map(nzBufferAccess_WriteOnly));
if (!ptr)
{
NazaraError("Failed to map vertex buffer");
Destroy();
return false;
}
// On avance jusqu'aux premières coordonnées de texture
ptr += s_declaration.GetElement(nzElementStream_VertexData, nzElementUsage_TexCoord)->offset;
for (unsigned int t = 0; t < header.num_tris; ++t)
{
for (unsigned int v = 0; v < 3; ++v)
{
const md2_texCoord& texC = texCoords[triangles[t].texCoords[v]];
NzVector2f* coords = reinterpret_cast<NzVector2f*>(ptr);
coords->x = texC.u / static_cast<float>(header.skinwidth);
coords->y = 1.f - texC.v / static_cast<float>(header.skinheight);
ptr += stride;
}
}
if (!m_vertexBuffer->Unmap())
{
NazaraError("Failed to unmap buffer");
Destroy();
return false;
}
m_vertexBuffer->AddResourceReference();
m_vertexBuffer->SetPersistent(false);
AnimateImpl(0, 0, 0.f);
return true;
}
void NzMD2Mesh::Destroy()
{
if (m_frames)
{
for (unsigned int i = 0; i < m_frameCount; ++i)
{
delete[] m_frames[i].normal;
delete[] m_frames[i].vertices;
}
delete[] m_frames;
m_frames = nullptr;
}
if (m_indexBuffer)
{
m_indexBuffer->RemoveResourceReference();
m_indexBuffer = nullptr;
}
if (m_vertexBuffer)
{
m_vertexBuffer->RemoveResourceReference();
m_vertexBuffer = nullptr;
}
}
const NzAxisAlignedBox& NzMD2Mesh::GetAABB() const
{
return m_aabb;
}
nzAnimationType NzMD2Mesh::GetAnimationType() const
{
if (m_frameCount > 1)
return nzAnimationType_Keyframe;
else
return nzAnimationType_Static;
}
unsigned int NzMD2Mesh::GetFrameCount() const
{
return m_frameCount;
}
const NzIndexBuffer* NzMD2Mesh::GetIndexBuffer() const
{
return nullptr;
//return m_indexBuffer;
}
nzPrimitiveType NzMD2Mesh::GetPrimitiveType() const
{
return nzPrimitiveType_TriangleList;
}
const NzVertexBuffer* NzMD2Mesh::GetVertexBuffer() const
{
return m_vertexBuffer;
}
const NzVertexDeclaration* NzMD2Mesh::GetVertexDeclaration() const
{
return &s_declaration;
}
void NzMD2Mesh::Initialize()
{
NzVertexElement elements[3];
elements[0].offset = 0;
elements[0].type = nzElementType_Float3;
elements[0].usage = nzElementUsage_Position;
elements[1].offset = 3*sizeof(float);
elements[1].type = nzElementType_Float3;
elements[1].usage = nzElementUsage_Normal;
elements[2].offset = 3*sizeof(float) + 3*sizeof(float);
elements[2].type = nzElementType_Float2;
elements[2].usage = nzElementUsage_TexCoord;
s_declaration.Create(elements, 3);
}
void NzMD2Mesh::Uninitialize()
{
s_declaration.Destroy();
}
void NzMD2Mesh::AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation)
{
nzUInt8* ptr = reinterpret_cast<nzUInt8*>(m_vertexBuffer->Map(nzBufferAccess_WriteOnly));
if (!ptr)
{
NazaraError("Failed to map vertex buffer");
return;
}
unsigned int stride = s_declaration.GetStride(nzElementStream_VertexData);
unsigned int positionOffset = s_declaration.GetElement(nzElementStream_VertexData, nzElementUsage_Position)->offset;
unsigned int normalOffset = s_declaration.GetElement(nzElementStream_VertexData, nzElementUsage_Normal)->offset;
Frame* fA = &m_frames[frameA];
Frame* fB = &m_frames[frameB];
for (unsigned int i = 0; i < m_vertexCount; ++i)
{
NzVector3f* position = reinterpret_cast<NzVector3f*>(ptr + positionOffset);
NzVector3f* normal = reinterpret_cast<NzVector3f*>(ptr + normalOffset);
*position = fA->vertices[i] + interpolation * (fB->vertices[i] - fA->vertices[i]);
*normal = md2Normals[fA->normal[i]] + interpolation * (md2Normals[fB->normal[i]] - md2Normals[fA->normal[i]]);
ptr += stride;
}
if (!m_vertexBuffer->Unmap())
NazaraWarning("Failed to unmap vertex buffer, expect mesh corruption");
// Interpolation de l'AABB
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;
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Loaders/MD2/Mesh.hpp>
#include <Nazara/Core/InputStream.hpp>
#include <Nazara/Math/Matrix4.hpp>
#include <Nazara/Utility/IndexBuffer.hpp>
#include <Nazara/Utility/Mesh.hpp>
#include <Nazara/Utility/VertexBuffer.hpp>
#include <Nazara/Utility/Debug.hpp>
NzMD2Mesh::NzMD2Mesh(const NzMesh* parent) :
NzKeyframeMesh(parent),
m_frames(nullptr),
m_indexBuffer(nullptr),
m_vertexBuffer(nullptr)
{
}
NzMD2Mesh::~NzMD2Mesh()
{
Destroy();
}
bool NzMD2Mesh::Create(const md2_header& header, NzInputStream& stream, const NzMeshParams& parameters)
{
Destroy();
unsigned int startFrame = NzClamp(parameters.animation.startFrame, 0U, static_cast<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_vertexCount = header.num_tris * 3;
/// Chargement des vertices
std::vector<md2_texCoord> texCoords(header.num_st);
std::vector<md2_triangle> triangles(header.num_tris);
// Lecture des coordonnées de texture
stream.SetCursorPos(header.offset_st);
stream.Read(&texCoords[0], header.num_st*sizeof(md2_texCoord));
#if defined(NAZARA_BIG_ENDIAN)
for (unsigned int i = 0; i < header.num_st; ++i)
{
NzByteSwap(&texCoords[i].u, sizeof(nzInt16));
NzByteSwap(&texCoords[i].v, sizeof(nzInt16));
}
#endif
stream.SetCursorPos(header.offset_tris);
stream.Read(&triangles[0], header.num_tris*sizeof(md2_triangle));
#if defined(NAZARA_BIG_ENDIAN)
for (unsigned int i = 0; i < header.num_tris; ++i)
{
NzByteSwap(&triangles[i].vertices[0], sizeof(nzUInt16));
NzByteSwap(&texCoords[i].texCoords[0], sizeof(nzUInt16));
NzByteSwap(&triangles[i].vertices[1], sizeof(nzUInt16));
NzByteSwap(&texCoords[i].texCoords[1], sizeof(nzUInt16));
NzByteSwap(&triangles[i].vertices[2], sizeof(nzUInt16));
NzByteSwap(&texCoords[i].texCoords[2], sizeof(nzUInt16));
}
#endif
stream.SetCursorPos(header.offset_frames + header.framesize*startFrame);
md2_frame frame;
frame.vertices.resize(header.num_vertices);
// Pour que le modèle soit correctement aligné, on génère un quaternion que nous appliquerons à chacune des vertices
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);
m_frames = new Frame[m_frameCount];
for (unsigned int i = 0; i < m_frameCount; ++i)
{
stream.Read(&frame.scale, sizeof(NzVector3f));
stream.Read(&frame.translate, sizeof(NzVector3f));
stream.Read(&frame.name, 16*sizeof(char));
stream.Read(&frame.vertices[0], header.num_vertices*sizeof(md2_vertex));
#if defined(NAZARA_BIG_ENDIAN)
NzByteSwap(&frame.scale.x, sizeof(float));
NzByteSwap(&frame.scale.y, sizeof(float));
NzByteSwap(&frame.scale.z, sizeof(float));
NzByteSwap(&frame.translate.x, sizeof(float));
NzByteSwap(&frame.translate.y, sizeof(float));
NzByteSwap(&frame.translate.z, sizeof(float));
#endif
m_frames[i].normal = new nzUInt8[m_vertexCount]; // Nous stockons l'indice 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)
{
for (unsigned int v = 0; v < 3; ++v)
{
const md2_vertex& vert = frame.vertices[triangles[t].vertices[v]];
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);
// On fait en sorte d'avoir deux vertices de délimitation, définissant un rectangle dans l'espace
max.Maximize(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].normal[index] = vert.n;
m_frames[i].vertices[index] = vertex;
}
}
m_frames[i].aabb.SetExtends(min, max);
}
m_indexBuffer = nullptr; // Pas d'indexbuffer pour l'instant
m_vertexBuffer = new NzVertexBuffer(m_vertexCount, (3+3+2)*sizeof(float), parameters.storage, nzBufferUsage_Dynamic);
nzUInt8* ptr = reinterpret_cast<nzUInt8*>(m_vertexBuffer->Map(nzBufferAccess_WriteOnly));
if (!ptr)
{
NazaraError("Failed to map vertex buffer");
Destroy();
return false;
}
// On avance jusqu'aux dernières coordonnées de texture et on les définit dans l'ordre inverse
ptr += s_declaration.GetElement(nzElementStream_VertexData, nzElementUsage_TexCoord)->offset + stride * (m_vertexCount-1);
for (unsigned int t = 0; t < header.num_tris; ++t)
{
for (unsigned int v = 0; v < 3; ++v)
{
const md2_texCoord& texC = texCoords[triangles[t].texCoords[v]];
NzVector2f* coords = reinterpret_cast<NzVector2f*>(ptr);
coords->x = texC.u / static_cast<float>(header.skinwidth);
coords->y = 1.f - texC.v / static_cast<float>(header.skinheight);
ptr -= stride;
}
}
if (!m_vertexBuffer->Unmap())
{
NazaraError("Failed to unmap buffer");
Destroy();
return false;
}
m_vertexBuffer->AddResourceReference();
m_vertexBuffer->SetPersistent(false);
AnimateImpl(0, 0, 0.f);
return true;
}
void NzMD2Mesh::Destroy()
{
if (m_frames)
{
for (unsigned int i = 0; i < m_frameCount; ++i)
{
delete[] m_frames[i].normal;
delete[] m_frames[i].vertices;
}
delete[] m_frames;
m_frames = nullptr;
}
if (m_indexBuffer)
{
m_indexBuffer->RemoveResourceReference();
m_indexBuffer = nullptr;
}
if (m_vertexBuffer)
{
m_vertexBuffer->RemoveResourceReference();
m_vertexBuffer = nullptr;
}
}
const NzAxisAlignedBox& NzMD2Mesh::GetAABB() const
{
return m_aabb;
}
nzAnimationType NzMD2Mesh::GetAnimationType() const
{
if (m_frameCount > 1)
return nzAnimationType_Keyframe;
else
return nzAnimationType_Static;
}
unsigned int NzMD2Mesh::GetFrameCount() const
{
return m_frameCount;
}
const NzIndexBuffer* NzMD2Mesh::GetIndexBuffer() const
{
return nullptr;
//return m_indexBuffer;
}
nzPrimitiveType NzMD2Mesh::GetPrimitiveType() const
{
return nzPrimitiveType_TriangleList;
}
const NzVertexBuffer* NzMD2Mesh::GetVertexBuffer() const
{
return m_vertexBuffer;
}
const NzVertexDeclaration* NzMD2Mesh::GetVertexDeclaration() const
{
return &s_declaration;
}
void NzMD2Mesh::Initialize()
{
NzVertexElement elements[3];
elements[0].offset = 0;
elements[0].type = nzElementType_Float3;
elements[0].usage = nzElementUsage_Position;
elements[1].offset = 3*sizeof(float);
elements[1].type = nzElementType_Float3;
elements[1].usage = nzElementUsage_Normal;
elements[2].offset = 3*sizeof(float) + 3*sizeof(float);
elements[2].type = nzElementType_Float2;
elements[2].usage = nzElementUsage_TexCoord;
s_declaration.Create(elements, 3);
}
void NzMD2Mesh::Uninitialize()
{
s_declaration.Destroy();
}
void NzMD2Mesh::AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation)
{
nzUInt8* ptr = reinterpret_cast<nzUInt8*>(m_vertexBuffer->Map(nzBufferAccess_WriteOnly));
if (!ptr)
{
NazaraError("Failed to map vertex buffer");
return;
}
unsigned int stride = s_declaration.GetStride(nzElementStream_VertexData);
unsigned int positionOffset = s_declaration.GetElement(nzElementStream_VertexData, nzElementUsage_Position)->offset;
unsigned int normalOffset = s_declaration.GetElement(nzElementStream_VertexData, nzElementUsage_Normal)->offset;
Frame* fA = &m_frames[frameA];
Frame* fB = &m_frames[frameB];
for (unsigned int i = 0; i < m_vertexCount; ++i)
{
NzVector3f* position = reinterpret_cast<NzVector3f*>(ptr + positionOffset);
NzVector3f* normal = reinterpret_cast<NzVector3f*>(ptr + normalOffset);
*position = fA->vertices[i] + interpolation * (fB->vertices[i] - fA->vertices[i]);
*normal = md2Normals[fA->normal[i]] + interpolation * (md2Normals[fB->normal[i]] - md2Normals[fA->normal[i]]);
ptr += stride;
}
if (!m_vertexBuffer->Unmap())
NazaraWarning("Failed to unmap vertex buffer, expect mesh corruption");
// Interpolation de l'AABB
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
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Loaders/PCX.hpp>
#include <Nazara/Core/Endianness.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/File.hpp>
#include <Nazara/Core/InputStream.hpp>
#include <Nazara/Core/MemoryStream.hpp>
#include <Nazara/Utility/Image.hpp>
#include <Nazara/Utility/Debug.hpp>
// Auteur du loader original : David Henry
namespace
{
struct pcx_header
{
nzUInt8 manufacturer;
nzUInt8 version;
nzUInt8 encoding;
nzUInt8 bitsPerPixel;
nzUInt16 xmin, ymin;
nzUInt16 xmax, ymax;
nzUInt16 horzRes, vertRes;
nzUInt8 palette[48];
nzUInt8 reserved;
nzUInt8 numColorPlanes;
nzUInt16 bytesPerScanLine;
nzUInt16 paletteType;
nzUInt16 horzSize, vertSize;
nzUInt8 padding[54];
};
bool NzLoader_PCX_Check(NzInputStream& stream, const NzImageParams& parameters)
{
NazaraUnused(parameters);
nzUInt8 manufacturer;
if (stream.Read(&manufacturer, 1) != 1)
return false;
return manufacturer == 0x0a;
}
bool NzLoader_PCX_Load(NzImage* image, NzInputStream& stream, const NzImageParams& parameters)
{
NazaraUnused(parameters);
pcx_header header;
if (stream.Read(&header, sizeof(pcx_header)) != sizeof(pcx_header))
{
NazaraError("Failed to read header");
return false;
}
if (header.manufacturer != 0x0a)
{
NazaraError("Bad version number (" + NzString::Number(header.manufacturer) + ')');
return false;
}
#if defined(NAZARA_BIG_ENDIAN)
// Les fichiers PCX sont en little endian
NzByteSwap(&header.xmin, sizeof(nzUInt16));
NzByteSwap(&header.ymin, sizeof(nzUInt16));
NzByteSwap(&header.xmax, sizeof(nzUInt16));
NzByteSwap(&header.ymax, sizeof(nzUInt16));
NzByteSwap(&header.horzRes, sizeof(nzUInt16));
NzByteSwap(&header.vertRes, sizeof(nzUInt16));
NzByteSwap(&header.bytesPerScanLine, sizeof(nzUInt16));
NzByteSwap(&header.paletteType, sizeof(nzUInt16));
NzByteSwap(&header.horzSize, sizeof(nzUInt16));
NzByteSwap(&header.vertSize, sizeof(nzUInt16));
#endif
unsigned int bitCount = header.bitsPerPixel * header.numColorPlanes;
unsigned int width = header.xmax - header.xmin+1;
unsigned int height = header.ymax - header.ymin+1;
if (!image->Create(nzImageType_2D, nzPixelFormat_RGB8, width, height, 1, (parameters.levelCount > 0) ? parameters.levelCount : 1))
{
NazaraError("Failed to create image");
return false;
}
nzUInt8* pixels = image->GetPixels();
int rle_value = 0;
unsigned int rle_count = 0;
switch (bitCount)
{
case 1:
{
for (unsigned int y = 0; y < height; ++y)
{
nzUInt8* ptr = &pixels[y * width * 3];
int bytes = header.bytesPerScanLine;
/* decode line number y */
while (bytes--)
{
if (rle_count == 0)
{
if (!stream.Read(&rle_value, 1))
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
return false;
}
if (rle_value < 0xc0)
rle_count = 1;
else
{
rle_count = rle_value - 0xc0;
if (!stream.Read(&rle_value, 1))
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
return false;
}
}
}
rle_count--;
for (int i = 7; i >= 0; --i)
{
int colorIndex = ((rle_value & (1 << i)) > 0);
*ptr++ = header.palette[colorIndex * 3 + 0];
*ptr++ = header.palette[colorIndex * 3 + 1];
*ptr++ = header.palette[colorIndex * 3 + 2];
}
}
}
break;
}
case 4:
{
nzUInt8* colorIndex = new nzUInt8[width];
nzUInt8* line = new nzUInt8[header.bytesPerScanLine];
for (unsigned int y = 0; y < height; ++y)
{
nzUInt8* ptr = &pixels[y * width * 3];
std::memset(colorIndex, 0, width);
for (unsigned int c = 0; c < 4; ++c)
{
nzUInt8* pLine = line;
int bytes = header.bytesPerScanLine;
/* decode line number y */
while (bytes--)
{
if (rle_count == 0)
{
if (!stream.Read(&rle_value, 1))
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
delete[] colorIndex;
delete[] line;
return false;
}
if (rle_value < 0xc0)
rle_count = 1;
else
{
rle_count = rle_value - 0xc0;
if (!stream.Read(&rle_value, 1))
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
delete[] colorIndex;
delete[] line;
return false;
}
}
}
rle_count--;
*(pLine++) = rle_value;
}
/* compute line's color indexes */
for (unsigned int x = 0; x < width; ++x)
{
if (line[x / 8] & (128 >> (x % 8)))
colorIndex[x] += (1 << c);
}
}
/* decode scan line. color index => rgb */
for (unsigned int x = 0; x < width; ++x)
{
*ptr++ = header.palette[colorIndex[x] * 3 + 0];
*ptr++ = header.palette[colorIndex[x] * 3 + 1];
*ptr++ = header.palette[colorIndex[x] * 3 + 2];
}
}
/* release memory */
delete[] colorIndex;
delete[] line;
break;
}
case 8:
{
nzUInt8 palette[768];
/* the palette is contained in the last 769 bytes of the file */
unsigned int curPos = stream.GetCursorPos();
stream.SetCursorPos(stream.GetSize()-769);
nzUInt8 magic;
if (!stream.Read(&magic, 1))
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
return false;
}
/* first byte must be equal to 0x0c (12) */
if (magic != 0x0c)
{
NazaraError("Colormap's first byte must be 0x0c (0x" + NzString::Number(magic, 16) + ')');
return false;
}
/* read palette */
if (stream.Read(palette, 768) != 768)
{
NazaraError("Failed to read palette");
return false;
}
stream.SetCursorPos(curPos);
/* read pixel data */
for (unsigned int y = 0; y < height; ++y)
{
nzUInt8* ptr = &pixels[y * width * 3];
int bytes = header.bytesPerScanLine;
/* decode line number y */
while (bytes--)
{
if (rle_count == 0)
{
if (!stream.Read(&rle_value, 1))
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
return false;
}
if (rle_value < 0xc0)
rle_count = 1;
else
{
rle_count = rle_value - 0xc0;
if (!stream.Read(&rle_value, 1))
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
return false;
}
}
}
rle_count--;
*ptr++ = palette[rle_value * 3 + 0];
*ptr++ = palette[rle_value * 3 + 1];
*ptr++ = palette[rle_value * 3 + 2];
}
}
break;
}
case 24:
{
for (unsigned int y = 0; y < height; ++y)
{
/* for each color plane */
for (int c = 0; c < 3; ++c)
{
nzUInt8* ptr = &pixels[y * width * 4];
int bytes = header.bytesPerScanLine;
/* decode line number y */
while (bytes--)
{
if (rle_count == 0)
{
if (!stream.Read(&rle_value, 1))
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
return false;
}
if (rle_value < 0xc0)
rle_count = 1;
else
{
rle_count = rle_value - 0xc0;
if (!stream.Read(&rle_value, 1))
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
return false;
}
}
}
rle_count--;
ptr[c] = static_cast<nzUInt8>(rle_value);
ptr += 3;
}
}
}
break;
}
default:
NazaraError("Failed to load " + NzString::Number(bitCount) + " bitcount pcx files");
return false;
}
if (parameters.loadFormat != nzPixelFormat_Undefined)
image->Convert(parameters.loadFormat);
return true;
}
}
void NzLoaders_PCX_Register()
{
NzImageLoader::RegisterLoader("pcx", NzLoader_PCX_Check, NzLoader_PCX_Load);
}
void NzLoaders_PCX_Unregister()
{
NzImageLoader::UnregisterLoader("pcx", NzLoader_PCX_Check, NzLoader_PCX_Load);
}
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Loaders/PCX.hpp>
#include <Nazara/Core/Endianness.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/File.hpp>
#include <Nazara/Core/InputStream.hpp>
#include <Nazara/Core/MemoryStream.hpp>
#include <Nazara/Utility/Image.hpp>
#include <Nazara/Utility/Debug.hpp>
// Auteur du loader original : David Henry
namespace
{
struct pcx_header
{
nzUInt8 manufacturer;
nzUInt8 version;
nzUInt8 encoding;
nzUInt8 bitsPerPixel;
nzUInt16 xmin, ymin;
nzUInt16 xmax, ymax;
nzUInt16 horzRes, vertRes;
nzUInt8 palette[48];
nzUInt8 reserved;
nzUInt8 numColorPlanes;
nzUInt16 bytesPerScanLine;
nzUInt16 paletteType;
nzUInt16 horzSize, vertSize;
nzUInt8 padding[54];
};
bool NzLoader_PCX_Check(NzInputStream& stream, const NzImageParams& parameters)
{
NazaraUnused(parameters);
nzUInt8 manufacturer;
if (stream.Read(&manufacturer, 1) != 1)
return false;
return manufacturer == 0x0a;
}
bool NzLoader_PCX_Load(NzImage* image, NzInputStream& stream, const NzImageParams& parameters)
{
NazaraUnused(parameters);
pcx_header header;
if (stream.Read(&header, sizeof(pcx_header)) != sizeof(pcx_header))
{
NazaraError("Failed to read header");
return false;
}
#if defined(NAZARA_BIG_ENDIAN)
// Les fichiers PCX sont en little endian
NzByteSwap(&header.xmin, sizeof(nzUInt16));
NzByteSwap(&header.ymin, sizeof(nzUInt16));
NzByteSwap(&header.xmax, sizeof(nzUInt16));
NzByteSwap(&header.ymax, sizeof(nzUInt16));
NzByteSwap(&header.horzRes, sizeof(nzUInt16));
NzByteSwap(&header.vertRes, sizeof(nzUInt16));
NzByteSwap(&header.bytesPerScanLine, sizeof(nzUInt16));
NzByteSwap(&header.paletteType, sizeof(nzUInt16));
NzByteSwap(&header.horzSize, sizeof(nzUInt16));
NzByteSwap(&header.vertSize, sizeof(nzUInt16));
#endif
unsigned int bitCount = header.bitsPerPixel * header.numColorPlanes;
unsigned int width = header.xmax - header.xmin+1;
unsigned int height = header.ymax - header.ymin+1;
if (!image->Create(nzImageType_2D, nzPixelFormat_RGB8, width, height, 1, (parameters.levelCount > 0) ? parameters.levelCount : 1))
{
NazaraError("Failed to create image");
return false;
}
nzUInt8* pixels = image->GetPixels();
int rle_value = 0;
unsigned int rle_count = 0;
switch (bitCount)
{
case 1:
{
for (unsigned int y = 0; y < height; ++y)
{
nzUInt8* ptr = &pixels[y * width * 3];
int bytes = header.bytesPerScanLine;
/* decode line number y */
while (bytes--)
{
if (rle_count == 0)
{
if (!stream.Read(&rle_value, 1))
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
return false;
}
if (rle_value < 0xc0)
rle_count = 1;
else
{
rle_count = rle_value - 0xc0;
if (!stream.Read(&rle_value, 1))
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
return false;
}
}
}
rle_count--;
for (int i = 7; i >= 0; --i)
{
int colorIndex = ((rle_value & (1 << i)) > 0);
*ptr++ = header.palette[colorIndex * 3 + 0];
*ptr++ = header.palette[colorIndex * 3 + 1];
*ptr++ = header.palette[colorIndex * 3 + 2];
}
}
}
break;
}
case 4:
{
nzUInt8* colorIndex = new nzUInt8[width];
nzUInt8* line = new nzUInt8[header.bytesPerScanLine];
for (unsigned int y = 0; y < height; ++y)
{
nzUInt8* ptr = &pixels[y * width * 3];
std::memset(colorIndex, 0, width);
for (unsigned int c = 0; c < 4; ++c)
{
nzUInt8* pLine = line;
int bytes = header.bytesPerScanLine;
/* decode line number y */
while (bytes--)
{
if (rle_count == 0)
{
if (!stream.Read(&rle_value, 1))
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
delete[] colorIndex;
delete[] line;
return false;
}
if (rle_value < 0xc0)
rle_count = 1;
else
{
rle_count = rle_value - 0xc0;
if (!stream.Read(&rle_value, 1))
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
delete[] colorIndex;
delete[] line;
return false;
}
}
}
rle_count--;
*(pLine++) = rle_value;
}
/* compute line's color indexes */
for (unsigned int x = 0; x < width; ++x)
{
if (line[x / 8] & (128 >> (x % 8)))
colorIndex[x] += (1 << c);
}
}
/* decode scan line. color index => rgb */
for (unsigned int x = 0; x < width; ++x)
{
*ptr++ = header.palette[colorIndex[x] * 3 + 0];
*ptr++ = header.palette[colorIndex[x] * 3 + 1];
*ptr++ = header.palette[colorIndex[x] * 3 + 2];
}
}
/* release memory */
delete[] colorIndex;
delete[] line;
break;
}
case 8:
{
nzUInt8 palette[768];
/* the palette is contained in the last 769 bytes of the file */
unsigned int curPos = stream.GetCursorPos();
stream.SetCursorPos(stream.GetSize()-769);
nzUInt8 magic;
if (!stream.Read(&magic, 1))
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
return false;
}
/* first byte must be equal to 0x0c (12) */
if (magic != 0x0c)
{
NazaraError("Colormap's first byte must be 0x0c (0x" + NzString::Number(magic, 16) + ')');
return false;
}
/* read palette */
if (stream.Read(palette, 768) != 768)
{
NazaraError("Failed to read palette");
return false;
}
stream.SetCursorPos(curPos);
/* read pixel data */
for (unsigned int y = 0; y < height; ++y)
{
nzUInt8* ptr = &pixels[y * width * 3];
int bytes = header.bytesPerScanLine;
/* decode line number y */
while (bytes--)
{
if (rle_count == 0)
{
if (!stream.Read(&rle_value, 1))
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
return false;
}
if (rle_value < 0xc0)
rle_count = 1;
else
{
rle_count = rle_value - 0xc0;
if (!stream.Read(&rle_value, 1))
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
return false;
}
}
}
rle_count--;
*ptr++ = palette[rle_value * 3 + 0];
*ptr++ = palette[rle_value * 3 + 1];
*ptr++ = palette[rle_value * 3 + 2];
}
}
break;
}
case 24:
{
for (unsigned int y = 0; y < height; ++y)
{
/* for each color plane */
for (int c = 0; c < 3; ++c)
{
nzUInt8* ptr = &pixels[y * width * 4];
int bytes = header.bytesPerScanLine;
/* decode line number y */
while (bytes--)
{
if (rle_count == 0)
{
if (!stream.Read(&rle_value, 1))
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
return false;
}
if (rle_value < 0xc0)
rle_count = 1;
else
{
rle_count = rle_value - 0xc0;
if (!stream.Read(&rle_value, 1))
{
NazaraError("Failed to read stream (byte " + NzString::Number(stream.GetCursorPos()) + ')');
return false;
}
}
}
rle_count--;
ptr[c] = static_cast<nzUInt8>(rle_value);
ptr += 3;
}
}
}
break;
}
default:
NazaraError("Failed to load " + NzString::Number(bitCount) + " bitcount pcx files");
return false;
}
if (parameters.loadFormat != nzPixelFormat_Undefined)
image->Convert(parameters.loadFormat);
return true;
}
}
void NzLoaders_PCX_Register()
{
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
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/StaticMesh.hpp>
#include <Nazara/Core/Error.hpp>
#include <stdexcept>
#include <Nazara/Utility/Debug.hpp>
NzStaticMesh::NzStaticMesh(const NzMesh* parent) :
NzSubMesh(parent)
{
}
NzStaticMesh::NzStaticMesh(const NzMesh* parent, const NzVertexDeclaration* vertexDeclaration, NzVertexBuffer* vertexBuffer, NzIndexBuffer* indexBuffer) :
NzSubMesh(parent)
{
#ifdef NAZARA_DEBUG
if (!Create(vertexDeclaration, vertexBuffer, indexBuffer))
{
NazaraError("Failed to create mesh");
throw std::runtime_error("Constructor failed");
}
#else
Create(vertexDeclaration, vertexBuffer, indexBuffer);
#endif
}
NzStaticMesh::~NzStaticMesh()
{
Destroy();
}
bool NzStaticMesh::Create(const NzVertexDeclaration* vertexDeclaration, NzVertexBuffer* vertexBuffer, NzIndexBuffer* indexBuffer)
{
Destroy();
#if NAZARA_UTILITY_SAFE
if (!vertexDeclaration)
{
NazaraError("Vertex declaration is null");
return false;
}
if (!vertexBuffer)
{
NazaraError("Vertex buffer is null");
return false;
}
#endif
if (indexBuffer)
{
m_indexBuffer = indexBuffer;
m_indexBuffer->AddResourceReference();
}
m_vertexBuffer = vertexBuffer;
m_vertexBuffer->AddResourceReference();
m_vertexDeclaration = vertexDeclaration;
m_vertexDeclaration->AddResourceReference();
return true;
}
void NzStaticMesh::Destroy()
{
m_aabb.SetNull();
if (m_indexBuffer)
{
m_indexBuffer->RemoveResourceReference();
m_indexBuffer = nullptr;
}
if (m_vertexBuffer)
{
m_vertexBuffer->RemoveResourceReference();
m_vertexBuffer = nullptr;
}
if (m_vertexDeclaration)
{
m_vertexDeclaration->RemoveResourceReference();
m_vertexDeclaration = nullptr;
}
}
bool NzStaticMesh::GenerateAABB()
{
if (!m_aabb.IsNull())
return true;
const NzVertexElement* position = m_vertexDeclaration->GetElement(nzElementStream_VertexData, nzElementUsage_Position);
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
nzUInt8* buffer = reinterpret_cast<nzUInt8*>(m_vertexBuffer->Map(nzBufferAccess_ReadOnly));
if (!buffer)
{
NazaraWarning("Failed to lock vertex buffer");
return false;
}
buffer += position->offset;
unsigned int stride = m_vertexDeclaration->GetStride(nzElementStream_VertexData);
unsigned int vertexCount = m_vertexBuffer->GetVertexCount();
for (unsigned int i = 0; i < vertexCount; ++i)
{
m_aabb.ExtendTo(*reinterpret_cast<NzVector3f*>(buffer));
buffer += stride;
}
if (!m_vertexBuffer->Unmap())
NazaraWarning("Failed to unmap vertex buffer");
}
return true;
}
const NzAxisAlignedBox& NzStaticMesh::GetAABB() const
{
return m_aabb;
}
nzAnimationType NzStaticMesh::GetAnimationType() const
{
return nzAnimationType_Static;
}
unsigned int NzStaticMesh::GetFrameCount() const
{
return 1;
}
const NzIndexBuffer* NzStaticMesh::GetIndexBuffer() const
{
return m_indexBuffer;
}
nzPrimitiveType NzStaticMesh::GetPrimitiveType() const
{
return m_primitiveType;
}
const NzVertexBuffer* NzStaticMesh::GetVertexBuffer() const
{
return m_vertexBuffer;
}
const NzVertexDeclaration* NzStaticMesh::GetVertexDeclaration() const
{
return m_vertexDeclaration;
}
bool NzStaticMesh::IsAnimated() const
{
return false;
}
bool NzStaticMesh::IsValid() const
{
return m_vertexBuffer != nullptr && m_vertexDeclaration != nullptr;
}
void NzStaticMesh::SetAABB(const NzAxisAlignedBox& aabb)
{
m_aabb = aabb;
}
void NzStaticMesh::SetPrimitiveType(nzPrimitiveType primitiveType)
{
m_primitiveType = primitiveType;
}
void NzStaticMesh::AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation)
{
NazaraUnused(frameA);
NazaraUnused(frameB);
NazaraUnused(interpolation);
// Le safe mode est censé nous protéger de cet appel
NazaraError("Static mesh have no animation, please enable safe mode");
}
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/StaticMesh.hpp>
#include <Nazara/Core/Error.hpp>
#include <stdexcept>
#include <Nazara/Utility/Debug.hpp>
NzStaticMesh::NzStaticMesh(const NzMesh* parent) :
NzSubMesh(parent)
{
}
NzStaticMesh::NzStaticMesh(const NzMesh* parent, const NzVertexDeclaration* vertexDeclaration, NzVertexBuffer* vertexBuffer, NzIndexBuffer* indexBuffer) :
NzSubMesh(parent)
{
#ifdef NAZARA_DEBUG
if (!Create(vertexDeclaration, vertexBuffer, indexBuffer))
{
NazaraError("Failed to create mesh");
throw std::runtime_error("Constructor failed");
}
#else
Create(vertexDeclaration, vertexBuffer, indexBuffer);
#endif
}
NzStaticMesh::~NzStaticMesh()
{
Destroy();
}
bool NzStaticMesh::Create(const NzVertexDeclaration* vertexDeclaration, NzVertexBuffer* vertexBuffer, NzIndexBuffer* indexBuffer)
{
Destroy();
#if NAZARA_UTILITY_SAFE
if (!vertexDeclaration)
{
NazaraError("Invalid vertex declaration");
return false;
}
if (!vertexBuffer)
{
NazaraError("Invalid vertex buffer");
return false;
}
#endif
if (indexBuffer)
indexBuffer->AddResourceListener(this);
m_indexBuffer = indexBuffer;
m_vertexBuffer = vertexBuffer;
m_vertexBuffer->AddResourceListener(this);
m_vertexDeclaration = vertexDeclaration;
m_vertexDeclaration->AddResourceListener(this);
return true;
}
void NzStaticMesh::Destroy()
{
m_aabb.SetNull();
if (m_indexBuffer)
{
m_indexBuffer->RemoveResourceListener(this);
m_indexBuffer = nullptr;
}
if (m_vertexBuffer)
{
m_vertexBuffer->RemoveResourceListener(this);
m_vertexBuffer = nullptr;
}
if (m_vertexDeclaration)
{
m_vertexDeclaration->RemoveResourceListener(this);
m_vertexDeclaration = nullptr;
}
}
bool NzStaticMesh::GenerateAABB()
{
if (!m_aabb.IsNull())
return true;
const NzVertexElement* position = m_vertexDeclaration->GetElement(nzElementStream_VertexData, nzElementUsage_Position);
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
nzUInt8* buffer = reinterpret_cast<nzUInt8*>(m_vertexBuffer->Map(nzBufferAccess_ReadOnly));
if (!buffer)
{
NazaraWarning("Failed to lock vertex buffer");
return false;
}
buffer += position->offset;
unsigned int stride = m_vertexDeclaration->GetStride(nzElementStream_VertexData);
unsigned int vertexCount = m_vertexBuffer->GetVertexCount();
for (unsigned int i = 0; i < vertexCount; ++i)
{
m_aabb.ExtendTo(*reinterpret_cast<NzVector3f*>(buffer));
buffer += stride;
}
if (!m_vertexBuffer->Unmap())
NazaraWarning("Failed to unmap vertex buffer");
}
return true;
}
const NzAxisAlignedBox& NzStaticMesh::GetAABB() const
{
return m_aabb;
}
nzAnimationType NzStaticMesh::GetAnimationType() const
{
return nzAnimationType_Static;
}
unsigned int NzStaticMesh::GetFrameCount() const
{
return 1;
}
const NzIndexBuffer* NzStaticMesh::GetIndexBuffer() const
{
return m_indexBuffer;
}
nzPrimitiveType NzStaticMesh::GetPrimitiveType() const
{
return m_primitiveType;
}
const NzVertexBuffer* NzStaticMesh::GetVertexBuffer() const
{
return m_vertexBuffer;
}
const NzVertexDeclaration* NzStaticMesh::GetVertexDeclaration() const
{
return m_vertexDeclaration;
}
bool NzStaticMesh::IsAnimated() const
{
return false;
}
bool NzStaticMesh::IsValid() const
{
return m_vertexBuffer != nullptr && m_vertexDeclaration != nullptr;
}
void NzStaticMesh::SetAABB(const NzAxisAlignedBox& aabb)
{
m_aabb = aabb;
}
void NzStaticMesh::SetPrimitiveType(nzPrimitiveType primitiveType)
{
m_primitiveType = primitiveType;
}
void NzStaticMesh::AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation)
{
NazaraUnused(frameA);
NazaraUnused(frameB);
NazaraUnused(interpolation);
// Le safe mode est censé nous protéger de cet appel
NazaraError("Static mesh have no animation, please enable safe mode");
}
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
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/VertexDeclaration.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Utility/Config.hpp>
#include <algorithm>
#include <cstring>
#include <stdexcept>
#include <vector>
#if NAZARA_UTILITY_THREADSAFE && NAZARA_THREADSAFETY_VERTEXDECLARATION
#include <Nazara/Core/ThreadSafety.hpp>
#else
#include <Nazara/Core/ThreadSafetyOff.hpp>
#endif
#include <Nazara/Utility/Debug.hpp>
namespace
{
const unsigned int size[] =
{
sizeof(nzUInt32), // nzElementType_Color
1*sizeof(double), // nzElementType_Double1
2*sizeof(double), // nzElementType_Double2
3*sizeof(double), // nzElementType_Double3
4*sizeof(double), // nzElementType_Double4
1*sizeof(float), // nzElementType_Float1
2*sizeof(float), // nzElementType_Float2
3*sizeof(float), // nzElementType_Float3
4*sizeof(float) // nzElementType_Float4
};
bool VertexElementCompare(const NzVertexElement& elementA, const NzVertexElement& elementB)
{
// Nous classons d'abord par stream
if (elementA.stream == elementB.stream)
{
// Ensuite par usage
if (elementA.usage == elementB.usage)
// Et finalement par usageIndex
return elementA.usageIndex < elementB.usageIndex;
else
return elementA.usage < elementB.usage;
}
else
return elementA.stream < elementB.stream;
}
}
struct NzVertexDeclarationImpl
{
std::vector<NzVertexElement> elements;
int elementPos[nzElementStream_Max+1][nzElementUsage_Max+1];
int streamPos[nzElementStream_Max+1];
unsigned int stride[nzElementStream_Max+1] = {0};
unsigned short refCount = 1;
NazaraMutex(mutex)
};
NzVertexDeclaration::NzVertexDeclaration(const NzVertexElement* elements, unsigned int elementCount)
{
#ifdef NAZARA_DEBUG
if (!Create(elements, elementCount))
{
NazaraError("Failed to create declaration");
throw std::runtime_error("Constructor failed");
}
#else
Create(elements, elementCount);
#endif
}
NzVertexDeclaration::NzVertexDeclaration(const NzVertexDeclaration& declaration) :
NzResource(),
m_sharedImpl(declaration.m_sharedImpl)
{
if (m_sharedImpl)
{
NazaraMutexLock(m_sharedImpl->mutex);
m_sharedImpl->refCount++;
NazaraMutexUnlock(m_sharedImpl->mutex);
}
}
NzVertexDeclaration::NzVertexDeclaration(NzVertexDeclaration&& declaration) noexcept :
m_sharedImpl(declaration.m_sharedImpl)
{
declaration.m_sharedImpl = nullptr;
}
NzVertexDeclaration::~NzVertexDeclaration()
{
Destroy();
}
bool NzVertexDeclaration::Create(const NzVertexElement* elements, unsigned int elementCount)
{
Destroy();
#if NAZARA_UTILITY_SAFE
if (!elements || elementCount == 0)
{
NazaraError("No element");
return false;
}
#endif
NzVertexDeclarationImpl* impl = new NzVertexDeclarationImpl;
std::memset(&impl->elementPos, -1, (nzElementStream_Max+1)*(nzElementUsage_Max+1)*sizeof(int));
std::memset(&impl->streamPos, -1, (nzElementStream_Max+1)*sizeof(int));
// On copie et trie les éléments
impl->elements.resize(elementCount);
std::memcpy(&impl->elements[0], elements, elementCount*sizeof(NzVertexElement));
std::sort(impl->elements.begin(), impl->elements.end(), VertexElementCompare);
for (unsigned int i = 0; i < elementCount; ++i)
{
NzVertexElement& current = impl->elements[i];
#if NAZARA_UTILITY_SAFE
// Notre tableau étant trié, s'il y a collision, les deux éléments identiques se suivent...
if (i > 0)
{
NzVertexElement& previous = impl->elements[i-1]; // On accède à l'élément précédent
if (previous.usage == current.usage && previous.usageIndex == current.usageIndex && previous.stream == current.stream)
{
// Les deux éléments sont identiques là où ils ne devraient pas, nous avons une collision...
NazaraError("Element usage 0x" + NzString::Number(current.usage, 16) + " collision with usage index " + NzString::Number(current.usageIndex) + " on stream 0x" + NzString::Number(current.stream, 16));
delete impl;
return false;
}
}
#endif
if (current.usageIndex == 0)
impl->elementPos[current.stream][current.usage] = i;
if (impl->streamPos[current.stream] == -1)
impl->streamPos[current.stream] = i; // Premier élément du stream (via le triage)
impl->stride[current.stream] += size[current.type];
}
#if NAZARA_UTILITY_FORCE_DECLARATION_STRIDE_MULTIPLE_OF_32
for (unsigned int& stride : impl->stride)
stride = ((static_cast<int>(stride)-1)/32+1)*32;
#endif
m_sharedImpl = impl;
return true;
}
void NzVertexDeclaration::Destroy()
{
if (!m_sharedImpl)
return;
NazaraMutexLock(m_sharedImpl->mutex);
bool freeSharedImpl = (--m_sharedImpl->refCount == 0);
NazaraMutexUnlock(m_sharedImpl->mutex);
if (freeSharedImpl)
delete m_sharedImpl;
m_sharedImpl = nullptr;
}
const NzVertexElement* NzVertexDeclaration::GetElement(unsigned int i) const
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
{
NazaraError("Declaration not created");
return nullptr;
}
if (i >= m_sharedImpl->elements.size())
{
NazaraError("Element index out of range (" + NzString::Number(i) + " >= " + NzString::Number(m_sharedImpl->elements.size()) + ')');
return nullptr;
}
#endif
return &m_sharedImpl->elements[i];
}
const NzVertexElement* NzVertexDeclaration::GetElement(nzElementStream stream, unsigned int i) const
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
{
NazaraError("Declaration not created");
return nullptr;
}
int streamPos = m_sharedImpl->streamPos[stream];
if (streamPos == -1)
{
NazaraError("Declaration has no stream 0x" + NzString::Number(stream, 16));
return nullptr;
}
unsigned int upperLimit = GetElementCount(stream);
if (i >= upperLimit)
{
NazaraError("Element index out of range (" + NzString::Number(i) + " >= " + NzString::Number(upperLimit) + ')');
return nullptr;
}
#endif
return &m_sharedImpl->elements[m_sharedImpl->streamPos[stream]+i];
}
const NzVertexElement* NzVertexDeclaration::GetElement(nzElementStream stream, nzElementUsage usage, unsigned int usageIndex) const
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
{
NazaraError("Declaration not created");
return nullptr;
}
#endif
int elementPos = m_sharedImpl->elementPos[stream][usage];
if (elementPos == -1)
return nullptr;
elementPos += usageIndex;
if (static_cast<unsigned int>(elementPos) >= m_sharedImpl->elements.size())
return nullptr;
NzVertexElement& element = m_sharedImpl->elements[elementPos];
if (element.stream != stream || element.usage != usage || element.usageIndex != usageIndex)
return nullptr;
return &element;
}
unsigned int NzVertexDeclaration::GetElementCount() const
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
{
NazaraError("Declaration not created");
return 0;
}
#endif
return m_sharedImpl->elements.size();
}
unsigned int NzVertexDeclaration::GetElementCount(nzElementStream stream) const
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
{
NazaraError("Declaration not created");
return 0;
}
#endif
int streamPos = m_sharedImpl->streamPos[stream];
if (streamPos == -1)
return 0;
unsigned int upperLimit = 0;
if (stream == nzElementStream_Max)
upperLimit = m_sharedImpl->elements.size();
else
{
for (unsigned int upperStream = stream+1; upperStream <= nzElementStream_Max; ++upperStream)
{
if (m_sharedImpl->streamPos[upperStream] != -1)
{
upperLimit = m_sharedImpl->streamPos[upperStream];
break;
}
else if (upperStream == nzElementStream_Max) // Dernier stream, toujours pas de limite
upperLimit = m_sharedImpl->elements.size();
}
}
return upperLimit-streamPos;
}
unsigned int NzVertexDeclaration::GetStride(nzElementStream stream) const
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
{
NazaraError("Declaration not created");
return 0;
}
#endif
return m_sharedImpl->stride[stream];
}
bool NzVertexDeclaration::HasStream(nzElementStream stream) const
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
{
NazaraError("Declaration not created");
return false;
}
#endif
return m_sharedImpl->streamPos[stream] != -1;
}
bool NzVertexDeclaration::IsValid() const
{
return m_sharedImpl != nullptr;
}
NzVertexDeclaration& NzVertexDeclaration::operator=(const NzVertexDeclaration& declaration)
{
Destroy();
m_sharedImpl = declaration.m_sharedImpl;
if (m_sharedImpl)
{
NazaraMutexLock(m_sharedImpl->mutex);
m_sharedImpl->refCount++;
NazaraMutexUnlock(m_sharedImpl->mutex);
}
return *this;
}
NzVertexDeclaration& NzVertexDeclaration::operator=(NzVertexDeclaration&& declaration) noexcept
{
Destroy();
m_sharedImpl = declaration.m_sharedImpl;
declaration.m_sharedImpl = nullptr;
return *this;
}
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/VertexDeclaration.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Utility/Config.hpp>
#include <algorithm>
#include <cstring>
#include <stdexcept>
#include <vector>
#if NAZARA_UTILITY_THREADSAFE && NAZARA_THREADSAFETY_VERTEXDECLARATION
#include <Nazara/Core/ThreadSafety.hpp>
#else
#include <Nazara/Core/ThreadSafetyOff.hpp>
#endif
#include <Nazara/Utility/Debug.hpp>
namespace
{
const unsigned int elementCount[] =
{
4, // nzElementType_Color
1, // nzElementType_Double1
2, // nzElementType_Double2
3, // nzElementType_Double3
4, // nzElementType_Double4
1, // nzElementType_Float1
2, // nzElementType_Float2
3, // nzElementType_Float3
4 // nzElementType_Float4
};
const unsigned int elementSize[] =
{
4*sizeof(nzUInt8), // nzElementType_Color
1*sizeof(double), // nzElementType_Double1
2*sizeof(double), // nzElementType_Double2
3*sizeof(double), // nzElementType_Double3
4*sizeof(double), // nzElementType_Double4
1*sizeof(float), // nzElementType_Float1
2*sizeof(float), // nzElementType_Float2
3*sizeof(float), // nzElementType_Float3
4*sizeof(float) // nzElementType_Float4
};
bool VertexElementCompare(const NzVertexElement& elementA, const NzVertexElement& elementB)
{
// Nous classons d'abord par stream
if (elementA.stream == elementB.stream)
{
// Ensuite par usage
if (elementA.usage == elementB.usage)
// Et finalement par usageIndex
return elementA.usageIndex < elementB.usageIndex;
else
return elementA.usage < elementB.usage;
}
else
return elementA.stream < elementB.stream;
}
}
struct NzVertexDeclarationImpl
{
std::vector<NzVertexElement> elements;
int elementPos[nzElementStream_Max+1][nzElementUsage_Max+1];
int streamPos[nzElementStream_Max+1];
unsigned int stride[nzElementStream_Max+1] = {0};
unsigned short refCount = 1;
NazaraMutex(mutex)
};
NzVertexDeclaration::NzVertexDeclaration(const NzVertexElement* elements, unsigned int elementCount)
{
#ifdef NAZARA_DEBUG
if (!Create(elements, elementCount))
{
NazaraError("Failed to create declaration");
throw std::runtime_error("Constructor failed");
}
#else
Create(elements, elementCount);
#endif
}
NzVertexDeclaration::NzVertexDeclaration(const NzVertexDeclaration& declaration) :
NzResource(),
m_sharedImpl(declaration.m_sharedImpl)
{
if (m_sharedImpl)
{
NazaraMutexLock(m_sharedImpl->mutex);
m_sharedImpl->refCount++;
NazaraMutexUnlock(m_sharedImpl->mutex);
}
}
NzVertexDeclaration::NzVertexDeclaration(NzVertexDeclaration&& declaration) noexcept :
m_sharedImpl(declaration.m_sharedImpl)
{
declaration.m_sharedImpl = nullptr;
}
NzVertexDeclaration::~NzVertexDeclaration()
{
Destroy();
}
bool NzVertexDeclaration::Create(const NzVertexElement* elements, unsigned int elementCount)
{
Destroy();
#if NAZARA_UTILITY_SAFE
if (!elements || elementCount == 0)
{
NazaraError("No element");
return false;
}
#endif
NzVertexDeclarationImpl* impl = new NzVertexDeclarationImpl;
std::memset(&impl->elementPos, -1, (nzElementStream_Max+1)*(nzElementUsage_Max+1)*sizeof(int));
std::memset(&impl->streamPos, -1, (nzElementStream_Max+1)*sizeof(int));
// On copie et trie les éléments
impl->elements.resize(elementCount);
std::memcpy(&impl->elements[0], elements, elementCount*sizeof(NzVertexElement));
std::sort(impl->elements.begin(), impl->elements.end(), VertexElementCompare);
for (unsigned int i = 0; i < elementCount; ++i)
{
NzVertexElement& current = impl->elements[i];
#if NAZARA_UTILITY_SAFE
// Notre tableau étant trié, s'il y a collision, les deux éléments identiques se suivent...
if (i > 0)
{
NzVertexElement& previous = impl->elements[i-1]; // On accède à l'élément précédent
if (previous.usage == current.usage && previous.usageIndex == current.usageIndex && previous.stream == current.stream)
{
// Les deux éléments sont identiques là où ils ne devraient pas, nous avons une collision...
NazaraError("Element usage 0x" + NzString::Number(current.usage, 16) + " collision with usage index " + NzString::Number(current.usageIndex) + " on stream 0x" + NzString::Number(current.stream, 16));
delete impl;
return false;
}
}
#endif
if (current.usageIndex == 0)
impl->elementPos[current.stream][current.usage] = i;
if (impl->streamPos[current.stream] == -1)
impl->streamPos[current.stream] = i; // Premier élément du stream (via le triage)
impl->stride[current.stream] += elementSize[current.type];
}
#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
m_sharedImpl = impl;
NotifyCreated();
return true;
}
void NzVertexDeclaration::Destroy()
{
if (!m_sharedImpl)
return;
NotifyDestroy();
NazaraMutexLock(m_sharedImpl->mutex);
bool freeSharedImpl = (--m_sharedImpl->refCount == 0);
NazaraMutexUnlock(m_sharedImpl->mutex);
if (freeSharedImpl)
delete m_sharedImpl;
m_sharedImpl = nullptr;
}
const NzVertexElement* NzVertexDeclaration::GetElement(unsigned int i) const
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
{
NazaraError("Declaration not created");
return nullptr;
}
if (i >= m_sharedImpl->elements.size())
{
NazaraError("Element index out of range (" + NzString::Number(i) + " >= " + NzString::Number(m_sharedImpl->elements.size()) + ')');
return nullptr;
}
#endif
return &m_sharedImpl->elements[i];
}
const NzVertexElement* NzVertexDeclaration::GetElement(nzElementStream stream, unsigned int i) const
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
{
NazaraError("Declaration not created");
return nullptr;
}
int streamPos = m_sharedImpl->streamPos[stream];
if (streamPos == -1)
{
NazaraError("Declaration has no stream 0x" + NzString::Number(stream, 16));
return nullptr;
}
unsigned int upperLimit = GetElementCount(stream);
if (i >= upperLimit)
{
NazaraError("Element index out of range (" + NzString::Number(i) + " >= " + NzString::Number(upperLimit) + ')');
return nullptr;
}
#endif
return &m_sharedImpl->elements[m_sharedImpl->streamPos[stream]+i];
}
const NzVertexElement* NzVertexDeclaration::GetElement(nzElementStream stream, nzElementUsage usage, unsigned int usageIndex) const
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
{
NazaraError("Declaration not created");
return nullptr;
}
#endif
int elementPos = m_sharedImpl->elementPos[stream][usage];
if (elementPos == -1)
return nullptr;
elementPos += usageIndex;
if (static_cast<unsigned int>(elementPos) >= m_sharedImpl->elements.size())
return nullptr;
NzVertexElement& element = m_sharedImpl->elements[elementPos];
if (element.stream != stream || element.usage != usage || element.usageIndex != usageIndex)
return nullptr;
return &element;
}
unsigned int NzVertexDeclaration::GetElementCount() const
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
{
NazaraError("Declaration not created");
return 0;
}
#endif
return m_sharedImpl->elements.size();
}
unsigned int NzVertexDeclaration::GetElementCount(nzElementStream stream) const
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
{
NazaraError("Declaration not created");
return 0;
}
#endif
int streamPos = m_sharedImpl->streamPos[stream];
if (streamPos == -1)
return 0;
unsigned int upperLimit = 0;
if (stream == nzElementStream_Max)
upperLimit = m_sharedImpl->elements.size();
else
{
for (unsigned int upperStream = stream+1; upperStream <= nzElementStream_Max; ++upperStream)
{
if (m_sharedImpl->streamPos[upperStream] != -1)
{
upperLimit = m_sharedImpl->streamPos[upperStream];
break;
}
else if (upperStream == nzElementStream_Max) // Dernier stream, toujours pas de limite
upperLimit = m_sharedImpl->elements.size();
}
}
return upperLimit-streamPos;
}
unsigned int NzVertexDeclaration::GetStride(nzElementStream stream) const
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
{
NazaraError("Declaration not created");
return 0;
}
#endif
return m_sharedImpl->stride[stream];
}
bool NzVertexDeclaration::HasStream(nzElementStream stream) const
{
#if NAZARA_UTILITY_SAFE
if (!m_sharedImpl)
{
NazaraError("Declaration not created");
return false;
}
#endif
return m_sharedImpl->streamPos[stream] != -1;
}
bool NzVertexDeclaration::IsValid() const
{
return m_sharedImpl != nullptr;
}
NzVertexDeclaration& NzVertexDeclaration::operator=(const NzVertexDeclaration& declaration)
{
Destroy();
m_sharedImpl = declaration.m_sharedImpl;
if (m_sharedImpl)
{
NazaraMutexLock(m_sharedImpl->mutex);
m_sharedImpl->refCount++;
NazaraMutexUnlock(m_sharedImpl->mutex);
}
return *this;
}
NzVertexDeclaration& NzVertexDeclaration::operator=(NzVertexDeclaration&& declaration) 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