Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Remi Beges
2012-07-24 14:35:05 +02:00
112 changed files with 4780 additions and 1469 deletions

View File

@@ -13,8 +13,6 @@
#error OS not handled
#endif
#define NAZARA_CLASS_CLOCK
#include <Nazara/Core/ThreadSafety.hpp>
#include <Nazara/Core/Debug.hpp>
NzClock::NzClock() :

View File

@@ -16,8 +16,6 @@
#error OS not handled
#endif
#define NAZARA_CLASS_DIRECTORY
#include <Nazara/Core/ThreadSafety.hpp>
#include <Nazara/Core/Debug.hpp>
namespace

View File

@@ -14,8 +14,6 @@
#error No implementation for this platform
#endif
#define NAZARA_CLASS_DYNLIB
#include <Nazara/Core/ThreadSafety.hpp>
#include <Nazara/Core/Debug.hpp>
NzDynLib::NzDynLib(const NzString& libraryPath) :

View File

@@ -19,8 +19,6 @@
#error OS not handled
#endif
#define NAZARA_CLASS_FILE
#include <Nazara/Core/ThreadSafety.hpp>
#include <Nazara/Core/Debug.hpp>
NzFile::NzFile() :
@@ -295,6 +293,7 @@ std::size_t NzFile::Read(void* buffer, std::size_t size)
return m_impl->Read(buffer, size);
else
{
// Si nous ne devons rien lire, nous avançons simplement
nzUInt64 currentPos = m_impl->GetCursorPos();
m_impl->SetCursorPos(NzFile::AtCurrent, size);

View File

@@ -13,8 +13,6 @@
#include <cstdio>
#endif
#define NAZARA_CLASS_LOG
#include <Nazara/Core/ThreadSafety.hpp>
#include <Nazara/Core/Debug.hpp>
namespace

View File

@@ -13,15 +13,13 @@
#include <cstring>
#include <sstream>
#include <Utfcpp/utf8.h>
#define NAZARA_CLASS_STRING
#include <Nazara/Core/ThreadSafety.hpp>
#include <Nazara/Core/Debug.hpp>
inline unsigned int nzPow2(unsigned int n)
{
unsigned int x = 1;
// Tant que x est plus petit que n, on décale ses bits vers la gauche, ce qui revient à multiplier par deux
while(x <= n)
x <<= 1;
@@ -265,9 +263,15 @@ NzString& NzString::Append(const NzString& string)
return *this;
}
void NzString::Clear()
void NzString::Clear(bool keepBuffer)
{
ReleaseString();
if (keepBuffer)
{
EnsureOwnership();
m_sharedString->size = 0;
}
else
ReleaseString();
}
bool NzString::Contains(char character, int start, nzUInt32 flags) const
@@ -2843,7 +2847,7 @@ unsigned int NzString::Replace(const char* oldString, const char* replaceString,
else ///TODO: Algorithme de remplacement sans changement de buffer (si rSize < oSize)
{
unsigned int newSize = m_sharedString->size + Count(oldString)*(rSize - oSize);
if (newSize == m_sharedString->size) // Count(oldString) == 0
if (newSize == m_sharedString->size) // Alors c'est que Count(oldString) == 0
return 0;
char* newString = new char[newSize+1];
@@ -2913,7 +2917,7 @@ unsigned int NzString::Replace(const NzString& oldString, const NzString& replac
else
{
unsigned int newSize = m_sharedString->size + Count(oldString)*(replaceString.m_sharedString->size - oldString.m_sharedString->size);
if (newSize == m_sharedString->size) // Count(oldString) == 0
if (newSize == m_sharedString->size) // Alors c'est que Count(oldString) == 0
return 0;
char* newString = new char[newSize+1];
@@ -3198,6 +3202,9 @@ void NzString::Reserve(unsigned int bufferSize)
NzString& NzString::Resize(int size, char character)
{
if (size == 0)
Clear(true);
if (size < 0)
size = std::max(static_cast<int>(m_sharedString->size + size), 0);
@@ -3242,6 +3249,9 @@ NzString& NzString::Resize(int size, char character)
NzString NzString::Resized(int size, char character) const
{
if (size == 0)
return NzString();
if (size < 0)
size = m_sharedString->size + size;
@@ -3492,8 +3502,9 @@ unsigned int NzString::SplitAny(std::vector<NzString>& result, const char* separ
if (m_sharedString->size == 0)
return 0;
unsigned int lastSep = FindAny(separations, start, flags);
unsigned int oldSize = result.size();
unsigned int lastSep = FindAny(separations, start, flags);
if (lastSep == npos)
{
result.push_back(*this);
@@ -3842,7 +3853,7 @@ bool NzString::ToBool(bool* value, nzUInt32 flags) const
bool NzString::ToDouble(double* value) const
{
if (m_sharedString->size)
if (m_sharedString->size == 0)
return false;
if (value)
@@ -3853,13 +3864,15 @@ bool NzString::ToDouble(double* value) const
bool NzString::ToInteger(long long* value, nzUInt8 base) const
{
if (!IsNumber(base))
return false;
if (value)
*value = NzStringToNumber(*this, base);
{
bool ok;
*value = NzStringToNumber(*this, base, &ok);
return true;
return ok;
}
else
return IsNumber(base);
}
NzString NzString::ToLower(nzUInt32 flags) const
@@ -5089,11 +5102,12 @@ void NzString::ReleaseString()
return;
NazaraMutexLock(m_sharedString->mutex);
m_sharedString->refCount--;
bool freeSharedString = (--m_sharedString->refCount == 0);
NazaraMutexUnlock(m_sharedString->mutex);
if (m_sharedString->refCount == 0)
if (freeSharedString)
{
NazaraMutexUnlock(m_sharedString->mutex);
delete[] m_sharedString->string;
delete m_sharedString;
}

View File

@@ -6,49 +6,46 @@
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Debug.hpp>
namespace NzUnicode
#if NAZARA_CORE_INCLUDE_UNICODEDATA
struct Character
{
#if NAZARA_CORE_INCLUDE_UNICODEDATA
struct Character
{
nzUInt16 category; // Le type du caractère
nzUInt8 direction; // Le sens de lecure du caractère
nzUInt32 lowerCase; // Le caractère correspondant en minuscule
nzUInt32 titleCase; // Le caractère correspondant en titre
nzUInt32 upperCase; // Le caractère correspondant en majuscule
};
nzUInt16 category; // Le type du caractère
nzUInt8 direction; // Le sens de lecure du caractère
nzUInt32 lowerCase; // Le caractère correspondant en minuscule
nzUInt32 titleCase; // Le caractère correspondant en titre
nzUInt32 upperCase; // Le caractère correspondant en majuscule
};
#include <Nazara/Core/UnicodeData.hpp>
#include <Nazara/Core/UnicodeData.hpp>
#else // Implémentation bidon
#else // Implémentation bidon
Category GetCategory(char32_t character)
{
NazaraUnused(character);
NzUnicode::Category NzUnicode::GetCategory(char32_t character)
{
NazaraUnused(character);
return Category_NoCategory;
}
Direction GetDirection(char32_t character)
{
NazaraUnused(character);
return Direction_Boundary_Neutral;
}
char32_t GetLowercase(char32_t character)
{
return character;
}
char32_t GetTitlecase(char32_t character)
{
return character;
}
char32_t GetUppercase(char32_t character)
{
return character;
}
#endif
return Category_NoCategory;
}
NzUnicode::Direction NzUnicode::GetDirection(char32_t character)
{
NazaraUnused(character);
return Direction_Boundary_Neutral;
}
char32_t NzUnicode::GetLowercase(char32_t character)
{
return character;
}
char32_t NzUnicode::GetTitlecase(char32_t character)
{
return character;
}
char32_t NzUnicode::GetUppercase(char32_t character)
{
return character;
}
#endif

View File

@@ -2,13 +2,13 @@
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
#pragma once
#ifndef NAZARA_THREADCONDITIONIMPL_HPP
#define NAZARA_THREADCONDITIONIMPL_HPP
// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
#include <Nazara/Prerequesites.hpp>
#include <windows.h>

View File

@@ -1,243 +0,0 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/Buffer.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/HardwareBuffer.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/SoftwareBuffer.hpp>
#include <stdexcept>
#include <Nazara/Renderer/Debug.hpp>
namespace
{
nzRendererCap storageToCapability[] = {
nzRendererCap_HardwareBuffer, // nzBufferStorage_Hardware
nzRendererCap_SoftwareBuffer, // nzBufferStorage_Software
};
}
NzBuffer::NzBuffer(nzBufferType type) :
m_type(type),
m_typeSize(0),
m_impl(nullptr),
m_length(0)
{
}
NzBuffer::NzBuffer(nzBufferType type, unsigned int length, nzUInt8 typeSize, nzBufferUsage usage) :
m_type(type),
m_impl(nullptr)
{
Create(length, typeSize, usage);
#ifdef NAZARA_DEBUG
if (!m_impl)
{
NazaraError("Failed to create buffer");
throw std::runtime_error("Constructor failed");
}
#endif
}
NzBuffer::~NzBuffer()
{
Destroy();
}
bool NzBuffer::CopyContent(NzBuffer& buffer)
{
void* ptr = buffer.Map(nzBufferAccess_ReadOnly);
if (!ptr)
{
NazaraError("Failed to map source buffer");
return false;
}
bool r = Fill(ptr, 0, m_length);
if (!buffer.Unmap())
NazaraWarning("Failed to unmap source buffer");
return r;
}
bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage)
{
Destroy();
// On tente d'abord de faire un buffer hardware, si supporté
if (NazaraRenderer->HasCapability(nzRendererCap_HardwareBuffer))
{
m_impl = new NzHardwareBuffer(this, m_type);
if (!m_impl->Create(length*typeSize, usage))
{
NazaraWarning("Failed to create hardware buffer, trying to create software buffer...");
delete m_impl;
m_impl = nullptr;
}
}
if (!m_impl)
{
if (!NazaraRenderer->HasCapability(nzRendererCap_SoftwareBuffer))
{
// Ne devrait jamais arriver
NazaraError("Software buffer not supported");
return false;
}
m_impl = new NzSoftwareBuffer(this, m_type);
if (!m_impl->Create(length*typeSize, usage))
{
NazaraError("Failed to create software buffer");
delete m_impl;
m_impl = nullptr;
return false;
}
}
m_length = length;
m_typeSize = typeSize;
m_usage = usage;
// Si on arrive ici c'est que tout s'est bien passé.
return true;
}
void NzBuffer::Destroy()
{
if (m_impl)
{
m_impl->Destroy();
delete m_impl;
m_impl = nullptr;
}
}
bool NzBuffer::Fill(const void* data, unsigned int offset, unsigned int length)
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Buffer not created");
return false;
}
if (offset+length > m_length)
{
NazaraError("Exceeding buffer size");
return false;
}
#endif
return m_impl->Fill(data, offset*m_typeSize, length*m_typeSize);
}
void* NzBuffer::GetBufferPtr()
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Buffer not created");
return nullptr;
}
#endif
return m_impl->GetBufferPtr();
}
const void* NzBuffer::GetBufferPtr() const
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Buffer not created");
return nullptr;
}
#endif
return m_impl->GetBufferPtr();
}
NzBufferImpl* NzBuffer::GetImpl() const
{
return m_impl;
}
unsigned int NzBuffer::GetLength() const
{
return m_length;
}
unsigned int NzBuffer::GetSize() const
{
return m_length*m_typeSize;
}
nzBufferStorage NzBuffer::GetStorage() const
{
return m_storage;
}
nzBufferType NzBuffer::GetType() const
{
return m_type;
}
nzUInt8 NzBuffer::GetTypeSize() const
{
return m_typeSize;
}
nzBufferUsage NzBuffer::GetUsage() const
{
return m_usage;
}
bool NzBuffer::IsHardware() const
{
return m_storage == nzBufferStorage_Hardware;
}
void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length)
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Buffer not created");
return nullptr;
}
if (offset+length > m_length)
{
NazaraError("Exceeding buffer size");
return nullptr;
}
#endif
return m_impl->Map(access, offset*m_typeSize, length*m_typeSize);
}
bool NzBuffer::Unmap()
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Buffer not created");
return false;
}
#endif
return m_impl->Unmap();
}
bool NzBuffer::IsSupported(nzBufferStorage storage)
{
return NazaraRenderer->HasCapability(storageToCapability[storage]);
}

View File

@@ -1,33 +0,0 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_BUFFERIMPL_HPP
#define NAZARA_BUFFERIMPL_HPP
#include <Nazara/Renderer/Buffer.hpp>
class NzBufferImpl
{
public:
NzBufferImpl() = default;
virtual ~NzBufferImpl();
virtual void Bind() = 0;
virtual bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static) = 0;
virtual void Destroy() = 0;
virtual bool Fill(const void* data, unsigned int offset, unsigned int size) = 0;
virtual void* GetBufferPtr() = 0;
virtual bool IsHardware() const = 0;
virtual void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0) = 0;
virtual bool Unmap() = 0;
};
#endif // NAZARA_BUFFERIMPL_INCLUDED

View File

@@ -290,7 +290,8 @@ bool NzContext::EnsureContext()
threadContext = context;
}
else if (!threadContext->SetActive(true))
if (!threadContext->SetActive(true))
{
NazaraError("Failed to active thread context");
return false;

View File

@@ -6,15 +6,27 @@
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/Debug.hpp>
nzUInt8 NzContextParameters::defaultMajorVersion; // Initialisé par NzOpenGL
nzUInt8 NzContextParameters::defaultMinorVersion; // Initialisé par NzOpenGL
// Version majeure d'OpenGL, initialisé par NzOpenGL::Initialize()
nzUInt8 NzContextParameters::defaultMajorVersion;
// Version majeure d'OpenGL, initialisé par NzOpenGL::Initialize()
nzUInt8 NzContextParameters::defaultMinorVersion;
// Contexte de partage par défaut, initialisé par NzOpenGL::Initialize()
const NzContext* NzContextParameters::defaultShareContext = nullptr;
NzWindowHandle NzContextParameters::defaultWindow = 0;
// Si possible, garder la compatibilité avec les fonctionnalités dépréciées
bool NzContextParameters::defaultCompatibilityProfile = false;
// Mode debug d'OpenGL par défaut
#if NAZARA_RENDERER_OPENGL_DEBUG || defined(NAZARA_DEBUG)
bool NzContextParameters::defaultDebugMode = true;
#else
bool NzContextParameters::defaultDebugMode = false;
#endif
// Active le double-buffering sur les contextes
bool NzContextParameters::defaultDoubleBuffered = false;
// Active le partage des ressources entre contextes (Via le defaultShareContext)
bool NzContextParameters::defaultShared = true;

View File

@@ -9,7 +9,7 @@
#include <Nazara/Renderer/Context.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/Texture.hpp>
#include <Nazara/Renderer/VertexDeclaration.hpp>
#include <Nazara/Utility/VertexDeclaration.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace
@@ -24,7 +24,7 @@ namespace
4 // nzElementUsage_TexCoord
};
const GLenum shaderType[nzShaderType_Count] = {
const GLenum shaderType[nzShaderType_Max+1] = {
GL_FRAGMENT_SHADER, // nzShaderType_Fragment
GL_GEOMETRY_SHADER, // nzShaderType_Geometry
GL_VERTEX_SHADER // nzShaderType_Vertex
@@ -98,6 +98,7 @@ bool NzGLSLShader::Compile()
glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &length);
if (length > 1)
{
m_log.Clear(true);
m_log.Reserve(length+19-1); // La taille retournée est celle du buffer (Avec caractère de fin)
m_log.Prepend("Linkage error: ");
m_log.Resize(length+19-1); // Extension du buffer d'écriture pour ajouter le log
@@ -129,14 +130,15 @@ bool NzGLSLShader::Create()
glBindAttribLocation(m_program, attribIndex[nzElementUsage_Diffuse], "Diffuse");
glBindAttribLocation(m_program, attribIndex[nzElementUsage_Tangent], "Tangent");
NzString uniformName = "TexCoordi";
for (unsigned int i = 0; i < 8; ++i)
NzString uniform = "TexCoord";
unsigned int maxTexCoords = NazaraRenderer->GetMaxTextureUnits();
for (unsigned int i = 0; i < maxTexCoords; ++i)
{
uniformName[8] = '0'+i;
NzString uniformName = uniform + NzString::Number(i);
glBindAttribLocation(m_program, attribIndex[nzElementUsage_TexCoord]+i, uniformName.GetConstBuffer());
}
for (int i = 0; i < nzShaderType_Count; ++i)
for (int i = 0; i <= nzShaderType_Max; ++i)
m_shaders[i] = 0;
return true;
@@ -242,6 +244,7 @@ bool NzGLSLShader::Load(nzShaderType type, const NzString& source)
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
if (length > 1)
{
m_log.Clear(true);
m_log.Reserve(length+19-1); // La taille retournée est celle du buffer (Avec caractère de fin)
m_log.Prepend("Compilation error: ");
m_log.Resize(length+19-1); // Extension du buffer d'écriture pour ajouter le log

View File

@@ -63,7 +63,7 @@ class NzGLSLShader : public NzShaderImpl
mutable std::map<NzString, GLint> m_idCache;
std::map<GLint, TextureSlot> m_textures;
GLuint m_program;
GLuint m_shaders[nzShaderType_Count];
GLuint m_shaders[nzShaderType_Max+1];
NzShader* m_parent;
NzString m_log;
};

View File

@@ -52,14 +52,14 @@ namespace
if (access == nzBufferAccess_DiscardAndWrite)
{
GLint size;
glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_SIZE, &size);
GLint bufferSize;
glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_SIZE, &bufferSize);
GLint usage;
glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_USAGE, &usage);
GLint bufferUsage;
glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_USAGE, &bufferUsage);
// On discard le buffer
glBufferData(bufferTargetBinding[type], size, nullptr, usage);
glBufferData(bufferTargetBinding[type], bufferSize, nullptr, bufferUsage);
}
void* ptr = glMapBuffer(bufferTarget[type], bufferLock[access]);
@@ -154,8 +154,8 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int
if (size < 32*1024)
{
// http://www.opengl.org/wiki/Vertex_Specification_Best_Practices
if (size == m_parent->GetLength())
glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetStorage()]); // Discard
if (size == m_parent->GetSize())
glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetUsage()]); // Discard
glBufferSubData(bufferTarget[m_type], offset, size, data);
}
@@ -188,7 +188,7 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int
return true;
}
void* NzHardwareBuffer::GetBufferPtr()
void* NzHardwareBuffer::GetPointer()
{
return nullptr;
}
@@ -198,7 +198,7 @@ bool NzHardwareBuffer::IsHardware() const
return true;
}
void* NzHardwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length)
void* NzHardwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size)
{
NzContext::EnsureContext();
@@ -209,7 +209,7 @@ void* NzHardwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned
if (previous != m_buffer)
glBindBuffer(bufferTarget[m_type], m_buffer);
void* ptr = mapBuffer(m_type, access, offset, length);
void* ptr = mapBuffer(m_type, access, offset, size);
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérrations chaînées)
if (previous != m_buffer && previous != 0)
@@ -235,14 +235,14 @@ bool NzHardwareBuffer::Unmap()
glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetStorage()]);
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérrations chaînées)
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées)
if (previous != m_buffer && previous != 0)
glBindBuffer(bufferTarget[m_type], previous);
return false;
}
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérrations chaînées)
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées)
if (previous != m_buffer && previous != 0)
glBindBuffer(bufferTarget[m_type], previous);

