| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414 |
- #include "core/particles/ParticleTechnique.h"
- #include <OgreLogManager.h>
- #include <OgreStringConverter.h>
- #include "core/particles/ParticleSystemManager.h"
- #include "core/particles/ParticleVisual.h"
- //------------------------------------------------------------------------------
- ParticleTechnique::ParticleTechnique():
- m_Renderer(nullptr),
- m_VisualParticleQuota(10),
- m_VisualParticlePoolIncreased(false),
- m_EmittedEmitterQuota(10),
- m_ParticleEmitterPoolIncreased(false)
- {
- }
- //------------------------------------------------------------------------------
- ParticleTechnique::~ParticleTechnique()
- {
- DestroyAllEmitters();
- DestroyRenderer();
- }
- //------------------------------------------------------------------------------
- void
- ParticleTechnique::CopyAttributesTo(ParticleTechnique* technique)
- {
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::CopyAttributesTo start");
- // Destroy the emitters, affectors, etc.
- technique->DestroyAllEmitters();
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::CopyAttributesTo 1");
- technique->DestroyRenderer();
- technique->m_ParentSystem = m_ParentSystem;
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::CopyAttributesTo 2");
- // Copy the renderer
- ParticleRenderer* cloned_renderer = ParticleSystemManager::getSingletonPtr()->CloneRenderer(m_Renderer);
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::CopyAttributesTo 3");
- technique->SetRenderer(cloned_renderer);
- technique->m_VisualParticleQuota = m_VisualParticleQuota;
- technique->m_VisualParticlePoolIncreased = false;
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::CopyAttributesTo 4");
- technique->m_EmittedEmitterQuota = m_EmittedEmitterQuota;
- technique->m_ParticleEmitterPoolIncreased = false;
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::CopyAttributesTo 5");
- // Copy all emitters
- ParticleEmitter* cloned_emitter;
- for( unsigned int i = 0; i < m_Emitters.size(); ++i )
- {
- cloned_emitter = ParticleSystemManager::getSingletonPtr()->CloneEmitter( m_Emitters[ i ] );
- technique->AddEmitter( cloned_emitter );
- }
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::CopyAttributesTo end");
- }
- //------------------------------------------------------------------------------
- void
- ParticleTechnique::UpdateRenderQueue(Ogre::RenderQueue* queue)
- {
- if (m_Renderer && m_Renderer->IsRendererInitialised())
- {
- m_Renderer->UpdateRenderQueue(queue, m_VisualParticlesPool);
- }
- }
- //------------------------------------------------------------------------------
- void
- ParticleTechnique::Initialize()
- {
- if (m_Renderer && m_Renderer->IsRendererInitialised() == false)
- {
- m_Renderer->Initialize();
- }
- // Create new visual particles if the quota has been increased
- if (m_VisualParticlePoolIncreased == false)
- {
- int old_size = m_VisualParticlesPool.GetSize();
- if (m_VisualParticleQuota > old_size)
- {
- // Create new visual particles
- VisualParticle* particle = nullptr;
- for (int i = old_size; i < m_VisualParticleQuota; ++i)
- {
- particle = new VisualParticle();
- m_VisualParticlesPool.AddElement(particle);
- m_VisualParticles.push_back(particle);
- }
- }
- m_VisualParticlePoolIncreased = true;
- }
- // Create new emitter particles if the quota has been increased
- if (m_ParticleEmitterPoolIncreased == false)
- {
- int old_size = m_ParticleEmitterPool.GetSize();
- if (m_EmittedEmitterQuota > old_size)
- {
- // Create new emitters, based on the already created emitters in the technique and which are marked for emission.
- int numberOfEmittedEmitters = GetNumEmittableEmitters();
- if (numberOfEmittedEmitters == 0)
- {
- return;
- }
- ParticleEmitter* existing_emitter = 0;
- ParticleEmitter* cloned_emitter = 0;
- // Distribute size equally
- int increment = m_EmittedEmitterQuota / numberOfEmittedEmitters;
- // Run through emitters of the technique
- for( unsigned int i = 0; i < m_Emitters.size(); ++i )
- {
- if( m_Emitters[ i ]->IsEmittable() )
- {
- // Clone the emitter 'increment' times and add to the pool
- for (int j = 0; j < increment; ++j)
- {
- cloned_emitter = ParticleSystemManager::getSingletonPtr()->CloneEmitter(m_Emitters[i]);
- cloned_emitter->SetEmittable(true);
- m_ParticleEmitterPool.AddElement(cloned_emitter->GetName(), cloned_emitter);
- }
- }
- }
- }
- m_ParticleEmitterPoolIncreased = true;
- }
- }
- //------------------------------------------------------------------------------
- void
- ParticleTechnique::Update(Ogre::Real time_elapsed)
- {
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::Update START");
- // Perform some initialisation type of activities (if needed). This must be done within the update-loop,
- // because settings could be changed (i.e. changing quota), which must trigger a re-initialisation.
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::Update initialize start");
- Initialize();
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::Update initialize end");
- // Process the emitters
- for( unsigned int i = 0; i < m_Emitters.size(); ++i )
- {
- // emitted particles handled in pool update
- if( m_Emitters[ i ]->IsEmittable() == false )
- {
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::Update emit static emitters");
- ExecuteEmitParticles(m_Emitters[i], m_Emitters[i]->CalculateRequestedParticles(time_elapsed), time_elapsed);
- }
- }
- if (m_VisualParticlesPool.IsEmpty() == false)
- {
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::Update: visual particle started.");
- VisualParticle* particle = m_VisualParticlesPool.GetFirst();
- while (!m_VisualParticlesPool.End())
- {
- if (particle != nullptr)
- {
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::Update found particle with ttl " + Ogre::StringConverter::toString(particle->time_to_live));
- if (particle->time_to_live > time_elapsed)
- {
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::Update update visual start");
- particle->Update(time_elapsed);
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::Update update visual end");
- }
- else
- {
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::Update expire visual start");
- particle->InitForExpiration();
- m_VisualParticlesPool.LockLatestElement();
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::Update expire visual end");
- }
- // Decrement time to live
- particle->time_to_live -= time_elapsed;
- }
- particle = m_VisualParticlesPool.GetNext();
- }
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::Update: visual particle finished.");
- }
- // Process all particles
- if (m_ParticleEmitterPool.IsEmpty() == false)
- {
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::Update: emitter particle started.");
- ParticleEmitter* particle = m_ParticleEmitterPool.GetFirst();
- while (!m_ParticleEmitterPool.End())
- {
- if (particle)
- {
- if (particle->time_to_live > time_elapsed)
- {
- particle->Update(time_elapsed);
- ExecuteEmitParticles(particle, particle->CalculateRequestedParticles(time_elapsed), time_elapsed);
- }
- else
- {
- particle->InitForExpiration();
- m_ParticleEmitterPool.LockLatestElement();
- }
- // Decrement time to live
- particle->time_to_live -= time_elapsed;
- }
- particle = m_ParticleEmitterPool.GetNext();
- }
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::Update: emitter particle finished.");
- }
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::Update END");
- }
- //------------------------------------------------------------------------------
- ParticleRenderer*
- ParticleTechnique::CreateRenderer(const Ogre::String& renderer_type)
- {
- if (m_Renderer)
- {
- DestroyRenderer();
- }
- if (renderer_type != Ogre::StringUtil::BLANK)
- {
- m_Renderer = ParticleSystemManager::getSingletonPtr()->CreateRenderer(renderer_type);
- m_Renderer->SetParentTechnique(this);
- m_Renderer->SetRendererInitialised(false);
- }
- return m_Renderer;
- }
- //------------------------------------------------------------------------------
- void
- ParticleTechnique::SetRenderer(ParticleRenderer* renderer)
- {
- if (m_Renderer)
- {
- DestroyRenderer();
- }
- m_Renderer = renderer;
- m_Renderer->SetParentTechnique(this);
- m_Renderer->SetRendererInitialised(false);
- }
- //------------------------------------------------------------------------------
- void
- ParticleTechnique::DestroyRenderer()
- {
- if (m_Renderer)
- {
- ParticleSystemManager::getSingletonPtr()->DestroyRenderer(m_Renderer);
- m_Renderer = nullptr;
- }
- }
- //------------------------------------------------------------------------------
- ParticleEmitter*
- ParticleTechnique::CreateEmitter(const Ogre::String& emitter_type)
- {
- ParticleEmitter* emitter = nullptr;
- if (emitter_type != Ogre::StringUtil::BLANK)
- {
- emitter = ParticleSystemManager::getSingletonPtr()->CreateEmitter(emitter_type);
- m_Emitters.push_back(emitter);
- emitter->SetParentTechnique(this);
- EmissionChange();
- }
- return emitter;
- }
- //------------------------------------------------------------------------------
- void
- ParticleTechnique::AddEmitter(ParticleEmitter* emitter)
- {
- if (emitter != nullptr)
- {
- m_Emitters.push_back(emitter);
- emitter->SetParentTechnique(this);
- EmissionChange();
- }
- }
- //------------------------------------------------------------------------------
- void
- ParticleTechnique::DestroyAllEmitters()
- {
- for( unsigned int i = 0; i < m_Emitters.size(); ++i )
- {
- ParticleSystemManager::getSingletonPtr()->DestroyEmitter(m_Emitters[i]);
- }
- m_Emitters.clear();
- }
- //------------------------------------------------------------------------------
- int
- ParticleTechnique::GetNumEmittableEmitters() const
- {
- int count = 0;
- for( unsigned int i = 0; i < m_Emitters.size(); ++i )
- {
- if (m_Emitters[i]->IsEmittable())
- {
- count++;
- }
- }
- return count;
- }
- //------------------------------------------------------------------------------
- void
- ParticleTechnique::EmissionChange()
- {
- // Run through all emitters and set MarkedForEmission to false.
- for( unsigned int i = 0; i < m_Emitters.size(); ++i )
- {
- m_Emitters[i]->SetEmittable(false);
- }
- // Run through all emitters and determine which objects each one emits.
- for( unsigned int i = 0; i < m_Emitters.size(); ++i )
- {
- Ogre::String name = m_Emitters[i]->GetEmitsName();
- if (name != m_Emitters[i]->GetName())
- {
- // Search the emitter to be emitted
- for( unsigned int j = 0; j < m_Emitters.size(); ++j )
- {
- if (m_Emitters[j]->GetName() == name)
- {
- m_Emitters[j]->SetEmittable(true);
- }
- }
- }
- }
- }
- //------------------------------------------------------------------------------
- void
- ParticleTechnique::ExecuteEmitParticles(ParticleEmitter* emitter, int requested, Ogre::Real time_elapsed)
- {
- // Only proceed if the emitter and technique are enabled
- if (emitter->IsEnabled() == false)
- {
- return;
- }
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::ExecuteEmitParticles request " + Ogre::StringConverter::toString(requested) + " particles to emit.");
- for (int j = 0; j < requested; ++j)
- {
- // Create a new particle & init using emitter
- Particle* particle = nullptr;
- switch (emitter->GetEmitsType())
- {
- case Particle::PT_VISUAL: particle = m_VisualParticlesPool.ReleaseElement(); break;
- case Particle::PT_EMITTER: particle = m_ParticleEmitterPool.ReleaseElement(emitter->GetEmitsName()); break;
- }
- // Return if there is no particle left anymore, or the name cannot be found
- if (particle == nullptr)
- {
- Ogre::LogManager::getSingletonPtr()->logMessage("ParticleTechnique::ExecuteEmitParticles request there is no particles left.");
- return;
- }
- particle->InitForEmission();
- // Initialise the particle with data from the emitter.
- emitter->InitParticleForEmission(particle);
- }
- }
- //------------------------------------------------------------------------------
- void
- ParticleTechnique::ResetVisualParticles()
- {
- for( unsigned int i = 0; i < m_VisualParticles.size(); ++i )
- {
- m_VisualParticles[i]->additional_data = nullptr;
- }
- m_VisualParticlesPool.LockAllElements();
- }
- //------------------------------------------------------------------------------
|