338 lines
10 KiB
C++
338 lines
10 KiB
C++
// 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 <Nazara/Graphics/ParticleDeclaration.hpp>
|
|
#include <Nazara/Core/Error.hpp>
|
|
#include <Nazara/Core/ErrorFlags.hpp>
|
|
#include <Nazara/Core/OffsetOf.hpp>
|
|
#include <Nazara/Graphics/Config.hpp>
|
|
#include <Nazara/Graphics/Enums.hpp>
|
|
#include <Nazara/Graphics/ParticleStruct.hpp>
|
|
#include <Nazara/Utility/Utility.hpp>
|
|
#include <cstring>
|
|
#include <Nazara/Graphics/Debug.hpp>
|
|
|
|
namespace Nz
|
|
{
|
|
/*!
|
|
* \ingroup graphics
|
|
* \class Nz::ParticleDeclaration
|
|
* \brief Graphics class that represents the declaration of the particle, works like an ECS
|
|
*/
|
|
|
|
/*!
|
|
* \brief Constructs a ParticleDeclaration object by default
|
|
*/
|
|
|
|
ParticleDeclaration::ParticleDeclaration() :
|
|
m_stride(0)
|
|
{
|
|
}
|
|
|
|
/*!
|
|
* \brief Constructs a ParticleDeclaration object by assignation
|
|
*
|
|
* \param declaration ParticleDeclaration to copy into this
|
|
*/
|
|
|
|
ParticleDeclaration::ParticleDeclaration(const ParticleDeclaration& declaration) :
|
|
RefCounted(),
|
|
m_components(declaration.m_components),
|
|
m_stride(declaration.m_stride)
|
|
{
|
|
}
|
|
|
|
/*!
|
|
* \brief Destructs the object and calls OnParticleDeclarationRelease
|
|
*
|
|
* \see OnParticleDeclarationRelease
|
|
*/
|
|
|
|
ParticleDeclaration::~ParticleDeclaration()
|
|
{
|
|
OnParticleDeclarationRelease(this);
|
|
}
|
|
|
|
/*!
|
|
* \brief Disables a component
|
|
*
|
|
* \param component Component to disable in the declaration
|
|
*
|
|
* \remark Produces a NazaraError with NAZARA_DEBUG defined if enumeration is invalid
|
|
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if enumeration is equal to ParticleComponent_Unused
|
|
*/
|
|
|
|
void ParticleDeclaration::DisableComponent(ParticleComponent component)
|
|
{
|
|
#ifdef NAZARA_DEBUG
|
|
if (component > ParticleComponent_Max)
|
|
{
|
|
NazaraError("Vertex component out of enum");
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
#if NAZARA_GRAPHICS_SAFE
|
|
if (component == ParticleComponent_Unused)
|
|
{
|
|
NazaraError("Cannot disable \"unused\" component");
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
Component& vertexComponent = m_components[component];
|
|
if (vertexComponent.enabled)
|
|
{
|
|
vertexComponent.enabled = false;
|
|
m_stride -= Utility::ComponentStride[vertexComponent.type];
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* \brief Enables a component
|
|
*
|
|
* \param component Component to enable in the declaration
|
|
* \param type Type of this component
|
|
* \param offset Offset in the declaration
|
|
*
|
|
* \remark Produces a NazaraError with NAZARA_DEBUG defined if enumeration is invalid
|
|
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if type is not supported
|
|
*/
|
|
|
|
void ParticleDeclaration::EnableComponent(ParticleComponent component, ComponentType type, unsigned int offset)
|
|
{
|
|
#ifdef NAZARA_DEBUG
|
|
if (component > ParticleComponent_Max)
|
|
{
|
|
NazaraError("Vertex component out of enum");
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
#if NAZARA_GRAPHICS_SAFE
|
|
if (!IsTypeSupported(type))
|
|
{
|
|
NazaraError("Component type 0x" + String::Number(type, 16) + " is not supported by particle declarations");
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (component != ParticleComponent_Unused)
|
|
{
|
|
Component& particleComponent = m_components[component];
|
|
if (particleComponent.enabled)
|
|
m_stride -= Utility::ComponentStride[particleComponent.type];
|
|
else
|
|
particleComponent.enabled = true;
|
|
|
|
particleComponent.offset = offset;
|
|
particleComponent.type = type;
|
|
}
|
|
|
|
m_stride += Utility::ComponentStride[type];
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets a component
|
|
*
|
|
* \param component Component in the declaration
|
|
* \param enabled Optional argument to get if this component is enabled
|
|
* \param type Optional argument to get if the type of the component
|
|
* \param offset Optional argument to get if the offset in the declaration
|
|
*
|
|
* \remark Produces a NazaraError with NAZARA_DEBUG defined if enumeration is invalid
|
|
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if enumeration is equal to ParticleComponent_Unused
|
|
*/
|
|
|
|
void ParticleDeclaration::GetComponent(ParticleComponent component, bool* enabled, ComponentType* type, unsigned int* offset) const
|
|
{
|
|
#ifdef NAZARA_DEBUG
|
|
if (component > ParticleComponent_Max)
|
|
{
|
|
NazaraError("Particle component out of enum");
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
#if NAZARA_GRAPHICS_SAFE
|
|
if (component == ParticleComponent_Unused)
|
|
{
|
|
NazaraError("Cannot get \"unused\" component");
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
const Component& particleComponent = m_components[component];
|
|
|
|
if (enabled)
|
|
*enabled = particleComponent.enabled;
|
|
|
|
if (type)
|
|
*type = particleComponent.type;
|
|
|
|
if (offset)
|
|
*offset = particleComponent.offset;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the stride of the declaration
|
|
* \return Stride of the declaration
|
|
*/
|
|
|
|
unsigned int ParticleDeclaration::GetStride() const
|
|
{
|
|
return m_stride;
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets the stride of the declaration
|
|
*
|
|
* \param stride Stride of the declaration
|
|
*/
|
|
|
|
void ParticleDeclaration::SetStride(unsigned int stride)
|
|
{
|
|
m_stride = stride;
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets the current particle declaration with the content of the other one
|
|
* \return A reference to this
|
|
*
|
|
* \param declaration The other ParticleDeclaration
|
|
*/
|
|
|
|
ParticleDeclaration& ParticleDeclaration::operator=(const ParticleDeclaration& declaration)
|
|
{
|
|
m_components = declaration.m_components;
|
|
m_stride = declaration.m_stride;
|
|
|
|
return *this;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the particle declaration based on the layout
|
|
* \return Pointer to the declaration
|
|
*
|
|
* \param layout Layout of the particle declaration
|
|
*
|
|
* \remark Produces a NazaraError with NAZARA_DEBUG if enumeration is invalid
|
|
*/
|
|
|
|
ParticleDeclaration* ParticleDeclaration::Get(ParticleLayout layout)
|
|
{
|
|
NazaraAssert(layout <= ParticleLayout_Max, "Particle layout out of enum");
|
|
|
|
return &s_declarations[layout];
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks whether the type is supported
|
|
* \return true If it is the case
|
|
*
|
|
* \param type Type of the component
|
|
*
|
|
* \remark Produces a NazaraError if enumeration is invalid
|
|
*/
|
|
|
|
bool ParticleDeclaration::IsTypeSupported(ComponentType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case ComponentType_Color:
|
|
case ComponentType_Double1:
|
|
case ComponentType_Double2:
|
|
case ComponentType_Double3:
|
|
case ComponentType_Double4:
|
|
case ComponentType_Float1:
|
|
case ComponentType_Float2:
|
|
case ComponentType_Float3:
|
|
case ComponentType_Float4:
|
|
case ComponentType_Int1:
|
|
case ComponentType_Int2:
|
|
case ComponentType_Int3:
|
|
case ComponentType_Int4:
|
|
case ComponentType_Quaternion:
|
|
return true;
|
|
}
|
|
|
|
NazaraError("Component type not handled (0x" + String::Number(type, 16) + ')');
|
|
return false;
|
|
}
|
|
|
|
/*!
|
|
* \brief Initializes the particle declaration librairies
|
|
* \return true If successful
|
|
*
|
|
* \remark Produces a NazaraError if the particle declaration library failed to be initialized
|
|
* \remark Produces a NazaraAssert if memory layout of declaration does not match the corresponding structure
|
|
*/
|
|
|
|
bool ParticleDeclaration::Initialize()
|
|
{
|
|
if (!ParticleDeclarationLibrary::Initialize())
|
|
{
|
|
NazaraError("Failed to initialise library");
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
ErrorFlags flags(ErrorFlag_Silent | ErrorFlag_ThrowException);
|
|
|
|
// Layout : Type
|
|
ParticleDeclaration* declaration;
|
|
|
|
// ParticleLayout_Billboard : ParticleStruct_Billboard
|
|
declaration = &s_declarations[ParticleLayout_Billboard];
|
|
declaration->EnableComponent(ParticleComponent_Color, ComponentType_Color, NazaraOffsetOf(ParticleStruct_Billboard, color));
|
|
declaration->EnableComponent(ParticleComponent_Life, ComponentType_Int1, NazaraOffsetOf(ParticleStruct_Billboard, life));
|
|
declaration->EnableComponent(ParticleComponent_Normal, ComponentType_Float3, NazaraOffsetOf(ParticleStruct_Billboard, normal));
|
|
declaration->EnableComponent(ParticleComponent_Position, ComponentType_Float3, NazaraOffsetOf(ParticleStruct_Billboard, position));
|
|
declaration->EnableComponent(ParticleComponent_Rotation, ComponentType_Float1, NazaraOffsetOf(ParticleStruct_Billboard, rotation));
|
|
declaration->EnableComponent(ParticleComponent_Velocity, ComponentType_Float3, NazaraOffsetOf(ParticleStruct_Billboard, velocity));
|
|
|
|
NazaraAssert(declaration->GetStride() == sizeof(ParticleStruct_Billboard), "Invalid stride for declaration ParticleLayout_Billboard");
|
|
|
|
// ParticleLayout_Model : ParticleStruct_Model
|
|
declaration = &s_declarations[ParticleLayout_Model];
|
|
declaration->EnableComponent(ParticleComponent_Life, ComponentType_Int1, NazaraOffsetOf(ParticleStruct_Model, life));
|
|
declaration->EnableComponent(ParticleComponent_Position, ComponentType_Float3, NazaraOffsetOf(ParticleStruct_Model, position));
|
|
declaration->EnableComponent(ParticleComponent_Rotation, ComponentType_Quaternion, NazaraOffsetOf(ParticleStruct_Model, rotation));
|
|
declaration->EnableComponent(ParticleComponent_Velocity, ComponentType_Float3, NazaraOffsetOf(ParticleStruct_Model, velocity));
|
|
|
|
NazaraAssert(declaration->GetStride() == sizeof(ParticleStruct_Model), "Invalid stride for declaration ParticleLayout_Model");
|
|
|
|
// ParticleLayout_Sprite : ParticleStruct_Sprite
|
|
declaration = &s_declarations[ParticleLayout_Sprite];
|
|
declaration->EnableComponent(ParticleComponent_Color, ComponentType_Color, NazaraOffsetOf(ParticleStruct_Sprite, color));
|
|
declaration->EnableComponent(ParticleComponent_Life, ComponentType_Int1, NazaraOffsetOf(ParticleStruct_Sprite, life));
|
|
declaration->EnableComponent(ParticleComponent_Position, ComponentType_Float2, NazaraOffsetOf(ParticleStruct_Sprite, position));
|
|
declaration->EnableComponent(ParticleComponent_Rotation, ComponentType_Float1, NazaraOffsetOf(ParticleStruct_Sprite, rotation));
|
|
declaration->EnableComponent(ParticleComponent_Velocity, ComponentType_Float2, NazaraOffsetOf(ParticleStruct_Sprite, velocity));
|
|
|
|
NazaraAssert(declaration->GetStride() == sizeof(ParticleStruct_Sprite), "Invalid stride for declaration ParticleLayout_Sprite");
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
NazaraError("Failed to initialize particle declarations: " + String(e.what()));
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*!
|
|
* \brief Uninitializes the particle declaration librairies
|
|
*/
|
|
|
|
void ParticleDeclaration::Uninitialize()
|
|
{
|
|
ParticleDeclarationLibrary::Uninitialize();
|
|
}
|
|
|
|
std::array<ParticleDeclaration, ParticleLayout_Max + 1> ParticleDeclaration::s_declarations;
|
|
ParticleDeclarationLibrary::LibraryMap ParticleDeclaration::s_library;
|
|
}
|