View File

@@ -8,8 +8,8 @@
#define NAZARA_HARDWAREBUFFER_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Renderer/BufferImpl.hpp>
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Utility/BufferImpl.hpp>
class NzHardwareBuffer : public NzBufferImpl
{
@@ -22,13 +22,13 @@ class NzHardwareBuffer : public NzBufferImpl
bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static);
void Destroy();
bool Fill(const void* data, unsigned int offset, unsigned int length);
bool Fill(const void* data, unsigned int offset, unsigned int size);
void* GetBufferPtr();
void* GetPointer();
bool IsHardware() const;
void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0);
void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0);
bool Unmap();
private:

View File

@@ -298,7 +298,8 @@ bool NzOpenGL::Initialize()
return false;
}
// Fonctions optionnelles
/****************************************Extensions****************************************/
glGetStringi = reinterpret_cast<PFNGLGETSTRINGIPROC>(LoadEntry("glGetStringi", false));
glMapBufferRange = reinterpret_cast<PFNGLMAPBUFFERRANGEPROC>(LoadEntry("glMapBufferRange", false));
@@ -310,8 +311,6 @@ bool NzOpenGL::Initialize()
glXSwapInterval = reinterpret_cast<PFNGLXSWAPINTERVALSGIPROC>(LoadEntry("glXSwapIntervalSGI", false));
#endif
/****************************************Extensions****************************************/
if (!glGetStringi || !LoadExtensions3())
{
if (openGLversion >= 300) // Dans le cas contraire c'est normal
@@ -353,7 +352,7 @@ bool NzOpenGL::Initialize()
}
catch (const std::exception& e)
{
NazaraError("Failed to load GL_ARB_debug_output: " + NzString(e.what()));
NazaraWarning("Failed to load GL_ARB_debug_output: " + NzString(e.what()));
}
}
@@ -371,7 +370,7 @@ bool NzOpenGL::Initialize()
}
catch (const std::exception& e)
{
NazaraError("Failed to load ARB_gpu_shader_fp64: " + NzString(e.what()));
NazaraWarning("Failed to load ARB_gpu_shader_fp64: " + NzString(e.what()));
}
}
@@ -396,10 +395,13 @@ bool NzOpenGL::Initialize()
}
catch (const std::exception& e)
{
NazaraError("Failed to load ARB_framebuffer_object: (" + NzString(e.what()) + ")");
NazaraWarning("Failed to load ARB_framebuffer_object: (" + NzString(e.what()) + ")");
}
}
// PixelBufferObject
openGLextensions[NzOpenGL::PixelBufferObject] = (openGLversion >= 210 || IsSupported("GL_ARB_pixel_buffer_object"));
// SeparateShaderObjects
if (openGLversion >= 400 || IsSupported("GL_ARB_gpu_shader_fp64"))
{
@@ -449,7 +451,7 @@ bool NzOpenGL::Initialize()
}
catch (const std::exception& e)
{
NazaraError("Failed to load EXT_texture3D: " + NzString(e.what()));
NazaraWarning("Failed to load EXT_texture3D: " + NzString(e.what()));
}
}
}
@@ -470,7 +472,7 @@ bool NzOpenGL::Initialize()
}
catch (const std::exception& e)
{
NazaraError("Failed to load ARB_texture_storage: " + NzString(e.what()));
NazaraWarning("Failed to load ARB_texture_storage: " + NzString(e.what()));
}
}
@@ -487,10 +489,14 @@ bool NzOpenGL::Initialize()
}
catch (const std::exception& e)
{
NazaraError("Failed to load ARB_vertex_array_object: " + NzString(e.what()));
NazaraWarning("Failed to load ARB_vertex_array_object: " + NzString(e.what()));
}
}
// Fonctions de substitut
if (!glGenerateMipmap)
glGenerateMipmap = reinterpret_cast<PFNGLGENERATEMIPMAPEXTPROC>(LoadEntry("glGenerateMipmapEXT", false));
/****************************************Contexte de référence****************************************/
///FIXME: Utiliser le contexte de chargement comme référence ? (Vérifier mode debug)
@@ -502,6 +508,8 @@ bool NzOpenGL::Initialize()
return false;
}
NzContextParameters::defaultShareContext = NzContext::GetReference();
return true;
}

View File

@@ -6,16 +6,17 @@
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Core/Color.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/BufferImpl.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <Nazara/Renderer/IndexBuffer.hpp>
#include <Nazara/Renderer/HardwareBuffer.hpp>
#include <Nazara/Renderer/RenderTarget.hpp>
#include <Nazara/Renderer/Shader.hpp>
#include <Nazara/Renderer/ShaderImpl.hpp>
#include <Nazara/Renderer/VertexBuffer.hpp>
#include <Nazara/Renderer/VertexDeclaration.hpp>
#include <Nazara/Utility/BufferImpl.hpp>
#include <Nazara/Utility/IndexBuffer.hpp>
#include <Nazara/Utility/Utility.hpp>
#include <Nazara/Utility/VertexBuffer.hpp>
#include <Nazara/Utility/VertexDeclaration.hpp>
#include <stdexcept>
#include <Nazara/Renderer/Debug.hpp>
@@ -27,7 +28,8 @@ namespace
1, // nzElementUsage_Normal
0, // nzElementUsage_Position
3, // nzElementUsage_Tangent
4 // nzElementUsage_TexCoord
4 // nzElementUsage_TexCoord (Doit être le dernier de la liste car extensible)
};
@@ -128,6 +130,11 @@ namespace
GL_REPLACE, // nzStencilOperation_Replace
GL_ZERO // nzStencilOperation_Zero
};
NzBufferImpl* HardwareBufferFunction(NzBuffer* parent, nzBufferType type)
{
return new NzHardwareBuffer(parent, type);
}
}
NzRenderer::NzRenderer()
@@ -197,29 +204,34 @@ void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int f
return;
}
nzUInt8 indexSize = m_indexBuffer->GetIndexSize();
GLenum type;
switch (indexSize)
if (m_indexBuffer->IsSequential())
glDrawArrays(openglPrimitive[primitive], m_indexBuffer->GetStartIndex(), m_indexBuffer->GetIndexCount());
else
{
case 1:
type = GL_UNSIGNED_BYTE;
break;
nzUInt8 indexSize = m_indexBuffer->GetIndexSize();
case 2:
type = GL_UNSIGNED_SHORT;
break;
GLenum type;
switch (indexSize)
{
case 1:
type = GL_UNSIGNED_BYTE;
break;
case 4:
type = GL_UNSIGNED_INT;
break;
case 2:
type = GL_UNSIGNED_SHORT;
break;
default:
NazaraError("Invalid index size (" + NzString::Number(indexSize) + ')');
return;
case 4:
type = GL_UNSIGNED_INT;
break;
default:
NazaraError("Invalid index size (" + NzString::Number(indexSize) + ')');
return;
}
glDrawElements(openglPrimitive[primitive], indexCount, type, reinterpret_cast<const nzUInt8*>(m_indexBuffer->GetPointer()) + firstIndex*indexSize);
}
glDrawElements(openglPrimitive[primitive], indexCount, type, reinterpret_cast<const nzUInt8*>(m_indexBuffer->GetBufferPtr()) + firstIndex*indexSize);
}
void NzRenderer::DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount)
@@ -333,15 +345,13 @@ bool NzRenderer::Initialize()
m_utilityModule = new NzUtility;
m_utilityModule->Initialize();
}
else
m_utilityModule = nullptr;
if (NzOpenGL::Initialize())
{
NzContext::EnsureContext();
const NzContext* context = NzContext::GetReference();
bool compatibility = context->GetParameters().compatibilityProfile;
m_vaoUpdated = false;
m_indexBuffer = nullptr;
m_shader = nullptr;
m_stencilCompare = nzRendererComparison_Always;
@@ -353,6 +363,7 @@ bool NzRenderer::Initialize()
m_stencilReference = 0;
m_stencilZFail = nzStencilOperation_Keep;
m_target = nullptr;
m_vaoUpdated = false;
m_vertexBuffer = nullptr;
m_vertexDeclaration = nullptr;
@@ -362,7 +373,7 @@ bool NzRenderer::Initialize()
m_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 1.5
m_capabilities[nzRendererCap_MultipleRenderTargets] = true; // Natif depuis OpenGL 2.0
m_capabilities[nzRendererCap_OcclusionQuery] = true; // Natif depuis OpenGL 1.5
m_capabilities[nzRendererCap_SoftwareBuffer] = compatibility || NzOpenGL::GetVersion() <= 300; // Déprécié en OpenGL 3
m_capabilities[nzRendererCap_PixelBufferObject] = NzOpenGL::IsSupported(NzOpenGL::PixelBufferObject);
m_capabilities[nzRendererCap_Texture3D] = NzOpenGL::IsSupported(NzOpenGL::Texture3D);
m_capabilities[nzRendererCap_TextureCubemap] = true; // Natif depuis OpenGL 1.3
m_capabilities[nzRendererCap_TextureMulti] = true; // Natif depuis OpenGL 1.3
@@ -393,11 +404,17 @@ bool NzRenderer::Initialize()
GLint maxTextureUnits;
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
m_maxTextureUnit = static_cast<unsigned int>(maxTextureUnits);
GLint maxVertexAttribs;
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
// Impossible de binder plus de texcoords que d'attributes (en sachant qu'un certain nombre est déjà pris par les autres attributs)
m_maxTextureUnit = static_cast<unsigned int>(std::min(maxTextureUnits, maxVertexAttribs-attribIndex[nzElementUsage_TexCoord]));
}
else
m_maxTextureUnit = 1;
NzBuffer::SetBufferFunction(nzBufferStorage_Hardware, HardwareBufferFunction);
s_initialized = true;
return true;
@@ -497,9 +514,16 @@ void NzRenderer::SetFaceFilling(nzFaceFilling fillingMode)
glPolygonMode(GL_FRONT_AND_BACK, faceFillingMode[fillingMode]);
}
bool NzRenderer::SetIndexBuffer(const NzIndexBuffer* indexBuffer)
{
#if NAZARA_RENDERER_SAFE
if (indexBuffer && !indexBuffer->IsHardware() && !indexBuffer->IsSequential())
{
NazaraError("Buffer must be hardware");
return false;
}
#endif
if (indexBuffer != m_indexBuffer)
{
m_indexBuffer = indexBuffer;
@@ -537,8 +561,6 @@ bool NzRenderer::SetShader(NzShader* shader)
return false;
}
}
else
m_shader = nullptr;
m_shader = shader;
@@ -635,6 +657,14 @@ bool NzRenderer::SetTarget(NzRenderTarget* target)
bool NzRenderer::SetVertexBuffer(const NzVertexBuffer* vertexBuffer)
{
#if NAZARA_RENDERER_SAFE
if (vertexBuffer && !vertexBuffer->IsHardware())
{
NazaraError("Buffer must be hardware");
return false;
}
#endif
if (m_vertexBuffer != vertexBuffer)
{
m_vertexBuffer = vertexBuffer;
@@ -675,13 +705,7 @@ void NzRenderer::SetViewport(const NzRectui& viewport)
}
unsigned int width = m_target->GetWidth();
if (viewport.x+viewport.width >= width)
{
NazaraError("Rectangle dimensions are out of bounds");
return;
}
if (viewport.y+viewport.height >= height)
if (viewport.x+viewport.width > width || viewport.y+viewport.height > height)
{
NazaraError("Rectangle dimensions are out of bounds");
return;
@@ -812,31 +836,35 @@ bool NzRenderer::EnsureStateUpdate()
if (update)
{
m_vertexBuffer->GetBuffer()->GetImpl()->Bind();
NzHardwareBuffer* vertexBuffer = static_cast<NzHardwareBuffer*>(m_vertexBuffer->GetBuffer()->GetImpl());
vertexBuffer->Bind();
const nzUInt8* buffer = reinterpret_cast<const nzUInt8*>(m_vertexBuffer->GetBufferPtr());
const nzUInt8* buffer = reinterpret_cast<const nzUInt8*>(m_vertexBuffer->GetPointer());
///FIXME: Améliorer les déclarations pour permettre de faire ça plus simplement
for (int i = 0; i < 12; ++i) // Solution temporaire, à virer
glDisableVertexAttribArray(i); // Chaque itération tue un chaton :(
unsigned int stride = m_vertexDeclaration->GetStride();
unsigned int elementCount = m_vertexDeclaration->GetElementCount();
for (unsigned int i = 0; i < elementCount; ++i)
unsigned int stride = m_vertexDeclaration->GetStride(nzElementStream_VertexData);
for (unsigned int i = 0; i <= nzElementUsage_Max; ++i)
{
const NzVertexDeclaration::Element* element = m_vertexDeclaration->GetElement(i);
const NzVertexElement* element = m_vertexDeclaration->GetElement(nzElementStream_VertexData, static_cast<nzElementUsage>(i));
glEnableVertexAttribArray(attribIndex[element->usage]+element->usageIndex);
glVertexAttribPointer(attribIndex[element->usage]+element->usageIndex,
openglSize[element->type],
openglType[element->type],
(element->type == nzElementType_Color) ? GL_TRUE : GL_FALSE,
stride,
&buffer[element->offset]);
if (element)
{
glEnableVertexAttribArray(attribIndex[i]);
glVertexAttribPointer(attribIndex[i],
openglSize[element->type],
openglType[element->type],
(element->type == nzElementType_Color) ? GL_TRUE : GL_FALSE,
stride,
&buffer[element->offset]);
}
else
glDisableVertexAttribArray(attribIndex[i]);
}
if (m_indexBuffer)
m_indexBuffer->GetBuffer()->GetImpl()->Bind();
{
NzHardwareBuffer* indexBuffer = static_cast<NzHardwareBuffer*>(m_indexBuffer->GetBuffer()->GetImpl());
indexBuffer->Bind();
}
}
if (vaoSupported)

View File

@@ -124,7 +124,6 @@ namespace
return true;
case nzPixelFormat_Undefined:
case nzPixelFormat_Count:
NazaraInternalError("Invalid pixel format");
return false;
}
@@ -252,8 +251,8 @@ namespace
return true;
}
static unsigned short lockedLevel[nzImageType_Count] = {0};
static GLuint lockedPrevious[nzImageType_Count] = {0};
static unsigned short lockedLevel[nzImageType_Max+1] = {0};
static GLuint lockedPrevious[nzImageType_Max+1] = {0};
void LockTexture(NzTextureImpl* impl)
{
@@ -342,7 +341,7 @@ bool NzTexture::Bind() const
glBindTexture(openglTarget[m_impl->type], m_impl->id);
if (!m_impl->mipmapsUpdated)
if (m_impl->mipmapping && !m_impl->mipmapsUpdated)
{
glGenerateMipmap(openglTarget[m_impl->type]);
m_impl->mipmapsUpdated = true;
@@ -434,7 +433,13 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt
NzContext::EnsureContext();
levelCount = std::min(levelCount, NzImage::GetMaxLevel(width, height, depth));
if (IsMipmappingSupported())
levelCount = std::min(levelCount, NzImage::GetMaxLevel(width, height, depth));
else if (levelCount > 1)
{
NazaraWarning("Mipmapping not supported, reducing level count to 1");
levelCount = 1;
}
NzTextureImpl* impl = new NzTextureImpl;
glGenTextures(1, &impl->id);
@@ -478,10 +483,7 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt
SetWrapMode(nzTextureWrap_Repeat);
if (m_impl->levelCount > 1U)
{
m_impl->mipmapping = true;
m_impl->mipmapsUpdated = false;
}
EnableMipmapping(true);
if (!lock)
UnlockTexture(impl);
@@ -578,25 +580,17 @@ bool NzTexture::EnableMipmapping(bool enable)
}
#endif
if (!glGenerateMipmap)
if (m_impl->levelCount == 1)
return true;
if (!IsMipmappingSupported())
{
NazaraError("Mipmapping not supported");
return false;
}
if (!m_impl->mipmapping && enable)
{
GLint tex;
glGetIntegerv(openglTargetBinding[m_impl->type], &tex);
if (m_impl->id == static_cast<GLuint>(tex))
{
glGenerateMipmap(openglTarget[m_impl->type]);
m_impl->mipmapsUpdated = true;
}
else
m_impl->mipmapsUpdated = false;
}
m_impl->mipmapsUpdated = false;
m_impl->mipmapping = enable;
@@ -849,7 +843,6 @@ bool NzTexture::LoadFromImage(const NzImage& image)
if (!IsFormatSupported(format))
{
nzPixelFormat newFormat = (NzPixelFormat::HasAlpha(format)) ? nzPixelFormat_BGRA8 : nzPixelFormat_BGR8;
NazaraWarning("Format not supported, trying to convert it to " + NzPixelFormat::ToString(newFormat) + "...");
if (NzPixelFormat::IsConversionSupported(format, newFormat))
@@ -873,14 +866,13 @@ bool NzTexture::LoadFromImage(const NzImage& image)
}
nzImageType type = newImage.GetType();
nzUInt8 levelCount = newImage.GetLevelCount();
if (!Create(type, format, newImage.GetWidth(), newImage.GetHeight(), newImage.GetDepth(), levelCount, true))
if (!Create(type, format, newImage.GetWidth(), newImage.GetHeight(), newImage.GetDepth(), newImage.GetLevelCount(), true))
{
NazaraError("Failed to create texture");
return false;
}
for (nzUInt8 level = 0; level < levelCount; ++level)
for (nzUInt8 level = 0; level < m_impl->levelCount; ++level)
{
if (!Update(newImage.GetConstPixels(level), level))
{
@@ -943,13 +935,13 @@ bool NzTexture::SetAnisotropyLevel(unsigned int anistropyLevel)
NazaraError("Texture must be valid");
return false;
}
#endif
if (!NzOpenGL::IsSupported(NzOpenGL::AnisotropicFilter))
{
NazaraError("Anisotropic filter not supported");
return false;
}
#endif
LockTexture(m_impl);
@@ -982,7 +974,7 @@ bool NzTexture::SetFilterMode(nzTextureFilter filter)
switch (filter)
{
case nzTextureFilter_Bilinear:
if (m_impl->levelCount > 1)
if (m_impl->mipmapping > 1)
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
else
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -991,7 +983,7 @@ bool NzTexture::SetFilterMode(nzTextureFilter filter)
break;
case nzTextureFilter_Nearest:
if (m_impl->levelCount > 1)
if (m_impl->mipmapping > 1)
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
else
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -1354,12 +1346,13 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve
nzUInt8 bpp = NzPixelFormat::GetBPP(m_impl->format);
// Inversion de la texture pour le repère d'OpenGL
NzImage mirrored;
mirrored.Create(m_impl->type, m_impl->format, cube.width, cube.height, cube.depth);
mirrored.Update(pixels);
if (!mirrored.FlipVertically())
unsigned int size = cube.width*cube.height*cube.depth*bpp;
nzUInt8* mirrored = new nzUInt8[size];
if (!NzPixelFormat::Flip(nzPixelFlipping_Vertically, m_impl->format, cube.width, cube.height, cube.depth, pixels, mirrored))
{
NazaraWarning("Failed to flip image");
std::memcpy(mirrored, pixels, size);
}
SetUnpackAlignement(bpp);
@@ -1367,15 +1360,15 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve
switch (m_impl->type)
{
case nzImageType_1D:
glTexSubImage1D(GL_TEXTURE_1D, level, cube.x, cube.width, format.dataFormat, format.dataType, mirrored.GetConstPixels());
glTexSubImage1D(GL_TEXTURE_1D, level, cube.x, cube.width, format.dataFormat, format.dataType, mirrored);
break;
case nzImageType_2D:
glTexSubImage2D(GL_TEXTURE_2D, level, cube.x, height-cube.height-cube.y, cube.width, cube.height, format.dataFormat, format.dataType, mirrored.GetConstPixels());
glTexSubImage2D(GL_TEXTURE_2D, level, cube.x, height-cube.height-cube.y, cube.width, cube.height, format.dataFormat, format.dataType, mirrored);
break;
case nzImageType_3D:
glTexSubImage3D(GL_TEXTURE_3D, level, cube.x, height-cube.height-cube.y, cube.z, cube.width, cube.height, cube.depth, format.dataFormat, format.dataType, mirrored.GetConstPixels());
glTexSubImage3D(GL_TEXTURE_3D, level, cube.x, height-cube.height-cube.y, cube.z, cube.width, cube.height, cube.depth, format.dataFormat, format.dataType, mirrored);
break;
default:
@@ -1383,6 +1376,8 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve
}
UnlockTexture(m_impl);
delete[] mirrored;
return true;
}
@@ -1503,19 +1498,21 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRe
nzUInt8 bpp = NzPixelFormat::GetBPP(m_impl->format);
// Inversion de la texture pour le repère d'OpenGL
NzImage mirrored;
mirrored.Create(m_impl->type, m_impl->format, rect.width, rect.height);
mirrored.Update(pixels);
if (!mirrored.FlipVertically())
unsigned int size = rect.width*rect.height*bpp;
nzUInt8* mirrored = new nzUInt8[size];
if (!NzPixelFormat::Flip(nzPixelFlipping_Vertically, m_impl->format, rect.width, rect.height, 1, pixels, mirrored))
{
NazaraWarning("Failed to flip image");
std::memcpy(mirrored, pixels, size);
}
SetUnpackAlignement(bpp);
LockTexture(m_impl);
glTexSubImage2D(cubemapFace[face], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, mirrored.GetConstPixels());
glTexSubImage2D(cubemapFace[face], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, mirrored);
UnlockTexture(m_impl);
return true;
}
@@ -1576,7 +1573,6 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format)
}
case nzPixelFormat_Undefined:
case nzPixelFormat_Count:
break;
}
@@ -1585,6 +1581,11 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format)
return false;
}
bool NzTexture::IsMipmappingSupported()
{
return glGenerateMipmap != nullptr;
}
bool NzTexture::IsTypeSupported(nzImageType type)
{
switch (type)

View File

@@ -1,127 +0,0 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/VertexDeclaration.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace
{
const unsigned int size[] =
{
4, // nzElementType_Color
8, // nzElementType_Double1
16, // nzElementType_Double2
24, // nzElementType_Double3
32, // nzElementType_Double4
4, // nzElementType_Float1
8, // nzElementType_Float2
12, // nzElementType_Float3
16 // nzElementType_Float4
};
}
bool NzVertexDeclaration::Create(const NzVertexElement* elements, unsigned int elementCount)
{
for (unsigned int i = 0; i < elementCount; ++i)
{
unsigned int stream = elements[i].stream;
if (stream >= m_streams.size())
m_streams.resize(stream+1);
#if NAZARA_RENDERER_SAFE
else // Seulement si le stream ne vient pas d'être créé (Autrement c'est inutile)
{
bool fp64 = NazaraRenderer->HasCapability(nzRendererCap_FP64);
for (unsigned int j = 0; j < i; ++j)
{
if (elements[j].stream == stream && elements[j].usage == elements[i].usage && elements[j].usageIndex == elements[i].usageIndex)
{
NazaraError("Element usage (" + NzString::Number(elements[j].usage, 16) + ") collision on stream " + NzString::Number(stream) + " with usage index " + NzString::Number(elements[j].usageIndex));
return false;
}
else if (!fp64 && elements[j].type >= nzElementType_Double1 && elements[j].type <= nzElementType_Double4)
{
NazaraError("FP64 not supported");
return false;
}
}
}
#endif
Element element;
element.offset = elements[i].offset;
element.type = elements[i].type;
element.usage = elements[i].usage;
element.usageIndex = elements[i].usageIndex;
m_streams[stream].elements.push_back(element);
}
for (Stream& stream : m_streams)
{
stream.stride = 0;
for (const Element& element : stream.elements)
stream.stride += size[element.type];
#if NAZARA_RENDERER_FORCE_DECLARATION_STRIDE_MULTIPLE_OF_32
stream.stride = ((static_cast<int>(stream.stride)-1)/32+1)*32;
#endif
}
return true;
}
const NzVertexDeclaration::Element* NzVertexDeclaration::GetElement(unsigned int i, unsigned int stream) const
{
#if NAZARA_RENDERER_SAFE
if (stream >= m_streams.size())
{
NazaraError("Stream out of range");
return nullptr;
}
if (i >= m_streams[stream].elements.size())
{
NazaraError("Index out of range");
return nullptr;
}
#endif
return &m_streams[stream].elements[i];
}
unsigned int NzVertexDeclaration::GetElementCount(unsigned int stream) const
{
#if NAZARA_RENDERER_SAFE
if (stream >= m_streams.size())
{
NazaraError("Stream out of range");
return 0;
}
#endif
return m_streams[stream].elements.size();
}
unsigned int NzVertexDeclaration::GetStreamCount() const
{
return m_streams.size();
}
unsigned int NzVertexDeclaration::GetStride(unsigned int stream) const
{
#if NAZARA_RENDERER_SAFE
if (stream >= m_streams.size())
{
NazaraError("Stream out of range");
return 0;
}
#endif
return m_streams[stream].stride;
}

View File

@@ -0,0 +1,318 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Animation.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Utility/Config.hpp>
#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);
}
std::list<NzAnimationLoader::MemoryLoader> NzAnimation::s_memoryLoaders;
std::list<NzAnimationLoader::StreamLoader> NzAnimation::s_streamLoaders;
std::multimap<NzString, NzAnimationLoader::LoadFileFunction> NzAnimation::s_fileLoaders;

