diff --git a/include/Nazara/Graphics/Sprite.hpp b/include/Nazara/Graphics/Sprite.hpp index 502254e36..babb30546 100644 --- a/include/Nazara/Graphics/Sprite.hpp +++ b/include/Nazara/Graphics/Sprite.hpp @@ -8,56 +8,60 @@ #define NAZARA_SPRITE_HPP #include +#include #include #include #include #include -class NAZARA_GRAPHICS_API NzSprite : public NzSceneNode +class NzSprite; + +using NzSpriteConstRef = NzObjectRef; +using NzSpriteLibrary = NzObjectLibrary; +using NzSpriteRef = NzObjectRef; + +class NAZARA_GRAPHICS_API NzSprite : public NzInstancedRenderable { public: - NzSprite(); - NzSprite(NzTexture* texture); - NzSprite(const NzSprite& sprite); + inline NzSprite(); + inline NzSprite(NzMaterialRef material); + inline NzSprite(NzTexture* texture); + inline NzSprite(const NzSprite& sprite); ~NzSprite() = default; - void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override; + void AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const InstanceData& instanceData) const override; - NzSprite* Clone() const; - NzSprite* Create() const; + inline const NzColor& GetColor() const; + inline const NzMaterialRef& GetMaterial() const; + inline const NzVector2f& GetSize() const; + inline const NzRectf& GetTextureCoords() const; - const NzColor& GetColor() const; - NzMaterial* GetMaterial() const; - nzSceneNodeType GetSceneNodeType() const override; - const NzVector2f& GetSize() const; - const NzRectf& GetTextureCoords() const; + inline void SetColor(const NzColor& color); + inline void SetDefaultMaterial(); + inline void SetMaterial(NzMaterialRef material, bool resizeSprite = true); + inline void SetSize(const NzVector2f& size); + inline void SetSize(float sizeX, float sizeY); + inline void SetTexture(NzTextureRef texture, bool resizeSprite = true); + inline void SetTextureCoords(const NzRectf& coords); + inline void SetTextureRect(const NzRectui& rect); - bool IsDrawable() const; + inline NzSprite& operator=(const NzSprite& sprite); - void SetColor(const NzColor& color); - void SetDefaultMaterial(); - void SetMaterial(NzMaterial* material, bool resizeSprite = true); - void SetSize(const NzVector2f& size); - void SetSize(float sizeX, float sizeY); - void SetTexture(NzTexture* texture, bool resizeSprite = true); - void SetTextureCoords(const NzRectf& coords); - void SetTextureRect(const NzRectui& rect); - - NzSprite& operator=(const NzSprite& sprite); + template static NzSpriteRef New(Args&&... args); private: - void InvalidateNode() override; + inline void InvalidateVertices(); void MakeBoundingVolume() const override; - void Register() override; - void Unregister() override; - void UpdateVertices() const; + void UpdateData(InstanceData* instanceData) const override; NzColor m_color; NzMaterialRef m_material; NzRectf m_textureCoords; NzVector2f m_size; - mutable std::array m_vertices; - mutable bool m_verticesUpdated; + + static NzSpriteLibrary::LibraryMap s_library; }; +#include + #endif // NAZARA_SPRITE_HPP diff --git a/include/Nazara/Graphics/Sprite.inl b/include/Nazara/Graphics/Sprite.inl new file mode 100644 index 000000000..7b7cb5b24 --- /dev/null +++ b/include/Nazara/Graphics/Sprite.inl @@ -0,0 +1,165 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +inline NzSprite::NzSprite() : +m_color(NzColor::White), +m_textureCoords(0.f, 0.f, 1.f, 1.f), +m_size(64.f, 64.f) +{ + SetDefaultMaterial(); +} + +inline NzSprite::NzSprite(NzMaterialRef material) : +m_color(NzColor::White), +m_textureCoords(0.f, 0.f, 1.f, 1.f), +m_size(64.f, 64.f) +{ + SetMaterial(std::move(material), true); +} + +inline NzSprite::NzSprite(NzTexture* texture) : +m_color(NzColor::White), +m_textureCoords(0.f, 0.f, 1.f, 1.f), +m_size(64.f, 64.f) +{ + SetTexture(texture, true); +} + +inline NzSprite::NzSprite(const NzSprite& sprite) : +NzInstancedRenderable(sprite), +m_color(sprite.m_color), +m_material(sprite.m_material), +m_textureCoords(sprite.m_textureCoords), +m_size(sprite.m_size) +{ +} + +inline const NzColor& NzSprite::GetColor() const +{ + return m_color; +} + +inline const NzMaterialRef& NzSprite::GetMaterial() const +{ + return m_material; +} + +inline const NzVector2f& NzSprite::GetSize() const +{ + return m_size; +} + +inline const NzRectf& NzSprite::GetTextureCoords() const +{ + return m_textureCoords; +} + +inline void NzSprite::SetColor(const NzColor& color) +{ + m_color = color; + + InvalidateVertices(); +} + +inline void NzSprite::SetDefaultMaterial() +{ + NzMaterialRef material = NzMaterial::New(); + material->Enable(nzRendererParameter_FaceCulling, false); + material->EnableLighting(false); + + SetMaterial(material); +} + +inline void NzSprite::SetMaterial(NzMaterialRef material, bool resizeSprite) +{ + m_material = std::move(material); + if (m_material && resizeSprite) + { + NzTexture* diffuseMap = m_material->GetDiffuseMap(); + if (diffuseMap && diffuseMap->IsValid()) + SetSize(NzVector2f(NzVector2ui(diffuseMap->GetSize()))); + } +} + +inline void NzSprite::SetSize(const NzVector2f& size) +{ + m_size = size; + + // On invalide la bounding box + InvalidateBoundingVolume(); + InvalidateVertices(); +} + +inline void NzSprite::SetSize(float sizeX, float sizeY) +{ + SetSize(NzVector2f(sizeX, sizeY)); +} + +inline void NzSprite::SetTexture(NzTextureRef texture, bool resizeSprite) +{ + if (!m_material) + SetDefaultMaterial(); + else if (m_material->GetReferenceCount() > 1) + m_material = NzMaterial::New(*m_material); // Copie + + if (resizeSprite && texture && texture->IsValid()) + SetSize(NzVector2f(NzVector2ui(texture->GetSize()))); + + m_material->SetDiffuseMap(std::move(texture)); +} + +inline void NzSprite::SetTextureCoords(const NzRectf& coords) +{ + m_textureCoords = coords; + InvalidateVertices(); +} + +inline void NzSprite::SetTextureRect(const NzRectui& rect) +{ + NazaraAssert(material, "Sprite has no material"); + NazaraAssert(m_material->HasDiffuseMap(), "Sprite material has no diffuse map"); + + NzTexture* diffuseMap = m_material->GetDiffuseMap(); + + float invWidth = 1.f/diffuseMap->GetWidth(); + float invHeight = 1.f/diffuseMap->GetHeight(); + + SetTextureCoords(NzRectf(invWidth*rect.x, invHeight*rect.y, invWidth*rect.width, invHeight*rect.height)); +} + +inline NzSprite& NzSprite::operator=(const NzSprite& sprite) +{ + NzInstancedRenderable::operator=(sprite); + + m_color = sprite.m_color; + m_material = sprite.m_material; + m_textureCoords = sprite.m_textureCoords; + m_size = sprite.m_size; + + // On ne copie pas les sommets finaux car il est très probable que nos paramètres soient modifiés et qu'ils doivent être régénérés de toute façon + InvalidateBoundingVolume(); + InvalidateVertices(); + + return *this; +} + +inline void NzSprite::InvalidateVertices() +{ + InvalidateInstanceData(0); +} + +template +NzSpriteRef NzSprite::New(Args&&... args) +{ + std::unique_ptr object(new NzSprite(std::forward(args)...)); + object->SetPersistent(false); + + return object.release(); +} + +#include diff --git a/src/Nazara/Graphics/Sprite.cpp b/src/Nazara/Graphics/Sprite.cpp index a4cf6eed3..7ad9b797f 100644 --- a/src/Nazara/Graphics/Sprite.cpp +++ b/src/Nazara/Graphics/Sprite.cpp @@ -10,230 +10,42 @@ #include #include -NzSprite::NzSprite() : -m_color(NzColor::White), -m_textureCoords(0.f, 0.f, 1.f, 1.f), -m_size(64.f, 64.f), -m_verticesUpdated(false) -{ - SetDefaultMaterial(); -} - -NzSprite::NzSprite(NzTexture* texture) : -m_color(NzColor::White), -m_textureCoords(0.f, 0.f, 1.f, 1.f), -m_size(64.f, 64.f), -m_verticesUpdated(false) -{ - SetTexture(texture, true); -} - -NzSprite::NzSprite(const NzSprite& sprite) : -NzSceneNode(sprite), -m_color(sprite.m_color), -m_material(sprite.m_material), -m_textureCoords(sprite.m_textureCoords), -m_size(sprite.m_size), -m_vertices(sprite.m_vertices), -m_verticesUpdated(sprite.m_verticesUpdated) -{ - SetParent(sprite.GetParent()); -} - -void NzSprite::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const -{ - if (!m_verticesUpdated) - UpdateVertices(); - - renderQueue->AddSprites(m_material, m_vertices.data(), 1); -} - -NzSprite* NzSprite::Clone() const -{ - return new NzSprite(*this); -} - -NzSprite* NzSprite::Create() const -{ - return new NzSprite; -} - -const NzColor& NzSprite::GetColor() const -{ - return m_color; -} - -NzMaterial* NzSprite::GetMaterial() const -{ - return m_material; -} - -nzSceneNodeType NzSprite::GetSceneNodeType() const -{ - return nzSceneNodeType_Sprite; -} - -const NzVector2f& NzSprite::GetSize() const -{ - return m_size; -} - -const NzRectf& NzSprite::GetTextureCoords() const -{ - return m_textureCoords; -} - -bool NzSprite::IsDrawable() const -{ - return m_material != nullptr; -} - -void NzSprite::SetColor(const NzColor& color) -{ - m_color = color; - m_verticesUpdated = false; -} - -void NzSprite::SetDefaultMaterial() -{ - NzMaterialRef material = NzMaterial::New(); - material->Enable(nzRendererParameter_FaceCulling, false); - material->EnableLighting(false); - - SetMaterial(material); -} - -void NzSprite::SetMaterial(NzMaterial* material, bool resizeSprite) -{ - m_material = material; - if (m_material && resizeSprite) - { - NzTexture* diffuseMap = m_material->GetDiffuseMap(); - if (diffuseMap && diffuseMap->IsValid()) - SetSize(NzVector2f(NzVector2ui(diffuseMap->GetSize()))); - } -} - -void NzSprite::SetSize(const NzVector2f& size) -{ - m_size = size; - - // On invalide la bounding box - m_boundingVolume.MakeNull(); - m_boundingVolumeUpdated = false; - m_verticesUpdated = false; -} - -void NzSprite::SetSize(float sizeX, float sizeY) -{ - SetSize(NzVector2f(sizeX, sizeY)); -} - -void NzSprite::SetTexture(NzTexture* texture, bool resizeSprite) +void NzSprite::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const InstanceData& instanceData) const { if (!m_material) - SetDefaultMaterial(); - else if (m_material->GetReferenceCount() > 1) - m_material = NzMaterial::New(*m_material); // Copie - - m_material->SetDiffuseMap(texture); - if (resizeSprite && texture && texture->IsValid()) - SetSize(NzVector2f(NzVector2ui(texture->GetSize()))); -} - -void NzSprite::SetTextureCoords(const NzRectf& coords) -{ - m_textureCoords = coords; - m_verticesUpdated = false; -} - -void NzSprite::SetTextureRect(const NzRectui& rect) -{ - #if NAZARA_GRAPHICS_SAFE - if (!m_material) - { - NazaraError("Sprite has no material"); return; - } - if (!m_material->HasDiffuseMap()) - { - NazaraError("Sprite material has no diffuse map"); - return; - } - #endif - - NzTexture* diffuseMap = m_material->GetDiffuseMap(); - - float invWidth = 1.f/diffuseMap->GetWidth(); - float invHeight = 1.f/diffuseMap->GetHeight(); - - SetTextureCoords(NzRectf(invWidth*rect.x, invHeight*rect.y, invWidth*rect.width, invHeight*rect.height)); -} - -NzSprite& NzSprite::operator=(const NzSprite& sprite) -{ - NzSceneNode::operator=(sprite); - - m_color = sprite.m_color; - m_material = sprite.m_material; - m_textureCoords = sprite.m_textureCoords; - m_size = sprite.m_size; - - // On ne copie pas les sommets finaux car il est très probable que nos paramètres soient modifiés et qu'ils doivent être régénérés de toute façon - m_verticesUpdated = false; - - return *this; -} - -void NzSprite::InvalidateNode() -{ - NzSceneNode::InvalidateNode(); - - m_verticesUpdated = false; -} - -void NzSprite::Register() -{ - // Le changement de scène peut affecter les sommets - m_verticesUpdated = false; -} - -void NzSprite::Unregister() -{ + const NzVertexStruct_XYZ_Color_UV* vertices = reinterpret_cast(instanceData.data.data()); + renderQueue->AddSprites(m_material, vertices, 1); } void NzSprite::MakeBoundingVolume() const { - NzVector3f down = (m_scene) ? m_scene->GetDown() : NzVector3f::Down(); - NzVector3f right = (m_scene) ? m_scene->GetRight() : NzVector3f::Right(); - - m_boundingVolume.Set(NzVector3f(0.f), m_size.x*right + m_size.y*down); + m_boundingVolume.Set(NzVector3f(0.f), m_size.x*NzVector3f::Right() + m_size.y*NzVector3f::Down()); } -void NzSprite::UpdateVertices() const +void NzSprite::UpdateData(InstanceData* instanceData) const { - if (!m_transformMatrixUpdated) - UpdateTransformMatrix(); + instanceData->data.resize(4 * sizeof(NzVertexStruct_XYZ_Color_UV)); + NzVertexStruct_XYZ_Color_UV* vertices = reinterpret_cast(instanceData->data.data()); - NzVector3f down = (m_scene) ? m_scene->GetDown() : NzVector3f::Down(); - NzVector3f right = (m_scene) ? m_scene->GetRight() : NzVector3f::Right(); + NzSparsePtr colorPtr(&vertices[0].color, sizeof(NzVertexStruct_XYZ_Color_UV)); + NzSparsePtr posPtr(&vertices[0].position, sizeof(NzVertexStruct_XYZ_Color_UV)); + NzSparsePtr texCoordPtr(&vertices[0].uv, sizeof(NzVertexStruct_XYZ_Color_UV)); - m_vertices[0].color = m_color; - m_vertices[0].position = m_transformMatrix.Transform(NzVector3f(0.f)); - m_vertices[0].uv.Set(m_textureCoords.GetCorner(nzRectCorner_LeftTop)); + *colorPtr++ = m_color; + *posPtr++ = instanceData->transformMatrix.Transform(NzVector3f(0.f)); + *texCoordPtr++ = m_textureCoords.GetCorner(nzRectCorner_LeftTop); - m_vertices[1].color = m_color; - m_vertices[1].position = m_transformMatrix.Transform(m_size.x*right); - m_vertices[1].uv.Set(m_textureCoords.GetCorner(nzRectCorner_RightTop)); + *colorPtr++ = m_color; + *posPtr++ = instanceData->transformMatrix.Transform(m_size.x*NzVector3f::Right()); + *texCoordPtr++ = m_textureCoords.GetCorner(nzRectCorner_RightTop); - m_vertices[2].color = m_color; - m_vertices[2].position = m_transformMatrix.Transform(m_size.y*down); - m_vertices[2].uv.Set(m_textureCoords.GetCorner(nzRectCorner_LeftBottom)); + *colorPtr++ = m_color; + *posPtr++ = instanceData->transformMatrix.Transform(m_size.y*NzVector3f::Down()); + *texCoordPtr++ = m_textureCoords.GetCorner(nzRectCorner_LeftBottom); - m_vertices[3].color = m_color; - m_vertices[3].position = m_transformMatrix.Transform(m_size.x*right + m_size.y*down); - m_vertices[3].uv.Set(m_textureCoords.GetCorner(nzRectCorner_RightBottom)); - - m_verticesUpdated = true; + *colorPtr++ = m_color; + *posPtr++ = instanceData->transformMatrix.Transform(m_size.x*NzVector3f::Right() + m_size.y*NzVector3f::Down()); + *texCoordPtr++ = m_textureCoords.GetCorner(nzRectCorner_RightBottom); }