Graphics: Add support of skins to InstancedRenderable + big clean up

This commit is contained in:
Lynix 2017-01-09 01:52:00 +01:00
parent d2ee4744a9
commit 6b949afb9b
21 changed files with 579 additions and 504 deletions

View File

@ -32,6 +32,40 @@ namespace Ndk
/*********************************** Nz::InstancedRenderable ***********************************/ /*********************************** Nz::InstancedRenderable ***********************************/
instancedRenderable.Reset("InstancedRenderable"); instancedRenderable.Reset("InstancedRenderable");
{ {
instancedRenderable.BindMethod("GetMaterial", [] (Nz::LuaInstance& lua, Nz::InstancedRenderable* instance, std::size_t argumentCount) -> int
{
std::size_t argCount = std::min<std::size_t>(argumentCount, 2U);
switch (argCount)
{
case 0:
case 1:
{
int argIndex = 2;
std::size_t matIndex(lua.Check<std::size_t>(&argIndex, 0));
return lua.Push(instance->GetMaterial(matIndex));
}
case 2:
{
int argIndex = 2;
std::size_t skinIndex(lua.Check<std::size_t>(&argIndex));
std::size_t matIndex(lua.Check<std::size_t>(&argIndex));
return lua.Push(instance->GetMaterial(skinIndex, matIndex));
}
}
lua.Error("No matching overload for method GetMaterial");
return 0;
});
instancedRenderable.BindMethod("GetMaterialCount", &Nz::InstancedRenderable::GetMaterialCount);
instancedRenderable.BindMethod("GetSkin", &Nz::InstancedRenderable::GetSkin);
instancedRenderable.BindMethod("GetSkinCount", &Nz::InstancedRenderable::GetSkinCount);
instancedRenderable.BindMethod("SetSkin", &Nz::InstancedRenderable::SetSkin);
instancedRenderable.BindMethod("SetSkinCount", &Nz::InstancedRenderable::SetSkinCount);
} }
/*********************************** Nz::Material ***********************************/ /*********************************** Nz::Material ***********************************/
@ -269,22 +303,72 @@ namespace Ndk
return true; return true;
}); });
//model.BindMethod("GetMaterial", &Nz::Model::GetMaterial);
model.BindMethod("GetMaterialCount", &Nz::Model::GetMaterialCount);
//modelClass.SetMethod("GetMesh", &Nz::Model::GetMesh); //modelClass.SetMethod("GetMesh", &Nz::Model::GetMesh);
model.BindMethod("GetSkin", &Nz::Model::GetSkin);
model.BindMethod("GetSkinCount", &Nz::Model::GetSkinCount);
model.BindMethod("IsAnimated", &Nz::Model::IsAnimated); model.BindMethod("IsAnimated", &Nz::Model::IsAnimated);
model.BindMethod("LoadFromFile", &Nz::Model::LoadFromFile, Nz::ModelParameters()); model.BindMethod("LoadFromFile", &Nz::Model::LoadFromFile, Nz::ModelParameters());
model.BindMethod("Reset", &Nz::Model::Reset);
//model.BindMethod("SetMaterial", &Nz::Model::SetMaterial); model.BindMethod("SetMaterial", [] (Nz::LuaInstance& lua, Nz::Model* instance, std::size_t argumentCount) -> int
{
std::size_t argCount = std::min<std::size_t>(argumentCount, 3U);
switch (argCount)
{
case 2:
{
int argIndex = 2;
if (lua.IsOfType(argIndex, Nz::LuaType_Number))
{
std::size_t matIndex(lua.Check<std::size_t>(&argIndex));
Nz::MaterialRef material(lua.Check<Nz::MaterialRef>(&argIndex));
instance->SetMaterial(matIndex, std::move(material));
return 0;
}
else if (lua.IsOfType(argIndex, Nz::LuaType_String))
{
Nz::String subMesh(lua.Check<Nz::String>(&argIndex));
Nz::MaterialRef material(lua.Check<Nz::MaterialRef>(&argIndex));
instance->SetMaterial(subMesh, std::move(material));
return 0;
}
break;
}
case 3:
{
int argIndex = 2;
if (lua.IsOfType(argIndex, Nz::LuaType_Number))
{
std::size_t skinIndex(lua.Check<std::size_t>(&argIndex));
std::size_t matIndex(lua.Check<std::size_t>(&argIndex));
Nz::MaterialRef material(lua.Check<Nz::MaterialRef>(&argIndex));
instance->SetMaterial(skinIndex, matIndex, std::move(material));
return 0;
}
else if (lua.IsOfType(argIndex, Nz::LuaType_String))
{
std::size_t skinIndex(lua.Check<std::size_t>(&argIndex));
Nz::String subMesh(lua.Check<Nz::String>(&argIndex));
Nz::MaterialRef material(lua.Check<Nz::MaterialRef>(&argIndex));
instance->SetMaterial(skinIndex, subMesh, std::move(material));
return 0;
}
break;
}
}
lua.Error("No matching overload for method SetMaterial");
return 0;
});
//modelClass.SetMethod("SetMesh", &Nz::Model::SetMesh); //modelClass.SetMethod("SetMesh", &Nz::Model::SetMesh);
//modelClass.SetMethod("SetSequence", &Nz::Model::SetSequence); //modelClass.SetMethod("SetSequence", &Nz::Model::SetSequence);
model.BindMethod("SetSkin", &Nz::Model::SetSkin);
model.BindMethod("SetSkinCount", &Nz::Model::SetSkinCount);
} }
/*********************************** Nz::Sprite ***********************************/ /*********************************** Nz::Sprite ***********************************/
@ -303,7 +387,6 @@ namespace Ndk
sprite.BindMethod("GetColor", &Nz::Sprite::GetColor); sprite.BindMethod("GetColor", &Nz::Sprite::GetColor);
sprite.BindMethod("GetCornerColor", &Nz::Sprite::GetCornerColor); sprite.BindMethod("GetCornerColor", &Nz::Sprite::GetCornerColor);
sprite.BindMethod("GetMaterial", &Nz::Sprite::GetMaterial);
sprite.BindMethod("GetOrigin", &Nz::Sprite::GetOrigin); sprite.BindMethod("GetOrigin", &Nz::Sprite::GetOrigin);
sprite.BindMethod("GetSize", &Nz::Sprite::GetSize); sprite.BindMethod("GetSize", &Nz::Sprite::GetSize);
sprite.BindMethod("GetTextureCoords", &Nz::Sprite::GetTextureCoords); sprite.BindMethod("GetTextureCoords", &Nz::Sprite::GetTextureCoords);
@ -319,12 +402,28 @@ namespace Ndk
sprite.BindMethod("SetMaterial", [] (Nz::LuaInstance& lua, Nz::SpriteRef& instance, std::size_t /*argumentCount*/) -> int sprite.BindMethod("SetMaterial", [] (Nz::LuaInstance& lua, Nz::SpriteRef& instance, std::size_t /*argumentCount*/) -> int
{ {
int argIndex = 2; int argIndex = 2;
if (lua.IsOfType(argIndex, "Material"))
{
bool resizeSprite = lua.CheckBoolean(argIndex + 1, true);
instance->SetMaterial(*static_cast<Nz::MaterialRef*>(lua.ToUserdata(argIndex)), resizeSprite);
}
else if (lua.IsOfType(argIndex, Nz::LuaType_String))
{
bool resizeSprite = lua.CheckBoolean(argIndex + 1, true);
instance->SetMaterial(lua.ToString(argIndex), resizeSprite);
}
else if (lua.IsOfType(argIndex, Nz::LuaType_Number))
{
std::size_t skinIndex(lua.Check<std::size_t>(&argIndex));
bool resizeSprite = lua.CheckBoolean(argIndex + 1, true); bool resizeSprite = lua.CheckBoolean(argIndex + 1, true);
if (lua.IsOfType(argIndex, "Material")) if (lua.IsOfType(argIndex, "Material"))
instance->SetMaterial(*static_cast<Nz::MaterialRef*>(lua.ToUserdata(argIndex)), resizeSprite); instance->SetMaterial(skinIndex, *static_cast<Nz::MaterialRef*>(lua.ToUserdata(argIndex)), resizeSprite);
else else
instance->SetMaterial(lua.Check<Nz::String>(&argIndex), resizeSprite); instance->SetMaterial(skinIndex, lua.Check<Nz::String>(&argIndex), resizeSprite);
}
return 0; return 0;
}); });
@ -332,12 +431,28 @@ namespace Ndk
sprite.BindMethod("SetTexture", [] (Nz::LuaInstance& lua, Nz::SpriteRef& instance, std::size_t /*argumentCount*/) -> int sprite.BindMethod("SetTexture", [] (Nz::LuaInstance& lua, Nz::SpriteRef& instance, std::size_t /*argumentCount*/) -> int
{ {
int argIndex = 2; int argIndex = 2;
if (lua.IsOfType(argIndex, "Texture"))
{
bool resizeSprite = lua.CheckBoolean(argIndex + 1, true);
instance->SetTexture(*static_cast<Nz::TextureRef*>(lua.ToUserdata(argIndex)), resizeSprite);
}
else if (lua.IsOfType(argIndex, Nz::LuaType_String))
{
bool resizeSprite = lua.CheckBoolean(argIndex + 1, true);
instance->SetTexture(lua.ToString(argIndex), resizeSprite);
}
else if (lua.IsOfType(argIndex, Nz::LuaType_Number))
{
std::size_t skinIndex(lua.Check<std::size_t>(&argIndex));
bool resizeSprite = lua.CheckBoolean(argIndex + 1, true); bool resizeSprite = lua.CheckBoolean(argIndex + 1, true);
if (lua.IsOfType(argIndex, "Texture")) if (lua.IsOfType(argIndex, "Texture"))
instance->SetTexture(*static_cast<Nz::TextureRef*>(lua.ToUserdata(argIndex)), resizeSprite); instance->SetTexture(skinIndex, *static_cast<Nz::TextureRef*>(lua.ToUserdata(argIndex)), resizeSprite);
else else
instance->SetTexture(lua.Check<Nz::String>(&argIndex), resizeSprite); instance->SetTexture(skinIndex, lua.Check<Nz::String>(&argIndex), resizeSprite);
}
return 0; return 0;
}); });