View File

@@ -0,0 +1,336 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <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};

View File

@@ -2,7 +2,7 @@
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/BufferImpl.hpp>
#include <Nazara/Renderer/Debug.hpp>
#include <Nazara/Utility/BufferImpl.hpp>
#include <Nazara/Utility/Debug.hpp>
NzBufferImpl::~NzBufferImpl() = default;

View File

@@ -0,0 +1,61 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Cursor.hpp>
#if defined(NAZARA_PLATFORM_WINDOWS)
#include <Nazara/Utility/Win32/CursorImpl.hpp>
#elif defined(NAZARA_PLATFORM_LINUX)
#include <Nazara/Utility/Linux/CursorImpl.hpp>
#else
#error Lack of implementation: Cursor
#endif
#include <Nazara/Utility/Debug.hpp>
NzCursor::NzCursor() :
m_impl(nullptr)
{
}
NzCursor::~NzCursor()
{
Destroy();
}
bool NzCursor::Create(const NzImage& cursor, int hotSpotX, int hotSpotY)
{
Destroy();
m_impl = new NzCursorImpl;
if (!m_impl->Create(cursor, hotSpotX, hotSpotY))
{
NazaraError("Failed to create cursor implementation");
delete m_impl;
m_impl = nullptr;
return false;
}
return true;
}
bool NzCursor::Create(const NzImage& cursor, const NzVector2i& hotSpot)
{
return Create(cursor, hotSpot.x, hotSpot.y);
}
void NzCursor::Destroy()
{
if (m_impl)
{
m_impl->Destroy();
delete m_impl;
m_impl = nullptr;
}
}
bool NzCursor::IsValid() const
{
return m_impl != nullptr;
}

View File

@@ -0,0 +1,56 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Icon.hpp>
#if defined(NAZARA_PLATFORM_WINDOWS)
#include <Nazara/Utility/Win32/IconImpl.hpp>
#elif defined(NAZARA_PLATFORM_LINUX)
#include <Nazara/Utility/Linux/IconImpl.hpp>
#else
#error Lack of implementation: Icon
#endif
#include <Nazara/Utility/Debug.hpp>
NzIcon::NzIcon() :
m_impl(nullptr)
{
}
NzIcon::~NzIcon()
{
Destroy();
}
bool NzIcon::Create(const NzImage& icon)
{
Destroy();
m_impl = new NzIconImpl;
if (!m_impl->Create(icon))
{
NazaraError("Failed to create icon implementation");
delete m_impl;
m_impl = nullptr;
return false;
}
return true;
}
void NzIcon::Destroy()
{
if (m_impl)
{
m_impl->Destroy();
delete m_impl;
m_impl = nullptr;
}
}
bool NzIcon::IsValid() const
{
return m_impl != nullptr;
}

View File

@@ -5,7 +5,6 @@
#include <Nazara/Utility/Image.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Utility/Config.hpp>
#include <Nazara/Utility/ResourceLoader.hpp>
#include <cmath>
#include <Nazara/Utility/Debug.hpp>
@@ -22,6 +21,11 @@ namespace
}
}
bool NzImageParams::IsValid() const
{
return true;
}
NzImage::NzImage() :
m_sharedImage(&emptyImage)
{
@@ -494,24 +498,12 @@ bool NzImage::FlipHorizontally()
EnsureOwnership();
nzUInt8 bpp = NzPixelFormat::GetBPP(m_sharedImage->format);
unsigned int width = m_sharedImage->width;
unsigned int height = m_sharedImage->height;
unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : m_sharedImage->depth;
for (unsigned int level = 0; level < m_sharedImage->levelCount; ++level)
{
for (unsigned int z = 0; z < depth; ++z)
{
nzUInt8* ptr = &m_sharedImage->pixels[level][width*height*z];
unsigned int lineStride = width*bpp;
for (unsigned int y = 0; y < height; ++y)
{
for (unsigned int x = 0; x < width/2; ++x)
std::swap_ranges(&ptr[x*bpp], &ptr[(x+1)*bpp], &ptr[(width-x)*bpp]);
ptr += lineStride;
}
}
NzPixelFormat::Flip(nzPixelFlipping_Horizontally, m_sharedImage->format, width, height, depth, m_sharedImage->pixels[level], m_sharedImage->pixels[level]);
if (width > 1U)
width >>= 1;
@@ -545,19 +537,12 @@ bool NzImage::FlipVertically()
EnsureOwnership();
nzUInt8 bpp = NzPixelFormat::GetBPP(m_sharedImage->format);
unsigned int width = m_sharedImage->width;
unsigned int height = m_sharedImage->height;
unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : m_sharedImage->depth;
for (unsigned int level = 0; level < m_sharedImage->levelCount; ++level)
{
for (unsigned int z = 0; z < depth; ++z)
{
nzUInt8* ptr = &m_sharedImage->pixels[level][width*height*z];
unsigned int lineStride = width*bpp;
for (unsigned int y = 0; y < height/2; ++y)
std::swap_ranges(&ptr[y*lineStride], &ptr[(y+1)*lineStride-1], &ptr[(height-y-1)*lineStride]);
}
NzPixelFormat::Flip(nzPixelFlipping_Vertically, m_sharedImage->format, width, height, depth, m_sharedImage->pixels[level], m_sharedImage->pixels[level]);
if (width > 1U)
width >>= 1;
@@ -818,17 +803,17 @@ bool NzImage::IsValid() const
bool NzImage::LoadFromFile(const NzString& filePath, const NzImageParams& params)
{
return NzResourceLoader<NzImage, NzImageParams>::LoadResourceFromFile(this, filePath, params);
return NzImageLoader::LoadFromFile(this, filePath, params);
}
bool NzImage::LoadFromMemory(const void* data, std::size_t size, const NzImageParams& params)
{
return NzResourceLoader<NzImage, NzImageParams>::LoadResourceFromMemory(this, data, size, params);
return NzImageLoader::LoadFromMemory(this, data, size, params);
}
bool NzImage::LoadFromStream(NzInputStream& stream, const NzImageParams& params)
{
return NzResourceLoader<NzImage, NzImageParams>::LoadResourceFromStream(this, stream, params);
return NzImageLoader::LoadFromStream(this, stream, params);
}
bool NzImage::SetLevelCount(nzUInt8 levelCount)
@@ -1110,36 +1095,6 @@ nzUInt8 NzImage::GetMaxLevel(unsigned int width, unsigned int height, unsigned i
return std::max(std::max(std::max(widthLevel, heightLevel), depthLevel), 1U);
}
void NzImage::RegisterFileLoader(const NzString& extensions, LoadFileFunction loadFile)
{
return RegisterResourceFileLoader(extensions, loadFile);
}
void NzImage::RegisterMemoryLoader(IsMemoryLoadingSupportedFunction isLoadingSupported, LoadMemoryFunction loadMemory)
{
return RegisterResourceMemoryLoader(isLoadingSupported, loadMemory);
}
void NzImage::RegisterStreamLoader(IsStreamLoadingSupportedFunction isLoadingSupported, LoadStreamFunction loadStream)
{
return RegisterResourceStreamLoader(isLoadingSupported, loadStream);
}
void NzImage::UnregisterFileLoader(const NzString& extensions, LoadFileFunction loadFile)
{
UnregisterResourceFileLoader(extensions, loadFile);
}
void NzImage::UnregisterMemoryLoader(IsMemoryLoadingSupportedFunction isLoadingSupported, LoadMemoryFunction loadMemory)
{
UnregisterResourceMemoryLoader(isLoadingSupported, loadMemory);
}
void NzImage::UnregisterStreamLoader(IsStreamLoadingSupportedFunction isLoadingSupported, LoadStreamFunction loadStream)
{
UnregisterResourceStreamLoader(isLoadingSupported, loadStream);
}
void NzImage::EnsureOwnership()
{
if (m_sharedImage == &emptyImage)
@@ -1168,10 +1123,10 @@ void NzImage::ReleaseImage()
return;
NazaraMutexLock(m_sharedImage->mutex);
m_sharedImage->refCount--;
bool freeSharedImage = (--m_sharedImage->refCount == 0);
NazaraMutexUnlock(m_sharedImage->mutex);
if (m_sharedImage->refCount == 0)
if (freeSharedImage)
{
for (unsigned int i = 0; i < m_sharedImage->levelCount; ++i)
delete[] m_sharedImage->pixels[i];
@@ -1184,3 +1139,6 @@ void NzImage::ReleaseImage()
}
NzImage::SharedImage NzImage::emptyImage(0, nzImageType_2D, nzPixelFormat_Undefined, 1, nullptr, 0, 0, 0);
std::list<NzImageLoader::MemoryLoader> NzImage::s_memoryLoaders;
std::list<NzImageLoader::StreamLoader> NzImage::s_streamLoaders;
std::multimap<NzString, NzImageLoader::LoadFileFunction> NzImage::s_fileLoaders;

View File

@@ -2,11 +2,11 @@
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/IndexBuffer.hpp>
#include <Nazara/Utility/IndexBuffer.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Utility/Config.hpp>
#include <stdexcept>
#include <Nazara/Renderer/Debug.hpp>
#include <Nazara/Utility/Debug.hpp>
NzIndexBuffer::NzIndexBuffer(NzBuffer* buffer, unsigned int startIndex, unsigned int indexCount) :
m_buffer(buffer),
@@ -31,7 +31,7 @@ m_startIndex(startIndex)
}
}
NzIndexBuffer::NzIndexBuffer(unsigned int length, nzUInt8 indexSize, nzBufferUsage usage) :
NzIndexBuffer::NzIndexBuffer(unsigned int length, nzUInt8 indexSize, nzBufferStorage storage, nzBufferUsage usage) :
m_ownsBuffer(true),
m_indexCount(length),
m_startIndex(0)
@@ -46,13 +46,15 @@ m_startIndex(0)
}
#endif
m_buffer = new NzBuffer(nzBufferType_Index, length, indexSize, usage);
m_buffer = new NzBuffer(nzBufferType_Index, length, indexSize, storage, usage);
m_buffer->AddResourceReference();
m_buffer->SetPersistent(false);
}
NzIndexBuffer::NzIndexBuffer(const NzIndexBuffer& indexBuffer) :
NzResource(true),
m_buffer(indexBuffer.m_buffer),
m_ownsBuffer(indexBuffer.m_ownsBuffer),
m_indexCount(indexBuffer.m_indexCount),
m_startIndex(indexBuffer.m_startIndex)
{
@@ -60,7 +62,9 @@ m_startIndex(indexBuffer.m_startIndex)
{
if (m_ownsBuffer)
{
m_buffer = new NzBuffer(nzBufferType_Index, indexBuffer.m_buffer->GetLength(), indexBuffer.m_buffer->GetSize(), indexBuffer.m_buffer->GetUsage());
NzBuffer* buffer = indexBuffer.m_buffer;
m_buffer = new NzBuffer(nzBufferType_Index, buffer->GetLength(), buffer->GetSize(), buffer->GetStorage(), buffer->GetUsage());
m_buffer->AddResourceReference();
m_buffer->SetPersistent(false);
m_buffer->CopyContent(*indexBuffer.m_buffer);
@@ -71,8 +75,6 @@ m_startIndex(indexBuffer.m_startIndex)
m_buffer->AddResourceReference();
}
}
else
m_buffer = nullptr;
}
NzIndexBuffer::~NzIndexBuffer()
@@ -83,10 +85,10 @@ NzIndexBuffer::~NzIndexBuffer()
bool NzIndexBuffer::Fill(const void* data, unsigned int offset, unsigned int length)
{
#if NAZARA_RENDERER_SAFE
#if NAZARA_UTILITY_SAFE
if (!m_buffer)
{
NazaraError("Impossible to fill sequential buffer");
NazaraError("Impossible to fill sequential buffers");
return false;
}
@@ -105,38 +107,12 @@ NzBuffer* NzIndexBuffer::GetBuffer() const
return m_buffer;
}
void* NzIndexBuffer::GetBufferPtr()
{
#if NAZARA_RENDERER_SAFE
if (!m_buffer)
{
NazaraError("Sequential index buffer: Buffer has no pointer");
return nullptr;
}
#endif
return reinterpret_cast<nzUInt8*>(m_buffer->GetBufferPtr()) + m_startIndex*m_buffer->GetTypeSize();
}
const void* NzIndexBuffer::GetBufferPtr() const
{
#if NAZARA_RENDERER_SAFE
if (!m_buffer)
{
NazaraError("Sequential index buffer: Buffer has no pointer");
return nullptr;
}
#endif
return reinterpret_cast<const nzUInt8*>(m_buffer->GetBufferPtr()) + m_startIndex*m_buffer->GetTypeSize();
}
nzUInt8 NzIndexBuffer::GetIndexSize() const
{
#if NAZARA_RENDERER_SAFE
#if NAZARA_UTILITY_SAFE
if (!m_buffer)
{
NazaraError("Sequential index buffer: Buffer has no index size");
NazaraError("Sequential buffers have no index size");
return 0;
}
#endif
@@ -144,6 +120,32 @@ nzUInt8 NzIndexBuffer::GetIndexSize() const
return m_buffer->GetTypeSize();
}
void* NzIndexBuffer::GetPointer()
{
#if NAZARA_UTILITY_SAFE
if (!m_buffer)
{
NazaraError("Sequential buffers have no pointer");
return nullptr;
}
#endif
return reinterpret_cast<nzUInt8*>(m_buffer->GetPointer()) + m_startIndex*m_buffer->GetTypeSize();
}
const void* NzIndexBuffer::GetPointer() const
{
#if NAZARA_UTILITY_SAFE
if (!m_buffer)
{
NazaraError("Sequential buffers have no pointer");
return nullptr;
}
#endif
return reinterpret_cast<const nzUInt8*>(m_buffer->GetPointer()) + m_startIndex*m_buffer->GetTypeSize();
}
unsigned int NzIndexBuffer::GetIndexCount() const
{
return m_indexCount;
@@ -156,10 +158,10 @@ unsigned int NzIndexBuffer::GetStartIndex() const
bool NzIndexBuffer::IsHardware() const
{
#if NAZARA_RENDERER_SAFE
#if NAZARA_UTILITY_SAFE
if (!m_buffer)
{
NazaraError("Sequential index buffer is neither hardware or software");
NazaraWarning("Sequential index buffers are neither hardware or software");
return false;
}
#endif
@@ -174,10 +176,10 @@ bool NzIndexBuffer::IsSequential() const
void* NzIndexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length)
{
#if NAZARA_RENDERER_SAFE
#if NAZARA_UTILITY_SAFE
if (!m_buffer)
{
NazaraError("Impossible to map sequential index buffer");
NazaraError("Impossible to map sequential buffers");
return nullptr;
}
@@ -191,12 +193,25 @@ void* NzIndexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned in
return m_buffer->Map(access, m_startIndex+offset, (length) ? length : m_indexCount-offset);
}
bool NzIndexBuffer::Unmap()
bool NzIndexBuffer::SetStorage(nzBufferStorage storage)
{
#if NAZARA_RENDERER_SAFE
#if NAZARA_UTILITY_SAFE
if (!m_buffer)
{
NazaraError("Impossible to unlock sequential index buffer");
NazaraWarning("Sequential buffers have no storage");
return true;
}
#endif
return m_buffer->SetStorage(storage);
}
bool NzIndexBuffer::Unmap()
{
#if NAZARA_UTILITY_SAFE
if (!m_buffer)
{
NazaraError("Impossible to unlock sequential buffers");
return false;
}
#endif

View File

@@ -0,0 +1,13 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/KeyframeMesh.hpp>
#include <Nazara/Utility/Debug.hpp>
NzKeyframeMesh::NzKeyframeMesh(const NzMesh* parent) :
NzSubMesh(parent)
{
}
NzKeyframeMesh::~NzKeyframeMesh() = default;

View File

@@ -0,0 +1,15 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_LOADERS_MD2_HPP
#define NAZARA_LOADERS_MD2_HPP
#include <Nazara/Prerequesites.hpp>
void NzLoaders_MD2_Register();
void NzLoaders_MD2_Unregister();
#endif // NAZARA_LOADERS_MD2_HPP

View File

@@ -0,0 +1,173 @@
// Copyright (C) 2011 Jérôme Leclercq
// This file is part of the "Ungine".
// For conditions of distribution and use, see copyright notice in Core.h
#include <Nazara/Utility/Loaders/MD2/Constants.hpp>
const nzUInt32 md2Ident = 'I' + ('D'<<8) + ('P'<<16) + ('2'<<24);
const NzVector3f md2Normals[162] =
{
NzVector3f(-0.525731f, 0.000000f, 0.850651f),
NzVector3f(-0.442863f, 0.238856f, 0.864188f),
NzVector3f(-0.295242f, 0.000000f, 0.955423f),
NzVector3f(-0.309017f, 0.500000f, 0.809017f),
NzVector3f(-0.162460f, 0.262866f, 0.951056f),
NzVector3f(0.000000f, 0.000000f, 1.000000f),
NzVector3f(0.000000f, 0.850651f, 0.525731f),
NzVector3f(-0.147621f, 0.716567f, 0.681718f),
NzVector3f(0.147621f, 0.716567f, 0.681718f),
NzVector3f(0.000000f, 0.525731f, 0.850651f),
NzVector3f(0.309017f, 0.500000f, 0.809017f),
NzVector3f(0.525731f, 0.000000f, 0.850651f),
NzVector3f(0.295242f, 0.000000f, 0.955423f),
NzVector3f(0.442863f, 0.238856f, 0.864188f),
NzVector3f(0.162460f, 0.262866f, 0.951056f),
NzVector3f(-0.681718f, 0.147621f, 0.716567f),
NzVector3f(-0.809017f, 0.309017f, 0.500000f),
NzVector3f(-0.587785f, 0.425325f, 0.688191f),
NzVector3f(-0.850651f, 0.525731f, 0.000000f),
NzVector3f(-0.864188f, 0.442863f, 0.238856f),
NzVector3f(-0.716567f, 0.681718f, 0.147621f),
NzVector3f(-0.688191f, 0.587785f, 0.425325f),
NzVector3f(-0.500000f, 0.809017f, 0.309017f),
NzVector3f(-0.238856f, 0.864188f, 0.442863f),
NzVector3f(-0.425325f, 0.688191f, 0.587785f),
NzVector3f(-0.716567f, 0.681718f, -0.147621f),
NzVector3f(-0.500000f, 0.809017f, -0.309017f),
NzVector3f(-0.525731f, 0.850651f, 0.000000f),
NzVector3f(0.000000f, 0.850651f, -0.525731f),
NzVector3f(-0.238856f, 0.864188f, -0.442863f),
NzVector3f(0.000000f, 0.955423f, -0.295242f),
NzVector3f(-0.262866f, 0.951056f, -0.162460f),
NzVector3f(0.000000f, 1.000000f, 0.000000f),
NzVector3f(0.000000f, 0.955423f, 0.295242f),
NzVector3f(-0.262866f, 0.951056f, 0.162460f),
NzVector3f(0.238856f, 0.864188f, 0.442863f),
NzVector3f(0.262866f, 0.951056f, 0.162460f),
NzVector3f(0.500000f, 0.809017f, 0.309017f),
NzVector3f(0.238856f, 0.864188f, -0.442863f),
NzVector3f(0.262866f, 0.951056f, -0.162460f),
NzVector3f(0.500000f, 0.809017f, -0.309017f),
NzVector3f(0.850651f, 0.525731f, 0.000000f),
NzVector3f(0.716567f, 0.681718f, 0.147621f),
NzVector3f(0.716567f, 0.681718f, -0.147621f),
NzVector3f(0.525731f, 0.850651f, 0.000000f),
NzVector3f(0.425325f, 0.688191f, 0.587785f),
NzVector3f(0.864188f, 0.442863f, 0.238856f),
NzVector3f(0.688191f, 0.587785f, 0.425325f),
NzVector3f(0.809017f, 0.309017f, 0.500000f),
NzVector3f(0.681718f, 0.147621f, 0.716567f),
NzVector3f(0.587785f, 0.425325f, 0.688191f),
NzVector3f(0.955423f, 0.295242f, 0.000000f),
NzVector3f(1.000000f, 0.000000f, 0.000000f),
NzVector3f(0.951056f, 0.162460f, 0.262866f),
NzVector3f(0.850651f, -0.525731f, 0.000000f),
NzVector3f(0.955423f, -0.295242f, 0.000000f),
NzVector3f(0.864188f, -0.442863f, 0.238856f),
NzVector3f(0.951056f, -0.162460f, 0.262866f),
NzVector3f(0.809017f, -0.309017f, 0.500000f),
NzVector3f(0.681718f, -0.147621f, 0.716567f),
NzVector3f(0.850651f, 0.000000f, 0.525731f),
NzVector3f(0.864188f, 0.442863f, -0.238856f),
NzVector3f(0.809017f, 0.309017f, -0.500000f),
NzVector3f(0.951056f, 0.162460f, -0.262866f),
NzVector3f(0.525731f, 0.000000f, -0.850651f),
NzVector3f(0.681718f, 0.147621f, -0.716567f),
NzVector3f(0.681718f, -0.147621f, -0.716567f),
NzVector3f(0.850651f, 0.000000f, -0.525731f),
NzVector3f(0.809017f, -0.309017f, -0.500000f),
NzVector3f(0.864188f, -0.442863f, -0.238856f),
NzVector3f(0.951056f, -0.162460f, -0.262866f),
NzVector3f(0.147621f, 0.716567f, -0.681718f),
NzVector3f(0.309017f, 0.500000f, -0.809017f),
NzVector3f(0.425325f, 0.688191f, -0.587785f),
NzVector3f(0.442863f, 0.238856f, -0.864188f),
NzVector3f(0.587785f, 0.425325f, -0.688191f),
NzVector3f(0.688191f, 0.587785f, -0.425325f),
NzVector3f(-0.147621f, 0.716567f, -0.681718f),
NzVector3f(-0.309017f, 0.500000f, -0.809017f),
NzVector3f(0.000000f, 0.525731f, -0.850651f),
NzVector3f(-0.525731f, 0.000000f, -0.850651f),
NzVector3f(-0.442863f, 0.238856f, -0.864188f),
NzVector3f(-0.295242f, 0.000000f, -0.955423f),
NzVector3f(-0.162460f, 0.262866f, -0.951056f),
NzVector3f(0.000000f, 0.000000f, -1.000000f),
NzVector3f(0.295242f, 0.000000f, -0.955423f),
NzVector3f(0.162460f, 0.262866f, -0.951056f),
NzVector3f(-0.442863f, -0.238856f, -0.864188f),
NzVector3f(-0.309017f, -0.500000f, -0.809017f),
NzVector3f(-0.162460f, -0.262866f, -0.951056f),
NzVector3f(0.000000f, -0.850651f, -0.525731f),
NzVector3f(-0.147621f, -0.716567f, -0.681718f),
NzVector3f(0.147621f, -0.716567f, -0.681718f),
NzVector3f(0.000000f, -0.525731f, -0.850651f),
NzVector3f(0.309017f, -0.500000f, -0.809017f),
NzVector3f(0.442863f, -0.238856f, -0.864188f),
NzVector3f(0.162460f, -0.262866f, -0.951056f),
NzVector3f(0.238856f, -0.864188f, -0.442863f),
NzVector3f(0.500000f, -0.809017f, -0.309017f),
NzVector3f(0.425325f, -0.688191f, -0.587785f),
NzVector3f(0.716567f, -0.681718f, -0.147621f),
NzVector3f(0.688191f, -0.587785f, -0.425325f),
NzVector3f(0.587785f, -0.425325f, -0.688191f),
NzVector3f(0.000000f, -0.955423f, -0.295242f),
NzVector3f(0.000000f, -1.000000f, 0.000000f),
NzVector3f(0.262866f, -0.951056f, -0.162460f),
NzVector3f(0.000000f, -0.850651f, 0.525731f),
NzVector3f(0.000000f, -0.955423f, 0.295242f),
NzVector3f(0.238856f, -0.864188f, 0.442863f),
NzVector3f(0.262866f, -0.951056f, 0.162460f),
NzVector3f(0.500000f, -0.809017f, 0.309017f),
NzVector3f(0.716567f, -0.681718f, 0.147621f),
NzVector3f(0.525731f, -0.850651f, 0.000000f),
NzVector3f(-0.238856f, -0.864188f, -0.442863f),
NzVector3f(-0.500000f, -0.809017f, -0.309017f),
NzVector3f(-0.262866f, -0.951056f, -0.162460f),
NzVector3f(-0.850651f, -0.525731f, 0.000000f),
NzVector3f(-0.716567f, -0.681718f, -0.147621f),
NzVector3f(-0.716567f, -0.681718f, 0.147621f),
NzVector3f(-0.525731f, -0.850651f, 0.000000f),
NzVector3f(-0.500000f, -0.809017f, 0.309017f),
NzVector3f(-0.238856f, -0.864188f, 0.442863f),
NzVector3f(-0.262866f, -0.951056f, 0.162460f),
NzVector3f(-0.864188f, -0.442863f, 0.238856f),
NzVector3f(-0.809017f, -0.309017f, 0.500000f),
NzVector3f(-0.688191f, -0.587785f, 0.425325f),
NzVector3f(-0.681718f, -0.147621f, 0.716567f),
NzVector3f(-0.442863f, -0.238856f, 0.864188f),
NzVector3f(-0.587785f, -0.425325f, 0.688191f),
NzVector3f(-0.309017f, -0.500000f, 0.809017f),
NzVector3f(-0.147621f, -0.716567f, 0.681718f),
NzVector3f(-0.425325f, -0.688191f, 0.587785f),
NzVector3f(-0.162460f, -0.262866f, 0.951056f),
NzVector3f(0.442863f, -0.238856f, 0.864188f),
NzVector3f(0.162460f, -0.262866f, 0.951056f),
NzVector3f(0.309017f, -0.500000f, 0.809017f),
NzVector3f(0.147621f, -0.716567f, 0.681718f),
NzVector3f(0.000000f, -0.525731f, 0.850651f),
NzVector3f(0.425325f, -0.688191f, 0.587785f),
NzVector3f(0.587785f, -0.425325f, 0.688191f),
NzVector3f(0.688191f, -0.587785f, 0.425325f),
NzVector3f(-0.955423f, 0.295242f, 0.000000f),
NzVector3f(-0.951056f, 0.162460f, 0.262866f),
NzVector3f(-1.000000f, 0.000000f, 0.000000f),
NzVector3f(-0.850651f, 0.000000f, 0.525731f),
NzVector3f(-0.955423f, -0.295242f, 0.000000f),
NzVector3f(-0.951056f, -0.162460f, 0.262866f),
NzVector3f(-0.864188f, 0.442863f, -0.238856f),
NzVector3f(-0.951056f, 0.162460f, -0.262866f),
NzVector3f(-0.809017f, 0.309017f, -0.500000f),
NzVector3f(-0.864188f, -0.442863f, -0.238856f),
NzVector3f(-0.951056f, -0.162460f, -0.262866f),
NzVector3f(-0.809017f, -0.309017f, -0.500000f),
NzVector3f(-0.681718f, 0.147621f, -0.716567f),
NzVector3f(-0.681718f, -0.147621f, -0.716567f),
NzVector3f(-0.850651f, 0.000000f, -0.525731f),
NzVector3f(-0.688191f, 0.587785f, -0.425325f),
NzVector3f(-0.587785f, 0.425325f, -0.688191f),
NzVector3f(-0.425325f, 0.688191f, -0.587785f),
NzVector3f(-0.425325f, -0.688191f, -0.587785f),
NzVector3f(-0.587785f, -0.425325f, -0.688191f),
NzVector3f(-0.688191f, -0.587785f, -0.425325f)
};

View File

@@ -0,0 +1,65 @@
// Copyright (C) 2011 Jérôme Leclercq
// This file is part of the "Ungine".
// For conditions of distribution and use, see copyright notice in Core.h
#ifndef NAZARA_LOADERS_MD2_CONSTANTS_HPP
#define NAZARA_LOADERS_MD2_CONSTANTS_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Math/Vector3.hpp>
#include <vector>
struct md2_header
{
nzUInt32 ident; // nombre magique : "IDP2"
nzUInt32 version; // version du format : 8
nzUInt32 skinwidth; // largeur texture
nzUInt32 skinheight; // hauteur texture
nzUInt32 framesize; // taille d'une frame en octets
nzUInt32 num_skins; // nombre de skins
nzUInt32 num_vertices; // nombre de vertices par frame
nzUInt32 num_st; // nombre de coordonnées de texture
nzUInt32 num_tris; // nombre de triangles
nzUInt32 num_glcmds; // nombre de commandes opengl
nzUInt32 num_frames; // nombre de frames
nzUInt32 offset_skins; // offset données skins
nzUInt32 offset_st; // offset données coordonnées de texture
nzUInt32 offset_tris; // offset données triangles
nzUInt32 offset_frames; // offset données frames
nzUInt32 offset_glcmds; // offset données commandes OpenGL
nzUInt32 offset_end; // offset fin de fichier
};
struct md2_vertex
{
nzUInt8 x, y, z;
nzUInt8 n;
};
struct md2_texCoord
{
nzInt16 u, v;
};
struct md2_triangle
{
nzUInt16 vertices[3];
nzUInt16 texCoords[3];
};
struct md2_frame
{
NzVector3f scale;
NzVector3f translate;
char name[16];
std::vector<md2_vertex> vertices;
};
extern const nzUInt32 md2Ident;
extern const NzVector3f md2Normals[162];
#endif // NAZARA_LOADERS_MD2_CONSTANTS_HPP

View File

@@ -0,0 +1,266 @@
// Copyright (C) 2011 Jérôme Leclercq
// This file is part of the "Ungine".
// For conditions of distribution and use, see copyright notice in Core.h
#include <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_LoadStream(NzMesh* mesh, NzInputStream& stream, const NzMeshParams& parameters);
bool NzLoader_MD2_LoadFile(NzMesh* mesh, const NzString& filePath, const NzMeshParams& parameters)
{
NzFile file(filePath);
if (!file.Open(NzFile::ReadOnly))
{
NazaraError("Failed to open file");
return false;
}
return NzLoader_MD2_LoadStream(mesh, file, parameters);
}
bool NzLoader_MD2_LoadMemory(NzMesh* mesh, const void* data, unsigned int size, const NzMeshParams& parameters)
{
NzMemoryStream stream(data, size);
return NzLoader_MD2_LoadStream(mesh, stream, parameters);
}
bool NzLoader_MD2_LoadStream(NzMesh* mesh, NzInputStream& stream, const NzMeshParams& parameters)
{
md2_header header;
if (stream.Read(&header, sizeof(md2_header)) != sizeof(md2_header))
{
NazaraError("Failed to read header");
return false;
}
// Les fichiers MD2 sont en little endian
#if NAZARA_BIG_ENDIAN
NzByteSwap(&header.ident, sizeof(nzUInt32));
#endif
if (header.ident != md2Ident)
{
NazaraError("Invalid MD2 file");
return false;
}
#if NAZARA_BIG_ENDIAN
NzByteSwap(&header.version, sizeof(nzUInt32));
#endif
if (header.version != 8)
{
NazaraError("Bad version number (" + NzString::Number(header.version) + ')');
return false;
}
#if NAZARA_BIG_ENDIAN
NzByteSwap(&header.skinwidth, sizeof(nzUInt32));
NzByteSwap(&header.skinheight, sizeof(nzUInt32));
NzByteSwap(&header.framesize, sizeof(nzUInt32));
NzByteSwap(&header.num_skins, sizeof(nzUInt32));
NzByteSwap(&header.num_vertices, sizeof(nzUInt32));
NzByteSwap(&header.num_st, sizeof(nzUInt32));
NzByteSwap(&header.num_tris, sizeof(nzUInt32));
NzByteSwap(&header.num_glcmds, sizeof(nzUInt32));
NzByteSwap(&header.num_frames, sizeof(nzUInt32));
NzByteSwap(&header.offset_skins, sizeof(nzUInt32));
NzByteSwap(&header.offset_st, sizeof(nzUInt32));
NzByteSwap(&header.offset_tris, sizeof(nzUInt32));
NzByteSwap(&header.offset_frames, sizeof(nzUInt32));
NzByteSwap(&header.offset_glcmds, sizeof(nzUInt32));
NzByteSwap(&header.offset_end, sizeof(nzUInt32));
#endif
if (stream.GetSize() < header.offset_end)
{
NazaraError("Incomplete MD2 file");
return false;
}
/// Création du mesh
// Animé ou statique, c'est la question
bool animated;
unsigned int startFrame = NzClamp(parameters.animation.startFrame, 0U, static_cast<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))
{
NzString frameName;
NzSequence sequence;
sequence.framePerSecond = 10; // Par défaut pour les animations MD2
char name[16], last[16];
stream.SetCursorPos(header.offset_frames + startFrame*header.framesize + offsetof(md2_frame, name));
stream.Read(last, 16*sizeof(char));
int pos = std::strlen(last)-1;
for (unsigned int j = 0; j < 2; ++j)
{
if (!std::isdigit(last[pos]))
break;
pos--;
}
last[pos+1] = '\0';
unsigned int numFrames = 0;
for (unsigned int i = startFrame; i <= endFrame; ++i)
{
stream.SetCursorPos(header.offset_frames + i*header.framesize + offsetof(md2_frame, name));
stream.Read(name, 16*sizeof(char));
int pos = std::strlen(name)-1;
for (unsigned int j = 0; j < 2; ++j)
{
if (!std::isdigit(name[pos]))
break;
pos--;
}
name[pos+1] = '\0';
if (std::strcmp(name, last) != 0) // Si les deux frames n'ont pas le même nom
{
// Alors on enregistre la séquence
sequence.firstFrame = i-numFrames;
sequence.lastFrame = i-1;
sequence.name = last;
animation->AddSequence(sequence);
std::strcpy(last, name);
numFrames = 0;
}
numFrames++;
}
// On ajoute la dernière frame (Qui n'a pas été traitée par la boucle)
sequence.firstFrame = endFrame-numFrames;
sequence.lastFrame = endFrame;
sequence.name = last;
animation->AddSequence(sequence);
mesh->SetAnimation(animation);
animation->SetPersistent(false);
}
else
NazaraInternalError("Failed to create animaton");
}
/// Chargement des submesh
// Actuellement le loader ne charge qu'un submesh
// TODO: Utiliser les commandes OpenGL pour accélérer le rendu
NzMD2Mesh* subMesh = new NzMD2Mesh(mesh);
if (!subMesh->Create(header, stream, parameters))
{
NazaraError("Failed to create MD2 mesh");
return false;
}
mesh->AddSubMesh(subMesh);
return true;
}
bool NzLoader_MD2_IdentifyMemory(const void* data, unsigned int size, const NzMeshParams& parameters)
{
NazaraUnused(parameters);
if (size < sizeof(md2_header))
return false;
const md2_header* header = reinterpret_cast<const md2_header*>(data);
#if NAZARA_BIG_ENDIAN
nzUInt32 ident = header->ident;
nzUInt32 version = header->version;
NzByteSwap(&ident, sizeof(nzUInt32));
NzByteSwap(&version, sizeof(nzUInt32));
return ident == md2Ident && version == 8;
#else
return header->ident == md2Ident && header->version == 8;
#endif
}
bool NzLoader_MD2_IdentifyStream(NzInputStream& stream, const NzMeshParams& parameters)
{
NazaraUnused(parameters);
nzUInt32 magic[2];
if (stream.Read(&magic[0], 2*sizeof(nzUInt32)) != 2*sizeof(nzUInt32))
return false;
#if NAZARA_BIG_ENDIAN
NzByteSwap(&magic[0], sizeof(nzUInt32));
NzByteSwap(&magic[1], sizeof(nzUInt32));
#endif
return magic[0] == md2Ident && magic[1] == 8;
}
}
void NzLoaders_MD2_Register()
{
NzMD2Mesh::Initialize();
NzMeshLoader::RegisterFileLoader("md2", NzLoader_MD2_LoadFile);
NzMeshLoader::RegisterMemoryLoader(NzLoader_MD2_IdentifyMemory, NzLoader_MD2_LoadMemory);
NzMeshLoader::RegisterStreamLoader(NzLoader_MD2_IdentifyStream, NzLoader_MD2_LoadStream);
}
void NzLoaders_MD2_Unregister()
{
NzMeshLoader::UnregisterStreamLoader(NzLoader_MD2_IdentifyStream, NzLoader_MD2_LoadStream);
NzMeshLoader::UnregisterMemoryLoader(NzLoader_MD2_IdentifyMemory, NzLoader_MD2_LoadMemory);
NzMeshLoader::UnregisterFileLoader("md2", NzLoader_MD2_LoadFile);
NzMD2Mesh::Uninitialize();
}

View File

@@ -0,0 +1,275 @@
// Copyright (C) 2011 Jérôme Leclercq
// This file is part of the "Ungine".
// For conditions of distribution and use, see copyright notice in Core.h
#include <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 NAZARA_BIG_ENDIAN
for (unsigned int i = 0; i < header.num_st; ++i)
{
NzByteSwap(&texCoords[i].u, sizeof(nzInt16));
NzByteSwap(&texCoords[i].v, sizeof(nzInt16));
}
#endif
stream.SetCursorPos(header.offset_tris);
stream.Read(&triangles[0], header.num_tris*sizeof(md2_triangle));
#if NAZARA_BIG_ENDIAN
for (unsigned int i = 0; i < header.num_tris; ++i)
{
NzByteSwap(&triangles[i].vertices[0], sizeof(nzUInt16));
NzByteSwap(&texCoords[i].texCoords[0], sizeof(nzUInt16));
NzByteSwap(&triangles[i].vertices[1], sizeof(nzUInt16));
NzByteSwap(&texCoords[i].texCoords[1], sizeof(nzUInt16));
NzByteSwap(&triangles[i].vertices[2], sizeof(nzUInt16));
NzByteSwap(&texCoords[i].texCoords[2], sizeof(nzUInt16));
}
#endif
stream.SetCursorPos(header.offset_frames + header.framesize*startFrame);
md2_frame frame;
frame.vertices.resize(header.num_vertices);
// Pour que le modèle soit correctement aligné, on génère une matrice de rotation que nous appliquerons à chacune des vertices
NzMatrix4f rotationMatrix = NzMatrix4f::Rotate(NzEulerAnglesf(-90.f, 0.f, -90.f));
//NzMatrix4f rotationMatrix;
//rotationMatrix.SetIdentity();
unsigned int stride = s_declaration.GetStride(nzElementStream_VertexData);
m_frames = new Frame[m_frameCount];
for (unsigned int i = 0; i < m_frameCount; ++i)
{
stream.Read(&frame.scale, sizeof(NzVector3f));
stream.Read(&frame.translate, sizeof(NzVector3f));
stream.Read(&frame.name, 16*sizeof(char));
stream.Read(&frame.vertices[0], header.num_vertices*sizeof(md2_vertex));
#if NAZARA_BIG_ENDIAN
NzByteSwap(&frame.scale.x, sizeof(float));
NzByteSwap(&frame.scale.y, sizeof(float));
NzByteSwap(&frame.scale.z, sizeof(float));
NzByteSwap(&frame.translate.x, sizeof(float));
NzByteSwap(&frame.translate.y, sizeof(float));
NzByteSwap(&frame.translate.z, sizeof(float));
#endif
m_frames[i].normal = new nzUInt8[m_vertexCount]; // Nous stockons l'indice de la normale plutôt que la normale (gain d'espace)
m_frames[i].vertices = new NzVector3f[m_vertexCount];
for (unsigned int t = 0; t < header.num_tris; ++t)
{
for (unsigned int v = 0; v < 3; ++v)
{
const md2_vertex& vert = frame.vertices[triangles[t].vertices[v]];
NzVector3f vertex = rotationMatrix * NzVector3f(vert.x * frame.scale.x + frame.translate.x, vert.y * frame.scale.y + frame.translate.y, vert.z * frame.scale.z + frame.translate.z);
m_frames[i].normal[t*3+v] = vert.n;
m_frames[i].vertices[t*3+v] = vertex;
}
}
}
nzBufferStorage storage = (NzBuffer::IsSupported(nzBufferStorage_Hardware) && !parameters.forceSoftware) ? nzBufferStorage_Hardware : nzBufferStorage_Software;
m_indexBuffer = nullptr; // Pas d'indexbuffer pour l'instant
m_vertexBuffer = new NzVertexBuffer(m_vertexCount, (3+3+2)*sizeof(float), storage, nzBufferUsage_Dynamic);
nzUInt8* ptr = reinterpret_cast<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;
}
}
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");
}
NzVertexDeclaration NzMD2Mesh::s_declaration;

View File

@@ -0,0 +1,64 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_LOADERS_MD2_MESH_HPP
#define NAZARA_LOADERS_MD2_MESH_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Math/Vector3.hpp>
#include <Nazara/Utility/KeyframeMesh.hpp>
#include <Nazara/Utility/VertexDeclaration.hpp>
#include <Nazara/Utility/Loaders/MD2/Constants.hpp>
class NzIndexBuffer;
class NzInputStream;
class NzVertexBuffer;
struct NzMeshParams;
class NAZARA_API NzMD2Mesh : public NzKeyframeMesh
{
public:
NzMD2Mesh(const NzMesh* parent);
~NzMD2Mesh();
bool Create(const md2_header& header, NzInputStream& stream, const NzMeshParams& parameters);
void Destroy();
nzAnimationType GetAnimationType() const;
unsigned int GetFrameCount() const;
const NzIndexBuffer* GetIndexBuffer() const;
nzPrimitiveType GetPrimitiveType() const;
const NzVertexBuffer* GetVertexBuffer() const;
const NzVertexDeclaration* GetVertexDeclaration() const;
bool IsAnimated() const;
static void Initialize();
static void Uninitialize();
private:
void AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation);
struct Frame
{
//AxisAlignedBox aabb;
nzUInt8* normal;
NzVector3f* tangents;
NzVector3f* vertices;
char name[16];
};
//AxisAlignedBox m_aabb;
Frame* m_frames;
NzIndexBuffer* m_indexBuffer;
NzVertexBuffer* m_vertexBuffer;
unsigned int m_frameCount;
unsigned int m_vertexCount;
static NzVertexDeclaration s_declaration;
};
#endif // NAZARA_LOADERS_MD2_MESH_HPP

View File

