00001 //----------------------------------------------------------------------------------- 00002 // 00003 // Pro-Vocation Light Engine (PVLE) 00004 // Copyright (C) 2007-2009 Sukender, KinoX & Buzib 00005 // For more information, contact us : sukender@free.fr 00006 // 00007 // This program is free software; you can redistribute it and/or modify 00008 // it under the terms of the GNU General Public License as published by 00009 // the Free Software Foundation; either version 3 of the License, or 00010 // (at your option) any later version. 00011 // 00012 // For any use that is not compatible with the terms of the GNU 00013 // General Public License, please contact the authors for alternative 00014 // licensing options. 00015 // 00016 // This program is distributed in the hope that it will be useful, 00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 // GNU General Public License for more details. 00020 // 00021 // You should have received a copy of the GNU General Public License along 00022 // with this program; if not, write to the Free Software Foundation, Inc., 00023 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00024 // 00025 //----------------------------------------------------------------------------------- 00026 00029 00030 //#include <osgParticle/AutoParticleSystemUpdater> 00031 #include <PVLE/3D/AutoParticleSystemUpdater.h> 00032 #include <PVLE/Util/Assert.h> 00033 00034 //#include <osg/CopyOp> 00035 //#include <osg/Node> 00036 00037 #include <osgUtil/UpdateVisitor> 00038 #include <OpenThreads/ReadWriteMutex> 00039 00040 using namespace osg; 00041 00042 namespace osgParticle { 00043 00044 AutoParticleSystemUpdater::AutoParticleSystemUpdater() { 00045 pGeode = new osg::Geode(); // PVLE 00046 } 00047 00048 AutoParticleSystemUpdater::AutoParticleSystemUpdater(const AutoParticleSystemUpdater& copy, const osg::CopyOp& copyop) 00049 : ParticleSystemUpdater(copy, copyop) 00050 { 00051 ParticleSystemData_Vector::const_iterator i; 00052 for (i=copy._psdata.begin(); i!=copy._psdata.end(); ++i) { 00053 _psdata.push_back(*i); 00054 } 00055 } 00056 00057 bool AutoParticleSystemUpdater::addParticleSystem(ParticleSystem* ps) 00058 { 00059 ASSERT(getNumParticleSystems() == _psdata.size()); 00060 if (!ParticleSystemUpdater::addParticleSystem(ps)) return false; 00061 _psdata.push_back(false); 00062 pGeode->addDrawable(ps); 00063 return true; 00064 } 00065 00066 bool AutoParticleSystemUpdater::removeParticleSystem(unsigned int pos, unsigned int numParticleSystemsToRemove) 00067 { 00068 ASSERT(getNumParticleSystems() == _psdata.size()); 00069 // Remove particle system 00070 if (!ParticleSystemUpdater::removeParticleSystem(pos, numParticleSystemsToRemove)) return false; 00071 // Remove associated data 00072 unsigned int endOfRemoveRange = pos + numParticleSystemsToRemove; 00073 if( endOfRemoveRange > _psdata.size() ) endOfRemoveRange = _psdata.size(); 00074 _psdata.erase(_psdata.begin()+pos, _psdata.begin()+endOfRemoveRange); 00075 return true; 00076 } 00077 00078 bool AutoParticleSystemUpdater::setParticleSystem( unsigned int i, ParticleSystem* ps ) 00079 { 00080 ASSERT(getNumParticleSystems() == _psdata.size()); 00081 if (!ParticleSystemUpdater::setParticleSystem(i, ps)) return false; 00082 _psdata[i] = false; // Reset associated data 00083 return true; 00084 } 00085 00086 void AutoParticleSystemUpdater::traverse(osg::NodeVisitor& nv) 00087 { 00088 ASSERT(getNumParticleSystems() == _psdata.size()); 00089 00090 // Remove all dead systems 00091 if (nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR) { 00092 for(int i=static_cast<int>(getNumParticleSystems())-1; i>=0; --i) { // Cast to signed int to avoid underflow 00093 if (_psdata[i]) { 00094 ParticleSystem* pPS = getParticleSystem(i); 00095 ParticleSystem::ScopedWriteLock lock(*(pPS->getReadWriteMutex())); 00096 if (pPS->areAllParticlesDead()) { 00097 if (pGeode->containsDrawable(pPS)) pGeode->removeDrawable(pPS); 00098 #ifdef _DEBUG 00099 ASSERT(removeParticleSystem(i)); 00100 #else 00101 removeParticleSystem(i); 00102 #endif 00103 // No problem about loop variable 'i' while removing from N-1 to 0. 00104 } 00105 } else { 00106 // Patricle system has been updated once: we can delete it on next update. 00107 _psdata[i] = true; 00108 } 00109 } 00110 } 00111 00112 ParticleSystemUpdater::traverse(nv); 00113 00114 // We have a child, so we also traverse it (as a Group does). 00115 pGeode->accept(nv); 00116 } 00117 00118 } // namespace osgParticle