source: OGRE/trunk/ogrenew/OgreMain/src/OgreParticleSystem.cpp @ 657

Revision 657, 34.6 KB checked in by mattausch, 18 years ago (diff)

added ogre dependencies and patched ogre sources

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#include "OgreStableHeaders.h"
26
27#include "OgreParticleSystem.h"
28#include "OgreParticleSystemManager.h"
29#include "OgreRenderQueue.h"
30#include "OgreBillboardSet.h"
31#include "OgreParticleEmitter.h"
32#include "OgreParticleAffector.h"
33#include "OgreParticle.h"
34#include "OgreSceneNode.h"
35#include "OgreCamera.h"
36#include "OgreStringConverter.h"
37#include "OgreLogManager.h"
38#include "OgreException.h"
39#include "OgreParticleAffectorFactory.h"
40#include "OgreParticleSystemRenderer.h"
41#include "OgreMaterialManager.h"
42
43namespace Ogre {
44    // Init statics
45    ParticleSystem::CmdCull ParticleSystem::msCullCmd;
46    ParticleSystem::CmdHeight ParticleSystem::msHeightCmd;
47    ParticleSystem::CmdMaterial ParticleSystem::msMaterialCmd;
48    ParticleSystem::CmdQuota ParticleSystem::msQuotaCmd;
49    ParticleSystem::CmdWidth ParticleSystem::msWidthCmd;
50    ParticleSystem::CmdRenderer ParticleSystem::msRendererCmd;
51
52    //-----------------------------------------------------------------------
53    ParticleSystem::ParticleSystem()
54      : mBoundsAutoUpdate(true), mBoundsUpdateTime(10.0f),
55        mResourceGroupName(ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME),
56        mIsRendererConfigured(false), mSpeedFactor(1.0f), mRenderer(0),
57        mCullIndividual(false), mPoolSize(0)
58    {
59        initParameters();
60        mAABB.setExtents(-1, -1, -1, 1, 1, 1);
61        mBoundingRadius = 1;
62        // Init world AABB to something silly
63        Vector3 min( Math::POS_INFINITY, Math::POS_INFINITY, Math::POS_INFINITY );
64        Vector3 max( Math::NEG_INFINITY, Math::NEG_INFINITY, Math::NEG_INFINITY );
65        mWorldAABB.setExtents(min, max);
66
67        // Default to billboard renderer
68        setRenderer("billboard");
69
70    }
71    //-----------------------------------------------------------------------
72    ParticleSystem::ParticleSystem(const String& name, const String& resourceGroup)
73      : mBoundsAutoUpdate(true), mBoundsUpdateTime(10.0f),
74        mResourceGroupName(resourceGroup), mIsRendererConfigured(false),
75                mSpeedFactor(1.0f), mRenderer(0), mCullIndividual(false), mPoolSize(0)
76    {
77        mName = name;
78        setDefaultDimensions( 100, 100 );
79        setMaterialName( "BaseWhite" );
80        // Default to 10 particles, expect app to specify (will only be increased, not decreased)
81        setParticleQuota( 10 );
82        initParameters();
83        mAABB.setExtents(-1, -1, -1, 1, 1, 1);
84        mBoundingRadius = 1;
85        // Init world AABB to something silly
86        Vector3 min( Math::POS_INFINITY, Math::POS_INFINITY, Math::POS_INFINITY );
87        Vector3 max( Math::NEG_INFINITY, Math::NEG_INFINITY, Math::NEG_INFINITY );
88        mWorldAABB.setExtents(min, max);
89
90        // Default to billboard renderer
91        setRenderer("billboard");
92    }
93    //-----------------------------------------------------------------------
94    ParticleSystem::~ParticleSystem()
95    {
96                // Arrange for the deletion of emitters & affectors
97        removeAllEmitters();
98        removeAllAffectors();
99
100                // Deallocate all particles
101                destroyVisualParticles(0, mParticlePool.size());
102        // Free pool items
103        ParticlePool::iterator i;
104        for (i = mParticlePool.begin(); i != mParticlePool.end(); ++i)
105        {
106            delete *i;
107        }
108
109        if (mRenderer)
110        {
111            ParticleSystemManager::getSingleton()._destroyRenderer(mRenderer);
112            mRenderer = 0;
113        }
114
115    }
116    //-----------------------------------------------------------------------
117    ParticleEmitter* ParticleSystem::addEmitter(const String& emitterType)
118    {
119        ParticleEmitter* em =
120            ParticleSystemManager::getSingleton()._createEmitter(emitterType, this);
121        mEmitters.push_back(em);
122        return em;
123    }
124    //-----------------------------------------------------------------------
125    ParticleEmitter* ParticleSystem::getEmitter(unsigned short index) const
126    {
127        assert(index < mEmitters.size() && "Emitter index out of bounds!");
128        return mEmitters[index];
129    }
130    //-----------------------------------------------------------------------
131    unsigned short ParticleSystem::getNumEmitters(void) const
132    {
133        return static_cast< unsigned short >( mEmitters.size() );
134    }
135    //-----------------------------------------------------------------------
136    void ParticleSystem::removeEmitter(unsigned short index)
137    {
138        assert(index < mEmitters.size() && "Emitter index out of bounds!");
139        ParticleEmitterList::iterator ei = mEmitters.begin() + index;
140        ParticleSystemManager::getSingleton()._destroyEmitter(*ei);
141        mEmitters.erase(ei);
142    }
143    //-----------------------------------------------------------------------
144    void ParticleSystem::removeAllEmitters(void)
145    {
146        // DON'T delete directly, we don't know what heap these have been created on
147        ParticleEmitterList::iterator ei;
148        for (ei = mEmitters.begin(); ei != mEmitters.end(); ++ei)
149        {
150            ParticleSystemManager::getSingleton()._destroyEmitter(*ei);
151        }
152        mEmitters.clear();
153    }
154    //-----------------------------------------------------------------------
155    ParticleAffector* ParticleSystem::addAffector(const String& affectorType)
156    {
157        ParticleAffector* af =
158            ParticleSystemManager::getSingleton()._createAffector(affectorType, this);
159        mAffectors.push_back(af);
160        return af;
161    }
162    //-----------------------------------------------------------------------
163    ParticleAffector* ParticleSystem::getAffector(unsigned short index) const
164    {
165        assert(index < mAffectors.size() && "Affector index out of bounds!");
166        return mAffectors[index];
167    }
168    //-----------------------------------------------------------------------
169    unsigned short ParticleSystem::getNumAffectors(void) const
170    {
171        return static_cast< unsigned short >( mAffectors.size() );
172    }
173    //-----------------------------------------------------------------------
174    void ParticleSystem::removeAffector(unsigned short index)
175    {
176        assert(index < mAffectors.size() && "Affector index out of bounds!");
177        ParticleAffectorList::iterator ai = mAffectors.begin() + index;
178        ParticleSystemManager::getSingleton()._destroyAffector(*ai);
179        mAffectors.erase(ai);
180    }
181    //-----------------------------------------------------------------------
182    void ParticleSystem::removeAllAffectors(void)
183    {
184        // DON'T delete directly, we don't know what heap these have been created on
185        ParticleAffectorList::iterator ai;
186        for (ai = mAffectors.begin(); ai != mAffectors.end(); ++ai)
187        {
188            ParticleSystemManager::getSingleton()._destroyAffector(*ai);
189        }
190        mAffectors.clear();
191    }
192    //-----------------------------------------------------------------------
193    ParticleSystem& ParticleSystem::operator=(const ParticleSystem& rhs)
194    {
195        // Blank this system's emitters & affectors
196        removeAllEmitters();
197        removeAllAffectors();
198
199        // Copy emitters
200        unsigned int i;
201        for(i = 0; i < rhs.getNumEmitters(); ++i)
202        {
203            ParticleEmitter* rhsEm = rhs.getEmitter(i);
204            ParticleEmitter* newEm = addEmitter(rhsEm->getType());
205            rhsEm->copyParametersTo(newEm);
206        }
207        // Copy affectors
208        for(i = 0; i < rhs.getNumAffectors(); ++i)
209        {
210            ParticleAffector* rhsAf = rhs.getAffector(i);
211            ParticleAffector* newAf = addAffector(rhsAf->getType());
212            rhsAf->copyParametersTo(newAf);
213        }
214        setParticleQuota(rhs.getParticleQuota());
215        setMaterialName(rhs.mMaterialName);
216        setDefaultDimensions(rhs.mDefaultWidth, rhs.mDefaultHeight);
217        mCullIndividual = rhs.mCullIndividual;
218
219        setRenderer(rhs.getRendererName());
220        // Copy settings
221        if (mRenderer && rhs.getRenderer())
222        {
223            rhs.getRenderer()->copyParametersTo(mRenderer);
224        }
225
226        return *this;
227
228    }
229    //-----------------------------------------------------------------------
230    size_t ParticleSystem::getNumParticles(void) const
231    {
232        return mActiveParticles.size();
233    }
234    //-----------------------------------------------------------------------
235    size_t ParticleSystem::getParticleQuota(void) const
236    {
237        return mPoolSize;
238    }
239    //-----------------------------------------------------------------------
240    void ParticleSystem::setParticleQuota(size_t size)
241    {
242        // Never shrink below size()
243        size_t currSize = mParticlePool.size();
244
245        if( currSize < size )
246        {
247            // Will allocate particles on demand
248            mPoolSize = size;
249           
250        }
251    }
252    //-----------------------------------------------------------------------
253    void ParticleSystem::_update(Real timeElapsed)
254    {
255                // Scale incoming speed
256                timeElapsed *= mSpeedFactor;
257
258        // Init renderer if not done already
259        configureRenderer();
260
261                // Only update if attached to a node
262                if (mParentNode)
263                {
264                        // Update existing particles
265                _expire(timeElapsed);
266                _triggerAffectors(timeElapsed);
267                _applyMotion(timeElapsed);
268                        // Emit new particles
269                _triggerEmitters(timeElapsed);
270
271            if (!mBoundsAutoUpdate && mBoundsUpdateTime > 0.0f)
272                mBoundsUpdateTime -= timeElapsed; // count down
273            _updateBounds();
274                }
275
276
277    }
278    //-----------------------------------------------------------------------
279    void ParticleSystem::_expire(Real timeElapsed)
280    {
281        ActiveParticleList::iterator i, itEnd;
282        Particle* pParticle;
283
284        itEnd = mActiveParticles.end();
285
286        for (i = mActiveParticles.begin(); i != itEnd; )
287        {
288            pParticle = static_cast<Particle*>(*i);
289            if (pParticle->timeToLive < timeElapsed)
290            {
291                // Destroy this one
292                mFreeParticles.push_back( *i );
293                i = mActiveParticles.erase( i );
294            }
295            else
296            {
297                // Decrement TTL
298                pParticle->timeToLive -= timeElapsed;
299                                ++i;
300            }
301
302        }
303    }
304    //-----------------------------------------------------------------------
305    void ParticleSystem::_triggerEmitters(Real timeElapsed)
306    {
307        // Add up requests for emission
308        static std::vector<unsigned> requested;
309        if( requested.size() != mEmitters.size() )
310            requested.resize( mEmitters.size() );
311
312        size_t totalRequested, emitterCount, i, emissionAllowed;
313        ParticleEmitterList::iterator   itEmit, iEmitEnd;
314        ParticleAffectorList::iterator  itAff, itAffEnd;
315                           
316        iEmitEnd = mEmitters.end();
317        emitterCount = mEmitters.size();
318        emissionAllowed = mFreeParticles.size();
319        totalRequested = 0;
320
321        // Count up total requested emissions
322        for (itEmit = mEmitters.begin(), i = 0; itEmit != iEmitEnd; ++itEmit, ++i)
323        {
324            requested[i] = (*itEmit)->_getEmissionCount(timeElapsed);
325            totalRequested += requested[i];
326        }
327
328
329        // Check if the quota will be exceeded, if so reduce demand
330        if (totalRequested > emissionAllowed)
331        {
332            // Apportion down requested values to allotted values
333            Real ratio =  (Real)emissionAllowed / (Real)totalRequested;
334            for (i = 0; i < emitterCount; ++i)
335            {
336                requested[i] *= (unsigned int)ratio;
337            }
338        }
339
340        // Emit
341                // For each emission, apply a subset of the motion for the frame
342                // this ensures an even distribution of particles when many are
343                // emitted in a single frame
344        for (itEmit = mEmitters.begin(), i = 0; itEmit != iEmitEnd; ++itEmit, ++i)
345        {
346                        Real timePoint = 0.0f;
347                        Real timeInc = timeElapsed / requested[i];
348                for (unsigned int j = 0; j < requested[i]; ++j)
349            {
350                // Create a new particle & init using emitter
351                Particle* p = createParticle();
352                (*itEmit)->_initParticle(p);
353
354                                // Translate position & direction into world space
355                // Maybe make emitter do this?
356                p->position  = (mParentNode->_getDerivedOrientation() * p->position) + mParentNode->_getDerivedPosition();
357                p->direction = (mParentNode->_getDerivedOrientation() * p->direction);
358
359                                // apply partial frame motion to this particle
360                p->position += (p->direction * timePoint);
361
362                                // apply particle initialization by the affectors
363                                itAffEnd = mAffectors.end();
364                                for (itAff = mAffectors.begin(); itAff != itAffEnd; ++itAff)
365                                        (*itAff)->_initParticle(p);
366
367                                // Increment time fragment
368                                timePoint += timeInc;
369            }
370        }
371
372
373    }
374    //-----------------------------------------------------------------------
375    void ParticleSystem::_applyMotion(Real timeElapsed)
376    {
377        ActiveParticleList::iterator i, itEnd;
378        Particle* pParticle;
379
380        itEnd = mActiveParticles.end();
381        for (i = mActiveParticles.begin(); i != itEnd; ++i)
382        {
383            pParticle = static_cast<Particle*>(*i);
384            pParticle->position += (pParticle->direction * timeElapsed);
385        }
386
387    }
388    //-----------------------------------------------------------------------
389    void ParticleSystem::_triggerAffectors(Real timeElapsed)
390    {
391        ParticleAffectorList::iterator i, itEnd;
392       
393        itEnd = mAffectors.end();
394        for (i = mAffectors.begin(); i != itEnd; ++i)
395        {
396            (*i)->_affectParticles(this, timeElapsed);
397        }
398
399    }
400    //-----------------------------------------------------------------------
401    void ParticleSystem::increasePool(size_t size)
402    {
403        size_t oldSize = mParticlePool.size();
404
405        // Increase size
406        mParticlePool.reserve(size);
407        mParticlePool.resize(size);
408
409        // Create new particles
410        for( size_t i = oldSize; i < size; i++ )
411                {
412            mParticlePool[i] = new Particle();
413                }
414
415                if (mIsRendererConfigured)
416                {
417                        createVisualParticles(oldSize, size);
418                }
419
420
421    }
422    //-----------------------------------------------------------------------
423    ParticleIterator ParticleSystem::_getIterator(void)
424    {
425        return ParticleIterator(mActiveParticles.begin(), mActiveParticles.end());
426    }
427    //-----------------------------------------------------------------------
428        Particle* ParticleSystem::getParticle(size_t index)
429        {
430                assert (index < mActiveParticles.size() && "Index out of bounds!");
431                ActiveParticleList::iterator i = mActiveParticles.begin();
432                std::advance(i, index);
433                return *i;
434        }
435    //-----------------------------------------------------------------------
436    Particle* ParticleSystem::createParticle(void)
437    {
438        // Fast creation (don't use superclass since emitter will init)
439        Particle* p = mFreeParticles.front();
440        mFreeParticles.pop_front();
441        mActiveParticles.push_back(p);
442
443        p->_notifyOwner(this);
444
445        return p;
446
447    }
448    //-----------------------------------------------------------------------
449    void ParticleSystem::_updateRenderQueue(RenderQueue* queue)
450    {
451        if (mRenderer)
452        {
453            mRenderer->_updateRenderQueue(queue, mActiveParticles, mCullIndividual);
454        }
455    }
456    /*
457    //-----------------------------------------------------------------------
458    void ParticleSystem::genBillboardAxes(const Camera& cam, Vector3* pX, Vector3 *pY, const Billboard* pBill)   
459    {
460        // Orientation different from BillboardSet
461        // Billboards are in world space (to decouple them from emitters in node space)
462        Quaternion camQ;
463
464        switch (mBillboardType)
465        {
466        case BBT_POINT:
467            // Get camera world axes for X and Y (depth is irrelevant)
468            // No inverse transform
469            camQ = cam.getDerivedOrientation();
470            *pX = camQ * Vector3::UNIT_X;
471            *pY = camQ * Vector3::UNIT_Y;
472           
473            break;
474        case BBT_ORIENTED_COMMON:
475             // Y-axis is common direction
476            // X-axis is cross with camera direction
477            *pY = mCommonDirection;
478            *pX = cam.getDerivedDirection().crossProduct(*pY);
479           
480            break;
481        case BBT_ORIENTED_SELF:
482            // Y-axis is direction
483            // X-axis is cross with camera direction
484
485            // Scale direction first
486            *pY = (pBill->mDirection * 0.01);
487            *pX = cam.getDerivedDirection().crossProduct(*pY);
488
489            break;
490        }
491
492    }
493    //-----------------------------------------------------------------------
494    void ParticleSystem::getWorldTransforms(Matrix4* xform) const
495    {
496        // Particles are already in world space
497        *xform = Matrix4::IDENTITY;
498
499    }
500    //-----------------------------------------------------------------------
501    const Quaternion& ParticleSystem::getWorldOrientation(void) const
502    {
503        return mParentNode->_getDerivedOrientation();
504    }
505    //-----------------------------------------------------------------------
506    const Vector3& ParticleSystem::getWorldPosition(void) const
507    {
508        return mParentNode->_getDerivedPosition();
509    }
510    //-----------------------------------------------------------------------
511    */
512    void ParticleSystem::initParameters(void)
513    {
514        if (createParamDictionary("ParticleSystem"))
515        {
516            ParamDictionary* dict = getParamDictionary();
517
518            dict->addParameter(ParameterDef("quota",
519                "The maximum number of particle allowed at once in this system.",
520                PT_UNSIGNED_INT),
521                &msQuotaCmd);
522
523            dict->addParameter(ParameterDef("material",
524                "The name of the material to be used to render all particles in this system.",
525                PT_STRING),
526                &msMaterialCmd);
527
528            dict->addParameter(ParameterDef("particle_width",
529                "The width of particles in world units.",
530                PT_REAL),
531                &msWidthCmd);
532
533            dict->addParameter(ParameterDef("particle_height",
534                "The height of particles in world units.",
535                PT_REAL),
536                &msHeightCmd);
537
538            dict->addParameter(ParameterDef("cull_each",
539                "If true, each particle is culled in it's own right. If false, the entire system is culled as a whole.",
540                PT_BOOL),
541                &msCullCmd);
542
543                        dict->addParameter(ParameterDef("renderer",
544                                "Sets the particle system renderer to use (default 'billboard').",
545                                PT_STRING),
546                                &msRendererCmd);
547
548        }
549    }
550    //-----------------------------------------------------------------------
551    void ParticleSystem::_updateBounds()
552    {
553
554        if (mParentNode && (mBoundsAutoUpdate || mBoundsUpdateTime > 0.0f))
555        {
556
557            Vector3 min; 
558            Vector3 max;
559            if (!mBoundsAutoUpdate)
560            {
561                // We're on a limit, grow rather than reset each time
562                // so that we pick up the worst case scenario
563                min = mWorldAABB.getMinimum();
564                max = mWorldAABB.getMaximum();
565            }
566            else
567            {
568                min.x = min.y = min.z = Math::POS_INFINITY;
569                max.x = max.y = max.z = Math::NEG_INFINITY;
570            }
571            ActiveParticleList::iterator p;
572            Vector3 halfScale = Vector3::UNIT_SCALE * 0.5;
573            Vector3 defaultPadding =
574                halfScale * std::max(mDefaultHeight, mDefaultWidth);
575            for (p = mActiveParticles.begin(); p != mActiveParticles.end(); ++p)
576            {
577
578                if ((*p)->mOwnDimensions)
579                {
580                    Vector3 padding =
581                        halfScale * std::max((*p)->mWidth, (*p)->mHeight);
582                    min.makeFloor((*p)->position - padding);
583                    max.makeCeil((*p)->position + padding);
584                }
585                else
586                {
587                    min.makeFloor((*p)->position - defaultPadding);
588                    max.makeCeil((*p)->position + defaultPadding);
589                }
590            }
591            mWorldAABB.setExtents(min, max);
592
593
594            // We've already put particles in world space to decouple them from the
595            // node transform, so reverse transform back since we're expected to
596            // provide a local AABB
597            Vector3 temp;
598            const Vector3 *corner = mWorldAABB.getAllCorners();
599            Quaternion invQ = mParentNode->_getDerivedOrientation().Inverse();
600            Vector3 t = mParentNode->_getDerivedPosition();
601            min.x = min.y = min.z = Math::POS_INFINITY;
602            max.x = max.y = max.z = Math::NEG_INFINITY;
603            for (int i = 0; i < 8; ++i)
604            {
605                // Reverse transform corner
606                temp = invQ * (corner[i] - t);
607                min.makeFloor(temp);
608                max.makeCeil(temp);
609            }
610            AxisAlignedBox newAABB;
611            newAABB.setExtents(min, max);
612            // Merge calculated box with current AABB to preserve any user-set AABB
613            mAABB.merge(newAABB);
614
615            mParentNode->needUpdate();
616        }
617    }
618    //-----------------------------------------------------------------------
619    void ParticleSystem::fastForward(Real time, Real interval)
620    {
621        // First make sure all transforms are up to date
622
623        for (Real ftime = 0; ftime < time; ftime += interval)
624        {
625            _update(interval);
626        }
627    }
628    //-----------------------------------------------------------------------
629    const String& ParticleSystem::getMovableType(void) const
630    {
631        static String mType = "ParticleSystem";
632        return mType;
633    }
634    //-----------------------------------------------------------------------
635    void ParticleSystem::_notifyParticleResized(void)
636    {
637        if (mRenderer)
638        {
639            mRenderer->_notifyParticleResized();
640        }
641    }
642    //-----------------------------------------------------------------------
643    void ParticleSystem::_notifyParticleRotated(void)
644    {
645        if (mRenderer)
646        {
647            mRenderer->_notifyParticleRotated();
648        }
649    }
650    //-----------------------------------------------------------------------
651    void ParticleSystem::setDefaultDimensions( Real width, Real height )
652    {
653        mDefaultWidth = width;
654        mDefaultHeight = height;
655        if (mRenderer)
656        {
657            mRenderer->_notifyDefaultDimensions(width, height);
658        }
659    }
660    //-----------------------------------------------------------------------
661    void ParticleSystem::setDefaultWidth(Real width)
662    {
663        mDefaultWidth = width;
664        if (mRenderer)
665        {
666            mRenderer->_notifyDefaultDimensions(mDefaultWidth, mDefaultHeight);
667        }
668    }
669    //-----------------------------------------------------------------------
670    Real ParticleSystem::getDefaultWidth(void) const
671    {
672        return mDefaultWidth;
673    }
674    //-----------------------------------------------------------------------
675    void ParticleSystem::setDefaultHeight(Real height)
676    {
677        mDefaultHeight = height;
678        if (mRenderer)
679        {
680            mRenderer->_notifyDefaultDimensions(mDefaultWidth, mDefaultHeight);
681        }
682    }
683    //-----------------------------------------------------------------------
684    Real ParticleSystem::getDefaultHeight(void) const
685    {
686        return mDefaultHeight;
687    }
688    //-----------------------------------------------------------------------
689    void ParticleSystem::_notifyCurrentCamera(Camera* cam)
690    {
691        if (mRenderer)
692        {
693                        if (!mIsRendererConfigured)
694                                configureRenderer();
695
696            mRenderer->_notifyCurrentCamera(cam);
697        }
698    }
699    //-----------------------------------------------------------------------
700    void ParticleSystem::_notifyAttached(Node* parent, bool isTagPoint)
701    {
702        MovableObject::_notifyAttached(parent, isTagPoint);
703        if (mRenderer)
704        {
705            mRenderer->_notifyAttached(parent, isTagPoint);
706        }
707    }
708    //-----------------------------------------------------------------------
709    void ParticleSystem::setMaterialName(const String& name)
710    {
711        mMaterialName = name;
712        if (mIsRendererConfigured)
713        {
714            MaterialPtr mat = MaterialManager::getSingleton().load(
715                mMaterialName, mResourceGroupName);
716            mRenderer->_setMaterial(mat);
717        }
718    }
719    //-----------------------------------------------------------------------
720    const String& ParticleSystem::getMaterialName(void) const
721    {
722        return mMaterialName;
723    }
724    //-----------------------------------------------------------------------
725    void ParticleSystem::clear()
726    {
727        // Insert actives into free list
728        mFreeParticles.insert(mFreeParticles.end(), mActiveParticles.begin(), mActiveParticles.end());
729
730        // Remove all active instances
731        mActiveParticles.clear();
732
733    }
734    //-----------------------------------------------------------------------
735    void ParticleSystem::setRenderer(const String& rendererName)
736    {
737                if (mRenderer)
738                {
739                        // Destroy existing
740                        destroyVisualParticles(0, mParticlePool.size());
741                        ParticleSystemManager::getSingleton()._destroyRenderer(mRenderer);
742                        mRenderer = 0;
743                }
744
745        if (!rendererName.empty())
746        {
747                        mRenderer = ParticleSystemManager::getSingleton()._createRenderer(rendererName);
748            mIsRendererConfigured = false;
749        }
750    }
751    //-----------------------------------------------------------------------
752    void ParticleSystem::configureRenderer(void)
753    {
754        // Actual allocate particles
755        size_t currSize = mParticlePool.size();
756        size_t size = mPoolSize;
757        if( currSize < size )
758        {
759            this->increasePool(size);
760
761            for( size_t i = currSize; i < size; ++i )
762            {
763                // Add new items to the queue
764                mFreeParticles.push_back( mParticlePool[i] );
765            }
766
767            // Tell the renderer, if already configured
768            if (mRenderer && mIsRendererConfigured)
769            {
770                mRenderer->_notifyParticleQuota(size);
771            }
772        }
773
774        if (mRenderer && !mIsRendererConfigured)
775        {
776            mRenderer->_notifyParticleQuota(mParticlePool.size());
777            if (mParentNode)
778                mRenderer->_notifyAttached(mParentNode, mParentIsTagPoint);
779            mRenderer->_notifyDefaultDimensions(mDefaultWidth, mDefaultHeight);
780            createVisualParticles(0, mParticlePool.size());
781            MaterialPtr mat = MaterialManager::getSingleton().load(
782                mMaterialName, mResourceGroupName);
783            mRenderer->_setMaterial(mat);
784                        if (mRenderQueueIDSet)
785                                mRenderer->setRenderQueueGroup(mRenderQueueID);
786            mIsRendererConfigured = true;
787        }
788    }
789    //-----------------------------------------------------------------------
790    ParticleSystemRenderer* ParticleSystem::getRenderer(void) const
791    {
792        return mRenderer;
793    }
794    //-----------------------------------------------------------------------
795    const String& ParticleSystem::getRendererName(void) const
796    {
797        if (mRenderer)
798        {
799            return mRenderer->getType();
800        }
801        else
802        {
803            return StringUtil::BLANK;
804        }
805    }
806    //-----------------------------------------------------------------------
807    bool ParticleSystem::getCullIndividually(void) const
808    {
809        return mCullIndividual;
810    }
811    //-----------------------------------------------------------------------
812    void ParticleSystem::setCullIndividually(bool cullIndividual)
813    {
814        mCullIndividual = cullIndividual;
815    }
816    //-----------------------------------------------------------------------
817        void ParticleSystem::createVisualParticles(size_t poolstart, size_t poolend)
818        {
819                ParticlePool::iterator i = mParticlePool.begin();
820                ParticlePool::iterator iend = mParticlePool.begin();
821                std::advance(i, poolstart);
822                std::advance(iend, poolend);
823                for (; i != iend; ++i)
824                {
825                        (*i)->_notifyVisualData(
826                                mRenderer->_createVisualData());
827                }
828        }
829    //-----------------------------------------------------------------------
830        void ParticleSystem::destroyVisualParticles(size_t poolstart, size_t poolend)
831        {
832                ParticlePool::iterator i = mParticlePool.begin();
833                ParticlePool::iterator iend = mParticlePool.begin();
834                std::advance(i, poolstart);
835                std::advance(iend, poolend);
836                for (; i != iend; ++i)
837                {
838                        mRenderer->_destroyVisualData((*i)->getVisualData());
839                        (*i)->_notifyVisualData(0);
840                }
841        }
842    //-----------------------------------------------------------------------
843    void ParticleSystem::setBounds(const AxisAlignedBox& aabb)
844    {
845        mAABB = aabb;
846        Real sqDist = std::max(mAABB.getMinimum().squaredLength(),
847            mAABB.getMaximum().squaredLength());
848        mBoundingRadius = Math::Sqrt(sqDist);
849
850    }
851    //-----------------------------------------------------------------------
852    void ParticleSystem::setBoundsAutoUpdated(bool autoUpdate, Real stopIn)
853    {
854        mBoundsAutoUpdate = autoUpdate;
855        mBoundsUpdateTime = stopIn;
856    }
857        //-----------------------------------------------------------------------
858        void ParticleSystem::setRenderQueueGroup(RenderQueueGroupID queueID)
859        {
860                MovableObject::setRenderQueueGroup(queueID);
861                if (mRenderer)
862                {
863                        mRenderer->setRenderQueueGroup(queueID);
864                }
865        }
866    //-----------------------------------------------------------------------
867    String ParticleSystem::CmdCull::doGet(const void* target) const
868    {
869        return StringConverter::toString(
870            static_cast<const ParticleSystem*>(target)->getCullIndividually() );
871    }
872    void ParticleSystem::CmdCull::doSet(void* target, const String& val)
873    {
874        static_cast<ParticleSystem*>(target)->setCullIndividually(
875            StringConverter::parseBool(val));
876    }
877    //-----------------------------------------------------------------------
878    String ParticleSystem::CmdHeight::doGet(const void* target) const
879    {
880        return StringConverter::toString(
881            static_cast<const ParticleSystem*>(target)->getDefaultHeight() );
882    }
883    void ParticleSystem::CmdHeight::doSet(void* target, const String& val)
884    {
885        static_cast<ParticleSystem*>(target)->setDefaultHeight(
886            StringConverter::parseReal(val));
887    }
888    //-----------------------------------------------------------------------
889    String ParticleSystem::CmdWidth::doGet(const void* target) const
890    {
891        return StringConverter::toString(
892            static_cast<const ParticleSystem*>(target)->getDefaultWidth() );
893    }
894    void ParticleSystem::CmdWidth::doSet(void* target, const String& val)
895    {
896        static_cast<ParticleSystem*>(target)->setDefaultWidth(
897            StringConverter::parseReal(val));
898    }
899    //-----------------------------------------------------------------------
900    String ParticleSystem::CmdMaterial::doGet(const void* target) const
901    {
902        return static_cast<const ParticleSystem*>(target)->getMaterialName();
903    }
904    void ParticleSystem::CmdMaterial::doSet(void* target, const String& val)
905    {
906        static_cast<ParticleSystem*>(target)->setMaterialName(val);
907    }
908    //-----------------------------------------------------------------------
909    String ParticleSystem::CmdQuota::doGet(const void* target) const
910    {
911        return StringConverter::toString(
912            static_cast<const ParticleSystem*>(target)->getParticleQuota() );
913    }
914    void ParticleSystem::CmdQuota::doSet(void* target, const String& val)
915    {
916        static_cast<ParticleSystem*>(target)->setParticleQuota(
917            StringConverter::parseUnsignedInt(val));
918    }
919    //-----------------------------------------------------------------------
920    String ParticleSystem::CmdRenderer::doGet(const void* target) const
921    {
922        return static_cast<const ParticleSystem*>(target)->getRendererName();
923    }
924    void ParticleSystem::CmdRenderer::doSet(void* target, const String& val)
925    {
926        static_cast<ParticleSystem*>(target)->setRenderer(val);
927    }
928    //-----------------------------------------------------------------------
929    ParticleAffector::~ParticleAffector()
930    {
931    }
932    //-----------------------------------------------------------------------
933    ParticleAffectorFactory::~ParticleAffectorFactory()
934    {
935        // Destroy all affectors
936        std::vector<ParticleAffector*>::iterator i;
937        for (i = mAffectors.begin(); i != mAffectors.end(); ++i)
938        {
939            delete (*i);
940        }
941           
942        mAffectors.clear();
943
944    }
945    //-----------------------------------------------------------------------
946    void ParticleAffectorFactory::destroyAffector(ParticleAffector* e)
947    {
948        std::vector<ParticleAffector*>::iterator i;
949        for (i = mAffectors.begin(); i != mAffectors.end(); ++i)
950        {
951            if ((*i) == e)
952            {
953                mAffectors.erase(i);
954                delete e;
955                break;
956            }
957        }
958    }
959
960}
Note: See TracBrowser for help on using the repository browser.