@@ -37,9 +37,9 @@ namespace
nzUInt8 padding[54];
};
bool NzLoader_PCX_LoadStream(NzImage* resource, NzInputStream& stream, const NzImageParams& parameters);
bool NzLoader_PCX_LoadStream(NzImage* image, NzInputStream& stream, const NzImageParams& parameters);
bool NzLoader_PCX_LoadFile(NzImage* resource, const NzString& filePath, const NzImageParams& parameters)
bool NzLoader_PCX_LoadFile(NzImage* image, const NzString& filePath, const NzImageParams& parameters)
{
NzFile file(filePath);
if (!file.Open(NzFile::ReadOnly))
@@ -48,16 +48,16 @@ namespace
return false;
}
return NzLoader_PCX_LoadStream(resource, file, parameters);
return NzLoader_PCX_LoadStream(image, file, parameters);
}
bool NzLoader_PCX_LoadMemory(NzImage* resource, const void* data, unsigned int size, const NzImageParams& parameters)
bool NzLoader_PCX_LoadMemory(NzImage* image, const void* data, unsigned int size, const NzImageParams& parameters)
{
NzMemoryStream stream(data, size);
return NzLoader_PCX_LoadStream(resource, stream, parameters);
return NzLoader_PCX_LoadStream(image, stream, parameters);
}
bool NzLoader_PCX_LoadStream(NzImage* resource, NzInputStream& stream, const NzImageParams& parameters)
bool NzLoader_PCX_LoadStream(NzImage* image, NzInputStream& stream, const NzImageParams& parameters)
{
NazaraUnused(parameters);
@@ -93,13 +93,13 @@ namespace
unsigned int width = header.xmax - header.xmin+1;
unsigned int height = header.ymax - header.ymin+1;
if (!resource->Create(nzImageType_2D, nzPixelFormat_RGB8, width, height, 1, (parameters.levelCount > 0) ? parameters.levelCount : 1))
if (!image->Create(nzImageType_2D, nzPixelFormat_RGB8, width, height, 1, (parameters.levelCount > 0) ? parameters.levelCount : 1))
{
NazaraError("Failed to create image");
return false;
}
nzUInt8* pixels = resource->GetPixels();
nzUInt8* pixels = image->GetPixels();
int rle_value = 0;
unsigned int rle_count = 0;
@@ -339,17 +339,17 @@ namespace
}
default:
NazaraError("Unknown " + NzString::Number(bitCount) + " bitcount pcx files");
NazaraError("Unable to load " + NzString::Number(bitCount) + " bitcount pcx files");
return false;
}
if (parameters.loadFormat != nzPixelFormat_Undefined)
resource->Convert(parameters.loadFormat);
image->Convert(parameters.loadFormat);
return true;
}
bool NzLoader_PCX_IsMemoryLoadingSupported(const void* data, unsigned int size, const NzImageParams& parameters)
bool NzLoader_PCX_IdentifyMemory(const void* data, unsigned int size, const NzImageParams& parameters)
{
NazaraUnused(parameters);
@@ -359,12 +359,13 @@ namespace
return *reinterpret_cast<const nzUInt8*>(data) == 0x0a;
}
bool NzLoader_PCX_IsStreamLoadingSupported(NzInputStream& stream, const NzImageParams& parameters)
bool NzLoader_PCX_IdentifyStream(NzInputStream& stream, const NzImageParams& parameters)
{
NazaraUnused(parameters);
nzUInt8 manufacturer;
stream.Read(&manufacturer, 1);
if (stream.Read(&manufacturer, 1) != 1)
return false;
return manufacturer == 0x0a;
}
@@ -372,14 +373,14 @@ namespace
void NzLoaders_PCX_Register()
{
NzImage::RegisterFileLoader("pcx", NzLoader_PCX_LoadFile);
NzImage::RegisterMemoryLoader(NzLoader_PCX_IsMemoryLoadingSupported, NzLoader_PCX_LoadMemory);
NzImage::RegisterStreamLoader(NzLoader_PCX_IsStreamLoadingSupported, NzLoader_PCX_LoadStream);
NzImageLoader::RegisterFileLoader("pcx", NzLoader_PCX_LoadFile);
NzImageLoader::RegisterMemoryLoader(NzLoader_PCX_IdentifyMemory, NzLoader_PCX_LoadMemory);
NzImageLoader::RegisterStreamLoader(NzLoader_PCX_IdentifyStream, NzLoader_PCX_LoadStream);
}
void NzLoaders_PCX_Unregister()
{
NzImage::UnregisterStreamLoader(NzLoader_PCX_IsStreamLoadingSupported, NzLoader_PCX_LoadStream);
NzImage::UnregisterMemoryLoader(NzLoader_PCX_IsMemoryLoadingSupported, NzLoader_PCX_LoadMemory);
NzImage::UnregisterFileLoader("pcx", NzLoader_PCX_LoadFile);
NzImageLoader::UnregisterStreamLoader(NzLoader_PCX_IdentifyStream, NzLoader_PCX_LoadStream);
NzImageLoader::UnregisterMemoryLoader(NzLoader_PCX_IdentifyMemory, NzLoader_PCX_LoadMemory);
NzImageLoader::UnregisterFileLoader("pcx", NzLoader_PCX_LoadFile);
}

View File

@@ -15,8 +15,6 @@
#include <Nazara/Utility/Debug.hpp>
// Auteur du loader original : David Henry
namespace
{
int Read(void* userdata, char* data, int size)
@@ -39,9 +37,9 @@ namespace
static stbi_io_callbacks callbacks = {Read, Skip, Eof};
bool NzLoader_STB_LoadStream(NzImage* resource, NzInputStream& stream, const NzImageParams& parameters);
bool NzLoader_STB_LoadStream(NzImage* image, NzInputStream& stream, const NzImageParams& parameters);
bool NzLoader_STB_LoadFile(NzImage* resource, const NzString& filePath, const NzImageParams& parameters)
bool NzLoader_STB_LoadFile(NzImage* image, const NzString& filePath, const NzImageParams& parameters)
{
NzFile file(filePath);
if (!file.Open(NzFile::ReadOnly))
@@ -50,16 +48,16 @@ namespace
return false;
}
return NzLoader_STB_LoadStream(resource, file, parameters);
return NzLoader_STB_LoadStream(image, file, parameters);
}
bool NzLoader_STB_LoadMemory(NzImage* resource, const void* data, unsigned int size, const NzImageParams& parameters)
bool NzLoader_STB_LoadMemory(NzImage* image, const void* data, unsigned int size, const NzImageParams& parameters)
{
NzMemoryStream stream(data, size);
return NzLoader_STB_LoadStream(resource, stream, parameters);
return NzLoader_STB_LoadStream(image, stream, parameters);
}
bool NzLoader_STB_LoadStream(NzImage* resource, NzInputStream& stream, const NzImageParams& parameters)
bool NzLoader_STB_LoadStream(NzImage* image, NzInputStream& stream, const NzImageParams& parameters)
{
NazaraUnused(parameters);
@@ -112,7 +110,7 @@ namespace
if (format == nzPixelFormat_Undefined)
format = formats[bpp-1];
if (!resource->Create(nzImageType_2D, format, width, height, 1, (parameters.levelCount > 0) ? parameters.levelCount : 1))
if (!image->Create(nzImageType_2D, format, width, height, 1, (parameters.levelCount > 0) ? parameters.levelCount : 1))
{
NazaraError("Failed to create image");
stbi_image_free(ptr);
@@ -120,17 +118,17 @@ namespace
return false;
}
resource->Update(ptr);
image->Update(ptr);
stbi_image_free(ptr);
if (stbiFormat == STBI_default && parameters.loadFormat != nzPixelFormat_Undefined)
resource->Convert(parameters.loadFormat);
image->Convert(parameters.loadFormat);
return true;
}
bool NzLoader_STB_IsMemoryLoadingSupported(const void* data, unsigned int size, const NzImageParams& parameters)
bool NzLoader_STB_IdentifyMemory(const void* data, unsigned int size, const NzImageParams& parameters)
{
NazaraUnused(parameters);
@@ -138,7 +136,7 @@ namespace
return stbi_info_from_memory(reinterpret_cast<const stbi_uc*>(data), size, &width, &height, &bpp);
}
bool NzLoader_STB_IsStreamLoadingSupported(NzInputStream& stream, const NzImageParams& parameters)
bool NzLoader_STB_IdentifyStream(NzInputStream& stream, const NzImageParams& parameters)
{
NazaraUnused(parameters);
@@ -149,14 +147,14 @@ namespace
void NzLoaders_STB_Register()
{
NzImage::RegisterFileLoader("bmp, gif, hdr, jpg, jpeg, pic, png, psd, tga", NzLoader_STB_LoadFile);
NzImage::RegisterMemoryLoader(NzLoader_STB_IsMemoryLoadingSupported, NzLoader_STB_LoadMemory);
NzImage::RegisterStreamLoader(NzLoader_STB_IsStreamLoadingSupported, NzLoader_STB_LoadStream);
NzImageLoader::RegisterFileLoader("bmp, gif, hdr, jpg, jpeg, pic, png, psd, tga", NzLoader_STB_LoadFile);
NzImageLoader::RegisterMemoryLoader(NzLoader_STB_IdentifyMemory, NzLoader_STB_LoadMemory);
NzImageLoader::RegisterStreamLoader(NzLoader_STB_IdentifyStream, NzLoader_STB_LoadStream);
}
void NzLoaders_STB_Unregister()
{
NzImage::UnregisterStreamLoader(NzLoader_STB_IsStreamLoadingSupported, NzLoader_STB_LoadStream);
NzImage::UnregisterMemoryLoader(NzLoader_STB_IsMemoryLoadingSupported, NzLoader_STB_LoadMemory);
NzImage::UnregisterFileLoader("bmp, gif, hdr, jpg, jpeg, pic, png, psd, tga", NzLoader_STB_LoadFile);
NzImageLoader::UnregisterStreamLoader(NzLoader_STB_IdentifyStream, NzLoader_STB_LoadStream);
NzImageLoader::UnregisterMemoryLoader(NzLoader_STB_IdentifyMemory, NzLoader_STB_LoadMemory);
NzImageLoader::UnregisterFileLoader("bmp, gif, hdr, jpg, jpeg, pic, png, psd, tga", NzLoader_STB_LoadFile);
}

575
src/Nazara/Utility/Mesh.cpp Normal file
View File

@@ -0,0 +1,575 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Mesh.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Utility/Config.hpp>
#include <Nazara/Utility/SubMesh.hpp>
#include <cstring>
#include <deque>
#include <Nazara/Utility/Debug.hpp>
bool NzMeshParams::IsValid() const
{
if (!animation.IsValid())
{
NazaraError("Invalid animation parameters");
return false;
}
return true;
}
struct NzMeshImpl
{
std::map<NzString, nzUInt8> subMeshMap;
std::deque<NzString> skins;
std::vector<NzSubMesh*> subMeshes;
nzAnimationType animationType;
const NzAnimation* animation = nullptr;
};
NzMesh::~NzMesh()
{
Destroy();
}
unsigned int NzMesh::AddSkin(const NzString& skin, bool setDefault)
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return 0;
}
if (skin.IsEmpty())
{
NazaraError("Skin is empty");
return 0;
}
#endif
if (setDefault)
m_impl->skins.push_front(skin);
else
m_impl->skins.push_back(skin);
return m_impl->skins.size()-1;
}
nzUInt8 NzMesh::AddSubMesh(NzSubMesh* subMesh)
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return 0;
}
if (!subMesh)
{
NazaraError("Invalid submesh");
return 0;
}
#endif
subMesh->AddResourceReference();
m_impl->subMeshes.push_back(subMesh);
return m_impl->subMeshes.size()-1;
}
nzUInt8 NzMesh::AddSubMesh(const NzString& identifier, NzSubMesh* subMesh)
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return 0;
}
if (identifier.IsEmpty())
{
NazaraError("Identifier is empty");
return 0;
}
auto it = m_impl->subMeshMap.find(identifier);
if (it != m_impl->subMeshMap.end())
{
NazaraError("SubMesh identifier \"" + identifier + "\" is already used");
return it->second;
}
if (!subMesh)
{
NazaraError("Invalid submesh");
return 0;
}
#endif
nzUInt8 index = m_impl->subMeshes.size();
subMesh->AddResourceReference();
m_impl->subMeshes.push_back(subMesh);
m_impl->subMeshMap[identifier] = index;
return index;
}
void NzMesh::Animate(unsigned int frameA, unsigned int frameB, float interpolation)
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return;
}
if (!m_impl->animation)
{
NazaraError("Mesh has no animation");
return;
}
unsigned int frameCount = m_impl->animation->GetFrameCount();
if (frameA >= frameCount)
{
NazaraError("Frame A is out of range (" + NzString::Number(frameA) + " >= " + NzString::Number(frameCount) + ')');
return;
}
if (frameB >= frameCount)
{
NazaraError("Frame B is out of range (" + NzString::Number(frameB) + " >= " + NzString::Number(frameCount) + ')');
return;
}
if (interpolation < 0.f || interpolation > 1.f)
{
NazaraError("Interpolation must be in range [0..1] (Got " + NzString::Number(interpolation) + ')');
return;
}
#endif
for (NzSubMesh* subMesh : m_impl->subMeshes)
subMesh->AnimateImpl(frameA, frameB, interpolation);
}
bool NzMesh::Create(nzAnimationType type)
{
Destroy();
m_impl = new NzMeshImpl;
m_impl->animationType = type;
return true;
}
void NzMesh::Destroy()
{
if (m_impl)
{
if (m_impl->animation)
m_impl->animation->RemoveResourceReference();
for (NzSubMesh* subMesh : m_impl->subMeshes)
subMesh->RemoveResourceReference();
delete m_impl;
m_impl = nullptr;
}
}
const NzAnimation* NzMesh::GetAnimation() const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return nullptr;
}
#endif
return m_impl->animation;
}
nzAnimationType NzMesh::GetAnimationType() const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return nzAnimationType_Static;
}
#endif
return m_impl->animationType;
}
unsigned int NzMesh::GetFrameCount() const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return 0;
}
if (!m_impl->animation)
{
NazaraError("Mesh has no animation");
return 0;
}
#endif
return m_impl->animation->GetFrameCount();
}
NzString NzMesh::GetSkin(unsigned int index) const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return NzString();
}
if (index >= m_impl->skins.size())
{
NazaraError("Skin index out of range (" + NzString::Number(index) + " >= " + NzString::Number(m_impl->skins.size()) + ')');
return NzString();
}
#endif
return m_impl->skins[index];
}
unsigned int NzMesh::GetSkinCount() const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return 0;
}
#endif
return m_impl->skins.size();
}
NzSubMesh* NzMesh::GetSubMesh(const NzString& identifier)
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return nullptr;
}
auto it = m_impl->subMeshMap.find(identifier);
if (it == m_impl->subMeshMap.end())
{
NazaraError("SubMesh not found");
return nullptr;
}
return m_impl->subMeshes[it->second];
#else
return m_impl->subMeshes[m_impl->subMeshMap[identifier]];
#endif
}
NzSubMesh* NzMesh::GetSubMesh(nzUInt8 index)
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return nullptr;
}
if (index >= m_impl->subMeshes.size())
{
NazaraError("SubMesh index out of range (" + NzString::Number(index) + " >= " + NzString::Number(m_impl->subMeshes.size()) + ')');
return nullptr;
}
#endif
return m_impl->subMeshes[index];
}
const NzSubMesh* NzMesh::GetSubMesh(const NzString& identifier) const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return nullptr;
}
auto it = m_impl->subMeshMap.find(identifier);
if (it == m_impl->subMeshMap.end())
{
NazaraError("SubMesh not found");
return nullptr;
}
return m_impl->subMeshes[it->second];
#else
return m_impl->subMeshes[m_impl->subMeshMap[identifier]];
#endif
}
const NzSubMesh* NzMesh::GetSubMesh(nzUInt8 index) const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return nullptr;
}
if (index >= m_impl->subMeshes.size())
{
NazaraError("SubMesh index out of range (" + NzString::Number(index) + " >= " + NzString::Number(m_impl->subMeshes.size()) + ')');
return nullptr;
}
#endif
return m_impl->subMeshes[index];
}
nzUInt8 NzMesh::GetSubMeshCount() const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return 0;
}
#endif
return m_impl->subMeshes.size();
}
unsigned int NzMesh::GetVertexCount() const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return 0;
}
#endif
unsigned int vertexCount = 0;
for (NzSubMesh* subMesh : m_impl->subMeshes)
vertexCount += subMesh->GetVertexCount();
return vertexCount;
}
bool NzMesh::HasAnimation() const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return false;
}
#endif
return m_impl->animation != nullptr;
}
bool NzMesh::HasSkin(unsigned int index) const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return false;
}
#endif
return m_impl->skins.size() > index;
}
bool NzMesh::HasSubMesh(const NzString& identifier) const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return false;
}
#endif
return m_impl->subMeshMap.find(identifier) != m_impl->subMeshMap.end();
}
bool NzMesh::HasSubMesh(nzUInt8 index) const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return false;
}
#endif
return index < m_impl->subMeshes.size();
}
bool NzMesh::IsAnimable() const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return false;
}
#endif
return m_impl->animationType != nzAnimationType_Static;
}
bool NzMesh::IsValid() const
{
return m_impl != nullptr;
}
bool NzMesh::LoadFromFile(const NzString& filePath, const NzMeshParams& params)
{
return NzMeshLoader::LoadFromFile(this, filePath, params);
}
bool NzMesh::LoadFromMemory(const void* data, std::size_t size, const NzMeshParams& params)
{
return NzMeshLoader::LoadFromMemory(this, data, size, params);
}
bool NzMesh::LoadFromStream(NzInputStream& stream, const NzMeshParams& params)
{
return NzMeshLoader::LoadFromStream(this, stream, params);
}
void NzMesh::RemoveSkin(unsigned int index)
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return;
}
if (m_impl->skins.size() <= index)
{
NazaraError("Skin index out of range (" + NzString::Number(index) + " >= " + NzString::Number(m_impl->skins.size()) + ')');
return;
}
#endif
auto it = m_impl->skins.begin();
std::advance(it, index);
m_impl->skins.erase(it);
}
void NzMesh::RemoveSubMesh(const NzString& identifier)
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return;
}
auto it = m_impl->subMeshMap.find(identifier);
if (it == m_impl->subMeshMap.end())
{
NazaraError("SubMesh not found");
return;
}
unsigned int index = it->second;
#else
unsigned int index = m_impl->subMeshMap[identifier];
#endif
auto it2 = m_impl->subMeshes.begin();
std::advance(it2, index);
m_impl->subMeshes.erase(it2);
}
void NzMesh::RemoveSubMesh(nzUInt8 index)
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return;
}
if (index >= m_impl->subMeshes.size())
{
NazaraError("SubMesh index out of range (" + NzString::Number(index) + " >= " + NzString::Number(m_impl->subMeshes.size()) + ')');
return;
}
#endif
auto it = m_impl->subMeshes.begin();
std::advance(it, index);
m_impl->subMeshes.erase(it);
}
bool NzMesh::SetAnimation(const NzAnimation* animation)
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return false;
}
if (m_impl->animationType == nzAnimationType_Static)
{
NazaraError("Static meshes cannot have animation");
return false;
}
#endif
if (animation == m_impl->animation)
return true;
if (m_impl->animation)
m_impl->animation->RemoveResourceReference();
if (animation)
{
#if NAZARA_UTILITY_SAFE
if (animation->GetType() != m_impl->animationType)
{
NazaraError("Animation's type must match mesh animation type");
return false;
}
#endif
m_impl->animation = animation;
m_impl->animation->AddResourceReference();
}
else
m_impl->animation = nullptr;
return true;
}
std::list<NzMeshLoader::MemoryLoader> NzMesh::s_memoryLoaders;
std::list<NzMeshLoader::StreamLoader> NzMesh::s_streamLoaders;
std::multimap<NzString, NzMeshLoader::LoadFileFunction> NzMesh::s_fileLoaders;