View File

@ -32,17 +32,18 @@ namespace Nz
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const override; void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const override;
inline const Color& GetColor() const; inline const Color& GetColor() const;
inline const MaterialRef& GetMaterial() const;
inline float GetRotation() const; inline float GetRotation() const;
inline const Vector2f& GetSize() const; inline const Vector2f& GetSize() const;
inline void SetColor(const Color& color); inline void SetColor(const Color& color);
inline void SetDefaultMaterial(); inline void SetDefaultMaterial();
inline void SetMaterial(MaterialRef material, bool resizeBillboard = true); inline void SetMaterial(MaterialRef material, bool resizeBillboard = true);
inline void SetMaterial(std::size_t skinIndex, MaterialRef material, bool resizeBillboard = true);
inline void SetRotation(float rotation); inline void SetRotation(float rotation);
inline void SetSize(const Vector2f& size); inline void SetSize(const Vector2f& size);
inline void SetSize(float sizeX, float sizeY); inline void SetSize(float sizeX, float sizeY);
inline void SetTexture(TextureRef texture, bool resizeBillboard = true); inline void SetTexture(TextureRef texture, bool resizeBillboard = true);
inline void SetTexture(std::size_t skinIndex, TextureRef texture, bool resizeBillboard = true);
inline Billboard& operator=(const Billboard& billboard); inline Billboard& operator=(const Billboard& billboard);
Billboard& operator=(Billboard&&) = delete; Billboard& operator=(Billboard&&) = delete;
@ -53,7 +54,6 @@ namespace Nz
void MakeBoundingVolume() const override; void MakeBoundingVolume() const override;
Color m_color; Color m_color;
MaterialRef m_material;
Vector2f m_sinCos; Vector2f m_sinCos;
Vector2f m_size; Vector2f m_size;
float m_rotation; float m_rotation;

View File

