Main Page Namespace List Class Hierarchy Alphabetical List Compound List File List Namespace Members Compound Members File Members Related Pages

# OgreParticleSystem.cpp

Go to the documentation of this file.

    00001 /*
    00002 -----------------------------------------------------------------------------
    00003 This source file is part of OGRE
    00004     (Object-oriented Graphics Rendering Engine)
    00005 For the latest info, see http://www.ogre3d.org/
    00006
    00007 Copyright © 2000-2002 The OGRE Team
    00008 Also see acknowledgements in Readme.html
    00009
    00010 This program is free software; you can redistribute it and/or modify it under
    00011 the terms of the GNU Lesser General Public License as published by the Free Software
    00012 Foundation; either version 2 of the License, or (at your option) any later
    00013 version.
    00014
    00015 This program is distributed in the hope that it will be useful, but WITHOUT
    00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
    00018
    00019 You should have received a copy of the GNU Lesser General Public License along with
    00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
    00022 http://www.gnu.org/copyleft/lesser.txt.
    00023 -----------------------------------------------------------------------------
    00024 */
    00025 #include "OgreStableHeaders.h"
    00026
    00027 #include "OgreParticleSystem.h"
    00028 #include "OgreParticleSystemManager.h"
    00029 #include "OgreRenderQueue.h"
    00030 #include "OgreBillboardSet.h"
    00031 #include "OgreParticleEmitter.h"
    00032 #include "OgreParticleAffector.h"
    00033 #include "OgreParticle.h"
    00034 #include "OgreSceneNode.h"
    00035 #include "OgreCamera.h"
    00036 #include "OgreStringConverter.h"
    00037 #include "OgreLogManager.h"
    00038 #include "OgreException.h"
    00039
    00040
    00041
    00042 namespace Ogre {
    00043     // Init statics
    00044     ParticleSystem::CmdCull ParticleSystem::msCullCmd;
    00045     ParticleSystem::CmdHeight ParticleSystem::msHeightCmd;
    00046     ParticleSystem::CmdMaterial ParticleSystem::msMaterialCmd;
    00047     ParticleSystem::CmdQuota ParticleSystem::msQuotaCmd;
    00048     ParticleSystem::CmdWidth ParticleSystem::msWidthCmd;
    00049     ParticleSystem::CmdBillboardType ParticleSystem::msBillboardTypeCmd;
    00050     ParticleSystem::CmdCommonDirection ParticleSystem::msCommonDirectionCmd;
    00051
    00052     //-----------------------------------------------------------------------
    00053     ParticleSystem::ParticleSystem()
    00054     {
    00055         initParameters();
    00056     }
    00057     //-----------------------------------------------------------------------
    00058     ParticleSystem::ParticleSystem(const String& name)
    00059     {
    00060         // DO NOT use superclass constructor
    00061         // This will call setPoolSize in the BillboardSet context and create Billboard objects
    00062         //  instead of Particle objects
    00063         // Unavoidable due to C++ funky virtualisation rules & constructors
    00064         //mpPositions = 0;
    00065         //mpColours = 0;
    00066         //mpIndexes = 0;
    00067         mVertexData = 0;
    00068         mIndexData = 0;
    00069         //mpTexCoords = 0;
    00070         mAutoExtendPool = true;
    00071         mAllDefaultSize = true;
    00072         mOriginType = BBO_CENTER;
    00073         mName = name;
    00074         mCullIndividual = true;
    00075         setDefaultDimensions( 100, 100 );
    00076         setMaterialName( "BaseWhite" );
    00077         // Default to 10 particles, expect app to specify (will only be increased, not decreased)
    00078         setPoolSize( 10 );
    00079
    00080         initParameters();
    00081
    00082     }
    00083     //-----------------------------------------------------------------------
    00084     ParticleSystem::~ParticleSystem()
    00085     {
    00086         // Arrange for the deletion of emitters & affectors
    00087         removeAllEmitters();
    00088         removeAllAffectors();
    00089     }
    00090     //-----------------------------------------------------------------------
    00091     ParticleEmitter* ParticleSystem::addEmitter(const String& emitterType)
    00092     {
    00093         ParticleEmitter* em = ParticleSystemManager::getSingleton()._createEmitter(emitterType);
    00094         mEmitters.push_back(em);
    00095         return em;
    00096     }
    00097     //-----------------------------------------------------------------------
    00098     ParticleEmitter* ParticleSystem::getEmitter(unsigned short index) const
    00099     {
    00100         assert(index < mEmitters.size() && "Emitter index out of bounds!");
    00101         return mEmitters[index];
    00102     }
    00103     //-----------------------------------------------------------------------
    00104     unsigned short ParticleSystem::getNumEmitters(void) const
    00105     {
    00106         return static_cast< unsigned short >( mEmitters.size() );
    00107     }
    00108     //-----------------------------------------------------------------------
    00109     void ParticleSystem::removeEmitter(unsigned short index)
    00110     {
    00111         assert(index < mEmitters.size() && "Emitter index out of bounds!");
    00112         ParticleEmitterList::iterator ei = mEmitters.begin() + index;
    00113         ParticleSystemManager::getSingleton()._destroyEmitter(*ei);
    00114         mEmitters.erase(ei);
    00115     }
    00116     //-----------------------------------------------------------------------
    00117     void ParticleSystem::removeAllEmitters(void)
    00118     {
    00119         // DON'T delete directly, we don't know what heap these have been created on
    00120         ParticleEmitterList::iterator ei;
    00121         for (ei = mEmitters.begin(); ei != mEmitters.end(); ++ei)
    00122         {
    00123             ParticleSystemManager::getSingleton()._destroyEmitter(*ei);
    00124         }
    00125         mEmitters.clear();
    00126     }
    00127     //-----------------------------------------------------------------------
    00128     ParticleAffector* ParticleSystem::addAffector(const String& affectorType)
    00129     {
    00130         ParticleAffector* af = ParticleSystemManager::getSingleton()._createAffector(affectorType);
    00131         mAffectors.push_back(af);
    00132         return af;
    00133     }
    00134     //-----------------------------------------------------------------------
    00135     ParticleAffector* ParticleSystem::getAffector(unsigned short index) const
    00136     {
    00137         assert(index < mAffectors.size() && "Affector index out of bounds!");
    00138         return mAffectors[index];
    00139     }
    00140     //-----------------------------------------------------------------------
    00141     unsigned short ParticleSystem::getNumAffectors(void) const
    00142     {
    00143         return static_cast< unsigned short >( mAffectors.size() );
    00144     }
    00145     //-----------------------------------------------------------------------
    00146     void ParticleSystem::removeAffector(unsigned short index)
    00147     {
    00148         assert(index < mAffectors.size() && "Affector index out of bounds!");
    00149         ParticleAffectorList::iterator ai = mAffectors.begin() + index;
    00150         ParticleSystemManager::getSingleton()._destroyAffector(*ai);
    00151         mAffectors.erase(ai);
    00152     }
    00153     //-----------------------------------------------------------------------
    00154     void ParticleSystem::removeAllAffectors(void)
    00155     {
    00156         // DON'T delete directly, we don't know what heap these have been created on
    00157         ParticleAffectorList::iterator ai;
    00158         for (ai = mAffectors.begin(); ai != mAffectors.end(); ++ai)
    00159         {
    00160             ParticleSystemManager::getSingleton()._destroyAffector(*ai);
    00161         }
    00162         mAffectors.clear();
    00163     }
    00164     //-----------------------------------------------------------------------
    00165     ParticleSystem& ParticleSystem::operator=(const ParticleSystem& rhs)
    00166     {
    00167         // Blank this system's emitters & affectors
    00168         removeAllEmitters();
    00169         removeAllAffectors();
    00170
    00171         // Copy emitters
    00172         unsigned int i;
    00173         for(i = 0; i < rhs.getNumEmitters(); ++i)
    00174         {
    00175             ParticleEmitter* rhsEm = rhs.getEmitter(i);
    00176             ParticleEmitter* newEm = addEmitter(rhsEm->getType());
    00177             rhsEm->copyParametersTo(newEm);
    00178         }
    00179         // Copy affectors
    00180         for(i = 0; i < rhs.getNumAffectors(); ++i)
    00181         {
    00182             ParticleAffector* rhsAf = rhs.getAffector(i);
    00183             ParticleAffector* newAf = addAffector(rhsAf->getType());
    00184             rhsAf->copyParametersTo(newAf);
    00185         }
    00186         setPoolSize(rhs.getPoolSize());
    00187         setMaterialName(rhs.mMaterialName);
    00188         mOriginType = rhs.mOriginType;
    00189         mDefaultHeight = rhs.mDefaultHeight;
    00190         mDefaultWidth = rhs.mDefaultWidth;
    00191         mCullIndividual = rhs.mCullIndividual;
    00192         mBillboardType = rhs.mBillboardType;
    00193         mCommonDirection = rhs.mCommonDirection;
    00194
    00195
    00196         return *this;
    00197
    00198     }
    00199     //-----------------------------------------------------------------------
    00200     unsigned int ParticleSystem::getNumParticles(void) const
    00201     {
    00202         return (unsigned int)mActiveBillboards.size();
    00203     }
    00204     //-----------------------------------------------------------------------
    00205     unsigned int ParticleSystem::getParticleQuota(void) const
    00206     {
    00207         // This is basically a renamed property
    00208         return getPoolSize();
    00209     }
    00210     //-----------------------------------------------------------------------
    00211     void ParticleSystem::setParticleQuota(unsigned int quota)
    00212     {
    00213         // This is basically a renamed property
    00214         setPoolSize(quota);
    00215     }
    00216     //-----------------------------------------------------------------------
    00217     void ParticleSystem::_update(Real timeElapsed)
    00218     {
    00219         // Only update if attached to a node
    00220         if (mParentNode)
    00221         {
    00222             // Update existing particles
    00223             _expire(timeElapsed);
    00224             _triggerAffectors(timeElapsed);
    00225             _applyMotion(timeElapsed);
    00226             // Emit new particles
    00227             _triggerEmitters(timeElapsed);
    00228             // Update bounds
    00229             _updateBounds();
    00230         }
    00231
    00232
    00233     }
    00234     //-----------------------------------------------------------------------
    00235     void ParticleSystem::_expire(Real timeElapsed)
    00236     {
    00237         ActiveBillboardList::iterator i, itEnd;
    00238         Particle* pParticle;
    00239
    00240         itEnd = mActiveBillboards.end();
    00241
    00242         for (i = mActiveBillboards.begin(); i != itEnd; )
    00243         {
    00244             pParticle = static_cast<Particle*>(*i);
    00245             if (pParticle->mTimeToLive < timeElapsed)
    00246             {
    00247                 // Destroy this one
    00248                 mFreeBillboards.push_back( *i );
    00249                 i = mActiveBillboards.erase( i );
    00250             }
    00251             else
    00252             {
    00253                 // Decrement TTL
    00254                 pParticle->mTimeToLive -= timeElapsed;
    00255                 ++i;
    00256             }
    00257
    00258         }
    00259     }
    00260     //-----------------------------------------------------------------------
    00261     void ParticleSystem::_triggerEmitters(Real timeElapsed)
    00262     {
    00263         // Add up requests for emission
    00264         static std::vector<unsigned> requested;
    00265         if( requested.size() != mEmitters.size() )
    00266             requested.resize( mEmitters.size() );
    00267
    00268         size_t totalRequested, emitterCount, i, emissionAllowed;
    00269         ParticleEmitterList::iterator   itEmit, iEmitEnd;
    00270         ParticleAffectorList::iterator  itAff, itAffEnd;
    00271
    00272         iEmitEnd = mEmitters.end();
    00273         emitterCount = mEmitters.size();
    00274         emissionAllowed = getParticleQuota() - mActiveBillboards.size();
    00275         totalRequested = 0;
    00276
    00277         // Count up total requested emissions
    00278         for (itEmit = mEmitters.begin(), i = 0; itEmit != iEmitEnd; ++itEmit, ++i)
    00279         {
    00280             requested[i] = (*itEmit)->_getEmissionCount(timeElapsed);
    00281             totalRequested += requested[i];
    00282         }
    00283
    00284
    00285         // Check if the quota will be exceeded, if so reduce demand
    00286         if (totalRequested > emissionAllowed)
    00287         {
    00288             // Apportion down requested values to allotted values
    00289             Real ratio =  (Real)emissionAllowed / (Real)totalRequested;
    00290             for (i = 0; i < emitterCount; ++i)
    00291             {
    00292                 requested[i] *= (unsigned int)ratio;
    00293             }
    00294         }
    00295
    00296         // Emit
    00297         // For each emission, apply a subset of the motion for the frame
    00298         // this ensures an even distribution of particles when many are
    00299         // emitted in a single frame
    00300         for (itEmit = mEmitters.begin(), i = 0; itEmit != iEmitEnd; ++itEmit, ++i)
    00301         {
    00302             Real timePoint = 0.0f;
    00303             Real timeInc = timeElapsed / requested[i];
    00304             for (unsigned int j = 0; j < requested[i]; ++j)
    00305             {
    00306                 // Create a new particle & init using emitter
    00307                 Particle* p = addParticle();
    00308                 (*itEmit)->_initParticle(p);
    00309
    00310                 // Translate position & direction into world space
    00311                 // Maybe make emitter do this?
    00312                 p->mPosition  = (mParentNode->_getDerivedOrientation() * p->mPosition) + mParentNode->_getDerivedPosition();
    00313                 p->mDirection = (mParentNode->_getDerivedOrientation() * p->mDirection);
    00314
    00315                 // apply partial frame motion to this particle
    00316                 p->mPosition += (p->mDirection * timePoint);
    00317
    00318                 // apply particle initialization by the affectors
    00319                 itAffEnd = mAffectors.end();
    00320                 for (itAff = mAffectors.begin(); itAff != itAffEnd; ++itAff)
    00321                     (*itAff)->_initParticle(p);
    00322
    00323                 // Increment time fragment
    00324                 timePoint += timeInc;
    00325             }
    00326         }
    00327
    00328
    00329     }
    00330     //-----------------------------------------------------------------------
    00331     void ParticleSystem::_applyMotion(Real timeElapsed)
    00332     {
    00333         ActiveBillboardList::iterator i, itEnd;
    00334         Particle* pParticle;
    00335
    00336         itEnd = mActiveBillboards.end();
    00337         for (i = mActiveBillboards.begin(); i != itEnd; ++i)
    00338         {
    00339             pParticle = static_cast<Particle*>(*i);
    00340             pParticle->mPosition += (pParticle->mDirection * timeElapsed);
    00341         }
    00342
    00343     }
    00344     //-----------------------------------------------------------------------
    00345     void ParticleSystem::_triggerAffectors(Real timeElapsed)
    00346     {
    00347         ParticleAffectorList::iterator i, itEnd;
    00348
    00349         itEnd = mAffectors.end();
    00350         for (i = mAffectors.begin(); i != itEnd; ++i)
    00351         {
    00352             (*i)->_affectParticles(this, timeElapsed);
    00353         }
    00354
    00355     }
    00356     //-----------------------------------------------------------------------
    00357     void ParticleSystem::increasePool(unsigned int size)
    00358     {
    00359         size_t oldSize = mBillboardPool.size();
    00360
    00361         // Increase size
    00362         mBillboardPool.reserve(size);
    00363         mBillboardPool.resize(size);
    00364
    00365         // Create new particles
    00366         for( size_t i = oldSize; i < size; i++ )
    00367             mBillboardPool[i] = new Particle();
    00368
    00369     }
    00370     //-----------------------------------------------------------------------
    00371     ParticleIterator ParticleSystem::_getIterator(void)
    00372     {
    00373         return ParticleIterator(mActiveBillboards.begin(), mActiveBillboards.end());
    00374     }
    00375     //-----------------------------------------------------------------------
    00376     Particle* ParticleSystem::addParticle(void)
    00377     {
    00378         // Fast creation (don't use superclass since emitter will init)
    00379         Billboard* newBill = mFreeBillboards.front();
    00380         mFreeBillboards.pop_front();
    00381         mActiveBillboards.push_back(newBill);
    00382
    00383         newBill->_notifyOwner(this);
    00384
    00385         // Because we're creating objects here we know this is a Particle
    00386         return static_cast<Particle*>(newBill);
    00387
    00388     }
    00389     //-----------------------------------------------------------------------
    00390     void ParticleSystem::genBillboardAxes(const Camera& cam, Vector3* pX, Vector3 *pY, const Billboard* pBill)
    00391     {
    00392         // Orientation different from BillboardSet
    00393         // Billboards are in world space (to decouple them from emitters in node space)
    00394         Quaternion camQ;
    00395
    00396         switch (mBillboardType)
    00397         {
    00398         case BBT_POINT:
    00399             // Get camera world axes for X and Y (depth is irrelevant)
    00400             // No inverse transform
    00401             camQ = cam.getDerivedOrientation();
    00402             *pX = camQ * Vector3::UNIT_X;
    00403             *pY = camQ * Vector3::UNIT_Y;
    00404
    00405             break;
    00406         case BBT_ORIENTED_COMMON:
    00407              // Y-axis is common direction
    00408             // X-axis is cross with camera direction
    00409             *pY = mCommonDirection;
    00410             *pX = cam.getDerivedDirection().crossProduct(*pY);
    00411
    00412             break;
    00413         case BBT_ORIENTED_SELF:
    00414             // Y-axis is direction
    00415             // X-axis is cross with camera direction
    00416
    00417             // Scale direction first
    00418             *pY = (pBill->mDirection * 0.01);
    00419             *pX = cam.getDerivedDirection().crossProduct(*pY);
    00420
    00421             break;
    00422         }
    00423
    00424     }
    00425     //-----------------------------------------------------------------------
    00426     void ParticleSystem::getWorldTransforms(Matrix4* xform) const
    00427     {
    00428         // Particles are already in world space
    00429         *xform = Matrix4::IDENTITY;
    00430
    00431     }
    00432     //-----------------------------------------------------------------------
    00433     const Quaternion& ParticleSystem::getWorldOrientation(void) const
    00434     {
    00435         return mParentNode->_getDerivedOrientation();
    00436     }
    00437     //-----------------------------------------------------------------------
    00438     const Vector3& ParticleSystem::getWorldPosition(void) const
    00439     {
    00440         return mParentNode->_getDerivedPosition();
    00441     }
    00442     //-----------------------------------------------------------------------
    00443     void ParticleSystem::initParameters(void)
    00444     {
    00445         if (createParamDictionary("ParticleSystem"))
    00446         {
    00447             ParamDictionary* dict = getParamDictionary();
    00448
    00449             dict->addParameter(ParameterDef("quota",
    00450                 "The maximum number of particle allowed at once in this system.",
    00451                 PT_UNSIGNED_INT),
    00452                 &msQuotaCmd);
    00453
    00454             dict->addParameter(ParameterDef("material",
    00455                 "The name of the material to be used to render all particles in this system.",
    00456                 PT_STRING),
    00457                 &msMaterialCmd);
    00458
    00459             dict->addParameter(ParameterDef("particle_width",
    00460                 "The width of particles in world units.",
    00461                 PT_REAL),
    00462                 &msWidthCmd);
    00463
    00464             dict->addParameter(ParameterDef("particle_height",
    00465                 "The height of particles in world units.",
    00466                 PT_REAL),
    00467                 &msHeightCmd);
    00468
    00469             dict->addParameter(ParameterDef("cull_each",
    00470                 "If true, each particle is culled in it's own right. If false, the entire system is culled as a whole.",
    00471                 PT_BOOL),
    00472                 &msCullCmd);
    00473
    00474             dict->addParameter(ParameterDef("billboard_type",
    00475                 "The type of billboard to use. 'point' means a simulated spherical particle, "
    00476                 "'oriented_common' means all particles in the set are oriented around common_direction, "
    00477                 "and 'oriented_self' means particles are oriented around their own direction.",
    00478                 PT_STRING),
    00479                 &msBillboardTypeCmd);
    00480
    00481             dict->addParameter(ParameterDef("common_direction",
    00482                 "Only useful when billboard_type is oriented_common. This parameter sets the common "
    00483                 "orientation for all particles in the set (e.g. raindrops may all be oriented downwards).",
    00484                 PT_VECTOR3),
    00485                 &msCommonDirectionCmd);
    00486
    00487         }
    00488     }
    00489     //-----------------------------------------------------------------------
    00490     void ParticleSystem::_updateBounds()
    00491     {
    00492         // Call superclass
    00493         BillboardSet::_updateBounds();
    00494
    00495         if (mParentNode && !mAABB.isNull())
    00496         {
    00497             // Have to override because bounds are supposed to be in local node space
    00498             // but we've already put particles in world space to decouple them from the
    00499             // node transform, so reverse transform back
    00500
    00501             Vector3 min( Math::POS_INFINITY, Math::POS_INFINITY, Math::POS_INFINITY );
    00502             Vector3 max( Math::NEG_INFINITY, Math::NEG_INFINITY, Math::NEG_INFINITY );
    00503             Vector3 temp;
    00504             const Vector3 *corner = mAABB.getAllCorners();
    00505             Quaternion invQ = mParentNode->_getDerivedOrientation().Inverse();
    00506             Vector3 t = mParentNode->_getDerivedPosition();
    00507
    00508             for (int i = 0; i < 8; ++i)
    00509             {
    00510                 // Reverse transform corner
    00511                 temp = invQ * (corner[i] - t);
    00512                 min.makeFloor(temp);
    00513                 max.makeCeil(temp);
    00514             }
    00515             mAABB.setExtents(min, max);
    00516         }
    00517     }
    00518     //-----------------------------------------------------------------------
    00519
    00520     void ParticleSystem::fastForward(Real time, Real interval)
    00521     {
    00522         // First make sure all transforms are up to date
    00523
    00524         for (Real ftime = 0; ftime < time; ftime += interval)
    00525         {
    00526             _update(interval);
    00527         }
    00528     }
    00529     //-----------------------------------------------------------------------
    00530     const String& ParticleSystem::getMovableType(void) const
    00531     {
    00532         static String mType = "ParticleSystem";
    00533         return mType;
    00534     }
    00535
    00536     //-----------------------------------------------------------------------
    00537     String ParticleSystem::CmdCull::doGet(const void* target) const
    00538     {
    00539         return StringConverter::toString(
    00540             static_cast<const ParticleSystem*>(target)->getCullIndividually() );
    00541     }
    00542     void ParticleSystem::CmdCull::doSet(void* target, const String& val)
    00543     {
    00544         static_cast<ParticleSystem*>(target)->setCullIndividually(
    00545             StringConverter::parseBool(val));
    00546     }
    00547     //-----------------------------------------------------------------------
    00548     String ParticleSystem::CmdHeight::doGet(const void* target) const
    00549     {
    00550         return StringConverter::toString(
    00551             static_cast<const ParticleSystem*>(target)->getDefaultHeight() );
    00552     }
    00553     void ParticleSystem::CmdHeight::doSet(void* target, const String& val)
    00554     {
    00555         static_cast<ParticleSystem*>(target)->setDefaultHeight(
    00556             StringConverter::parseReal(val));
    00557     }
    00558     //-----------------------------------------------------------------------
    00559     String ParticleSystem::CmdWidth::doGet(const void* target) const
    00560     {
    00561         return StringConverter::toString(
    00562             static_cast<const ParticleSystem*>(target)->getDefaultWidth() );
    00563     }
    00564     void ParticleSystem::CmdWidth::doSet(void* target, const String& val)
    00565     {
    00566         static_cast<ParticleSystem*>(target)->setDefaultWidth(
    00567             StringConverter::parseReal(val));
    00568     }
    00569     //-----------------------------------------------------------------------
    00570     String ParticleSystem::CmdMaterial::doGet(const void* target) const
    00571     {
    00572         return static_cast<const ParticleSystem*>(target)->getMaterialName();
    00573     }
    00574     void ParticleSystem::CmdMaterial::doSet(void* target, const String& val)
    00575     {
    00576         static_cast<ParticleSystem*>(target)->setMaterialName(val);
    00577     }
    00578     //-----------------------------------------------------------------------
    00579     String ParticleSystem::CmdQuota::doGet(const void* target) const
    00580     {
    00581         return StringConverter::toString(
    00582             static_cast<const ParticleSystem*>(target)->getParticleQuota() );
    00583     }
    00584     void ParticleSystem::CmdQuota::doSet(void* target, const String& val)
    00585     {
    00586         static_cast<ParticleSystem*>(target)->setParticleQuota(
    00587             StringConverter::parseUnsignedInt(val));
    00588     }
    00589     //-----------------------------------------------------------------------
    00590     String ParticleSystem::CmdBillboardType::doGet(const void* target) const
    00591     {
    00592         BillboardType t = static_cast<const ParticleSystem*>(target)->getBillboardType();
    00593         switch(t)
    00594         {
    00595         case BBT_POINT:
    00596             return "point";
    00597             break;
    00598         case BBT_ORIENTED_COMMON:
    00599             return "oriented_common";
    00600             break;
    00601         case BBT_ORIENTED_SELF:
    00602             return "oriented_self";
    00603             break;
    00604         }
    00605         // Compiler nicety
    00606         return "";
    00607     }
    00608     void ParticleSystem::CmdBillboardType::doSet(void* target, const String& val)
    00609     {
    00610         BillboardType t;
    00611         if (val == "point")
    00612         {
    00613             t = BBT_POINT;
    00614         }
    00615         else if (val == "oriented_common")
    00616         {
    00617             t = BBT_ORIENTED_COMMON;
    00618         }
    00619         else if (val == "oriented_self")
    00620         {
    00621             t = BBT_ORIENTED_SELF;
    00622         }
    00623         else
    00624         {
    00625             Except(Exception::ERR_INVALIDPARAMS,
    00626                 "Invalid billboard_type '" + val + "'",
    00627                 "ParticleSystem::CmdBillboardType::doSet");
    00628         }
    00629
    00630         static_cast<ParticleSystem*>(target)->setBillboardType(t);
    00631     }
    00632     //-----------------------------------------------------------------------
    00633     String ParticleSystem::CmdCommonDirection::doGet(const void* target) const
    00634     {
    00635         return StringConverter::toString(
    00636             static_cast<const ParticleSystem*>(target)->getCommonDirection() );
    00637     }
    00638     void ParticleSystem::CmdCommonDirection::doSet(void* target, const String& val)
    00639     {
    00640         static_cast<ParticleSystem*>(target)->setCommonDirection(
    00641             StringConverter::parseVector3(val));
    00642     }
    00643
    00644 }

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:38 2004