View File

@@ -1314,7 +1314,11 @@ bool NzPixelFormat::Initialize()
void NzPixelFormat::Uninitialize()
{
std::memset(s_convertFunctions, 0, nzPixelFormat_Count*nzPixelFormat_Count*sizeof(NzPixelFormat::ConvertFunction));
std::memset(s_convertFunctions, 0, (nzPixelFormat_Max+1)*(nzPixelFormat_Max+1)*sizeof(NzPixelFormat::ConvertFunction));
for (unsigned int i = 0; i <= nzPixelFlipping_Max; ++i)
s_flipFunctions[i].clear();
}
NzPixelFormat::ConvertFunction NzPixelFormat::s_convertFunctions[nzPixelFormat_Count][nzPixelFormat_Count] = {{0}}; ///FIXME: Fonctionne correctement ?
NzPixelFormat::ConvertFunction NzPixelFormat::s_convertFunctions[nzPixelFormat_Max+1][nzPixelFormat_Max+1] = {{0}}; ///FIXME: Fonctionne correctement ?
std::map<nzPixelFormat, NzPixelFormat::FlipFunction> NzPixelFormat::s_flipFunctions[nzPixelFlipping_Max+1];

View File

@@ -2,22 +2,12 @@
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/SoftwareBuffer.hpp>
#include <Nazara/Utility/SoftwareBuffer.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <Nazara/Utility/Config.hpp>
#include <cstring>
#include <stdexcept>
#include <Nazara/Renderer/Debug.hpp>
namespace
{
GLenum bufferTarget[] = {
GL_ELEMENT_ARRAY_BUFFER, // nzBufferType_Index,
GL_ARRAY_BUFFER, // nzBufferType_Vertex
};
}
#include <Nazara/Utility/Debug.hpp>
NzSoftwareBuffer::NzSoftwareBuffer(NzBuffer* parent, nzBufferType type) :
m_type(type)
@@ -29,19 +19,6 @@ NzSoftwareBuffer::~NzSoftwareBuffer()
{
}
void NzSoftwareBuffer::Bind()
{
#ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr)
{
NazaraError("No active context");
return;
}
#endif
glBindBuffer(bufferTarget[m_type], 0);
}
bool NzSoftwareBuffer::Create(unsigned int size, nzBufferUsage usage)
{
NazaraUnused(usage);
@@ -69,7 +46,7 @@ void NzSoftwareBuffer::Destroy()
bool NzSoftwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size)
{
#if NAZARA_RENDERER_SAFE
#if NAZARA_UTILITY_SAFE
if (m_mapped)
{
NazaraError("Buffer already mapped");
@@ -82,7 +59,7 @@ bool NzSoftwareBuffer::Fill(const void* data, unsigned int offset, unsigned int
return true;
}
void* NzSoftwareBuffer::GetBufferPtr()
void* NzSoftwareBuffer::GetPointer()
{
return m_buffer;
}
@@ -97,7 +74,7 @@ void* NzSoftwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned
NazaraUnused(access);
NazaraUnused(size);
#if NAZARA_RENDERER_SAFE
#if NAZARA_UTILITY_SAFE
if (m_mapped)
{
NazaraError("Buffer already mapped");
@@ -112,7 +89,7 @@ void* NzSoftwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned
bool NzSoftwareBuffer::Unmap()
{
#if NAZARA_RENDERER_SAFE
#if NAZARA_UTILITY_SAFE
if (!m_mapped)
{
NazaraError("Buffer not mapped");

View File

@@ -8,7 +8,7 @@
#define NAZARA_SOFTWAREBUFFER_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Renderer/BufferImpl.hpp>
#include <Nazara/Utility/BufferImpl.hpp>
class NzSoftwareBuffer : public NzBufferImpl
{
@@ -16,18 +16,16 @@ class NzSoftwareBuffer : public NzBufferImpl
NzSoftwareBuffer(NzBuffer* parent, nzBufferType type);
~NzSoftwareBuffer();
void Bind();
bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static);
void Destroy();
bool Fill(const void* data, unsigned int offset, unsigned int length);
bool Fill(const void* data, unsigned int offset, unsigned int size);
void* GetBufferPtr();
void* GetPointer();
bool IsHardware() const;
void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0);
void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0);
bool Unmap();
private:

View File

@@ -0,0 +1,141 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <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 NzVertexBuffer* vertexBuffer, const NzVertexDeclaration* vertexDeclaration, const NzIndexBuffer* indexBuffer) :
NzSubMesh(parent)
{
#ifdef NAZARA_DEBUG
if (!Create(vertexBuffer, vertexDeclaration, indexBuffer))
{
NazaraError("Failed to create mesh");
throw std::runtime_error("Constructor failed");
}
#else
Create(vertexBuffer, vertexDeclaration, indexBuffer);
#endif
}
NzStaticMesh::~NzStaticMesh()
{
Destroy();
}
bool NzStaticMesh::Create(const NzVertexBuffer* vertexBuffer, const NzVertexDeclaration* vertexDeclaration, const NzIndexBuffer* indexBuffer)
{
Destroy();
#if NAZARA_UTILITY_SAFE
if (!vertexBuffer)
{
NazaraError("Vertex buffer is null");
return false;
}
if (!vertexDeclaration)
{
NazaraError("Vertex declaration is null");
return false;
}
#endif
if (indexBuffer)
{
m_indexBuffer = indexBuffer;
m_indexBuffer->AddResourceReference();
}
m_vertexBuffer = vertexBuffer;
m_vertexBuffer->AddResourceReference();
m_vertexDeclaration = vertexDeclaration;
m_vertexDeclaration->AddResourceReference();
return true;
}
void NzStaticMesh::Destroy()
{
if (m_indexBuffer)
{
m_indexBuffer->RemoveResourceReference();
m_indexBuffer = nullptr;
}
if (m_vertexBuffer)
{
m_vertexBuffer->RemoveResourceReference();
m_vertexBuffer = nullptr;
}
if (m_vertexDeclaration)
{
m_vertexDeclaration->RemoveResourceReference();
m_vertexDeclaration = nullptr;
}
}
nzAnimationType NzStaticMesh::GetAnimationType() const
{
return nzAnimationType_Static;
}
unsigned int NzStaticMesh::GetFrameCount() const
{
return 1;
}
const NzIndexBuffer* NzStaticMesh::GetIndexBuffer() const
{
return m_indexBuffer;
}
nzPrimitiveType NzStaticMesh::GetPrimitiveType() const
{
return m_primitiveType;
}
const NzVertexBuffer* NzStaticMesh::GetVertexBuffer() const
{
return m_vertexBuffer;
}
const NzVertexDeclaration* NzStaticMesh::GetVertexDeclaration() const
{
return m_vertexDeclaration;
}
bool NzStaticMesh::IsAnimated() const
{
return false;
}
bool NzStaticMesh::IsValid() const
{
return m_vertexBuffer != nullptr && m_vertexDeclaration != nullptr;
}
void NzStaticMesh::SetPrimitiveType(nzPrimitiveType primitiveType)
{
m_primitiveType = primitiveType;
}
void NzStaticMesh::AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation)
{
NazaraUnused(frameA);
NazaraUnused(frameB);
NazaraUnused(interpolation);
// Le safe mode est censé nous protéger de cet appel
NazaraError("Static mesh have no animation, please enable safe mode");
}

View File

@@ -0,0 +1,68 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/SubMesh.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Utility/Config.hpp>
#include <Nazara/Utility/Mesh.hpp>
#include <stdexcept>
#include <Nazara/Utility/Debug.hpp>
NzSubMesh::NzSubMesh(const NzMesh* parent) :
NzResource(false), // Un SubMesh n'est pas persistant par défaut
m_parent(parent)
{
#if NAZARA_DEBUG
if (!m_parent)
{
NazaraError("Parent mesh is null");
throw std::invalid_argument("Parent mesh must be valid");
}
#endif
}
NzSubMesh::~NzSubMesh() = default;
void NzSubMesh::Animate(unsigned int frameA, unsigned int frameB, float interpolation)
{
#if NAZARA_UTILITY_SAFE
if (!m_parent->HasAnimation())
{
NazaraError("SubMesh is not animated");
return;
}
unsigned int frameCount = m_parent->GetFrameCount();
if (frameA >= frameCount)
{
NazaraError("Frame A is out of range (" + NzString::Number(frameA) + " >= " + NzString::Number(frameCount) + ')');
return;
}
if (frameB >= frameCount)
{
NazaraError("Frame B is out of range (" + NzString::Number(frameB) + " >= " + NzString::Number(frameCount) + ')');
return;
}
if (interpolation < 0.f || interpolation > 1.f)
{
NazaraError("Interpolation must be in range [0..1] (Got " + NzString::Number(interpolation) + ')');
return;
}
#endif
AnimateImpl(frameA, frameB, interpolation);
}
const NzMesh* NzSubMesh::GetParent() const
{
return m_parent;
}
unsigned int NzSubMesh::GetVertexCount() const
{
return GetVertexBuffer()->GetVertexCount();
}

View File

@@ -4,7 +4,9 @@
#include <Nazara/Utility/Utility.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Utility/Buffer.hpp>
#include <Nazara/Utility/Config.hpp>
#include <Nazara/Utility/Loaders/MD2.hpp>
#include <Nazara/Utility/Loaders/PCX.hpp>
#include <Nazara/Utility/Loaders/STB.hpp>
#include <Nazara/Utility/PixelFormat.hpp>
@@ -31,9 +33,15 @@ bool NzUtility::Initialize()
}
#endif
if (!NzBuffer::Initialize())
{
NazaraError("Failed to initialize buffers");
return false;
}
if (!NzPixelFormat::Initialize())
{
NazaraError("Failed to initialize pixel format");
NazaraError("Failed to initialize pixel formats");
return false;
}
@@ -45,10 +53,15 @@ bool NzUtility::Initialize()
return false;
}
// Loaders spécialisés
/// Loaders spécialisés
// Mesh
NzLoaders_MD2_Register(); // Loader de fichiers .MD2 (v8)
// Image
NzLoaders_PCX_Register(); // Loader de fichiers .PCX (1, 4, 8, 24)
// Loaders génériques (En dernier pour donner la priorité aux loaders spécialisés)
/// Loaders génériques (En dernier pour donner la priorité aux loaders spécialisés)
// Image
NzLoaders_STB_Register(); // Loader générique (STB)
s_initialized = true;
@@ -66,12 +79,13 @@ void NzUtility::Uninitialize()
}
#endif
NzLoaders_STB_Unregister();
NzLoaders_MD2_Unregister();
NzLoaders_PCX_Unregister();
NzLoaders_STB_Unregister();
NzWindow::Uninitialize();
NzPixelFormat::Uninitialize();
NzBuffer::Uninitialize();
s_initialized = false;
}

View File