@ -2,6 +2,7 @@
// This file is part of the "Nazara Engine - Graphics module" // This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/Billboard.hpp>
#include <memory> #include <memory>
#include <Nazara/Graphics/Debug.hpp> #include <Nazara/Graphics/Debug.hpp>
@ -13,6 +14,8 @@ namespace Nz
inline Billboard::Billboard() inline Billboard::Billboard()
{ {
ResetMaterials(1);
SetColor(Color::White); SetColor(Color::White);
SetDefaultMaterial(); SetDefaultMaterial();
SetRotation(0.f); SetRotation(0.f);
@ -27,6 +30,8 @@ namespace Nz
inline Billboard::Billboard(MaterialRef material) inline Billboard::Billboard(MaterialRef material)
{ {
ResetMaterials(1);
SetColor(Color::White); SetColor(Color::White);
SetMaterial(std::move(material), true); SetMaterial(std::move(material), true);
SetRotation(0.f); SetRotation(0.f);
@ -41,6 +46,8 @@ namespace Nz
inline Billboard::Billboard(Texture* texture) inline Billboard::Billboard(Texture* texture)
{ {
ResetMaterials(1);
SetColor(Color::White); SetColor(Color::White);
SetRotation(0.f); SetRotation(0.f);
SetSize(64.f, 64.f); SetSize(64.f, 64.f);
@ -56,7 +63,6 @@ namespace Nz
inline Billboard::Billboard(const Billboard& billboard) : inline Billboard::Billboard(const Billboard& billboard) :
InstancedRenderable(billboard), InstancedRenderable(billboard),
m_color(billboard.m_color), m_color(billboard.m_color),
m_material(billboard.m_material),
m_sinCos(billboard.m_sinCos), m_sinCos(billboard.m_sinCos),
m_size(billboard.m_size), m_size(billboard.m_size),
m_rotation(billboard.m_rotation) m_rotation(billboard.m_rotation)
@ -73,16 +79,6 @@ namespace Nz
return m_color; return m_color;
} }
/*!
* \brief Gets the material of the billboard
* \return Current material
*/
inline const MaterialRef& Billboard::GetMaterial() const
{
return m_material;
}
/*! /*!
* \brief Gets the rotation of the billboard * \brief Gets the rotation of the billboard
* \return Current rotation * \return Current rotation
@ -132,17 +128,32 @@ namespace Nz
* \param material Material for the billboard * \param material Material for the billboard
* \param resizeBillboard Should billboard be resized to the material size (diffuse map) * \param resizeBillboard Should billboard be resized to the material size (diffuse map)
*/ */
inline void Billboard::SetMaterial(MaterialRef material, bool resizeBillboard) inline void Billboard::SetMaterial(MaterialRef material, bool resizeBillboard)
{ {
m_material = std::move(material); SetMaterial(GetSkin(), std::move(material), resizeBillboard);
if (m_material && resizeBillboard) }
/*!
* \brief Sets the material of the billboard
*
* \param skinIndex Skin index to change
* \param material Material for the billboard
* \param resizeBillboard Should billboard be resized to the material size (diffuse map)
*/
inline void Billboard::SetMaterial(std::size_t skinIndex, MaterialRef material, bool resizeBillboard)
{ {
Texture* diffuseMap = m_material->GetDiffuseMap(); InstancedRenderable::SetMaterial(skinIndex, 0, std::move(material));
if (resizeBillboard)
{
if (const MaterialRef& material = GetMaterial())
{
const TextureRef& diffuseMap = material->GetDiffuseMap();
if (diffuseMap && diffuseMap->IsValid()) if (diffuseMap && diffuseMap->IsValid())
SetSize(Vector2f(Vector2ui(diffuseMap->GetSize()))); SetSize(Vector2f(Vector2ui(diffuseMap->GetSize())));
} }
} }
}
/*! /*!
* \brief Sets the rotation of the billboard * \brief Sets the rotation of the billboard
@ -188,18 +199,36 @@ namespace Nz
* \param texture Texture for the billboard * \param texture Texture for the billboard
* \param resizeBillboard Should billboard be resized to the texture size * \param resizeBillboard Should billboard be resized to the texture size
*/ */
inline void Billboard::SetTexture(TextureRef texture, bool resizeBillboard) inline void Billboard::SetTexture(TextureRef texture, bool resizeBillboard)
{ {
if (!m_material) SetTexture(GetSkin(), std::move(texture), resizeBillboard);
SetDefaultMaterial(); }
else if (m_material->GetReferenceCount() > 1)
m_material = Material::New(*m_material); // Copie
/*!
* \brief Sets the texture of the billboard for a specific index
*
* This function changes the diffuse map of the material associated with the specified skin index
*
* \param skinIndex Skin index to change
* \param texture Texture for the billboard
* \param resizeBillboard Should billboard be resized to the texture size
*/
inline void Billboard::SetTexture(std::size_t skinIndex, TextureRef texture, bool resizeBillboard)
{
if (resizeBillboard && texture && texture->IsValid()) if (resizeBillboard && texture && texture->IsValid())
SetSize(Vector2f(Vector2ui(texture->GetSize()))); SetSize(Vector2f(Vector2ui(texture->GetSize())));
m_material->SetDiffuseMap(std::move(texture)); const MaterialRef& material = GetMaterial(skinIndex);
if (material->GetReferenceCount() > 1)
{
MaterialRef newMat = Material::New(*material); // Copy
newMat->SetDiffuseMap(std::move(texture));
SetMaterial(skinIndex, std::move(newMat));
}
else
material->SetDiffuseMap(std::move(texture));
} }
/*! /*!
@ -214,7 +243,6 @@ namespace Nz
InstancedRenderable::operator=(billboard); InstancedRenderable::operator=(billboard);
m_color = billboard.m_color; m_color = billboard.m_color;
m_material = billboard.m_material;
m_size = billboard.m_size; m_size = billboard.m_size;
InvalidateBoundingVolume(); InvalidateBoundingVolume();

View File

@ -14,6 +14,7 @@
#include <Nazara/Core/Signal.hpp> #include <Nazara/Core/Signal.hpp>
#include <Nazara/Graphics/Config.hpp> #include <Nazara/Graphics/Config.hpp>
#include <Nazara/Graphics/CullingList.hpp> #include <Nazara/Graphics/CullingList.hpp>
#include <Nazara/Graphics/Material.hpp>
#include <Nazara/Math/BoundingVolume.hpp> #include <Nazara/Math/BoundingVolume.hpp>
#include <Nazara/Math/Frustum.hpp> #include <Nazara/Math/Frustum.hpp>
#include <Nazara/Math/Matrix4.hpp> #include <Nazara/Math/Matrix4.hpp>
@ -44,7 +45,18 @@ namespace Nz
inline void EnsureBoundingVolumeUpdated() const; inline void EnsureBoundingVolumeUpdated() const;
virtual const BoundingVolumef& GetBoundingVolume() const; virtual const BoundingVolumef& GetBoundingVolume() const;
inline const MaterialRef& GetMaterial(std::size_t matIndex = 0) const;
inline const MaterialRef& GetMaterial(std::size_t skinIndex, std::size_t matIndex) const;
inline std::size_t GetMaterialCount() const;
inline std::size_t GetSkin() const;
inline std::size_t GetSkinCount() const;
virtual void InvalidateData(InstanceData* instanceData, UInt32 flags) const; virtual void InvalidateData(InstanceData* instanceData, UInt32 flags) const;
inline void SetSkin(std::size_t skinIndex);
inline void SetSkinCount(std::size_t skinCount);
virtual void UpdateBoundingVolume(InstanceData* instanceData) const; virtual void UpdateBoundingVolume(InstanceData* instanceData) const;
virtual void UpdateData(InstanceData* instanceData) const; virtual void UpdateData(InstanceData* instanceData) const;
@ -92,11 +104,20 @@ namespace Nz
virtual void MakeBoundingVolume() const = 0; virtual void MakeBoundingVolume() const = 0;
inline void ResetMaterials(std::size_t matCount, std::size_t skinCount = 1);
inline void SetMaterial(std::size_t matIndex, MaterialRef material);
inline void SetMaterial(std::size_t skinIndex, std::size_t matIndex, MaterialRef material);
mutable BoundingVolumef m_boundingVolume; mutable BoundingVolumef m_boundingVolume;
private: private:
inline void UpdateBoundingVolume() const; inline void UpdateBoundingVolume() const;
std::size_t m_matCount;
std::size_t m_skin;
std::size_t m_skinCount;
std::vector<MaterialRef> m_materials;
mutable bool m_boundingVolumeUpdated; mutable bool m_boundingVolumeUpdated;
static InstancedRenderableLibrary::LibraryMap s_library; static InstancedRenderableLibrary::LibraryMap s_library;

View File

@ -2,6 +2,9 @@
// This file is part of the "Nazara Engine - Graphics module" // This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/InstancedRenderable.hpp>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz namespace Nz
{ {
/*! /*!
@ -20,6 +23,10 @@ namespace Nz
inline InstancedRenderable::InstancedRenderable(const InstancedRenderable& renderable) : inline InstancedRenderable::InstancedRenderable(const InstancedRenderable& renderable) :
RefCounted(), RefCounted(),
m_boundingVolume(renderable.m_boundingVolume), m_boundingVolume(renderable.m_boundingVolume),
m_matCount(renderable.m_matCount),
m_skin(renderable.m_skin),
m_skinCount(renderable.m_skinCount),
m_materials(renderable.m_materials),
m_boundingVolumeUpdated(renderable.m_boundingVolumeUpdated) m_boundingVolumeUpdated(renderable.m_boundingVolumeUpdated)
{ {
} }
@ -34,6 +41,111 @@ namespace Nz
UpdateBoundingVolume(); UpdateBoundingVolume();
} }
/*!
* \brief Gets one of the material used by the object.
* \return A reference to the material.
*
* This function returns the active material at the specified index, depending on the current active skin.
*
* \param matIndex Material index to query
*
* \see GetSkin, GetMaterialCount, SetSkin
*/
inline const MaterialRef& InstancedRenderable::GetMaterial(std::size_t matIndex) const
{
return GetMaterial(m_skin, matIndex);
}
/*!
* \brief Gets one of the material used by the object, independently from the active skin.
* \return A reference to the material.
*
* This function returns the active material at the specified index and the specified skin index.
* This function is the only way to query a material independently from the active skin.
*
* \param skinIndex Skin index to query
* \param matIndex Material index to query
*
* \see GetSkinCount, GetMaterialCount, SetSkin
*/
inline const MaterialRef& InstancedRenderable::GetMaterial(std::size_t skinIndex, std::size_t matIndex) const
{
NazaraAssert(skinIndex < m_skinCount, "Skin index out of bounds");
NazaraAssert(matIndex < m_materials.size(), "Material index out of bounds");
return m_materials[m_matCount * skinIndex + matIndex];
}
/*!
* \brief Gets the number of material per skin.
* \return The current material count per skin
*
* This function returns how many different materials entries exists per skin
* and is independent from the number of skin.
*/
inline std::size_t InstancedRenderable::GetMaterialCount() const
{
return m_matCount;
}
/*!
* \brief Gets the current active skin index
* \return Current skin index
*
* \see SetSkin
*/
inline std::size_t InstancedRenderable::GetSkin() const
{
return m_skin;
}
/*!
* \brief Gets the number of skins this object has
* \return Skin count
*
* \see GetSkin, SetSkinCount
*/
inline std::size_t InstancedRenderable::GetSkinCount() const
{
return m_skinCount;
}
/*!
* \brief Changes the active skin
*
* Each InstancedRenderable has the possibility to have multiples skins, which are sets of materials.
* Using this function allows you to have an object reference multiple materials, while using only some of thems (depending on the type of the object, see GetMaterialCount).
*
* \param skinIndex Skin index to change to
*
* \see SetSkinCount
*/
inline void InstancedRenderable::SetSkin(std::size_t skinIndex)
{
NazaraAssert(skinIndex < m_skinCount, "Skin index out of bounds");
m_skin = skinIndex;
// Force render queue invalidation
InvalidateInstanceData(0);
}
/*!
* \brief Changes the maximum skin count of the object
*
* This functions allows the object to store up to skinCount skins, which can then be switched to using SetSkin.
* Please note that the possibly new skins will be set to the default material, which should not be changed.
*
* \param skinCount Skin index to change to
*
* \see SetSkin
*/
inline void InstancedRenderable::SetSkinCount(std::size_t skinCount)
{
m_materials.resize(m_matCount * skinCount, Material::GetDefault());
m_skinCount = skinCount;
}
/*! /*!
* \brief Invalidates the bounding volume * \brief Invalidates the bounding volume
*/ */
@ -56,6 +168,71 @@ namespace Nz
OnInstancedRenderableInvalidateData(this, flags); OnInstancedRenderableInvalidateData(this, flags);
} }
/*!
* \brief Resets the materials, material count and skin count
*
* This function clears the materials in use by the InstancedRenderable and resets its material count per skin along with its skin count.
* This is the only way of setting the material count per skin and should be called at least by the constructor of the derived class.
* Please note that all materials will be set to the default material, which should not be changed.
*
* This function also resets the current skin to the first one.
*
* \param matCount The new material count per skin value, must be at least 1
* \param skinCount The new skin count value
*
* \see GetMaterial, GetMaterialCount, GetSkinCount, SetSkinCount
*/
inline void InstancedRenderable::ResetMaterials(std::size_t matCount, std::size_t skinCount)
{
NazaraAssert(skinCount != 0, "Invalid skin count (cannot be zero)");
m_materials.clear();
m_materials.resize(matCount * skinCount, Material::GetDefault());
m_matCount = matCount;
m_skinCount = skinCount;
m_skin = 0;
}
/*!
* \brief Changes the material used at the specified index by another one
*
* This function changes the active material at the specified index, depending on the current active skin, to the one passed as parameter.
*
* \param matIndex Material index
* \param material New material, cannot be null
*
* \remark If you wish to reset the material to the default one, use the default material (see Material::GetDefault)
*
* \see SetMaterial
*/
inline void InstancedRenderable::SetMaterial(std::size_t matIndex, MaterialRef material)
{
SetMaterial(m_skin, matIndex, std::move(material));
}
/*!
* \brief Changes the material used at the specified index by another one, independently from the active skin.
*
* This function changes the active material at the specified index and for the specified skin index, to the one passed as parameter.
*
* \param skinIndex Skin index
* \param matIndex Material index
* \param material New material, cannot be null
*
* \remark If you wish to reset the material to the default one, use the default material (see Material::GetDefault)
*
* \see SetMaterial
*/
inline void InstancedRenderable::SetMaterial(std::size_t skinIndex, std::size_t matIndex, MaterialRef material)
{
NazaraAssert(skinIndex < m_skinCount, "Skin index out of bounds");
NazaraAssert(matIndex < m_materials.size(), "Material index out of bounds");
NazaraAssert(material.IsValid(), "Material must be valid");
m_materials[m_matCount * skinIndex + matIndex] = std::move(material);
}
/*! /*!
* \brief Sets the current instanced renderable with the content of the other one * \brief Sets the current instanced renderable with the content of the other one
* \return A reference to this * \return A reference to this
@ -67,6 +244,10 @@ namespace Nz
{ {
m_boundingVolume = renderable.m_boundingVolume; m_boundingVolume = renderable.m_boundingVolume;
m_boundingVolumeUpdated = renderable.m_boundingVolumeUpdated; m_boundingVolumeUpdated = renderable.m_boundingVolumeUpdated;
m_matCount = renderable.m_matCount;
m_materials = renderable.m_materials;
m_skin = renderable.m_skin;
m_skinCount = renderable.m_skinCount;
return *this; return *this;
} }
@ -82,3 +263,5 @@ namespace Nz
m_boundingVolumeUpdated = true; m_boundingVolumeUpdated = true;
} }
} }
#include <Nazara/Graphics/DebugOff.hpp>

View File

@ -39,7 +39,7 @@ namespace Nz
friend ModelLoader; friend ModelLoader;
public: public:
Model(); inline Model();
Model(const Model& model) = default; Model(const Model& model) = default;
Model(Model&& model) = default; Model(Model&& model) = default;
virtual ~Model(); virtual ~Model();
@ -47,13 +47,9 @@ namespace Nz
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const override; void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const override;
inline void AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix, unsigned int renderOrder = 0); inline void AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix, unsigned int renderOrder = 0);
Material* GetMaterial(const String& subMeshName) const; using InstancedRenderable::GetMaterial;
Material* GetMaterial(unsigned int matIndex) const; const MaterialRef& GetMaterial(const String& subMeshName) const;
Material* GetMaterial(unsigned int skinIndex, const String& subMeshName) const; const MaterialRef& GetMaterial(std::size_t skinIndex, const String& subMeshName) const;
Material* GetMaterial(unsigned int skinIndex, unsigned int matIndex) const;
unsigned int GetMaterialCount() const;
unsigned int GetSkin() const;
unsigned int GetSkinCount() const;
Mesh* GetMesh() const; Mesh* GetMesh() const;
virtual bool IsAnimated() const; virtual bool IsAnimated() const;
@ -62,15 +58,11 @@ namespace Nz
bool LoadFromMemory(const void* data, std::size_t size, const ModelParameters& params = ModelParameters()); bool LoadFromMemory(const void* data, std::size_t size, const ModelParameters& params = ModelParameters());
bool LoadFromStream(Stream& stream, const ModelParameters& params = ModelParameters()); bool LoadFromStream(Stream& stream, const ModelParameters& params = ModelParameters());
void Reset(); using InstancedRenderable::SetMaterial;
bool SetMaterial(const String& subMeshName, MaterialRef material);
bool SetMaterial(std::size_t skinIndex, const String& subMeshName, MaterialRef material);
bool SetMaterial(const String& subMeshName, Material* material);
void SetMaterial(unsigned int matIndex, Material* material);
bool SetMaterial(unsigned int skinIndex, const String& subMeshName, Material* material);
void SetMaterial(unsigned int skinIndex, unsigned int matIndex, Material* material);
virtual void SetMesh(Mesh* mesh); virtual void SetMesh(Mesh* mesh);
void SetSkin(unsigned int skin);
void SetSkinCount(unsigned int skinCount);
Model& operator=(const Model& node) = default; Model& operator=(const Model& node) = default;
Model& operator=(Model&& node) = default; Model& operator=(Model&& node) = default;
@ -80,11 +72,7 @@ namespace Nz
protected: protected:
void MakeBoundingVolume() const override; void MakeBoundingVolume() const override;
std::vector<MaterialRef> m_materials;
MeshRef m_mesh; MeshRef m_mesh;
unsigned int m_matCount;
unsigned int m_skin;
unsigned int m_skinCount;
static ModelLoader::LoaderList s_loaders; static ModelLoader::LoaderList s_loaders;
}; };

View File

@ -7,6 +7,14 @@
namespace Nz namespace Nz
{ {
/*!
* \brief Constructs a Model object by default
*/
Model::Model()
{
ResetMaterials(0);
}
/*! /*!
* \brief Adds this model to a render queue, using user-specified transform matrix and render order * \brief Adds this model to a render queue, using user-specified transform matrix and render order
* *

View File

@ -61,8 +61,6 @@ namespace Nz
bool LoadFromMemory(const void* data, std::size_t size, const SkeletalModelParameters& params = SkeletalModelParameters()); bool LoadFromMemory(const void* data, std::size_t size, const SkeletalModelParameters& params = SkeletalModelParameters());
bool LoadFromStream(Stream& stream, const SkeletalModelParameters& params = SkeletalModelParameters()); bool LoadFromStream(Stream& stream, const SkeletalModelParameters& params = SkeletalModelParameters());
void Reset();
bool SetAnimation(Animation* animation); bool SetAnimation(Animation* animation);
void SetMesh(Mesh* mesh) override; void SetMesh(Mesh* mesh) override;
bool SetSequence(const String& sequenceName); bool SetSequence(const String& sequenceName);

View File

@ -38,7 +38,6 @@ namespace Nz
inline const Color& GetColor() const; inline const Color& GetColor() const;
inline const Color& GetCornerColor(RectCorner corner) const; inline const Color& GetCornerColor(RectCorner corner) const;
inline const MaterialRef& GetMaterial() const;
inline const Vector3f& GetOrigin() const; inline const Vector3f& GetOrigin() const;
inline const Vector2f& GetSize() const; inline const Vector2f& GetSize() const;
inline const Rectf& GetTextureCoords() const; inline const Rectf& GetTextureCoords() const;
@ -48,11 +47,15 @@ namespace Nz
inline void SetDefaultMaterial(); inline void SetDefaultMaterial();
inline void SetMaterial(MaterialRef material, bool resizeSprite = true); inline void SetMaterial(MaterialRef material, bool resizeSprite = true);
bool SetMaterial(String materialName, bool resizeSprite = true); bool SetMaterial(String materialName, bool resizeSprite = true);
inline void SetMaterial(std::size_t skinIndex, MaterialRef material, bool resizeSprite = true);
bool SetMaterial(std::size_t skinIndex, String materialName, bool resizeSprite = true);
inline void SetOrigin(const Vector3f& origin); inline void SetOrigin(const Vector3f& origin);
inline void SetSize(const Vector2f& size); inline void SetSize(const Vector2f& size);
inline void SetSize(float sizeX, float sizeY); inline void SetSize(float sizeX, float sizeY);
bool SetTexture(String textureName, bool resizeSprite = true); bool SetTexture(String textureName, bool resizeSprite = true);
inline void SetTexture(TextureRef texture, bool resizeSprite = true); inline void SetTexture(TextureRef texture, bool resizeSprite = true);
bool SetTexture(std::size_t skinIndex, String textureName, bool resizeSprite = true);
inline void SetTexture(std::size_t skinIndex, TextureRef texture, bool resizeSprite = true);
inline void SetTextureCoords(const Rectf& coords); inline void SetTextureCoords(const Rectf& coords);
inline void SetTextureRect(const Rectui& rect); inline void SetTextureRect(const Rectui& rect);
@ -71,7 +74,6 @@ namespace Nz
std::array<Color, 4> m_cornerColor; std::array<Color, 4> m_cornerColor;
Color m_color; Color m_color;
MaterialRef m_material;
Rectf m_textureCoords; Rectf m_textureCoords;
Vector2f m_size; Vector2f m_size;
Vector3f m_origin; Vector3f m_origin;

View File

@ -2,9 +2,10 @@
// This file is part of the "Nazara Engine - Graphics module" // This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/Sprite.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <memory> #include <memory>
#include <Nazara/Renderer/Debug.hpp> #include <Nazara/Graphics/Debug.hpp>
namespace Nz namespace Nz
{ {
@ -56,7 +57,6 @@ namespace Nz
inline Sprite::Sprite(const Sprite& sprite) : inline Sprite::Sprite(const Sprite& sprite) :
InstancedRenderable(sprite), InstancedRenderable(sprite),
m_color(sprite.m_color), m_color(sprite.m_color),
m_material(sprite.m_material),
m_textureCoords(sprite.m_textureCoords), m_textureCoords(sprite.m_textureCoords),
m_size(sprite.m_size), m_size(sprite.m_size),
m_origin(sprite.m_origin) m_origin(sprite.m_origin)
@ -94,15 +94,6 @@ namespace Nz
return m_cornerColor[corner]; return m_cornerColor[corner];
} }
/*!
* \brief Gets the material of the sprite
* \return Current material
*/
inline const MaterialRef& Sprite::GetMaterial() const
{
return m_material;
}
/*! /*!
* \brief Gets the origin of the sprite * \brief Gets the origin of the sprite
* *
@ -187,18 +178,34 @@ namespace Nz
* \brief Changes the material of the sprite * \brief Changes the material of the sprite
* *
* \param material Material for the sprite * \param material Material for the sprite
* \param resizeSprite Should the sprite be resized to the texture size? * \param resizeSprite Should billboard be resized to the material size (diffuse map)
*/ */
inline void Sprite::SetMaterial(MaterialRef material, bool resizeSprite) inline void Sprite::SetMaterial(MaterialRef material, bool resizeSprite)
{ {
m_material = std::move(material); SetMaterial(GetSkin(), std::move(material), resizeSprite);
if (m_material && resizeSprite) }
/*!
* \brief Sets the material of the sprite
*
* \param skinIndex Skin index to change
* \param material Material for the sprite
* \param resizeBillboard Should billboard be resized to the material size (diffuse map)
*/
inline void Sprite::SetMaterial(std::size_t skinIndex, MaterialRef material, bool resizeSprite)
{ {
Texture* diffuseMap = m_material->GetDiffuseMap(); InstancedRenderable::SetMaterial(skinIndex, 0, std::move(material));
if (resizeSprite)
{
if (const MaterialRef& material = GetMaterial())
{
const TextureRef& diffuseMap = material->GetDiffuseMap();
if (diffuseMap && diffuseMap->IsValid()) if (diffuseMap && diffuseMap->IsValid())
SetSize(Vector2f(Vector2ui(diffuseMap->GetSize()))); SetSize(Vector2f(Vector2ui(diffuseMap->GetSize())));
} }
} }
}
/*! /*!
* \brief Sets the origin of the sprite * \brief Sets the origin of the sprite
@ -246,9 +253,9 @@ namespace Nz
} }
/*! /*!
* \brief Sets the texture of the sprite * \brief Sets the texture of the sprite for the current skin
* *
* Assign a texture to the sprite material * This function changes the diffuse map of the material associated with the current skin
* *
* \param texture Texture for the sprite * \param texture Texture for the sprite
* \param resizeSprite Should the sprite be resized to the texture size? * \param resizeSprite Should the sprite be resized to the texture size?
@ -257,15 +264,36 @@ namespace Nz
*/ */
inline void Sprite::SetTexture(TextureRef texture, bool resizeSprite) inline void Sprite::SetTexture(TextureRef texture, bool resizeSprite)
{ {
if (!m_material) SetTexture(GetSkin(), std::move(texture), resizeSprite);
SetDefaultMaterial(); }
else if (m_material->GetReferenceCount() > 1)
m_material = Material::New(*m_material); // Copy the material
/*!
* \brief Sets the texture of the sprite for a specific skin
*
* This function changes the diffuse map of the material associated with the specified skin
*
* \param skinIndex Skin index to change
* \param texture Texture for the sprite
* \param resizeSprite Should the sprite be resized to the texture size?
*
* \remark The sprite material gets copied to prevent accidentally changing other drawable materials
*/
inline void Sprite::SetTexture(std::size_t skinIndex, TextureRef texture, bool resizeSprite)
{
if (resizeSprite && texture && texture->IsValid()) if (resizeSprite && texture && texture->IsValid())
SetSize(Vector2f(Vector2ui(texture->GetSize()))); SetSize(Vector2f(Vector2ui(texture->GetSize())));
m_material->SetDiffuseMap(std::move(texture)); const MaterialRef& material = GetMaterial(skinIndex);
if (material->GetReferenceCount() > 1)
{
MaterialRef newMat = Material::New(*material); // Copy
newMat->SetDiffuseMap(std::move(texture));
SetMaterial(skinIndex, std::move(newMat));
}
else
material->SetDiffuseMap(std::move(texture));
} }
/*! /*!
@ -277,6 +305,7 @@ namespace Nz
inline void Sprite::SetTextureCoords(const Rectf& coords) inline void Sprite::SetTextureCoords(const Rectf& coords)
{ {
m_textureCoords = coords; m_textureCoords = coords;
InvalidateVertices(); InvalidateVertices();
} }
@ -291,10 +320,10 @@ namespace Nz
inline void Sprite::SetTextureRect(const Rectui& rect) inline void Sprite::SetTextureRect(const Rectui& rect)
{ {
NazaraAssert(m_material, "Sprite has no material"); const MaterialRef& material = GetMaterial();
NazaraAssert(m_material->HasDiffuseMap(), "Sprite material has no diffuse map"); NazaraAssert(material->HasDiffuseMap(), "Sprite material has no diffuse map");
Texture* diffuseMap = m_material->GetDiffuseMap(); Texture* diffuseMap = material->GetDiffuseMap();
float invWidth = 1.f / diffuseMap->GetWidth(); float invWidth = 1.f / diffuseMap->GetWidth();
float invHeight = 1.f / diffuseMap->GetHeight(); float invHeight = 1.f / diffuseMap->GetHeight();
@ -314,7 +343,6 @@ namespace Nz
InstancedRenderable::operator=(sprite); InstancedRenderable::operator=(sprite);
m_color = sprite.m_color; m_color = sprite.m_color;
m_material = sprite.m_material;
m_origin = sprite.m_origin; m_origin = sprite.m_origin;
m_textureCoords = sprite.m_textureCoords; m_textureCoords = sprite.m_textureCoords;
m_size = sprite.m_size; m_size = sprite.m_size;
@ -352,5 +380,4 @@ namespace Nz
} }
} }
#include <Nazara/Renderer/DebugOff.hpp> #include <Nazara/Graphics/DebugOff.hpp>
#include "Sprite.hpp"

View File

@ -37,12 +37,12 @@ namespace Nz
inline void Clear(); inline void Clear();
inline const Color& GetColor() const; inline const Color& GetColor() const;
inline const MaterialRef& GetMaterial() const;
inline float GetScale() const; inline float GetScale() const;
inline void SetColor(const Color& color); inline void SetColor(const Color& color);
inline void SetDefaultMaterial(); inline void SetDefaultMaterial();
inline void SetMaterial(MaterialRef material); inline void SetMaterial(MaterialRef material);
inline void SetMaterial(std::size_t skinIndex, MaterialRef material);
inline void SetScale(float scale); inline void SetScale(float scale);
void Update(const AbstractTextDrawer& drawer); void Update(const AbstractTextDrawer& drawer);
@ -76,7 +76,6 @@ namespace Nz
mutable std::unordered_map<Texture*, RenderIndices> m_renderInfos; mutable std::unordered_map<Texture*, RenderIndices> m_renderInfos;
mutable std::vector<VertexStruct_XY_Color_UV> m_localVertices; mutable std::vector<VertexStruct_XY_Color_UV> m_localVertices;
Color m_color; Color m_color;
MaterialRef m_material;
Recti m_localBounds; Recti m_localBounds;
float m_scale; float m_scale;

View File

@ -2,8 +2,9 @@
// This file is part of the "Nazara Engine - Graphics module" // This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/TextSprite.hpp>
#include <memory> #include <memory>
#include <Nazara/Renderer/Debug.hpp> #include <Nazara/Graphics/Debug.hpp>
namespace Nz namespace Nz
{ {
@ -15,6 +16,8 @@ namespace Nz
m_color(Color::White), m_color(Color::White),
m_scale(1.f) m_scale(1.f)
{ {
ResetMaterials(1U);
SetDefaultMaterial(); SetDefaultMaterial();
} }
@ -41,7 +44,6 @@ namespace Nz
m_renderInfos(sprite.m_renderInfos), m_renderInfos(sprite.m_renderInfos),
m_localVertices(sprite.m_localVertices), m_localVertices(sprite.m_localVertices),
m_color(sprite.m_color), m_color(sprite.m_color),
m_material(sprite.m_material),
m_localBounds(sprite.m_localBounds), m_localBounds(sprite.m_localBounds),
m_scale(sprite.m_scale) m_scale(sprite.m_scale)
{ {
@ -78,16 +80,6 @@ namespace Nz
return m_color; return m_color;
} }
/*!
* \brief Gets the material of the text sprite
* \return Current material
*/
inline const MaterialRef& TextSprite::GetMaterial() const
{
return m_material;
}
/*! /*!
* \brief Gets the current scale of the text sprite * \brief Gets the current scale of the text sprite
* \return Current scale * \return Current scale
@ -136,7 +128,12 @@ namespace Nz
inline void TextSprite::SetMaterial(MaterialRef material) inline void TextSprite::SetMaterial(MaterialRef material)
{ {
m_material = std::move(material); InstancedRenderable::SetMaterial(0, std::move(material));
}
inline void TextSprite::SetMaterial(std::size_t skinIndex, MaterialRef material)
{
InstancedRenderable::SetMaterial(skinIndex, 0, std::move(material));
} }
/*! /*!
@ -167,7 +164,6 @@ namespace Nz
m_atlases.clear(); m_atlases.clear();
m_color = text.m_color; m_color = text.m_color;
m_material = text.m_material;
m_renderInfos = text.m_renderInfos; m_renderInfos = text.m_renderInfos;
m_localBounds = text.m_localBounds; m_localBounds = text.m_localBounds;
m_localVertices = text.m_localVertices; m_localVertices = text.m_localVertices;
@ -216,4 +212,4 @@ namespace Nz
} }
} }
#include <Nazara/Renderer/DebugOff.hpp> #include <Nazara/Graphics/DebugOff.hpp>

View File

@ -50,8 +50,6 @@ namespace Nz
inline void EnableTiles(const Vector2ui* tilesPos, std::size_t tileCount, const Rectf& coords, const Color& color = Color::White, std::size_t materialIndex = 0U); inline void EnableTiles(const Vector2ui* tilesPos, std::size_t tileCount, const Rectf& coords, const Color& color = Color::White, std::size_t materialIndex = 0U);
inline void EnableTiles(const Vector2ui* tilesPos, std::size_t tileCount, const Rectui& rect, const Color& color = Color::White, std::size_t materialIndex = 0U); inline void EnableTiles(const Vector2ui* tilesPos, std::size_t tileCount, const Rectui& rect, const Color& color = Color::White, std::size_t materialIndex = 0U);
inline const MaterialRef& GetMaterial(std::size_t index) const;
inline std::size_t GetMaterialCount() const;
inline const Vector2ui& GetMapSize() const; inline const Vector2ui& GetMapSize() const;
inline Vector2f GetSize() const; inline Vector2f GetSize() const;
inline const Tile& GetTile(const Vector2ui& tilePos) const; inline const Tile& GetTile(const Vector2ui& tilePos) const;
@ -59,7 +57,7 @@ namespace Nz
inline bool IsIsometricModeEnabled() const; inline bool IsIsometricModeEnabled() const;
inline void SetMaterial(std::size_t index, MaterialRef material); using InstancedRenderable::SetMaterial;
inline TileMap& operator=(const TileMap& TileMap); inline TileMap& operator=(const TileMap& TileMap);
TileMap& operator=(TileMap&& TileMap) = delete; TileMap& operator=(TileMap&& TileMap) = delete;
@ -83,7 +81,6 @@ namespace Nz
struct Layer struct Layer
{ {
MaterialRef material;
std::set<std::size_t> tiles; std::set<std::size_t> tiles;
}; };

View File

@ -32,8 +32,7 @@ namespace Nz
NazaraAssert(m_tileSize.x > 0 && m_tileSize.y > 0, "Invalid tile size"); NazaraAssert(m_tileSize.x > 0 && m_tileSize.y > 0, "Invalid tile size");
NazaraAssert(m_layers.size() != 0U, "Invalid material count"); NazaraAssert(m_layers.size() != 0U, "Invalid material count");
for (Layer& layer : m_layers) ResetMaterials(materialCount);
layer.material = Material::GetDefault();
InvalidateBoundingVolume(); InvalidateBoundingVolume();
} }
@ -183,9 +182,11 @@ namespace Nz
inline void TileMap::EnableTile(const Vector2ui& tilePos, const Rectui& rect, const Color& color, std::size_t materialIndex) inline void TileMap::EnableTile(const Vector2ui& tilePos, const Rectui& rect, const Color& color, std::size_t materialIndex)
{ {
NazaraAssert(materialIndex < m_layers.size(), "Material out of bounds"); NazaraAssert(materialIndex < m_layers.size(), "Material out of bounds");
NazaraAssert(m_layers[materialIndex].material->HasDiffuseMap(), "Material has no diffuse map");
Texture* diffuseMap = m_layers[materialIndex].material->GetDiffuseMap(); const MaterialRef& material = GetMaterial(materialIndex);
NazaraAssert(material->HasDiffuseMap(), "Material has no diffuse map");
Texture* diffuseMap = material->GetDiffuseMap();
float invWidth = 1.f / diffuseMap->GetWidth(); float invWidth = 1.f / diffuseMap->GetWidth();
float invHeight = 1.f / diffuseMap->GetHeight(); float invHeight = 1.f / diffuseMap->GetHeight();
@ -246,7 +247,7 @@ namespace Nz
{ {
NazaraAssert(materialIndex < m_layers.size(), "Material out of bounds"); NazaraAssert(materialIndex < m_layers.size(), "Material out of bounds");
Texture* diffuseMap = m_layers[materialIndex].material->GetDiffuseMap(); Texture* diffuseMap = GetMaterial(materialIndex)->GetDiffuseMap();
float invWidth = 1.f / diffuseMap->GetWidth(); float invWidth = 1.f / diffuseMap->GetWidth();
float invHeight = 1.f / diffuseMap->GetHeight(); float invHeight = 1.f / diffuseMap->GetHeight();
@ -321,9 +322,11 @@ namespace Nz
inline void TileMap::EnableTiles(const Vector2ui* tilesPos, std::size_t tileCount, const Rectui& rect, const Color& color, std::size_t materialIndex) inline void TileMap::EnableTiles(const Vector2ui* tilesPos, std::size_t tileCount, const Rectui& rect, const Color& color, std::size_t materialIndex)
{ {
NazaraAssert(materialIndex < m_layers.size(), "Material out of bounds"); NazaraAssert(materialIndex < m_layers.size(), "Material out of bounds");
NazaraAssert(m_layers[materialIndex].material->HasDiffuseMap(), "Material has no diffuse map");
Texture* diffuseMap = m_layers[materialIndex].material->GetDiffuseMap(); const MaterialRef& material = GetMaterial(materialIndex);
NazaraAssert(material->HasDiffuseMap(), "Material has no diffuse map");
Texture* diffuseMap = material->GetDiffuseMap();
float invWidth = 1.f / diffuseMap->GetWidth(); float invWidth = 1.f / diffuseMap->GetWidth();
float invHeight = 1.f / diffuseMap->GetHeight(); float invHeight = 1.f / diffuseMap->GetHeight();
@ -331,29 +334,6 @@ namespace Nz
EnableTiles(tilesPos, tileCount, unnormalizedCoords, color, materialIndex); EnableTiles(tilesPos, tileCount, unnormalizedCoords, color, materialIndex);
} }
/*!
* \brief Gets the material at position index used by the TileMap
*
* \param index Index of the material to query
*
* \return Material at index
*/
inline const MaterialRef& TileMap::GetMaterial(std::size_t index) const
{
NazaraAssert(index < m_layers.size(), "Material out of bounds");
return m_layers[index].material;
}
/*!
* \brief Gets the maximum material count this TileMap can use
* \return Material count
*/
inline std::size_t TileMap::GetMaterialCount() const
{
return m_layers.size();
}
/*! /*!
* \brief Gets the tilemap size (i.e. number of tiles in each dimension) * \brief Gets the tilemap size (i.e. number of tiles in each dimension)
* \return Number of tiles in each dimension * \return Number of tiles in each dimension
@ -415,19 +395,6 @@ namespace Nz
return m_isometricModeEnabled; return m_isometricModeEnabled;
} }
/*!
* \brief Sets a material of the TileMap
*
* \param index Index of the material to change
* \param material Material for the TileMap
*/
inline void TileMap::SetMaterial(std::size_t index, MaterialRef material)
{
NazaraAssert(index < m_layers.size(), "Material out of bounds");
m_layers[index].material = std::move(material);
}
/*! /*!
* \brief Sets the current TileMap with the content of the other one * \brief Sets the current TileMap with the content of the other one
* \return A reference to this * \return A reference to this

View File

@ -27,11 +27,8 @@ namespace Nz
void Billboard::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const void Billboard::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const
{ {
if (!m_material)
return;
Nz::Vector3f position = instanceData.transformMatrix.GetTranslation(); Nz::Vector3f position = instanceData.transformMatrix.GetTranslation();
renderQueue->AddBillboards(instanceData.renderOrder, m_material, 1, &position, &m_size, &m_sinCos, &m_color); renderQueue->AddBillboards(instanceData.renderOrder, GetMaterial(), 1, &position, &m_size, &m_sinCos, &m_color);
} }
/* /*

View File

@ -77,7 +77,6 @@ namespace Nz
return false; return false;
} }
model->Reset();
model->SetMesh(mesh); model->SetMesh(mesh);
if (parameters.loadMaterials) if (parameters.loadMaterials)
@ -114,7 +113,6 @@ namespace Nz
return false; return false;
} }
model->Reset();
model->SetMesh(mesh); model->SetMesh(mesh);
if (parameters.loadMaterials) if (parameters.loadMaterials)

View File

@ -41,26 +41,9 @@ namespace Nz
} }
/*! /*!
* \brief Constructs a Model object by default * \brief Destructs the object and cleans resources
*/ */
Model::~Model() = default;
Model::Model() :
m_matCount(0),
m_skin(0),
m_skinCount(1)
{
}
/*!
* \brief Destructs the object and calls Reset
*
* \see Reset
*/
Model::~Model()
{
Reset();
}
/*! /*!
* \brief Adds this model to the render queue * \brief Adds this model to the render queue
@ -75,7 +58,7 @@ namespace Nz
for (unsigned int i = 0; i < submeshCount; ++i) for (unsigned int i = 0; i < submeshCount; ++i)
{ {
const StaticMesh* mesh = static_cast<const StaticMesh*>(m_mesh->GetSubMesh(i)); const StaticMesh* mesh = static_cast<const StaticMesh*>(m_mesh->GetSubMesh(i));
Material* material = m_materials[mesh->GetMaterialIndex()]; const MaterialRef& material = GetMaterial(mesh->GetMaterialIndex());
MeshData meshData; MeshData meshData;
meshData.indexBuffer = mesh->GetIndexBuffer(); meshData.indexBuffer = mesh->GetIndexBuffer();
@ -96,54 +79,20 @@ namespace Nz
* \remark Produces a NazaraError if there is no subMesh with that name * \remark Produces a NazaraError if there is no subMesh with that name
* \remark Produces a NazaraError if material is invalid * \remark Produces a NazaraError if material is invalid
*/ */
const MaterialRef& Model::GetMaterial(const String& subMeshName) const
Material* Model::GetMaterial(const String& subMeshName) const
{ {
#if NAZARA_GRAPHICS_SAFE NazaraAssert(m_mesh, "Model has no mesh");
if (!m_mesh)
{
NazaraError("Model has no mesh");
return nullptr;
}
#endif
SubMesh* subMesh = m_mesh->GetSubMesh(subMeshName); SubMesh* subMesh = m_mesh->GetSubMesh(subMeshName);
if (!subMesh) if (!subMesh)
{ {
NazaraError("Mesh has no submesh \"" + subMeshName + '"'); NazaraError("Mesh has no submesh \"" + subMeshName + '"');
return nullptr;
static MaterialRef Invalid;
return Invalid;
} }
unsigned int matIndex = subMesh->GetMaterialIndex(); return GetMaterial(subMesh->GetMaterialIndex());
if (matIndex >= m_matCount)
{
NazaraError("Material index out of range (" + String::Number(matIndex) + " >= " + String::Number(m_matCount) + ')');
return nullptr;
}
return m_materials[m_skin * m_matCount + matIndex];
}
/*!
* \brief Gets the material by index
* \return Pointer to the current material
*
* \param matIndex Index of the material
*
* \remark Produces a NazaraError if index is invalid
*/
Material* Model::GetMaterial(unsigned int matIndex) const
{
#if NAZARA_GRAPHICS_SAFE
if (matIndex >= m_matCount)
{
NazaraError("Material index out of range (" + String::Number(matIndex) + " >= " + String::Number(m_matCount) + ')');
return nullptr;
}
#endif
return m_materials[m_skin * m_matCount + matIndex];
} }
/*! /*!
@ -157,72 +106,20 @@ namespace Nz
* \remark Produces a NazaraError if there is no subMesh with that name * \remark Produces a NazaraError if there is no subMesh with that name
* \remark Produces a NazaraError if material index is invalid * \remark Produces a NazaraError if material index is invalid
*/ */
const MaterialRef& Model::GetMaterial(std::size_t skinIndex, const String& subMeshName) const
Material* Model::GetMaterial(unsigned int skinIndex, const String& subMeshName) const
{ {
#if NAZARA_GRAPHICS_SAFE NazaraAssert(m_mesh, "Model has no mesh");
if (skinIndex >= m_skinCount)
{
NazaraError("Skin index out of range (" + String::Number(skinIndex) + " >= " + String::Number(m_skinCount) + ')');
return nullptr;
}
#endif
SubMesh* subMesh = m_mesh->GetSubMesh(subMeshName); SubMesh* subMesh = m_mesh->GetSubMesh(subMeshName);
if (!subMesh) if (!subMesh)
{ {
NazaraError("Mesh has no submesh \"" + subMeshName + '"'); NazaraError("Mesh has no submesh \"" + subMeshName + '"');
return nullptr;
static MaterialRef Invalid;
return Invalid;
} }
unsigned int matIndex = subMesh->GetMaterialIndex(); return GetMaterial(subMesh->GetMaterialIndex());
if (matIndex >= m_matCount)
{
NazaraError("Material index out of range (" + String::Number(matIndex) + " >= " + String::Number(m_matCount) + ')');
return nullptr;
}
return m_materials[skinIndex * m_matCount + matIndex];
}
/*!
* \brief Gets the material by index with skin
* \return Pointer to the current material
*
* \param skinIndex Index of the skin
* \param matIndex Index of the material
*
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if skinIndex is invalid
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if matIndex is invalid
*/
Material* Model::GetMaterial(unsigned int skinIndex, unsigned int matIndex) const
{
#if NAZARA_GRAPHICS_SAFE
if (skinIndex >= m_skinCount)
{
NazaraError("Skin index out of range (" + String::Number(skinIndex) + " >= " + String::Number(m_skinCount) + ')');
return nullptr;
}
if (matIndex >= m_matCount)
{
NazaraError("Material index out of range (" + String::Number(matIndex) + " >= " + String::Number(m_matCount) + ')');
return nullptr;
}
#endif
return m_materials[skinIndex * m_matCount + matIndex];
}
/*!
* \brief Gets the number of materials
* \return Current number of materials
*/
unsigned int Model::GetMaterialCount() const
{
return m_matCount;
} }
/*! /*!
@ -235,26 +132,6 @@ namespace Nz
return m_mesh; return m_mesh;
} }
/*!
* \brief Gets the skin
* \return Current skin
*/
unsigned int Model::GetSkin() const
{
return m_skin;
}
/*!
* \brief Gets the number of skins
* \return Current number of skins
*/
unsigned int Model::GetSkinCount() const
{
return m_skinCount;
}
/*! /*!
* \brief Checks whether the model is animated * \brief Checks whether the model is animated
* \return false * \return false
@ -305,22 +182,6 @@ namespace Nz
return ModelLoader::LoadFromStream(this, stream, params); return ModelLoader::LoadFromStream(this, stream, params);
} }
/*!
* \brief Resets the model, cleans everything
*/
void Model::Reset()
{
m_matCount = 0;
m_skinCount = 0;
if (m_mesh)
{
m_mesh.Reset();
m_materials.clear();
}
}
/*! /*!
* \brief Sets the material of the named submesh * \brief Sets the material of the named submesh
* \return true If successful * \return true If successful
@ -332,7 +193,7 @@ namespace Nz
* \remark Produces a NazaraError if material index is invalid * \remark Produces a NazaraError if material index is invalid
*/ */
bool Model::SetMaterial(const String& subMeshName, Material* material) bool Model::SetMaterial(const String& subMeshName, MaterialRef material)
{ {
SubMesh* subMesh = m_mesh->GetSubMesh(subMeshName); SubMesh* subMesh = m_mesh->GetSubMesh(subMeshName);
if (!subMesh) if (!subMesh)
@ -341,51 +202,10 @@ namespace Nz
return false; return false;
} }
unsigned int matIndex = subMesh->GetMaterialIndex(); SetMaterial(subMesh->GetMaterialIndex(), std::move(material));
if (matIndex >= m_matCount)
{
NazaraError("Material index out of range (" + String::Number(matIndex) + " >= " + String::Number(m_matCount) + ')');
return false;
}
unsigned int index = m_skin * m_matCount + matIndex;
if (material)
m_materials[index] = material;
else
m_materials[index] = Material::GetDefault();
return true; return true;
} }
/*!
* \brief Sets the material by index
* \return true If successful
*
* \param matIndex Index of the material
* \param material Pointer to the material
*
* \remark Produces a NazaraError with if NAZARA_GRAPHICS_SAFE defined index is invalid
*/
void Model::SetMaterial(unsigned int matIndex, Material* material)
{
#if NAZARA_GRAPHICS_SAFE
if (matIndex >= m_matCount)
{
NazaraError("Material index out of range (" + String::Number(matIndex) + " >= " + String::Number(m_matCount));
return;
}
#endif
unsigned int index = m_skin * m_matCount + matIndex;
if (material)
m_materials[index] = material;
else
m_materials[index] = Material::GetDefault();
}
/*! /*!
* \brief Sets the material by index of the named submesh * \brief Sets the material by index of the named submesh
* \return true If successful * \return true If successful
@ -398,17 +218,8 @@ namespace Nz
* \remark Produces a NazaraError if there is no subMesh with that name * \remark Produces a NazaraError if there is no subMesh with that name
* \remark Produces a NazaraError if material index is invalid * \remark Produces a NazaraError if material index is invalid
*/ */
bool Model::SetMaterial(std::size_t skinIndex, const String& subMeshName, MaterialRef material)
bool Model::SetMaterial(unsigned int skinIndex, const String& subMeshName, Material* material)
{ {
#if NAZARA_GRAPHICS_SAFE
if (skinIndex >= m_skinCount)
{
NazaraError("Skin index out of range (" + String::Number(skinIndex) + " >= " + String::Number(m_skinCount));
return false;
}
#endif
SubMesh* subMesh = m_mesh->GetSubMesh(subMeshName); SubMesh* subMesh = m_mesh->GetSubMesh(subMeshName);
if (!subMesh) if (!subMesh)
{ {
@ -416,59 +227,10 @@ namespace Nz
return false; return false;
} }
unsigned int matIndex = subMesh->GetMaterialIndex(); SetMaterial(skinIndex, subMesh->GetMaterialIndex(), std::move(material));
if (matIndex >= m_matCount)
{
NazaraError("Material index out of range (" + String::Number(matIndex) + " >= " + String::Number(m_matCount));
return false;
}
unsigned int index = skinIndex * m_matCount + matIndex;
if (material)
m_materials[index] = material;
else
m_materials[index] = Material::GetDefault();
return true; return true;
} }
/*!
* \brief Sets the material by index with skin
* \return true If successful
*
* \param skinIndex Index of the skin
* \param matIndex Index of the material
* \param material Pointer to the material
*
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if skinIndex is invalid
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if matIndex is invalid
*/
void Model::SetMaterial(unsigned int skinIndex, unsigned int matIndex, Material* material)
{
#if NAZARA_GRAPHICS_SAFE
if (skinIndex >= m_skinCount)
{
NazaraError("Skin index out of range (" + String::Number(skinIndex) + " >= " + String::Number(m_skinCount));
return;
}
if (matIndex >= m_matCount)
{
NazaraError("Material index out of range (" + String::Number(matIndex) + " >= " + String::Number(m_matCount));
return;
}
#endif
unsigned int index = skinIndex * m_matCount + matIndex;
if (material)
m_materials[index] = material;
else
m_materials[index] = Material::GetDefault();
}
/*! /*!
* \brief Sets the mesh * \brief Sets the mesh
* *
@ -490,65 +252,13 @@ namespace Nz
m_mesh = mesh; m_mesh = mesh;
if (m_mesh) if (m_mesh)
{ ResetMaterials(mesh->GetMaterialCount());
m_matCount = mesh->GetMaterialCount();
m_materials.clear();
m_materials.resize(m_matCount, Material::GetDefault());
m_skinCount = 1;
}
else else
{ ResetMaterials(0);
m_matCount = 0;
m_materials.clear();
m_skinCount = 0;
}
InvalidateBoundingVolume(); InvalidateBoundingVolume();
} }
/*!
* \brief Sets the skin
*
* \param skin Skin to use
*
* \remark Produces a NazaraError if skin is invalid
*/
void Model::SetSkin(unsigned int skin)
{
#if NAZARA_GRAPHICS_SAFE
if (skin >= m_skinCount)
{
NazaraError("Skin index out of range (" + String::Number(skin) + " >= " + String::Number(m_skinCount) + ')');
return;
}
#endif
m_skin = skin;
}
/*!
* \brief Sets the number of skins
*
* \param skinCount Number of skins
*
* \remark Produces a NazaraError if skinCount equals zero
*/
void Model::SetSkinCount(unsigned int skinCount)
{
#if NAZARA_GRAPHICS_SAFE
if (skinCount == 0)
{
NazaraError("Skin count must be over zero");
return;
}
#endif
m_materials.resize(m_matCount*skinCount, Material::GetDefault());
m_skinCount = skinCount;
}
/* /*
* \brief Makes the bounding volume of this billboard * \brief Makes the bounding volume of this billboard
*/ */

