Added particles first implementation
Former-commit-id: 2b98ce2f007927690bdecd4092e211013bf568cb
This commit is contained in:
parent
4acd61cf30
commit
e9267d7f43
|
|
@ -43,6 +43,40 @@ enum nzMaterialUniform
|
|||
nzMaterialUniform_Max = nzMaterialUniform_SpecularMap
|
||||
};
|
||||
|
||||
enum nzParticleComponent
|
||||
{
|
||||
nzParticleComponent_Unused = -1,
|
||||
|
||||
nzParticleComponent_Color,
|
||||
nzParticleComponent_Life,
|
||||
nzParticleComponent_Normal,
|
||||
nzParticleComponent_Position,
|
||||
nzParticleComponent_Radius,
|
||||
nzParticleComponent_Rotation,
|
||||
nzParticleComponent_Size,
|
||||
nzParticleComponent_Velocity,
|
||||
nzParticleComponent_Userdata0,
|
||||
nzParticleComponent_Userdata1,
|
||||
nzParticleComponent_Userdata2,
|
||||
nzParticleComponent_Userdata3,
|
||||
nzParticleComponent_Userdata4,
|
||||
nzParticleComponent_Userdata5,
|
||||
nzParticleComponent_Userdata6,
|
||||
nzParticleComponent_Userdata7,
|
||||
nzParticleComponent_Userdata8,
|
||||
|
||||
nzParticleComponent_Max = nzParticleComponent_Userdata8
|
||||
};
|
||||
|
||||
enum nzParticleLayout
|
||||
{
|
||||
nzParticleLayout_Billboard,
|
||||
nzParticleLayout_Model,
|
||||
nzParticleLayout_Sprite,
|
||||
|
||||
nzParticleLayout_Max = nzParticleLayout_Sprite
|
||||
};
|
||||
|
||||
enum nzRenderPassType
|
||||
{
|
||||
nzRenderPassType_AA,
|
||||
|
|
@ -73,6 +107,7 @@ enum nzSceneNodeType
|
|||
{
|
||||
nzSceneNodeType_Light, // NzLight
|
||||
nzSceneNodeType_Model, // NzModel
|
||||
nzSceneNodeType_ParticleEmitter, // NzParticleEmitter
|
||||
nzSceneNodeType_Root, // NzSceneRoot
|
||||
nzSceneNodeType_Sprite, // NzSprite
|
||||
nzSceneNodeType_User,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (C) 2014 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
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_PARTICLECONTROLLER_HPP
|
||||
#define NAZARA_PARTICLECONTROLLER_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Core/Resource.hpp>
|
||||
#include <Nazara/Core/ResourceRef.hpp>
|
||||
|
||||
class NzParticleController;
|
||||
class NzParticleEmitter;
|
||||
class NzParticleMapper;
|
||||
|
||||
using NzParticleControllerConstRef = NzResourceRef<const NzParticleController>;
|
||||
using NzParticleControllerRef = NzResourceRef<NzParticleController>;
|
||||
|
||||
class NAZARA_API NzParticleController : public NzResource
|
||||
{
|
||||
public:
|
||||
NzParticleController() = default;
|
||||
NzParticleController(const NzParticleController& controller);
|
||||
virtual ~NzParticleController();
|
||||
|
||||
virtual void Apply(NzParticleEmitter& emitter, NzParticleMapper& mapper, unsigned int offset, unsigned int particleCount, float elapsedTime) = 0;
|
||||
};
|
||||
|
||||
#endif // NAZARA_PARTICLECONTROLLER_HPP
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright (C) 2014 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
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_PARTICLEDECLARATION_HPP
|
||||
#define NAZARA_PARTICLEDECLARATION_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Core/Resource.hpp>
|
||||
#include <Nazara/Core/ResourceRef.hpp>
|
||||
#include <Nazara/Graphics/Enums.hpp>
|
||||
#include <Nazara/Utility/Enums.hpp>
|
||||
|
||||
class NzParticleDeclaration;
|
||||
|
||||
using NzParticleDeclarationConstRef = NzResourceRef<const NzParticleDeclaration>;
|
||||
using NzParticleDeclarationRef = NzResourceRef<NzParticleDeclaration>;
|
||||
|
||||
class NAZARA_API NzParticleDeclaration : public NzResource
|
||||
{
|
||||
friend class NzGraphics;
|
||||
|
||||
public:
|
||||
NzParticleDeclaration();
|
||||
NzParticleDeclaration(const NzParticleDeclaration& declaration);
|
||||
~NzParticleDeclaration();
|
||||
|
||||
void DisableComponent(nzParticleComponent component);
|
||||
void EnableComponent(nzParticleComponent component, nzComponentType type, unsigned int offset);
|
||||
|
||||
void GetComponent(nzParticleComponent component, bool* enabled, nzComponentType* type, unsigned int* offset) const;
|
||||
unsigned int GetStride() const;
|
||||
|
||||
void SetStride(unsigned int stride);
|
||||
|
||||
NzParticleDeclaration& operator=(const NzParticleDeclaration& declaration);
|
||||
|
||||
static NzParticleDeclaration* Get(nzParticleLayout layout);
|
||||
static bool IsTypeSupported(nzComponentType type);
|
||||
|
||||
private:
|
||||
static bool Initialize();
|
||||
static void Uninitialize();
|
||||
|
||||
struct Component
|
||||
{
|
||||
nzComponentType type;
|
||||
bool enabled = false;
|
||||
unsigned int offset;
|
||||
|
||||
/*
|
||||
** -Lynix:
|
||||
** Il serait aussi possible de préciser le stride de façon indépendante, ce que je ne permets pas
|
||||
** pour décomplexifier l'interface en enlevant quelque chose que je juge inutile.
|
||||
** Si vous pensez que ça peut être utile, n'hésitez pas à me le faire savoir !
|
||||
*/
|
||||
};
|
||||
|
||||
Component m_components[nzParticleComponent_Max+1];
|
||||
unsigned int m_stride;
|
||||
|
||||
static NzParticleDeclaration s_declarations[nzParticleLayout_Max+1];
|
||||
};
|
||||
|
||||
#endif // NAZARA_PARTICLEDECLARATION_HPP
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
// Copyright (C) 2014 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
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_PARTICLEEMITTER_HPP
|
||||
#define NAZARA_PARTICLEEMITTER_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Core/Updatable.hpp>
|
||||
#include <Nazara/Graphics/ParticleController.hpp>
|
||||
#include <Nazara/Graphics/ParticleDeclaration.hpp>
|
||||
#include <Nazara/Graphics/ParticleGenerator.hpp>
|
||||
#include <Nazara/Graphics/ParticleRenderer.hpp>
|
||||
#include <Nazara/Graphics/SceneNode.hpp>
|
||||
#include <Nazara/Math/BoundingVolume.hpp>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
class NAZARA_API NzParticleEmitter : public NzSceneNode, NzUpdatable
|
||||
{
|
||||
public:
|
||||
NzParticleEmitter(unsigned int maxParticleCount, nzParticleLayout layout);
|
||||
NzParticleEmitter(unsigned int maxParticleCount, NzParticleDeclaration* declaration);
|
||||
NzParticleEmitter(const NzParticleEmitter& emitter);
|
||||
NzParticleEmitter(NzParticleEmitter&& emitter) = default;
|
||||
~NzParticleEmitter();
|
||||
|
||||
void AddController(NzParticleController* controller);
|
||||
void AddGenerator(NzParticleGenerator* generator);
|
||||
void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const;
|
||||
|
||||
void* CreateParticle();
|
||||
void* CreateParticles(unsigned int count);
|
||||
|
||||
void* GenerateParticle();
|
||||
void* GenerateParticles(unsigned int count);
|
||||
|
||||
const NzBoundingVolumef& GetBoundingVolume() const override;
|
||||
|
||||
unsigned int GetEmissionCount() const;
|
||||
float GetEmissionRate() const;
|
||||
unsigned int GetMaxParticleCount() const;
|
||||
unsigned int GetParticleCount() const;
|
||||
unsigned int GetParticleSize() const;
|
||||
|
||||
nzSceneNodeType GetSceneNodeType() const override;
|
||||
|
||||
bool IsDrawable() const;
|
||||
|
||||
void KillParticle(unsigned int index);
|
||||
void KillParticles();
|
||||
|
||||
void RemoveController(NzParticleController* controller);
|
||||
void RemoveGenerator(NzParticleGenerator* generator);
|
||||
|
||||
void SetEmissionCount(unsigned int count);
|
||||
void SetEmissionRate(float rate);
|
||||
void SetRenderer(NzParticleRenderer* renderer);
|
||||
|
||||
NzParticleEmitter& operator=(const NzParticleEmitter& emitter);
|
||||
NzParticleEmitter& operator=(NzParticleEmitter&& emitter);
|
||||
|
||||
private:
|
||||
void GenerateAABB() const;
|
||||
void Register() override;
|
||||
void ResizeBuffer();
|
||||
void Unregister() override;
|
||||
void UpdateBoundingVolume() const;
|
||||
void Update() override;
|
||||
|
||||
std::set<unsigned int, std::greater<unsigned int>> m_dyingParticles;
|
||||
mutable std::vector<nzUInt8> m_buffer;
|
||||
std::vector<NzParticleControllerRef> m_controllers;
|
||||
std::vector<NzParticleGeneratorRef> m_generators;
|
||||
mutable NzBoundingVolumef m_boundingVolume;
|
||||
NzParticleDeclarationConstRef m_declaration;
|
||||
NzParticleRendererRef m_renderer;
|
||||
mutable bool m_boundingVolumeUpdated;
|
||||
bool m_processing;
|
||||
float m_emissionAccumulator;
|
||||
float m_emissionRate;
|
||||
unsigned int m_emissionCount;
|
||||
unsigned int m_maxParticleCount;
|
||||
unsigned int m_particleCount;
|
||||
unsigned int m_particleSize;
|
||||
};
|
||||
|
||||
#endif // NAZARA_PARTICLEEMITTER_HPP
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (C) 2014 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
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_PARTICLEGENERATOR_HPP
|
||||
#define NAZARA_PARTICLEGENERATOR_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Core/Resource.hpp>
|
||||
#include <Nazara/Core/ResourceRef.hpp>
|
||||
|
||||
class NzParticleEmitter;
|
||||
class NzParticleGenerator;
|
||||
class NzParticleMapper;
|
||||
|
||||
using NzParticleGeneratorConstRef = NzResourceRef<const NzParticleGenerator>;
|
||||
using NzParticleGeneratorRef = NzResourceRef<NzParticleGenerator>;
|
||||
|
||||
class NAZARA_API NzParticleGenerator : public NzResource
|
||||
{
|
||||
public:
|
||||
NzParticleGenerator() = default;
|
||||
NzParticleGenerator(const NzParticleGenerator& generator);
|
||||
virtual ~NzParticleGenerator();
|
||||
|
||||
virtual void Generate(NzParticleEmitter& emitter, NzParticleMapper& mapper, unsigned int offset, unsigned int particleCount) = 0;
|
||||
};
|
||||
|
||||
#endif // NAZARA_PARTICLEGENERATOR_HPP
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (C) 2014 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
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_PARTICLEMAPPER_HPP
|
||||
#define NAZARA_PARTICLEMAPPER_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Core/SparsePtr.hpp>
|
||||
#include <Nazara/Graphics/Enums.hpp>
|
||||
#include <Nazara/Graphics/ParticleDeclaration.hpp>
|
||||
|
||||
class NAZARA_API NzParticleMapper
|
||||
{
|
||||
public:
|
||||
NzParticleMapper(void* buffer, const NzParticleDeclaration* declaration);
|
||||
~NzParticleMapper();
|
||||
|
||||
template<typename T> NzSparsePtr<T> GetComponentPtr(nzParticleComponent component);
|
||||
template<typename T> NzSparsePtr<const T> GetComponentPtr(nzParticleComponent component) const;
|
||||
|
||||
private:
|
||||
const NzParticleDeclaration* m_declaration;
|
||||
nzUInt8* m_ptr;
|
||||
};
|
||||
|
||||
#include <Nazara/Graphics/ParticleMapper.inl>
|
||||
|
||||
#endif // NAZARA_PARTICLEMAPPER_HPP
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright (C) 2014 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/Core/Error.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
template <typename T>
|
||||
NzSparsePtr<T> NzParticleMapper::GetComponentPtr(nzParticleComponent component)
|
||||
{
|
||||
// Ensuite le composant qui nous intéresse
|
||||
bool enabled;
|
||||
nzComponentType type;
|
||||
unsigned int offset;
|
||||
m_declaration->GetComponent(component, &enabled, &type, &offset);
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
///TODO: Vérifier le rapport entre le type de l'attribut et le type template ?
|
||||
return NzSparsePtr<T>(m_ptr + offset, m_declaration->GetStride());
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraError("Attribute 0x" + NzString::Number(component, 16) + " is not enabled");
|
||||
return NzSparsePtr<T>();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
NzSparsePtr<const T> NzParticleMapper::GetComponentPtr(nzParticleComponent component) const
|
||||
{
|
||||
// Ensuite le composant qui nous intéresse
|
||||
bool enabled;
|
||||
nzComponentType type;
|
||||
unsigned int offset;
|
||||
m_declaration->GetComponent(component, &enabled, &type, &offset);
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
///TODO: Vérifier le rapport entre le type de l'attribut et le type template ?
|
||||
return NzSparsePtr<const T>(m_ptr + offset, m_declaration->GetStride());
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraError("Attribute 0x" + NzString::Number(component, 16) + " is not enabled");
|
||||
return NzSparsePtr<const T>();
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/DebugOff.hpp>
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (C) 2014 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
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_PARTICLERENDERER_HPP
|
||||
#define NAZARA_PARTICLERENDERER_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Core/Resource.hpp>
|
||||
#include <Nazara/Core/ResourceRef.hpp>
|
||||
|
||||
class NzAbstractRenderQueue;
|
||||
class NzParticleEmitter;
|
||||
class NzParticleMapper;
|
||||
class NzParticleRenderer;
|
||||
|
||||
using NzParticleRendererConstRef = NzResourceRef<const NzParticleRenderer>;
|
||||
using NzParticleRendererRef = NzResourceRef<NzParticleRenderer>;
|
||||
|
||||
class NAZARA_API NzParticleRenderer : public NzResource
|
||||
{
|
||||
public:
|
||||
NzParticleRenderer() = default;
|
||||
NzParticleRenderer(const NzParticleRenderer& renderer);
|
||||
virtual ~NzParticleRenderer();
|
||||
|
||||
virtual void Render(const NzParticleEmitter& emitter, const NzParticleMapper& mapper, unsigned int offset, unsigned int particleCount, NzAbstractRenderQueue* renderQueue) = 0;
|
||||
};
|
||||
|
||||
#endif // NAZARA_PARTICLERENDERER_HPP
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright (C) 2014 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
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_PARTICLESTRUCT_HPP
|
||||
#define NAZARA_PARTICLESTRUCT_HPP
|
||||
|
||||
#include <Nazara/Core/Color.hpp>
|
||||
#include <Nazara/Math/Quaternion.hpp>
|
||||
#include <Nazara/Math/Vector2.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
|
||||
struct NzParticleStruct_Billboard
|
||||
{
|
||||
NzColor color;
|
||||
NzVector3f normal;
|
||||
NzVector3f position;
|
||||
NzVector3f velocity;
|
||||
nzUInt32 life;
|
||||
float rotation;
|
||||
};
|
||||
|
||||
struct NzParticleStruct_Model
|
||||
{
|
||||
NzVector3f position;
|
||||
NzVector3f velocity;
|
||||
nzUInt32 life;
|
||||
NzQuaternionf rotation;
|
||||
};
|
||||
|
||||
struct NzParticleStruct_Sprite
|
||||
{
|
||||
NzColor color;
|
||||
NzVector2f position;
|
||||
NzVector2f velocity;
|
||||
nzUInt32 life;
|
||||
float rotation;
|
||||
};
|
||||
|
||||
#endif // NAZARA_PARTICLESTRUCT_HPP
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
#include <Nazara/Graphics/DeferredRenderTechnique.hpp>
|
||||
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
|
||||
#include <Nazara/Graphics/Material.hpp>
|
||||
#include <Nazara/Graphics/ParticleDeclaration.hpp>
|
||||
#include <Nazara/Graphics/RenderTechniques.hpp>
|
||||
#include <Nazara/Graphics/SkinningManager.hpp>
|
||||
#include <Nazara/Graphics/Loaders/Mesh.hpp>
|
||||
|
|
@ -44,6 +45,12 @@ bool NzGraphics::Initialize()
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!NzParticleDeclaration::Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialize particle declarations");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!NzSkinningManager::Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialize skinning manager");
|
||||
|
|
@ -98,6 +105,7 @@ void NzGraphics::Uninitialize()
|
|||
|
||||
NzDeferredRenderTechnique::Uninitialize();
|
||||
NzMaterial::Uninitialize();
|
||||
NzParticleDeclaration::Uninitialize();
|
||||
NzSkinningManager::Uninitialize();
|
||||
|
||||
NazaraNotice("Uninitialized: Graphics module");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (C) 2014 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/ParticleController.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
NzParticleController::NzParticleController(const NzParticleController& controller) :
|
||||
NzResource()
|
||||
{
|
||||
NazaraUnused(controller);
|
||||
}
|
||||
|
||||
NzParticleController::~NzParticleController() = default;
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
// Copyright (C) 2014 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>
|
||||
|
||||
NzParticleDeclaration::NzParticleDeclaration() :
|
||||
m_stride(0)
|
||||
{
|
||||
}
|
||||
|
||||
NzParticleDeclaration::NzParticleDeclaration(const NzParticleDeclaration& declaration) :
|
||||
NzResource(),
|
||||
m_stride(declaration.m_stride)
|
||||
{
|
||||
std::memcpy(m_components, declaration.m_components, sizeof(Component)*(nzParticleComponent_Max+1));
|
||||
}
|
||||
|
||||
NzParticleDeclaration::~NzParticleDeclaration()
|
||||
{
|
||||
NotifyDestroy();
|
||||
}
|
||||
|
||||
void NzParticleDeclaration::DisableComponent(nzParticleComponent component)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (component > nzParticleComponent_Max)
|
||||
{
|
||||
NazaraError("Vertex component out of enum");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
if (component == nzParticleComponent_Unused)
|
||||
{
|
||||
NazaraError("Cannot disable \"unused\" component");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Component& vertexComponent = m_components[component];
|
||||
if (vertexComponent.enabled)
|
||||
{
|
||||
vertexComponent.enabled = false;
|
||||
m_stride -= NzUtility::ComponentStride[vertexComponent.type];
|
||||
}
|
||||
}
|
||||
|
||||
void NzParticleDeclaration::EnableComponent(nzParticleComponent component, nzComponentType type, unsigned int offset)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (component > nzParticleComponent_Max)
|
||||
{
|
||||
NazaraError("Vertex component out of enum");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
if (!IsTypeSupported(type))
|
||||
{
|
||||
NazaraError("Component type 0x" + NzString::Number(type, 16) + " is not supported by particle declarations");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (component != nzParticleComponent_Unused)
|
||||
{
|
||||
Component& particleComponent = m_components[component];
|
||||
if (particleComponent.enabled)
|
||||
m_stride -= NzUtility::ComponentStride[particleComponent.type];
|
||||
else
|
||||
particleComponent.enabled = true;
|
||||
|
||||
particleComponent.offset = offset;
|
||||
particleComponent.type = type;
|
||||
}
|
||||
|
||||
m_stride += NzUtility::ComponentStride[type];
|
||||
}
|
||||
|
||||
void NzParticleDeclaration::GetComponent(nzParticleComponent component, bool* enabled, nzComponentType* type, unsigned int* offset) const
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (component > nzParticleComponent_Max)
|
||||
{
|
||||
NazaraError("Particle component out of enum");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
if (component == nzParticleComponent_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;
|
||||
}
|
||||
|
||||
unsigned int NzParticleDeclaration::GetStride() const
|
||||
{
|
||||
return m_stride;
|
||||
}
|
||||
|
||||
void NzParticleDeclaration::SetStride(unsigned int stride)
|
||||
{
|
||||
m_stride = stride;
|
||||
}
|
||||
|
||||
NzParticleDeclaration& NzParticleDeclaration::operator=(const NzParticleDeclaration& declaration)
|
||||
{
|
||||
std::memcpy(m_components, declaration.m_components, sizeof(Component)*(nzParticleComponent_Max+1));
|
||||
m_stride = declaration.m_stride;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzParticleDeclaration* NzParticleDeclaration::Get(nzParticleLayout layout)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (layout > nzParticleLayout_Max)
|
||||
{
|
||||
NazaraError("Particle layout out of enum");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
return &s_declarations[layout];
|
||||
}
|
||||
|
||||
bool NzParticleDeclaration::IsTypeSupported(nzComponentType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case nzComponentType_Color:
|
||||
case nzComponentType_Double1:
|
||||
case nzComponentType_Double2:
|
||||
case nzComponentType_Double3:
|
||||
case nzComponentType_Double4:
|
||||
case nzComponentType_Float1:
|
||||
case nzComponentType_Float2:
|
||||
case nzComponentType_Float3:
|
||||
case nzComponentType_Float4:
|
||||
case nzComponentType_Int1:
|
||||
case nzComponentType_Int2:
|
||||
case nzComponentType_Int3:
|
||||
case nzComponentType_Int4:
|
||||
case nzComponentType_Quaternion:
|
||||
return true;
|
||||
}
|
||||
|
||||
NazaraError("Component type not handled (0x" + NzString::Number(type, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NzParticleDeclaration::Initialize()
|
||||
{
|
||||
try
|
||||
{
|
||||
NzErrorFlags flags(nzErrorFlag_Silent | nzErrorFlag_ThrowException);
|
||||
|
||||
// Layout : Type
|
||||
NzParticleDeclaration* declaration;
|
||||
|
||||
// nzParticleLayout_Billboard : NzParticleStruct_Billboard
|
||||
declaration = &s_declarations[nzParticleLayout_Billboard];
|
||||
declaration->EnableComponent(nzParticleComponent_Color, nzComponentType_Color, NzOffsetOf(NzParticleStruct_Billboard, color));
|
||||
declaration->EnableComponent(nzParticleComponent_Life, nzComponentType_Int1, NzOffsetOf(NzParticleStruct_Billboard, life));
|
||||
declaration->EnableComponent(nzParticleComponent_Normal, nzComponentType_Float3, NzOffsetOf(NzParticleStruct_Billboard, normal));
|
||||
declaration->EnableComponent(nzParticleComponent_Position, nzComponentType_Float3, NzOffsetOf(NzParticleStruct_Billboard, position));
|
||||
declaration->EnableComponent(nzParticleComponent_Rotation, nzComponentType_Float1, NzOffsetOf(NzParticleStruct_Billboard, rotation));
|
||||
declaration->EnableComponent(nzParticleComponent_Velocity, nzComponentType_Float3, NzOffsetOf(NzParticleStruct_Billboard, velocity));
|
||||
|
||||
NazaraAssert(declaration->GetStride() == sizeof(NzParticleStruct_Billboard), "Invalid stride for declaration nzParticleLayout_Billboard");
|
||||
|
||||
// nzParticleLayout_Model : NzParticleStruct_Model
|
||||
declaration = &s_declarations[nzParticleLayout_Model];
|
||||
declaration->EnableComponent(nzParticleComponent_Life, nzComponentType_Int1, NzOffsetOf(NzParticleStruct_Model, life));
|
||||
declaration->EnableComponent(nzParticleComponent_Position, nzComponentType_Float3, NzOffsetOf(NzParticleStruct_Model, position));
|
||||
declaration->EnableComponent(nzParticleComponent_Rotation, nzComponentType_Quaternion, NzOffsetOf(NzParticleStruct_Model, rotation));
|
||||
declaration->EnableComponent(nzParticleComponent_Velocity, nzComponentType_Float3, NzOffsetOf(NzParticleStruct_Model, velocity));
|
||||
|
||||
NazaraAssert(declaration->GetStride() == sizeof(NzParticleStruct_Model), "Invalid stride for declaration nzParticleLayout_Model");
|
||||
|
||||
// nzParticleLayout_Sprite : NzParticleStruct_Sprite
|
||||
declaration = &s_declarations[nzParticleLayout_Sprite];
|
||||
declaration->EnableComponent(nzParticleComponent_Color, nzComponentType_Color, NzOffsetOf(NzParticleStruct_Sprite, color));
|
||||
declaration->EnableComponent(nzParticleComponent_Life, nzComponentType_Int1, NzOffsetOf(NzParticleStruct_Sprite, life));
|
||||
declaration->EnableComponent(nzParticleComponent_Position, nzComponentType_Float2, NzOffsetOf(NzParticleStruct_Sprite, position));
|
||||
declaration->EnableComponent(nzParticleComponent_Rotation, nzComponentType_Float1, NzOffsetOf(NzParticleStruct_Sprite, rotation));
|
||||
declaration->EnableComponent(nzParticleComponent_Velocity, nzComponentType_Float2, NzOffsetOf(NzParticleStruct_Sprite, velocity));
|
||||
|
||||
NazaraAssert(declaration->GetStride() == sizeof(NzParticleStruct_Sprite), "Invalid stride for declaration nzParticleLayout_Sprite");
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
NazaraError("Failed to initialize particle declarations: " + NzString(e.what()));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzParticleDeclaration::Uninitialize()
|
||||
{
|
||||
// Rien à faire
|
||||
}
|
||||
|
||||
NzParticleDeclaration NzParticleDeclaration::s_declarations[nzParticleLayout_Max+1];
|
||||
|
|
@ -0,0 +1,361 @@
|
|||
// Copyright (C) 2014 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/ParticleEmitter.hpp>
|
||||
#include <Nazara/Core/CallOnExit.hpp>
|
||||
#include <Nazara/Core/ErrorFlags.hpp>
|
||||
#include <Nazara/Core/StringStream.hpp>
|
||||
#include <Nazara/Graphics/ParticleMapper.hpp>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
NzParticleEmitter::NzParticleEmitter(unsigned int maxParticleCount, nzParticleLayout layout) :
|
||||
NzParticleEmitter(maxParticleCount, NzParticleDeclaration::Get(layout))
|
||||
{
|
||||
}
|
||||
|
||||
NzParticleEmitter::NzParticleEmitter(unsigned int maxParticleCount, NzParticleDeclaration* declaration) :
|
||||
m_declaration(declaration),
|
||||
m_boundingVolumeUpdated(false),
|
||||
m_emissionAccumulator(0.f),
|
||||
m_emissionRate(0.f),
|
||||
m_emissionCount(1),
|
||||
m_maxParticleCount(maxParticleCount),
|
||||
m_particleCount(0)
|
||||
{
|
||||
// En cas d'erreur, un constructeur ne peut que lancer une exception
|
||||
NzErrorFlags flags(nzErrorFlag_ThrowException, true);
|
||||
|
||||
m_particleSize = m_declaration->GetStride(); // La taille de chaque particule
|
||||
|
||||
ResizeBuffer();
|
||||
}
|
||||
|
||||
NzParticleEmitter::NzParticleEmitter(const NzParticleEmitter& emitter) :
|
||||
NzSceneNode(emitter),
|
||||
m_controllers(emitter.m_controllers),
|
||||
m_generators(emitter.m_generators),
|
||||
m_boundingVolume(emitter.m_boundingVolume),
|
||||
m_declaration(emitter.m_declaration),
|
||||
m_renderer(emitter.m_renderer),
|
||||
m_boundingVolumeUpdated(emitter.m_boundingVolumeUpdated),
|
||||
m_processing(false),
|
||||
m_emissionAccumulator(0.f),
|
||||
m_emissionRate(emitter.m_emissionRate),
|
||||
m_emissionCount(emitter.m_emissionCount),
|
||||
m_maxParticleCount(emitter.m_maxParticleCount),
|
||||
m_particleCount(emitter.m_particleCount),
|
||||
m_particleSize(emitter.m_particleSize)
|
||||
{
|
||||
NzErrorFlags flags(nzErrorFlag_ThrowException, true);
|
||||
|
||||
ResizeBuffer();
|
||||
|
||||
// On ne copie que les particules vivantes
|
||||
std::memcpy(m_buffer.data(), emitter.m_buffer.data(), emitter.m_particleCount*m_particleSize);
|
||||
}
|
||||
|
||||
NzParticleEmitter::~NzParticleEmitter() = default;
|
||||
|
||||
void NzParticleEmitter::AddController(NzParticleController* controller)
|
||||
{
|
||||
m_controllers.emplace_back(controller);
|
||||
}
|
||||
|
||||
void NzParticleEmitter::AddGenerator(NzParticleGenerator* generator)
|
||||
{
|
||||
m_generators.emplace_back(generator);
|
||||
}
|
||||
|
||||
void NzParticleEmitter::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const
|
||||
{
|
||||
///FIXME: Vérifier le renderer
|
||||
NzParticleMapper mapper(m_buffer.data(), m_declaration);
|
||||
|
||||
m_renderer->Render(*this, mapper, 0, m_particleCount, renderQueue);
|
||||
}
|
||||
|
||||
void* NzParticleEmitter::CreateParticle()
|
||||
{
|
||||
return CreateParticles(1);
|
||||
}
|
||||
|
||||
void* NzParticleEmitter::CreateParticles(unsigned int count)
|
||||
{
|
||||
if (m_particleCount+count > m_maxParticleCount)
|
||||
return nullptr;
|
||||
|
||||
unsigned int particlesIndex = m_particleCount;
|
||||
m_particleCount += count;
|
||||
|
||||
return &m_buffer[particlesIndex*m_particleSize];
|
||||
}
|
||||
|
||||
void* NzParticleEmitter::GenerateParticle()
|
||||
{
|
||||
return GenerateParticles(1);
|
||||
}
|
||||
|
||||
void* NzParticleEmitter::GenerateParticles(unsigned int count)
|
||||
{
|
||||
void* ptr = CreateParticles(count);
|
||||
if (!ptr)
|
||||
return nullptr;
|
||||
|
||||
NzParticleMapper mapper(ptr, m_declaration);
|
||||
for (NzParticleGenerator* generator : m_generators)
|
||||
generator->Generate(*this, mapper, 0, m_particleCount);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
const NzBoundingVolumef& NzParticleEmitter::GetBoundingVolume() const
|
||||
{
|
||||
if (!m_boundingVolumeUpdated)
|
||||
UpdateBoundingVolume();
|
||||
|
||||
return m_boundingVolume;
|
||||
}
|
||||
|
||||
unsigned int NzParticleEmitter::GetEmissionCount() const
|
||||
{
|
||||
return m_emissionCount;
|
||||
}
|
||||
|
||||
float NzParticleEmitter::GetEmissionRate() const
|
||||
{
|
||||
return m_emissionRate;
|
||||
}
|
||||
|
||||
unsigned int NzParticleEmitter::GetMaxParticleCount() const
|
||||
{
|
||||
return m_maxParticleCount;
|
||||
}
|
||||
|
||||
unsigned int NzParticleEmitter::GetParticleCount() const
|
||||
{
|
||||
return m_particleCount;
|
||||
}
|
||||
|
||||
unsigned int NzParticleEmitter::GetParticleSize() const
|
||||
{
|
||||
return m_particleSize;
|
||||
}
|
||||
|
||||
nzSceneNodeType NzParticleEmitter::GetSceneNodeType() const
|
||||
{
|
||||
return nzSceneNodeType_ParticleEmitter;
|
||||
}
|
||||
|
||||
bool NzParticleEmitter::IsDrawable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzParticleEmitter::KillParticle(unsigned int index)
|
||||
{
|
||||
///FIXME: Vérifier index
|
||||
|
||||
if (m_processing)
|
||||
{
|
||||
// Le buffer est en train d'être modifié, nous ne pouvons pas réduire sa taille, on place alors la particule dans une liste de secours
|
||||
m_dyingParticles.insert(index);
|
||||
return;
|
||||
}
|
||||
|
||||
// On déplace la dernière particule vivante à la place de celle-ci
|
||||
if (--m_particleCount > 0)
|
||||
std::memcpy(&m_buffer[index*m_particleSize], &m_buffer[m_particleCount*m_particleSize], m_particleSize);
|
||||
}
|
||||
|
||||
void NzParticleEmitter::KillParticles()
|
||||
{
|
||||
m_particleCount = 0;
|
||||
}
|
||||
|
||||
void NzParticleEmitter::RemoveController(NzParticleController* controller)
|
||||
{
|
||||
auto it = std::find(m_controllers.begin(), m_controllers.end(), controller);
|
||||
if (it != m_controllers.end())
|
||||
m_controllers.erase(it);
|
||||
}
|
||||
|
||||
void NzParticleEmitter::RemoveGenerator(NzParticleGenerator* generator)
|
||||
{
|
||||
auto it = std::find(m_generators.begin(), m_generators.end(), generator);
|
||||
if (it != m_generators.end())
|
||||
m_generators.erase(it);
|
||||
}
|
||||
|
||||
void NzParticleEmitter::SetEmissionCount(unsigned int count)
|
||||
{
|
||||
m_emissionCount = count;
|
||||
}
|
||||
|
||||
void NzParticleEmitter::SetEmissionRate(float rate)
|
||||
{
|
||||
m_emissionRate = rate;
|
||||
}
|
||||
|
||||
void NzParticleEmitter::SetRenderer(NzParticleRenderer* renderer)
|
||||
{
|
||||
m_renderer = renderer;
|
||||
}
|
||||
|
||||
NzParticleEmitter& NzParticleEmitter::operator=(const NzParticleEmitter& emitter)
|
||||
{
|
||||
NzErrorFlags flags(nzErrorFlag_ThrowException, true);
|
||||
|
||||
NzSceneNode::operator=(emitter);
|
||||
|
||||
m_boundingVolume = emitter.m_boundingVolume;
|
||||
m_boundingVolumeUpdated = emitter.m_boundingVolumeUpdated;
|
||||
m_controllers = emitter.m_controllers;
|
||||
m_declaration = emitter.m_declaration;
|
||||
m_emissionCount = emitter.m_emissionCount;
|
||||
m_emissionRate = emitter.m_emissionRate;
|
||||
m_generators = emitter.m_generators;
|
||||
m_maxParticleCount = emitter.m_maxParticleCount;
|
||||
m_particleCount = emitter.m_particleCount;
|
||||
m_particleSize = emitter.m_particleSize;
|
||||
m_renderer = emitter.m_renderer;
|
||||
|
||||
// La copie ne peut pas (ou plutôt ne devrait pas) avoir lieu pendant une mise à jour, inutile de copier
|
||||
m_dyingParticles.clear();
|
||||
m_emissionAccumulator = 0.f;
|
||||
m_processing = false;
|
||||
|
||||
m_buffer.clear(); // Pour éviter une recopie lors du resize() qui ne servira pas à grand chose
|
||||
ResizeBuffer();
|
||||
|
||||
// On ne copie que les particules vivantes
|
||||
std::memcpy(m_buffer.data(), emitter.m_buffer.data(), emitter.m_particleCount*m_particleSize);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzParticleEmitter& NzParticleEmitter::operator=(NzParticleEmitter&& emitter)
|
||||
{
|
||||
NzErrorFlags flags(nzErrorFlag_ThrowException, true);
|
||||
|
||||
NzSceneNode::operator=(emitter);
|
||||
|
||||
m_boundingVolume = std::move(emitter.m_boundingVolume);
|
||||
m_boundingVolumeUpdated = std::move(emitter.m_boundingVolumeUpdated);
|
||||
m_buffer = std::move(emitter.m_buffer);
|
||||
m_controllers = std::move(emitter.m_controllers);
|
||||
m_declaration = std::move(emitter.m_declaration);
|
||||
m_dyingParticles = std::move(emitter.m_dyingParticles);
|
||||
m_emissionAccumulator = std::move(emitter.m_emissionAccumulator);
|
||||
m_emissionCount = std::move(emitter.m_emissionCount);
|
||||
m_emissionRate = std::move(emitter.m_emissionRate);
|
||||
m_generators = std::move(emitter.m_generators);
|
||||
m_maxParticleCount = std::move(emitter.m_maxParticleCount);
|
||||
m_particleCount = std::move(emitter.m_particleCount);
|
||||
m_particleSize = std::move(emitter.m_particleSize);
|
||||
m_processing = std::move(emitter.m_processing);
|
||||
m_renderer = std::move(emitter.m_renderer);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void NzParticleEmitter::GenerateAABB() const
|
||||
{
|
||||
m_boundingVolume.MakeInfinite();
|
||||
}
|
||||
|
||||
void NzParticleEmitter::Register()
|
||||
{
|
||||
m_scene->RegisterForUpdate(this);
|
||||
}
|
||||
|
||||
void NzParticleEmitter::ResizeBuffer()
|
||||
{
|
||||
// Histoire de décrire un peu mieux l'erreur en cas d'échec
|
||||
try
|
||||
{
|
||||
m_buffer.resize(m_maxParticleCount*m_particleSize);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
NzStringStream stream;
|
||||
stream << "Failed to allocate particle buffer (" << e.what() << ") for " << m_maxParticleCount << " particles of size " << m_particleSize;
|
||||
|
||||
NazaraError(stream.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
void NzParticleEmitter::Unregister()
|
||||
{
|
||||
m_scene->UnregisterForUpdate(this);
|
||||
}
|
||||
|
||||
void NzParticleEmitter::UpdateBoundingVolume() const
|
||||
{
|
||||
if (m_boundingVolume.IsNull())
|
||||
GenerateAABB();
|
||||
|
||||
if (!m_transformMatrixUpdated)
|
||||
UpdateTransformMatrix();
|
||||
|
||||
m_boundingVolume.Update(m_transformMatrix);
|
||||
m_boundingVolumeUpdated = true;
|
||||
}
|
||||
|
||||
void NzParticleEmitter::Update()
|
||||
{
|
||||
float elapsedTime = m_scene->GetUpdateTime();
|
||||
|
||||
if (m_emissionRate > 0.f)
|
||||
{
|
||||
// On accumule la partie réelle (pour éviter qu'un taux d'update élevé empêche des particules de se former)
|
||||
m_emissionAccumulator += elapsedTime*m_emissionRate;
|
||||
|
||||
float emissionCount = std::floor(m_emissionAccumulator); // Le nombre d'émissions de cette mise à jour
|
||||
m_emissionAccumulator -= emissionCount; // On enlève la partie entière
|
||||
|
||||
if (emissionCount >= 1.f)
|
||||
{
|
||||
// On calcule le nombre maximum de particules pouvant être émises cette fois-ci
|
||||
unsigned int maxParticleCount = static_cast<unsigned int>(emissionCount)*m_emissionCount;
|
||||
|
||||
// On récupère le nombre de particules qu'il est possible de créer selon l'espace libre
|
||||
unsigned int particleCount = std::min(maxParticleCount, m_maxParticleCount - m_particleCount);
|
||||
|
||||
// Et on émet nos particules
|
||||
GenerateParticles(particleCount);
|
||||
}
|
||||
}
|
||||
|
||||
NzParticleMapper mapper(m_buffer.data(), m_declaration);
|
||||
|
||||
m_processing = true;
|
||||
|
||||
// Pour éviter un verrouillage en cas d'exception
|
||||
NzCallOnExit onExit([this]()
|
||||
{
|
||||
m_processing = false;
|
||||
});
|
||||
|
||||
for (NzParticleController* controller : m_controllers)
|
||||
controller->Apply(*this, mapper, 0, m_particleCount, elapsedTime);
|
||||
|
||||
m_processing = false;
|
||||
onExit.Reset();
|
||||
|
||||
// On tue maintenant les particules mortes durant la mise à jour
|
||||
if (m_dyingParticles.size() < m_particleCount)
|
||||
{
|
||||
// On tue les particules depuis la dernière vers la première (en terme de place), le std::set étant trié via std::greater
|
||||
// La raison est simple, étant donné que la mort d'une particule signifie le déplacement de la dernière particule du buffer,
|
||||
// sans cette solution certaines particules pourraient échapper à la mort
|
||||
for (unsigned int index : m_dyingParticles)
|
||||
KillParticle(index);
|
||||
}
|
||||
else
|
||||
KillParticles(); // Toutes les particules sont mortes, ceci est beaucoup plus rapide
|
||||
|
||||
m_dyingParticles.clear();
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (C) 2014 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/ParticleGenerator.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
NzParticleGenerator::NzParticleGenerator(const NzParticleGenerator& generator) :
|
||||
NzResource()
|
||||
{
|
||||
NazaraUnused(generator);
|
||||
}
|
||||
|
||||
NzParticleGenerator::~NzParticleGenerator() = default;
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright (C) 2014 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/ParticleMapper.hpp>
|
||||
#include <Nazara/Core/ErrorFlags.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
NzParticleMapper::NzParticleMapper(void* buffer, const NzParticleDeclaration* declaration) :
|
||||
m_declaration(declaration),
|
||||
m_ptr(static_cast<nzUInt8*>(buffer))
|
||||
{
|
||||
}
|
||||
|
||||
NzParticleMapper::~NzParticleMapper() = default;
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (C) 2014 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/ParticleRenderer.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
NzParticleRenderer::NzParticleRenderer(const NzParticleRenderer& renderer) :
|
||||
NzResource()
|
||||
{
|
||||
NazaraUnused(renderer);
|
||||
}
|
||||
|
||||
NzParticleRenderer::~NzParticleRenderer() = default;
|
||||
Loading…
Reference in New Issue