@@ -2,9 +2,10 @@
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/VertexBuffer.hpp>
#include <Nazara/Utility/VertexBuffer.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/Debug.hpp>
#include <stdexcept>
#include <Nazara/Utility/Debug.hpp>
NzVertexBuffer::NzVertexBuffer(NzBuffer* buffer, unsigned int startVertex, unsigned int vertexCount) :
m_buffer(buffer),
@@ -12,27 +13,38 @@ m_ownsBuffer(false),
m_startVertex(startVertex),
m_vertexCount(vertexCount)
{
#ifdef NAZARA_DEBUG
if (!m_buffer)
{
NazaraError("Buffer is null");
throw std::invalid_argument("Buffer must be valid");
}
#endif
m_buffer->AddResourceReference();
}
NzVertexBuffer::NzVertexBuffer(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage) :
NzVertexBuffer::NzVertexBuffer(unsigned int length, nzUInt8 typeSize, nzBufferStorage storage, nzBufferUsage usage) :
m_ownsBuffer(true),
m_startVertex(0),
m_vertexCount(length)
{
m_buffer = new NzBuffer(nzBufferType_Vertex, length, typeSize, usage);
m_buffer = new NzBuffer(nzBufferType_Vertex, length, typeSize, storage, usage);
m_buffer->AddResourceReference();
m_buffer->SetPersistent(false);
}
NzVertexBuffer::NzVertexBuffer(const NzVertexBuffer& vertexBuffer) :
NzResource(true),
m_ownsBuffer(vertexBuffer.m_ownsBuffer),
m_startVertex(vertexBuffer.m_startVertex),
m_vertexCount(vertexBuffer.m_vertexCount)
{
if (m_ownsBuffer)
{
m_buffer = new NzBuffer(nzBufferType_Vertex, vertexBuffer.m_buffer->GetLength(), vertexBuffer.m_buffer->GetSize(), vertexBuffer.m_buffer->GetUsage());
NzBuffer* buffer = vertexBuffer.m_buffer;
m_buffer = new NzBuffer(nzBufferType_Vertex, buffer->GetLength(), buffer->GetSize(), buffer->GetStorage(), buffer->GetUsage());
m_buffer->AddResourceReference();
m_buffer->SetPersistent(false);
m_buffer->CopyContent(*vertexBuffer.m_buffer);
@@ -51,7 +63,7 @@ NzVertexBuffer::~NzVertexBuffer()
bool NzVertexBuffer::Fill(const void* data, unsigned int offset, unsigned int length)
{
#if NAZARA_RENDERER_SAFE
#if NAZARA_UTILITY_SAFE
if (offset+length > m_vertexCount)
{
NazaraError("Exceeding virtual buffer size");
@@ -67,14 +79,14 @@ NzBuffer* NzVertexBuffer::GetBuffer() const
return m_buffer;
}
void* NzVertexBuffer::GetBufferPtr()
void* NzVertexBuffer::GetPointer()
{
return reinterpret_cast<nzUInt8*>(m_buffer->GetBufferPtr()) + m_startVertex*m_buffer->GetTypeSize();
return reinterpret_cast<nzUInt8*>(m_buffer->GetPointer()) + m_startVertex*m_buffer->GetTypeSize();
}
const void* NzVertexBuffer::GetBufferPtr() const
const void* NzVertexBuffer::GetPointer() const
{
return reinterpret_cast<const nzUInt8*>(m_buffer->GetBufferPtr()) + m_startVertex*m_buffer->GetTypeSize();
return reinterpret_cast<const nzUInt8*>(m_buffer->GetPointer()) + m_startVertex*m_buffer->GetTypeSize();
}
unsigned int NzVertexBuffer::GetStartVertex() const
@@ -99,7 +111,7 @@ bool NzVertexBuffer::IsHardware() const
void* NzVertexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length)
{
#if NAZARA_RENDERER_SAFE
#if NAZARA_UTILITY_SAFE
if (offset+length > m_vertexCount)
{
NazaraError("Exceeding virtual buffer size");
@@ -110,6 +122,11 @@ void* NzVertexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned i
return m_buffer->Map(access, m_startVertex+offset, (length) ? length : m_vertexCount-offset);
}
bool NzVertexBuffer::SetStorage(nzBufferStorage storage)
{
return m_buffer->SetStorage(storage);
}
bool NzVertexBuffer::Unmap()
{
return m_buffer->Unmap();

View File

@@ -0,0 +1,346 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/VertexDeclaration.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Utility/Config.hpp>
#include <algorithm>
#include <cstring>
#include <stdexcept>
#include <vector>
#if 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[] =
{
4, // nzElementType_Color
8, // nzElementType_Double1
16, // nzElementType_Double2
24, // nzElementType_Double3
32, // nzElementType_Double4
4, // nzElementType_Float1
8, // nzElementType_Float2
12, // nzElementType_Float3
16 // nzElementType_Float4
};
bool VertexElementCompare(const NzVertexElement& elementA, const NzVertexElement& elementB)
{
// Nous classons d'abord par stream
if (elementA.stream == elementB.stream)
{
// Ensuite par usage
if (elementA.usage == elementB.usage)
// Et finalement par usageIndex
return elementA.usageIndex < elementB.usageIndex;
else
return elementA.usage < elementB.usage;
}
else
return elementA.stream < elementB.stream;
}
}
struct NzVertexDeclarationImpl
{
std::vector<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;
NazaraMutex(mutex)
};
NzVertexDeclaration::NzVertexDeclaration(const NzVertexElement* elements, unsigned int elementCount)
{
#ifdef NAZARA_DEBUG
if (!Create(elements, elementCount))
{
NazaraError("Failed to create declaration");
throw std::runtime_error("Constructor failed");
}
#else
Create(elements, elementCount);
#endif
}
NzVertexDeclaration::NzVertexDeclaration(const NzVertexDeclaration& declaration) :
NzResource(),
m_sharedImpl(declaration.m_sharedImpl)
{
if (m_sharedImpl)
{
NazaraMutexLock(m_sharedImpl->mutex);
m_sharedImpl->refCount++;
NazaraMutexUnlock(m_sharedImpl->mutex);
}
}
NzVertexDeclaration::NzVertexDeclaration(NzVertexDeclaration&& declaration) :
m_sharedImpl(declaration.m_sharedImpl)
{
declaration.m_sharedImpl = nullptr;
}
NzVertexDeclaration::~NzVertexDeclaration()
{
Destroy();
}
bool NzVertexDeclaration::Create(const NzVertexElement* elements, unsigned int elementCount)
{
Destroy();
#if NAZARA_UTILITY_SAFE
if (!elements || elementCount == 0)
{
NazaraError("No element");
return false;
}
#endif
NzVertexDeclarationImpl* impl = new NzVertexDeclarationImpl;
std::memset(&impl->elementPos, -1, (nzElementStream_Max+1)*(nzElementUsage_Max+1)*sizeof(int));
std::memset(&impl->streamPos, -1, (nzElementStream_Max+1)*sizeof(int));
// On copie et trie les éléments
impl->elements.resize(elementCount);
std::memcpy(&impl->elements[0], elements, elementCount*sizeof(NzVertexElement));
std::sort(impl->elements.begin(), impl->elements.end(), VertexElementCompare);
for (unsigned int i = 0; i < elementCount; ++i)
{
NzVertexElement& current = impl->elements[i];
#if NAZARA_UTILITY_SAFE
// Notre tableau étant trié, s'il y a collision, les deux éléments identiques se suivent...
if (i > 0)
{
NzVertexElement& previous = impl->elements[i-1]; // On accède à l'élément précédent
if (previous.usage == current.usage && previous.usageIndex == current.usageIndex && previous.stream == current.stream)
{
// Les deux éléments sont identiques là où ils ne devraient pas, nous avons une collision...
NazaraError("Element usage 0x" + NzString::Number(current.usage, 16) + " collision with usage index " + NzString::Number(current.usageIndex) + " on stream 0x" + NzString::Number(current.stream, 16));
delete impl;
return false;
}
}
#endif
if (current.usageIndex == 0)
impl->elementPos[current.stream][current.usage] = i;
if (impl->streamPos[current.stream] == -1)
impl->streamPos[current.stream] = i; // Premier élément du stream (via le triage)
impl->stride[current.stream] += size[current.type];
}
#if NAZARA_RENDERER_FORCE_DECLARATION_STRIDE_MULTIPLE_OF_32
for (unsigned int& stride : impl->stride)
stride = ((static_cast<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)
{
Destroy();
m_sharedImpl = declaration.m_sharedImpl;
declaration.m_sharedImpl = nullptr;
return *this;
}

View File

@@ -0,0 +1,52 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Win32/CursorImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Utility/Image.hpp>
#include <Nazara/Utility/Debug.hpp>
bool NzCursorImpl::Create(const NzImage& cursor, int hotSpotX, int hotSpotY)
{
NzImage windowsCursor(cursor);
if (!windowsCursor.Convert(nzPixelFormat_BGRA8))
{
NazaraError("Failed to convert cursor to BGRA8");
return false;
}
HBITMAP bitmap = CreateBitmap(windowsCursor.GetWidth(), windowsCursor.GetHeight(), 1, 32, windowsCursor.GetConstPixels());
HBITMAP monoBitmap = CreateBitmap(windowsCursor.GetWidth(), windowsCursor.GetHeight(), 1, 1, nullptr);
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms648052(v=vs.85).aspx
ICONINFO iconInfo;
iconInfo.fIcon = FALSE;
iconInfo.xHotspot = hotSpotX;
iconInfo.yHotspot = hotSpotY;
iconInfo.hbmMask = monoBitmap;
iconInfo.hbmColor = bitmap;
m_cursor = CreateIconIndirect(&iconInfo);
DeleteObject(bitmap);
DeleteObject(monoBitmap);
if (!m_cursor)
{
NazaraError("Failed to create cursor: " + NzGetLastSystemError());
return false;
}
return true;
}
void NzCursorImpl::Destroy()
{
DestroyIcon(m_cursor);
}
HCURSOR NzCursorImpl::GetCursor()
{
return m_cursor;
}

View File

@@ -0,0 +1,26 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_CURSORIMPL_HPP
#define NAZARA_CURSORIMPL_HPP
#include <windows.h>
class NzImage;
class NzCursorImpl
{
public:
bool Create(const NzImage& image, int hotSpotX, int hotSpotY);
void Destroy();
HCURSOR GetCursor();
private:
HICON m_cursor = nullptr;
};
#endif // NAZARA_CURSORIMPL_HPP

View File

@@ -0,0 +1,49 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Win32/IconImpl.hpp>
#include <Nazara/Utility/Image.hpp>
#include <Nazara/Utility/Debug.hpp>
bool NzIconImpl::Create(const NzImage& icon)
{
NzImage windowsIcon(icon);
if (!windowsIcon.Convert(nzPixelFormat_BGRA8))
{
NazaraError("Failed to convert icon to BGRA8");
return false;
}
HBITMAP bitmap = CreateBitmap(windowsIcon.GetWidth(), windowsIcon.GetHeight(), 1, 32, windowsIcon.GetConstPixels());
HBITMAP monoBitmap = CreateBitmap(windowsIcon.GetWidth(), windowsIcon.GetHeight(), 1, 1, nullptr);
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms648052(v=vs.85).aspx
ICONINFO iconInfo;
iconInfo.fIcon = TRUE;
iconInfo.hbmMask = monoBitmap;
iconInfo.hbmColor = bitmap;
m_icon = CreateIconIndirect(&iconInfo);
DeleteObject(bitmap);
DeleteObject(monoBitmap);
if (!m_icon)
{
NazaraError("Failed to create icon: " + NzGetLastSystemError());
return false;
}
return true;
}
void NzIconImpl::Destroy()
{
DestroyIcon(m_icon);
}
HICON NzIconImpl::GetIcon()
{
return m_icon;
}

View File

@@ -0,0 +1,26 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_ICONIMPL_HPP
#define NAZARA_ICONIMPL_HPP
#include <windows.h>
class NzImage;
class NzIconImpl
{
public:
bool Create(const NzImage& image);
void Destroy();
HICON GetIcon();
private:
HICON m_icon = nullptr;
};
#endif // NAZARA_ICONIMPL_HPP

View File

@@ -12,13 +12,18 @@
#include <Nazara/Core/Thread.hpp>
#include <Nazara/Core/ThreadCondition.hpp>
#include <Nazara/Utility/Config.hpp>
#include <Nazara/Utility/Cursor.hpp>
#include <Nazara/Utility/Image.hpp>
#include <Nazara/Utility/Icon.hpp>
#include <Nazara/Utility/Win32/CursorImpl.hpp>
#include <Nazara/Utility/Win32/IconImpl.hpp>
#include <cstdio>
#include <windowsx.h>
#include <Nazara/Utility/Debug.hpp>
#ifdef _WIN64
#define GWL_USERDATA GWLP_USERDATA
#define GCL_HCURSOR GCLP_HCURSOR
#define GWL_USERDATA GWLP_USERDATA
#endif
// N'est pas définit avec MinGW apparemment
@@ -72,7 +77,7 @@ void NzWindowImpl::Close()
bool NzWindowImpl::Create(NzVideoMode mode, const NzString& title, nzUInt32 style)
{
bool fullscreen = (style & NzWindow::Fullscreen) != 0;
bool fullscreen = (style & nzWindowStyle_Fullscreen) != 0;
DWORD win32Style, win32StyleEx;
unsigned int x, y;
unsigned int width = mode.width;
@@ -109,13 +114,13 @@ bool NzWindowImpl::Create(NzVideoMode mode, const NzString& title, nzUInt32 styl
else
{
win32Style = WS_VISIBLE;
if (style & NzWindow::Titlebar)
if (style & nzWindowStyle_Titlebar)
{
win32Style |= WS_CAPTION | WS_MINIMIZEBOX;
if (style & NzWindow::Closable)
if (style & nzWindowStyle_Closable)
win32Style |= WS_SYSMENU;
if (style & NzWindow::Resizable)
if (style & nzWindowStyle_Resizable)
win32Style |= WS_MAXIMIZEBOX | WS_SIZEBOX;
}
else
@@ -272,6 +277,80 @@ bool NzWindowImpl::IsVisible() const
return IsWindowVisible(m_handle);
}
void NzWindowImpl::SetCursor(nzWindowCursor cursor)
{
switch (cursor)
{
case nzWindowCursor_Crosshair:
m_cursor = reinterpret_cast<HCURSOR>(LoadImage(nullptr, IDC_CROSS, IMAGE_CURSOR, 0, 0, LR_SHARED));
break;
case nzWindowCursor_Default:
m_cursor = reinterpret_cast<HCURSOR>(LoadImage(nullptr, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED));
break;
case nzWindowCursor_Hand:
case nzWindowCursor_Pointer:
m_cursor = reinterpret_cast<HCURSOR>(LoadImage(nullptr, IDC_HAND, IMAGE_CURSOR, 0, 0, LR_SHARED));
break;
case nzWindowCursor_Help:
m_cursor = reinterpret_cast<HCURSOR>(LoadImage(nullptr, IDC_HELP, IMAGE_CURSOR, 0, 0, LR_SHARED));
break;
case nzWindowCursor_Move:
m_cursor = reinterpret_cast<HCURSOR>(LoadImage(nullptr, IDC_SIZEALL, IMAGE_CURSOR, 0, 0, LR_SHARED));
break;
case nzWindowCursor_None:
m_cursor = nullptr;
break;
case nzWindowCursor_Progress:
m_cursor = reinterpret_cast<HCURSOR>(LoadImage(nullptr, IDC_APPSTARTING, IMAGE_CURSOR, 0, 0, LR_SHARED));
break;
case nzWindowCursor_ResizeN:
case nzWindowCursor_ResizeS:
m_cursor = reinterpret_cast<HCURSOR>(LoadImage(nullptr, IDC_SIZENS, IMAGE_CURSOR, 0, 0, LR_SHARED));
break;
case nzWindowCursor_ResizeNW:
case nzWindowCursor_ResizeSE:
m_cursor = reinterpret_cast<HCURSOR>(LoadImage(nullptr, IDC_SIZENESW, IMAGE_CURSOR, 0, 0, LR_SHARED));
break;
case nzWindowCursor_ResizeNE:
case nzWindowCursor_ResizeSW:
m_cursor = reinterpret_cast<HCURSOR>(LoadImage(nullptr, IDC_SIZENWSE, IMAGE_CURSOR, 0, 0, LR_SHARED));
break;
case nzWindowCursor_ResizeE:
case nzWindowCursor_ResizeW:
m_cursor = reinterpret_cast<HCURSOR>(LoadImage(nullptr, IDC_SIZEWE, IMAGE_CURSOR, 0, 0, LR_SHARED));
break;
case nzWindowCursor_Text:
m_cursor = reinterpret_cast<HCURSOR>(LoadImage(nullptr, IDC_IBEAM, IMAGE_CURSOR, 0, 0, LR_SHARED));
break;
case nzWindowCursor_Wait:
m_cursor = reinterpret_cast<HCURSOR>(LoadImage(nullptr, IDC_WAIT, IMAGE_CURSOR, 0, 0, LR_SHARED));
break;
}
// Pas besoin de libérer le curseur par la suite s'il est partagé
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms648045(v=vs.85).aspx
::SetCursor(m_cursor);
}
void NzWindowImpl::SetCursor(const NzCursor& cursor)
{
m_cursor = cursor.m_impl->GetCursor();
::SetCursor(m_cursor);
}
void NzWindowImpl::SetEventListener(bool listener)
{
if (m_ownsWindow)
@@ -297,6 +376,14 @@ void NzWindowImpl::SetFocus()
SetForegroundWindow(m_handle);
}
void NzWindowImpl::SetIcon(const NzIcon& icon)
{
HICON iconHandle = icon.m_impl->GetIcon();
SendMessage(m_handle, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(iconHandle));
SendMessage(m_handle, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(iconHandle));
}
void NzWindowImpl::SetMaximumSize(int width, int height)
{
RECT rect = {0, 0, width, height};
@@ -355,19 +442,6 @@ void NzWindowImpl::SetVisible(bool visible)
ShowWindow(m_handle, (visible) ? SW_SHOW : SW_HIDE);
}
void NzWindowImpl::ShowMouseCursor(bool show)
{
// Pas besoin de libérer le curseur par la suite s'il est partagé
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms648045(v=vs.85).aspx
if (show)
m_cursor = reinterpret_cast<HCURSOR>(LoadImage(nullptr, MAKEINTRESOURCE(OCR_NORMAL), IMAGE_CURSOR, 0, 0, LR_SHARED));
else
m_cursor = nullptr;
SetCursor(m_cursor);
}
void NzWindowImpl::StayOnTop(bool stayOnTop)
{
SetWindowPos(m_handle, (stayOnTop) ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
@@ -390,7 +464,7 @@ bool NzWindowImpl::HandleMessage(HWND window, UINT message, WPARAM wParam, LPARA
case WM_SETCURSOR:
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms648382(v=vs.85).aspx
if (LOWORD(lParam) == HTCLIENT)
SetCursor(m_cursor);
::SetCursor(m_cursor);
break;

View File

@@ -56,8 +56,11 @@ class NzWindowImpl : NzNonCopyable
bool IsMinimized() const;
bool IsVisible() const;
void SetCursor(nzWindowCursor cursor);
void SetCursor(const NzCursor& cursor);
void SetEventListener(bool listener);
void SetFocus();
void SetIcon(const NzIcon& icon);
void SetMaximumSize(int width, int height);
void SetMinimumSize(int width, int height);
void SetPosition(int x, int y);
@@ -65,7 +68,6 @@ class NzWindowImpl : NzNonCopyable
void SetTitle(const NzString& title);
void SetVisible(bool visible);
void ShowMouseCursor(bool show);
void StayOnTop(bool stayOnTop);
static bool Initialize();

View File

@@ -5,11 +5,18 @@
#include <Nazara/Utility/Window.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/LockGuard.hpp>
#include <Nazara/Utility/Cursor.hpp>
#include <Nazara/Utility/Image.hpp>
#include <Nazara/Utility/Icon.hpp>
#include <stdexcept>
#if defined(NAZARA_PLATFORM_WINDOWS)
#include <Nazara/Utility/Win32/CursorImpl.hpp>
#include <Nazara/Utility/Win32/IconImpl.hpp>
#include <Nazara/Utility/Win32/WindowImpl.hpp>
#elif defined(NAZARA_PLATFORM_LINUX)
#include <Nazara/Utility/Linux/CursorImpl.hpp>
#include <Nazara/Utility/Linux/IconImpl.hpp>
#include <Nazara/Utility/Linux/WindowImpl.hpp>
#else
#error Lack of implementation: Window
@@ -103,12 +110,12 @@ bool NzWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style)
Close();
// Inspiré du code de la SFML par Laurent Gomila
if (style & Fullscreen)
if (style & nzWindowStyle_Fullscreen)
{
if (fullscreenWindow)
{
NazaraError("Window (" + NzString::Pointer(fullscreenWindow) + ") already in fullscreen mode");
style &= ~Fullscreen;
style &= ~nzWindowStyle_Fullscreen;
}
else
{
@@ -121,8 +128,8 @@ bool NzWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style)
fullscreenWindow = this;
}
}
else if (style & Closable || style & Resizable)
style |= Titlebar;
else if (style & nzWindowStyle_Closable || style & nzWindowStyle_Resizable)
style |= nzWindowStyle_Titlebar;
m_impl = new NzWindowImpl(this);
if (!m_impl->Create(mode, title, style))
@@ -147,10 +154,10 @@ bool NzWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style)
m_impl->EnableKeyRepeat(true);
m_impl->EnableSmoothScrolling(false);
m_impl->SetCursor(nzWindowCursor_Default);
m_impl->SetMaximumSize(-1, -1);
m_impl->SetMinimumSize(-1, -1);
m_impl->SetVisible(true);
m_impl->ShowMouseCursor(true);
if (opened)
m_impl->SetPosition(position.x, position.y);
@@ -299,6 +306,26 @@ bool NzWindow::PollEvent(NzEvent* event)
return false;
}
void NzWindow::SetCursor(nzWindowCursor cursor)
{
if (m_impl)
m_impl->SetCursor(cursor);
}
void NzWindow::SetCursor(const NzCursor& cursor)
{
#if NAZARA_UTILITY_SAFE
if (!cursor.IsValid())
{
NazaraError("Cursor is not valid");
return;
}
#endif
if (m_impl)
m_impl->SetCursor(cursor);
}
void NzWindow::SetEventListener(bool listener)
{
if (!m_impl)
@@ -331,6 +358,20 @@ void NzWindow::SetFocus()
m_impl->SetFocus();
}
void NzWindow::SetIcon(const NzIcon& icon)
{
#if NAZARA_UTILITY_SAFE
if (!icon.IsValid())
{
NazaraError("Icon is not valid");
return;
}
#endif
if (m_impl)
m_impl->SetIcon(icon);
}
void NzWindow::SetMaximumSize(const NzVector2i& maxSize)
{
if (m_impl)
@@ -391,12 +432,6 @@ void NzWindow::SetVisible(bool visible)
m_impl->SetVisible(visible);
}
void NzWindow::ShowMouseCursor(bool show)
{
if (m_impl)
m_impl->ShowMouseCursor(show);
}
void NzWindow::StayOnTop(bool stayOnTop)
{
if (m_impl)