View File

@ -62,7 +62,7 @@ namespace Nz
for (unsigned int i = 0; i < submeshCount; ++i) for (unsigned int i = 0; i < submeshCount; ++i)
{ {
const SkeletalMesh* mesh = static_cast<const SkeletalMesh*>(m_mesh->GetSubMesh(i)); const SkeletalMesh* mesh = static_cast<const SkeletalMesh*>(m_mesh->GetSubMesh(i));
const Material* material = m_materials[mesh->GetMaterialIndex()]; const Material* material = GetMaterial(mesh->GetMaterialIndex());
MeshData meshData; MeshData meshData;
meshData.indexBuffer = mesh->GetIndexBuffer(); meshData.indexBuffer = mesh->GetIndexBuffer();
@ -261,17 +261,6 @@ namespace Nz
return SkeletalModelLoader::LoadFromStream(this, stream, params); return SkeletalModelLoader::LoadFromStream(this, stream, params);
} }
/*!
* \brief Resets the model
*/
void SkeletalModel::Reset()
{
Model::Reset();
m_skeleton.Destroy();
}
/*! /*!
* \brief Sets the animation for the model * \brief Sets the animation for the model
* \return true If successful * \return true If successful

View File

@ -26,11 +26,8 @@ namespace Nz
void Sprite::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const void Sprite::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const
{ {
if (!m_material)
return;
const VertexStruct_XYZ_Color_UV* vertices = reinterpret_cast<const VertexStruct_XYZ_Color_UV*>(instanceData.data.data()); const VertexStruct_XYZ_Color_UV* vertices = reinterpret_cast<const VertexStruct_XYZ_Color_UV*>(instanceData.data.data());
renderQueue->AddSprites(instanceData.renderOrder, m_material, vertices, 1); renderQueue->AddSprites(instanceData.renderOrder, GetMaterial(), vertices, 1);
} }
/*! /*!
@ -73,7 +70,37 @@ namespace Nz
} }
/*! /*!
* \brief Sets the texture of the sprite from a name * \brief Sets the material of the sprite from a name for a specific skin
*
* Tries to get a material from the MaterialLibrary and then the MaterialManager (which will treat the name as a path)
* Fails if the texture name is not a part of the MaterialLibrary nor the MaterialManager (which fails if it couldn't load the texture from its filepath)
*
* \param skinIndex Skin index to change
* \param materialName Named texture for the material
* \param resizeSprite Should the sprite be resized to the material diffuse map size?
*
* \return True if the material was found or loaded from its name/path, false if it couldn't
*/
bool Sprite::SetMaterial(std::size_t skinIndex, String materialName, bool resizeSprite)
{
MaterialRef material = MaterialLibrary::Query(materialName);
if (!material)
{
material = MaterialManager::Get(materialName);
if (!material)
{
NazaraError("Failed to get material \"" + materialName + "\"");
return false;
}
}
SetMaterial(skinIndex, std::move(material), resizeSprite);
return true;
}
/*!
* \brief Sets the texture of the sprite from a name for the current skin
* \return True if the texture was found or loaded from its name/path, false if it couldn't
* *
* Tries to get a texture from the TextureLibrary and then the TextureManager (which will treat the name as a path) * Tries to get a texture from the TextureLibrary and then the TextureManager (which will treat the name as a path)
* Fails if the texture name is not a part of the TextureLibrary nor the TextureManager (which fails if it couldn't load the texture from its filepath) * Fails if the texture name is not a part of the TextureLibrary nor the TextureManager (which fails if it couldn't load the texture from its filepath)
@ -81,8 +108,6 @@ namespace Nz
* \param textureName Named texture for the sprite * \param textureName Named texture for the sprite
* \param resizeSprite Should the sprite be resized to the texture size? * \param resizeSprite Should the sprite be resized to the texture size?
* *
* \return True if the texture was found or loaded from its name/path, false if it couldn't
*
* \remark The sprite material gets copied to prevent accidentally changing other drawable materials * \remark The sprite material gets copied to prevent accidentally changing other drawable materials
*/ */
bool Sprite::SetTexture(String textureName, bool resizeSprite) bool Sprite::SetTexture(String textureName, bool resizeSprite)
@ -102,6 +127,36 @@ namespace Nz
return true; return true;
} }
/*!
* \brief Sets the texture of the sprite from a name for a specific skin
* \return True if the texture was found or loaded from its name/path, false if it couldn't
*
* Tries to get a texture from the TextureLibrary and then the TextureManager (which will treat the name as a path)
* Fails if the texture name is not a part of the TextureLibrary nor the TextureManager (which fails if it couldn't load the texture from its filepath)
*
* \param skinIndex Named texture for the sprite
* \param textureName Named texture for the sprite
* \param resizeSprite Should the sprite be resized to the texture size?
*
* \remark The sprite material gets copied to prevent accidentally changing other drawable materials
*/
bool Sprite::SetTexture(std::size_t skinIndex, String textureName, bool resizeSprite)
{
TextureRef texture = TextureLibrary::Query(textureName);
if (!texture)
{
texture = TextureManager::Get(textureName);
if (!texture)
{
NazaraError("Failed to get texture \"" + textureName + "\"");
return false;
}
}
SetTexture(skinIndex, std::move(texture), resizeSprite);
return true;
}
/*! /*!
* \brief Updates the data of the sprite * \brief Updates the data of the sprite
* *

View File

@ -28,9 +28,6 @@ namespace Nz
void TextSprite::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const void TextSprite::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const
{ {
if (!m_material)
return;
for (auto& pair : m_renderInfos) for (auto& pair : m_renderInfos)
{ {
Texture* overlay = pair.first; Texture* overlay = pair.first;
@ -39,7 +36,7 @@ namespace Nz
if (indices.count > 0) if (indices.count > 0)
{ {
const VertexStruct_XYZ_Color_UV* vertices = reinterpret_cast<const VertexStruct_XYZ_Color_UV*>(instanceData.data.data()); const VertexStruct_XYZ_Color_UV* vertices = reinterpret_cast<const VertexStruct_XYZ_Color_UV*>(instanceData.data.data());
renderQueue->AddSprites(instanceData.renderOrder, m_material, &vertices[indices.first * 4], indices.count, overlay); renderQueue->AddSprites(instanceData.renderOrder, GetMaterial(), &vertices[indices.first * 4], indices.count, overlay);
} }
} }
} }

View File

@ -29,11 +29,11 @@ namespace Nz
{ {
const VertexStruct_XYZ_Color_UV* vertices = reinterpret_cast<const VertexStruct_XYZ_Color_UV*>(instanceData.data.data()); const VertexStruct_XYZ_Color_UV* vertices = reinterpret_cast<const VertexStruct_XYZ_Color_UV*>(instanceData.data.data());
std::size_t matCount = 0;
std::size_t spriteCount = 0; std::size_t spriteCount = 0;
for (const Layer& layer : m_layers) for (const Layer& layer : m_layers)
{ {
if (layer.material) renderQueue->AddSprites(instanceData.renderOrder, GetMaterial(matCount++), &vertices[spriteCount], layer.tiles.size());
renderQueue->AddSprites(instanceData.renderOrder, layer.material, &vertices[spriteCount], layer.tiles.size());
spriteCount += layer.tiles.size(); spriteCount += layer.tiles.size();
} }