mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-08-15 14:43:32 -07:00
Removes std::shared_ptr usages from particles
This commit is contained in:
parent
d2375de187
commit
5778ef6cac
8 changed files with 127 additions and 102 deletions
|
|
@ -112,7 +112,14 @@ bool CObjectEntry::BuildVariation(const std::vector<const std::set<CStr>*>& comp
|
|||
|
||||
if (!variation.particles.empty())
|
||||
{
|
||||
m_Model = std::make_unique<CModelParticleEmitter>(g_Renderer.GetSceneRenderer().GetParticleManager().LoadEmitterType(variation.particles));
|
||||
CParticleEmitterType* particleEmitterType{
|
||||
g_Renderer.GetSceneRenderer().GetParticleManager().LoadEmitterType(variation.particles)};
|
||||
if (!particleEmitterType)
|
||||
{
|
||||
LOGERROR("CObjectEntry::BuildVariation(): Failed to load particles %s", variation.particles.string8());
|
||||
return false;
|
||||
}
|
||||
m_Model = std::make_unique<CModelParticleEmitter>(*particleEmitterType);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -75,14 +75,14 @@ struct ParticleClosestInFrontCompare
|
|||
|
||||
} // anonymous namespace
|
||||
|
||||
CParticleEmitter::CParticleEmitter(const CParticleEmitterTypePtr& type) :
|
||||
m_Type(type), m_LastUpdateTime(type->m_Manager.GetCurrentTime()),
|
||||
CParticleEmitter::CParticleEmitter(const CParticleEmitterType& type) :
|
||||
m_Type(type), m_LastUpdateTime(type.m_Manager.GetCurrentTime()),
|
||||
m_IndexArray(Renderer::Backend::IBuffer::Usage::TRANSFER_DST),
|
||||
m_VertexArray(Renderer::Backend::IBuffer::Type::VERTEX,
|
||||
Renderer::Backend::IBuffer::Usage::DYNAMIC | Renderer::Backend::IBuffer::Usage::TRANSFER_DST),
|
||||
m_VertexUVArray(Renderer::Backend::IBuffer::Type::VERTEX,
|
||||
Renderer::Backend::IBuffer::Usage::TRANSFER_DST),
|
||||
m_LastFrameNumber(-1), m_UseInstancing{type->m_Manager.ShouldUseInstancing()}
|
||||
m_LastFrameNumber(-1), m_UseInstancing{type.m_Manager.ShouldUseInstancing()}
|
||||
{
|
||||
// If we should start with particles fully emitted, pretend that we
|
||||
// were created in the past so the first update will produce lots of
|
||||
|
|
@ -91,10 +91,10 @@ CParticleEmitter::CParticleEmitter(const CParticleEmitterTypePtr& type) :
|
|||
// lifetime-length update of all emitters when the game first starts
|
||||
// (so that e.g. buildings constructed later on won't have fully-started
|
||||
// emitters, but those at the start will)?
|
||||
if (m_Type->m_StartFull)
|
||||
m_LastUpdateTime -= m_Type->m_MaxLifetime;
|
||||
if (m_Type.m_StartFull)
|
||||
m_LastUpdateTime -= m_Type.m_MaxLifetime;
|
||||
|
||||
m_Particles.reserve(m_Type->m_MaxParticles);
|
||||
m_Particles.reserve(m_Type.m_MaxParticles);
|
||||
|
||||
m_AttributePos.format = Renderer::Backend::Format::R32G32B32_SFLOAT;
|
||||
m_VertexArray.AddAttribute(&m_AttributePos);
|
||||
|
|
@ -108,17 +108,17 @@ CParticleEmitter::CParticleEmitter(const CParticleEmitterTypePtr& type) :
|
|||
m_AttributeAxisY.format = Renderer::Backend::Format::R32G32B32A32_SFLOAT;
|
||||
m_VertexArray.AddAttribute(&m_AttributeAxisY);
|
||||
|
||||
m_VertexArray.SetNumberOfVertices(m_UseInstancing ? m_Type->m_MaxParticles : m_Type->m_MaxParticles * 4);
|
||||
m_VertexArray.SetNumberOfVertices(m_UseInstancing ? m_Type.m_MaxParticles : m_Type.m_MaxParticles * 4);
|
||||
m_VertexArray.Layout();
|
||||
|
||||
m_AttributeUV.format = Renderer::Backend::Format::R32G32_SFLOAT;
|
||||
m_VertexUVArray.AddAttribute(&m_AttributeUV);
|
||||
|
||||
m_VertexUVArray.SetNumberOfVertices(m_UseInstancing ? 4 : m_Type->m_MaxParticles * 4);
|
||||
m_VertexUVArray.SetNumberOfVertices(m_UseInstancing ? 4 : m_Type.m_MaxParticles * 4);
|
||||
m_VertexUVArray.Layout();
|
||||
|
||||
VertexArrayIterator<float[2]> attrUV = m_AttributeUV.GetIterator<float[2]>();
|
||||
for (uint32_t index{0}; index < (m_UseInstancing ? 1u : m_Type->m_MaxParticles); ++index)
|
||||
for (uint32_t index{0}; index < (m_UseInstancing ? 1u : m_Type.m_MaxParticles); ++index)
|
||||
{
|
||||
(*attrUV)[0] = 1;
|
||||
(*attrUV)[1] = 0;
|
||||
|
|
@ -137,10 +137,10 @@ CParticleEmitter::CParticleEmitter(const CParticleEmitterTypePtr& type) :
|
|||
m_VertexUVArray.Upload();
|
||||
m_VertexUVArray.FreeBackingStore();
|
||||
|
||||
m_IndexArray.SetNumberOfVertices(m_UseInstancing ? 6 : m_Type->m_MaxParticles * 6);
|
||||
m_IndexArray.SetNumberOfVertices(m_UseInstancing ? 6 : m_Type.m_MaxParticles * 6);
|
||||
m_IndexArray.Layout();
|
||||
VertexArrayIterator<u16> index = m_IndexArray.GetIterator();
|
||||
for (u16 i = 0; i < (m_UseInstancing ? 1 : m_Type->m_MaxParticles); ++i)
|
||||
for (u16 i = 0; i < (m_UseInstancing ? 1 : m_Type.m_MaxParticles); ++i)
|
||||
{
|
||||
*index++ = i*4 + 0;
|
||||
*index++ = i*4 + 1;
|
||||
|
|
@ -190,8 +190,8 @@ void CParticleEmitter::UpdateArrayData(int frameNumber)
|
|||
m_LastFrameNumber = frameNumber;
|
||||
|
||||
// Update m_Particles
|
||||
m_Type->UpdateEmitter(*this, m_Type->m_Manager.GetCurrentTime() - m_LastUpdateTime);
|
||||
m_LastUpdateTime = m_Type->m_Manager.GetCurrentTime();
|
||||
m_Type.UpdateEmitter(*this, m_Type.m_Manager.GetCurrentTime() - m_LastUpdateTime);
|
||||
m_LastUpdateTime = m_Type.m_Manager.GetCurrentTime();
|
||||
|
||||
// Regenerate the vertex array data:
|
||||
|
||||
|
|
@ -200,15 +200,15 @@ void CParticleEmitter::UpdateArrayData(int frameNumber)
|
|||
VertexArrayIterator<CVector4D> attrAxisX = m_AttributeAxisX.GetIterator<CVector4D>();
|
||||
VertexArrayIterator<CVector4D> attrAxisY = m_AttributeAxisY.GetIterator<CVector4D>();
|
||||
|
||||
ENSURE(m_Particles.size() <= m_Type->m_MaxParticles);
|
||||
ENSURE(m_Particles.size() <= m_Type.m_MaxParticles);
|
||||
|
||||
CBoundingBoxAligned bounds;
|
||||
|
||||
if (m_Type->m_SortMode != CParticleEmitterType::SortMode::UNSPECIFIED)
|
||||
if (m_Type.m_SortMode != CParticleEmitterType::SortMode::UNSPECIFIED)
|
||||
{
|
||||
sortedParticles.insert(sortedParticles.end(), m_Particles.begin(), m_Particles.end());
|
||||
|
||||
switch (m_Type->m_SortMode)
|
||||
switch (m_Type.m_SortMode)
|
||||
{
|
||||
case CParticleEmitterType::SortMode::YOUNGEST_IN_FRONT:
|
||||
std::sort(sortedParticles.begin(), sortedParticles.end(), ParticleYoungestInFrontCompare{});
|
||||
|
|
@ -228,7 +228,7 @@ void CParticleEmitter::UpdateArrayData(int frameNumber)
|
|||
m_NumberOfVisibleParticles = 0;
|
||||
|
||||
const std::span<SParticle> particles{
|
||||
m_Type->m_SortMode == CParticleEmitterType::SortMode::UNSPECIFIED ?
|
||||
m_Type.m_SortMode == CParticleEmitterType::SortMode::UNSPECIFIED ?
|
||||
std::span<SParticle>{m_Particles} : std::span<SParticle>{sortedParticles}};
|
||||
|
||||
if (m_UseInstancing)
|
||||
|
|
@ -248,8 +248,8 @@ void CParticleEmitter::UpdateArrayData(int frameNumber)
|
|||
|
||||
// Special case: If the blending depends on the source color, not the source alpha,
|
||||
// then pre-multiply by the alpha. (This is kind of a hack.)
|
||||
if (m_Type->m_BlendMode == CParticleEmitterType::BlendMode::OVERLAY ||
|
||||
m_Type->m_BlendMode == CParticleEmitterType::BlendMode::MULTIPLY)
|
||||
if (m_Type.m_BlendMode == CParticleEmitterType::BlendMode::OVERLAY ||
|
||||
m_Type.m_BlendMode == CParticleEmitterType::BlendMode::MULTIPLY)
|
||||
{
|
||||
color.R = (color.R * color.A) / 255;
|
||||
color.G = (color.G * color.A) / 255;
|
||||
|
|
@ -287,8 +287,8 @@ void CParticleEmitter::UpdateArrayData(int frameNumber)
|
|||
|
||||
// Special case: If the blending depends on the source color, not the source alpha,
|
||||
// then pre-multiply by the alpha. (This is kind of a hack.)
|
||||
if (m_Type->m_BlendMode == CParticleEmitterType::BlendMode::OVERLAY ||
|
||||
m_Type->m_BlendMode == CParticleEmitterType::BlendMode::MULTIPLY)
|
||||
if (m_Type.m_BlendMode == CParticleEmitterType::BlendMode::OVERLAY ||
|
||||
m_Type.m_BlendMode == CParticleEmitterType::BlendMode::MULTIPLY)
|
||||
{
|
||||
color.R = (color.R * color.A) / 255;
|
||||
color.G = (color.G * color.A) / 255;
|
||||
|
|
@ -339,7 +339,7 @@ void CParticleEmitter::Bind(
|
|||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
|
||||
Renderer::Backend::IShaderProgram* shader)
|
||||
{
|
||||
m_Type->m_Texture->UploadBackendTextureIfNeeded(deviceCommandContext);
|
||||
m_Type.m_Texture->UploadBackendTextureIfNeeded(deviceCommandContext);
|
||||
|
||||
CLOSTexture& los = g_Renderer.GetSceneRenderer().GetScene().GetLOSTexture();
|
||||
deviceCommandContext->SetTexture(
|
||||
|
|
@ -351,7 +351,7 @@ void CParticleEmitter::Bind(
|
|||
g_Renderer.GetSceneRenderer().GetLightEnv().Bind(deviceCommandContext, shader);
|
||||
|
||||
deviceCommandContext->SetTexture(
|
||||
shader->GetBindingSlot(str_baseTex), m_Type->m_Texture->GetBackendTexture());
|
||||
shader->GetBindingSlot(str_baseTex), m_Type.m_Texture->GetBackendTexture());
|
||||
}
|
||||
|
||||
void CParticleEmitter::RenderArray(
|
||||
|
|
@ -388,7 +388,7 @@ void CParticleEmitter::AddParticle(const SParticle& particle)
|
|||
else
|
||||
m_Particles[m_NextParticleIdx] = particle;
|
||||
|
||||
m_NextParticleIdx = (m_NextParticleIdx + 1) % m_Type->m_MaxParticles;
|
||||
m_NextParticleIdx = (m_NextParticleIdx + 1) % m_Type.m_MaxParticles;
|
||||
}
|
||||
|
||||
void CParticleEmitter::SetEntityVariable(const std::string& name, float value)
|
||||
|
|
@ -396,15 +396,14 @@ void CParticleEmitter::SetEntityVariable(const std::string& name, float value)
|
|||
m_EntityVariables[name] = value;
|
||||
}
|
||||
|
||||
CModelParticleEmitter::CModelParticleEmitter(const CParticleEmitterTypePtr& type) :
|
||||
m_Type(type)
|
||||
CModelParticleEmitter::CModelParticleEmitter(const CParticleEmitterType& type)
|
||||
: m_Type{type}, m_Emitter{std::make_unique<CParticleEmitter>(m_Type)}
|
||||
{
|
||||
m_Emitter = CParticleEmitterPtr(new CParticleEmitter(m_Type));
|
||||
}
|
||||
|
||||
CModelParticleEmitter::~CModelParticleEmitter()
|
||||
{
|
||||
m_Type->m_Manager.AddUnattachedEmitter(std::move(m_Emitter));
|
||||
m_Type.m_Manager.AddUnattachedEmitter(std::move(m_Emitter));
|
||||
}
|
||||
|
||||
void CModelParticleEmitter::SetEntityVariable(const std::string& name, float value)
|
||||
|
|
@ -423,7 +422,7 @@ void CModelParticleEmitter::CalcBounds()
|
|||
// current computed particle positions plus the emitter type's largest
|
||||
// potential bounding box at the current position
|
||||
|
||||
m_WorldBounds = m_Type->CalculateBounds(m_Emitter->GetPosition(), m_Emitter->GetParticleBounds());
|
||||
m_WorldBounds = m_Type.CalculateBounds(m_Emitter->GetPosition(), m_Emitter->GetParticleBounds());
|
||||
}
|
||||
|
||||
void CModelParticleEmitter::ValidatePosition()
|
||||
|
|
|
|||
|
|
@ -55,8 +55,6 @@ struct SParticle
|
|||
CVector3D axisX, axisY;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<CParticleEmitter> CParticleEmitterPtr;
|
||||
|
||||
/**
|
||||
* Particle emitter.
|
||||
*
|
||||
|
|
@ -80,7 +78,7 @@ typedef std::shared_ptr<CParticleEmitter> CParticleEmitterPtr;
|
|||
class CParticleEmitter
|
||||
{
|
||||
public:
|
||||
CParticleEmitter(const CParticleEmitterTypePtr& type);
|
||||
CParticleEmitter(const CParticleEmitterType& type);
|
||||
|
||||
/**
|
||||
* Set the position to be used for emission of new particles.
|
||||
|
|
@ -152,7 +150,7 @@ public:
|
|||
|
||||
void SetEntityVariable(const std::string& name, float value);
|
||||
|
||||
CParticleEmitterTypePtr m_Type;
|
||||
const CParticleEmitterType& m_Type;
|
||||
|
||||
/// Whether this emitter is still emitting new particles
|
||||
bool m_Active{true};
|
||||
|
|
@ -194,7 +192,7 @@ private:
|
|||
class CModelParticleEmitter : public CModelAbstract
|
||||
{
|
||||
public:
|
||||
CModelParticleEmitter(const CParticleEmitterTypePtr& type);
|
||||
CModelParticleEmitter(const CParticleEmitterType& type);
|
||||
~CModelParticleEmitter() override;
|
||||
|
||||
/// Dynamic cast
|
||||
|
|
@ -216,8 +214,8 @@ public:
|
|||
void InvalidatePosition() override;
|
||||
void SetTransform(const CMatrix3D& transform) override;
|
||||
|
||||
CParticleEmitterTypePtr m_Type;
|
||||
CParticleEmitterPtr m_Emitter;
|
||||
const CParticleEmitterType& m_Type;
|
||||
std::unique_ptr<CParticleEmitter> m_Emitter;
|
||||
};
|
||||
|
||||
#endif // INCLUDED_PARTICLEEMITTER
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ public:
|
|||
/// Computes and returns a new value.
|
||||
float Evaluate(CParticleEmitter& emitter)
|
||||
{
|
||||
m_LastValue = Compute(*emitter.m_Type, emitter);
|
||||
m_LastValue = Compute(emitter.m_Type, emitter);
|
||||
return m_LastValue;
|
||||
}
|
||||
|
||||
|
|
@ -268,11 +268,15 @@ private:
|
|||
|
||||
|
||||
|
||||
CParticleEmitterType::CParticleEmitterType(const VfsPath& path, CParticleManager& manager) :
|
||||
CParticleEmitterType::CParticleEmitterType(CParticleManager& manager) :
|
||||
m_Manager(manager)
|
||||
{
|
||||
LoadXML(path);
|
||||
// TODO: handle load failure
|
||||
}
|
||||
|
||||
bool CParticleEmitterType::Load(const VfsPath& path)
|
||||
{
|
||||
if (!LoadXML(path))
|
||||
return false;
|
||||
|
||||
// Upper bound on number of particles depends on maximum rate and lifetime
|
||||
m_MaxLifetime = m_Variables[VAR_LIFETIME]->Max(*this);
|
||||
|
|
@ -336,8 +340,12 @@ CParticleEmitterType::CParticleEmitterType(const VfsPath& path, CParticleManager
|
|||
// Offset by the initial positions
|
||||
m_MaxBounds[0] += CVector3D(m_Variables[VAR_POSITION_X]->Min(*this), m_Variables[VAR_POSITION_Y]->Min(*this), m_Variables[VAR_POSITION_Z]->Min(*this));
|
||||
m_MaxBounds[1] += CVector3D(m_Variables[VAR_POSITION_X]->Max(*this), m_Variables[VAR_POSITION_Y]->Max(*this), m_Variables[VAR_POSITION_Z]->Max(*this));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CParticleEmitterType::~CParticleEmitterType() = default;
|
||||
|
||||
int CParticleEmitterType::GetVariableID(const std::string& name)
|
||||
{
|
||||
if (name == "emissionrate") return VAR_EMISSIONRATE;
|
||||
|
|
@ -364,21 +372,21 @@ bool CParticleEmitterType::LoadXML(const VfsPath& path)
|
|||
// Initialise with sane defaults
|
||||
m_Variables.clear();
|
||||
m_Variables.resize(VAR__MAX);
|
||||
m_Variables[VAR_EMISSIONRATE] = IParticleVarPtr(new CParticleVarConstant(10.f));
|
||||
m_Variables[VAR_LIFETIME] = IParticleVarPtr(new CParticleVarConstant(3.f));
|
||||
m_Variables[VAR_POSITION_X] = IParticleVarPtr(new CParticleVarConstant(0.f));
|
||||
m_Variables[VAR_POSITION_Y] = IParticleVarPtr(new CParticleVarConstant(0.f));
|
||||
m_Variables[VAR_POSITION_Z] = IParticleVarPtr(new CParticleVarConstant(0.f));
|
||||
m_Variables[VAR_ANGLE] = IParticleVarPtr(new CParticleVarConstant(0.f));
|
||||
m_Variables[VAR_VELOCITY_X] = IParticleVarPtr(new CParticleVarConstant(0.f));
|
||||
m_Variables[VAR_VELOCITY_Y] = IParticleVarPtr(new CParticleVarConstant(1.f));
|
||||
m_Variables[VAR_VELOCITY_Z] = IParticleVarPtr(new CParticleVarConstant(0.f));
|
||||
m_Variables[VAR_VELOCITY_ANGLE] = IParticleVarPtr(new CParticleVarConstant(0.f));
|
||||
m_Variables[VAR_SIZE] = IParticleVarPtr(new CParticleVarConstant(1.f));
|
||||
m_Variables[VAR_SIZE_GROWTHRATE] = IParticleVarPtr(new CParticleVarConstant(0.f));
|
||||
m_Variables[VAR_COLOR_R] = IParticleVarPtr(new CParticleVarConstant(1.f));
|
||||
m_Variables[VAR_COLOR_G] = IParticleVarPtr(new CParticleVarConstant(1.f));
|
||||
m_Variables[VAR_COLOR_B] = IParticleVarPtr(new CParticleVarConstant(1.f));
|
||||
m_Variables[VAR_EMISSIONRATE] = std::make_unique<CParticleVarConstant>(10.f);
|
||||
m_Variables[VAR_LIFETIME] = std::make_unique<CParticleVarConstant>(3.f);
|
||||
m_Variables[VAR_POSITION_X] = std::make_unique<CParticleVarConstant>(0.f);
|
||||
m_Variables[VAR_POSITION_Y] = std::make_unique<CParticleVarConstant>(0.f);
|
||||
m_Variables[VAR_POSITION_Z] = std::make_unique<CParticleVarConstant>(0.f);
|
||||
m_Variables[VAR_ANGLE] = std::make_unique<CParticleVarConstant>(0.f);
|
||||
m_Variables[VAR_VELOCITY_X] = std::make_unique<CParticleVarConstant>(0.f);
|
||||
m_Variables[VAR_VELOCITY_Y] = std::make_unique<CParticleVarConstant>(1.f);
|
||||
m_Variables[VAR_VELOCITY_Z] = std::make_unique<CParticleVarConstant>(0.f);
|
||||
m_Variables[VAR_VELOCITY_ANGLE] = std::make_unique<CParticleVarConstant>(0.f);
|
||||
m_Variables[VAR_SIZE] = std::make_unique<CParticleVarConstant>(1.f);
|
||||
m_Variables[VAR_SIZE_GROWTHRATE] = std::make_unique<CParticleVarConstant>(0.f);
|
||||
m_Variables[VAR_COLOR_R] = std::make_unique<CParticleVarConstant>(1.f);
|
||||
m_Variables[VAR_COLOR_G] = std::make_unique<CParticleVarConstant>(1.f);
|
||||
m_Variables[VAR_COLOR_B] = std::make_unique<CParticleVarConstant>(1.f);
|
||||
m_BlendMode = BlendMode::ADD;
|
||||
m_SortMode = SortMode::UNSPECIFIED;
|
||||
m_StartFull = false;
|
||||
|
|
@ -390,7 +398,10 @@ bool CParticleEmitterType::LoadXML(const VfsPath& path)
|
|||
CXeromyces XeroFile;
|
||||
PSRETURN ret = XeroFile.Load(g_VFS, path, "particle");
|
||||
if (ret != PSRETURN_OK)
|
||||
{
|
||||
LOGERROR("Failed to load particle: '%s'", path.string8());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Define all the elements and attributes used in the XML file
|
||||
#define EL(x) int el_##x = XeroFile.GetElementID(#x)
|
||||
|
|
@ -476,9 +487,9 @@ bool CParticleEmitterType::LoadXML(const VfsPath& path)
|
|||
int id = GetVariableID(Child.GetAttributes().GetNamedItem(at_name));
|
||||
if (id != -1)
|
||||
{
|
||||
m_Variables[id] = IParticleVarPtr(new CParticleVarConstant(
|
||||
m_Variables[id] = std::make_unique<CParticleVarConstant>(
|
||||
Child.GetAttributes().GetNamedItem(at_value).ToFloat()
|
||||
));
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (Child.GetNodeName() == el_uniform)
|
||||
|
|
@ -490,9 +501,9 @@ bool CParticleEmitterType::LoadXML(const VfsPath& path)
|
|||
float max = Child.GetAttributes().GetNamedItem(at_max).ToFloat();
|
||||
// To avoid hangs in the RNG, only use it if [min, max) is non-empty
|
||||
if (min < max)
|
||||
m_Variables[id] = IParticleVarPtr(new CParticleVarUniform(min, max));
|
||||
m_Variables[id] = std::make_unique<CParticleVarUniform>(min, max);
|
||||
else
|
||||
m_Variables[id] = IParticleVarPtr(new CParticleVarConstant(min));
|
||||
m_Variables[id] = std::make_unique<CParticleVarConstant>(min);
|
||||
}
|
||||
}
|
||||
else if (Child.GetNodeName() == el_copy)
|
||||
|
|
@ -500,7 +511,7 @@ bool CParticleEmitterType::LoadXML(const VfsPath& path)
|
|||
int id = GetVariableID(Child.GetAttributes().GetNamedItem(at_name));
|
||||
int from = GetVariableID(Child.GetAttributes().GetNamedItem(at_from));
|
||||
if (id != -1 && from != -1)
|
||||
m_Variables[id] = IParticleVarPtr(new CParticleVarCopy(from));
|
||||
m_Variables[id] = std::make_unique<CParticleVarCopy>(from);
|
||||
}
|
||||
else if (Child.GetNodeName() == el_expr)
|
||||
{
|
||||
|
|
@ -509,14 +520,14 @@ bool CParticleEmitterType::LoadXML(const VfsPath& path)
|
|||
float mul = Child.GetAttributes().GetNamedItem(at_mul).ToFloat();
|
||||
float max = Child.GetAttributes().GetNamedItem(at_max).ToFloat();
|
||||
if (id != -1)
|
||||
m_Variables[id] = IParticleVarPtr(new CParticleVarExpr(from, mul, max));
|
||||
m_Variables[id] = std::make_unique<CParticleVarExpr>(from, mul, max);
|
||||
}
|
||||
else if (Child.GetNodeName() == el_force)
|
||||
{
|
||||
float x = Child.GetAttributes().GetNamedItem(at_x).ToFloat();
|
||||
float y = Child.GetAttributes().GetNamedItem(at_y).ToFloat();
|
||||
float z = Child.GetAttributes().GetNamedItem(at_z).ToFloat();
|
||||
m_Effectors.push_back(IParticleEffectorPtr(new CParticleEffectorForce(x, y, z)));
|
||||
m_Effectors.push_back(std::make_unique<CParticleEffectorForce>(x, y, z));
|
||||
}
|
||||
else if (Child.GetNodeName() == el_particle)
|
||||
{
|
||||
|
|
@ -576,7 +587,7 @@ void CParticleEmitterType::UpdateEmitter(CParticleEmitter& emitter, float dt) co
|
|||
|
||||
void CParticleEmitterType::UpdateEmitterStep(CParticleEmitter& emitter, float dt) const
|
||||
{
|
||||
ENSURE(emitter.m_Type.get() == this);
|
||||
ENSURE(&emitter.m_Type == this);
|
||||
|
||||
if (emitter.m_Active)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,7 +49,13 @@ class CParticleEmitterType
|
|||
{
|
||||
NONCOPYABLE(CParticleEmitterType); // reference member
|
||||
public:
|
||||
CParticleEmitterType(const VfsPath& path, CParticleManager& manager);
|
||||
CParticleEmitterType(CParticleManager& manager);
|
||||
~CParticleEmitterType();
|
||||
|
||||
/**
|
||||
* @return True if the emitter type was successfuly loaded.
|
||||
*/
|
||||
bool Load(const VfsPath& path);
|
||||
|
||||
private:
|
||||
friend class CModelParticleEmitter;
|
||||
|
|
@ -130,15 +136,10 @@ private:
|
|||
u16 m_MaxParticles;
|
||||
CBoundingBoxAligned m_MaxBounds;
|
||||
|
||||
typedef std::shared_ptr<IParticleVar> IParticleVarPtr;
|
||||
std::vector<IParticleVarPtr> m_Variables;
|
||||
|
||||
typedef std::shared_ptr<IParticleEffector> IParticleEffectorPtr;
|
||||
std::vector<IParticleEffectorPtr> m_Effectors;
|
||||
std::vector<std::unique_ptr<IParticleVar>> m_Variables;
|
||||
std::vector<std::unique_ptr<IParticleEffector>> m_Effectors;
|
||||
|
||||
CParticleManager& m_Manager;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<CParticleEmitterType> CParticleEmitterTypePtr;
|
||||
|
||||
#endif // INCLUDED_PARTICLEEMITTERTYPE
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "renderer/backend/IDevice.h"
|
||||
#include "renderer/Scene.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
|
@ -48,21 +49,23 @@ CParticleManager::~CParticleManager()
|
|||
UnregisterFileReloadFunc(ReloadChangedFileCB, this);
|
||||
}
|
||||
|
||||
CParticleEmitterTypePtr CParticleManager::LoadEmitterType(const VfsPath& path)
|
||||
CParticleEmitterType* CParticleManager::LoadEmitterType(const VfsPath& path)
|
||||
{
|
||||
std::unordered_map<VfsPath, CParticleEmitterTypePtr>::iterator it = m_EmitterTypes.find(path);
|
||||
if (it != m_EmitterTypes.end())
|
||||
return it->second;
|
||||
if (auto it{m_EmitterTypes.find(path)}; it != m_EmitterTypes.end())
|
||||
return it->second.get();
|
||||
|
||||
CParticleEmitterTypePtr emitterType(new CParticleEmitterType(path, *this));
|
||||
m_EmitterTypes[path] = emitterType;
|
||||
return emitterType;
|
||||
std::unique_ptr<CParticleEmitterType> emitterType{
|
||||
std::make_unique<CParticleEmitterType>(*this)};
|
||||
if (!emitterType->Load(path))
|
||||
return nullptr;
|
||||
|
||||
return m_EmitterTypes.emplace(path, std::move(emitterType)).first->second.get();
|
||||
}
|
||||
|
||||
void CParticleManager::AddUnattachedEmitter(const CParticleEmitterPtr& emitter)
|
||||
void CParticleManager::AddUnattachedEmitter(std::unique_ptr<CParticleEmitter> emitter)
|
||||
{
|
||||
emitter->m_Active = false;
|
||||
m_UnattachedEmitters.push_back(emitter);
|
||||
m_UnattachedEmitters.emplace_back(std::move(emitter));
|
||||
}
|
||||
|
||||
void CParticleManager::ClearUnattachedEmitters()
|
||||
|
|
@ -75,18 +78,19 @@ void CParticleManager::Interpolate(const float simFrameLength)
|
|||
m_CurrentTime += simFrameLength;
|
||||
}
|
||||
|
||||
struct ParticleAlive
|
||||
{
|
||||
bool operator()(const SParticle& particle) const
|
||||
{
|
||||
return particle.age < particle.maxAge;
|
||||
}
|
||||
};
|
||||
|
||||
struct EmitterHasNoParticles
|
||||
{
|
||||
bool operator()(const CParticleEmitterPtr& emitterPtr)
|
||||
bool operator()(const std::unique_ptr<CParticleEmitter>& emitter) const
|
||||
{
|
||||
CParticleEmitter& emitter = *emitterPtr.get();
|
||||
for (size_t i = 0; i < emitter.m_Particles.size(); ++i)
|
||||
{
|
||||
SParticle& p = emitter.m_Particles[i];
|
||||
if (p.age < p.maxAge)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return std::none_of(emitter->m_Particles.begin(), emitter->m_Particles.end(), ParticleAlive{});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -95,16 +99,21 @@ void CParticleManager::RenderSubmit(SceneCollector& collector, const CFrustum&)
|
|||
PROFILE("submit unattached particles");
|
||||
|
||||
// Delete any unattached emitters that have no particles left
|
||||
m_UnattachedEmitters.remove_if(EmitterHasNoParticles());
|
||||
std::erase_if(m_UnattachedEmitters, EmitterHasNoParticles());
|
||||
|
||||
// TODO: should do some frustum culling
|
||||
|
||||
for (std::list<CParticleEmitterPtr>::iterator it = m_UnattachedEmitters.begin(); it != m_UnattachedEmitters.end(); ++it)
|
||||
collector.Submit(it->get());
|
||||
for (std::unique_ptr<CParticleEmitter>& emitter : m_UnattachedEmitters)
|
||||
collector.Submit(emitter.get());
|
||||
}
|
||||
|
||||
Status CParticleManager::ReloadChangedFile(const VfsPath& path)
|
||||
{
|
||||
m_EmitterTypes.erase(path);
|
||||
if (auto it = m_EmitterTypes.find(path); it != m_EmitterTypes.end())
|
||||
{
|
||||
// We can't erase an emitter type because emitters might hold
|
||||
// a reference to it.
|
||||
it->second->Load(path);
|
||||
}
|
||||
return INFO::OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@
|
|||
#include "lib/path.h"
|
||||
#include "lib/status.h"
|
||||
|
||||
#include <list>
|
||||
#include <random>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
class CFrustum;
|
||||
class SceneCollector;
|
||||
|
|
@ -39,7 +39,7 @@ public:
|
|||
CParticleManager(Renderer::Backend::IDevice& device);
|
||||
~CParticleManager();
|
||||
|
||||
CParticleEmitterTypePtr LoadEmitterType(const VfsPath& path);
|
||||
CParticleEmitterType* LoadEmitterType(const VfsPath& path);
|
||||
|
||||
/**
|
||||
* Tell the manager to handle rendering of an emitter that is no longer
|
||||
|
|
@ -49,7 +49,7 @@ public:
|
|||
* will carry on rendering (until all particles have dissipated)
|
||||
* even when it's no longer attached to a model.
|
||||
*/
|
||||
void AddUnattachedEmitter(const CParticleEmitterPtr& emitter);
|
||||
void AddUnattachedEmitter(std::unique_ptr<CParticleEmitter> emitter);
|
||||
|
||||
/**
|
||||
* Delete unattached emitters if we don't wish to see them anymore (like in actor viewer)
|
||||
|
|
@ -72,9 +72,9 @@ public:
|
|||
private:
|
||||
float m_CurrentTime{0.0f};
|
||||
|
||||
std::list<CParticleEmitterPtr> m_UnattachedEmitters;
|
||||
std::vector<std::unique_ptr<CParticleEmitter>> m_UnattachedEmitters;
|
||||
|
||||
std::unordered_map<VfsPath, CParticleEmitterTypePtr> m_EmitterTypes;
|
||||
std::unordered_map<VfsPath, std::unique_ptr<CParticleEmitterType>> m_EmitterTypes;
|
||||
|
||||
bool m_UseInstancing{false};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ void ParticleRenderer::RenderParticles(
|
|||
}
|
||||
else
|
||||
{
|
||||
switch (emitter->m_Type->m_BlendMode)
|
||||
switch (emitter->m_Type.m_BlendMode)
|
||||
{
|
||||
case CParticleEmitterType::BlendMode::ADD: currentTech = m->techAdd.get(); break;
|
||||
case CParticleEmitterType::BlendMode::SUBTRACT: currentTech = m->techSubtract.get(); break;
|
||||
|
|
@ -195,7 +195,7 @@ void ParticleRenderer::RenderParticles(
|
|||
|
||||
const CMatrix3D rotationMatrix{emitter->GetRotation().ToMatrix()};
|
||||
CMatrix3D spaceTransform;
|
||||
if (emitter->m_Type->m_UseLocalSpace)
|
||||
if (emitter->m_Type.m_UseLocalSpace)
|
||||
{
|
||||
spaceTransform = rotationMatrix;
|
||||
spaceTransform.Translate(emitter->GetPosition());
|
||||
|
|
@ -219,7 +219,7 @@ void ParticleRenderer::RenderBounds(Renderer::Backend::IDeviceCommandContext& de
|
|||
for (const CParticleEmitter* emitter : m->emitters[cullGroup])
|
||||
{
|
||||
const CBoundingBoxAligned bounds =
|
||||
emitter->m_Type->CalculateBounds(emitter->GetPosition(), emitter->GetParticleBounds());
|
||||
emitter->m_Type.CalculateBounds(emitter->GetPosition(), emitter->GetParticleBounds());
|
||||
|
||||
g_Renderer.GetDebugRenderer().DrawBoundingBox(deviceCommandContext, bounds, CColor(0.0f, 1.0f, 0.0f, 1.0f), true);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue