NazaraEngine/include/Nazara/Graphics/InstancedRenderable.inl

281 lines
8.1 KiB
C++

// Copyright (C) 2020 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 <Nazara/Graphics/InstancedRenderable.hpp>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz
{
/*!
* \brief Constructs a InstancedRenderable object by default
*/
inline InstancedRenderable::InstancedRenderable() :
m_boundingVolumeUpdated(false)
{
}
/*!
* \brief Constructs a InstancedRenderable object by assignation
*
* \param renderable InstancedRenderable to copy into this
*/
inline InstancedRenderable::InstancedRenderable(const InstancedRenderable& renderable) :
RefCounted(),
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)
{
}
/*!
* \brief Ensures that the bounding volume is up to date
*/
inline void InstancedRenderable::EnsureBoundingVolumeUpdated() const
{
if (!m_boundingVolumeUpdated)
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 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");
MaterialRef& matEntry = m_materials[m_matCount * skinIndex + matIndex];
if (matEntry != material)
{
OnInstancedRenderableInvalidateMaterial(this, skinIndex, matIndex, material);
matEntry = std::move(material);
}
}
/*!
* \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");
if (m_skin != skinIndex)
{
OnInstancedRenderableSkinChange(this, skinIndex);
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
*/
inline void InstancedRenderable::InvalidateBoundingVolume()
{
m_boundingVolumeUpdated = false;
OnInstancedRenderableInvalidateBoundingVolume(this);
}
/*!
* \brief Invalidates the instance data based on flags
*
* \param flags Flags to invalidate
*/
inline void InstancedRenderable::InvalidateInstanceData(UInt32 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)");
OnInstancedRenderableResetMaterials(this, matCount);
m_materials.clear();
m_materials.resize(matCount * skinCount, Material::GetDefault());
m_matCount = matCount;
m_skinCount = skinCount;
m_skin = 0;
}
/*!
* \brief Sets the current instanced renderable with the content of the other one
* \return A reference to this
*
* \param renderable The other InstancedRenderable
*/
inline InstancedRenderable& InstancedRenderable::operator=(const InstancedRenderable& renderable)
{
m_boundingVolume = renderable.m_boundingVolume;
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;
}
/*!
* \brief Updates the bounding volume
*/
inline void InstancedRenderable::UpdateBoundingVolume() const
{
MakeBoundingVolume();
m_boundingVolumeUpdated = true;
}
}
#include <Nazara/Graphics/DebugOff.hpp>