///=========================================================================== void CParticleSystemShape::flushTextures(IDriver &driver, uint selectedTexture) { // if textures are already flushed, no-op if (!_CachedTex.empty()) return; if (_SharedSystem) { _SharedSystem->enumTexs(_CachedTex, driver); } else { s_PSSMutex.enter(); // must create an instance just to flush the textures CParticleSystem *myInstance = NULL; #ifdef PS_FAST_ALLOC nlassert(PSBlockAllocator == NULL); NLMISC::CContiguousBlockAllocator blockAllocator; PSBlockAllocator = &blockAllocator; blockAllocator.init(300000); // we release memory just after, and we don't want to fragment the memory, so provide large enough mem #endif // serialize from the memory stream if (!_ParticleSystemProto.isReading()) // we must be sure that we are reading the stream { _ParticleSystemProto.invert(); } _ParticleSystemProto.resetPtrTable(); _ParticleSystemProto.seek(0, NLMISC::IStream::begin); _ParticleSystemProto.serialPtr(myInstance); // instanciate the system #ifdef PS_FAST_ALLOC _NumBytesWanted = blockAllocator.getNumAllocatedBytes(); // next allocation will be fast because we know how much memory to allocate #endif myInstance->enumTexs(_CachedTex, driver); // tmp /* #ifdef NL_DEBUG for(uint k = 0; k < myInstance->getNbProcess(); ++k) { CPSLocated *loc = (CPSLocated *) myInstance->getProcess(k); for(uint l = 0; l < loc->getNbBoundObjects(); ++l) { if (dynamic_cast<CPSCentralGravity *>(loc->getBoundObject(l))) { nlwarning("PS %s uses central gravity", myInstance->getName().c_str()); break; } } } #endif */ // sort the process inside the fx myInstance->getSortingByEmitterPrecedence(_ProcessOrder); delete myInstance; #ifdef PS_FAST_ALLOC PSBlockAllocator = NULL; #endif s_PSSMutex.leave(); } for(uint k = 0; k < _CachedTex.size(); ++k) { //nlinfo(_CachedTex[k]->getShareName().c_str()); if (_CachedTex[k]) { _CachedTex[k]->setTextureCategory(CPSTextureCategory::get()); driver.setupTexture(*_CachedTex[k]); } } }
///=========================================================================== CParticleSystem *CParticleSystemShape::instanciatePS(CScene &scene, NLMISC::CContiguousBlockAllocator *blockAllocator /*= NULL*/) { if (_Sharing && _SharedSystem != NULL) // is sharing enabled, and is a system already instanciated { return _SharedSystem; } // avoid prb with concurrent thread (may happen if an instance group containing ps is loaded in background) s_PSSMutex.enter(); #ifdef PS_FAST_ALLOC nlassert(PSBlockAllocator == NULL); if (blockAllocator) { // set new allocator for particle system memory PSBlockAllocator = blockAllocator; blockAllocator->init(_NumBytesWanted); // if size wanted is already known, set it } #endif //NLMISC::TTicks start = NLMISC::CTime::getPerformanceTime(); // copy the datas CParticleSystem *myInstance = NULL; // serialize from the memory stream if (!_ParticleSystemProto.isReading()) // we must be sure that we are reading the stream { _ParticleSystemProto.invert(); } _ParticleSystemProto.resetPtrTable(); _ParticleSystemProto.seek(0, NLMISC::IStream::begin); // NLMISC::TTicks start = NLMISC::CTime::getPerformanceTime(); _ParticleSystemProto.serialPtr(myInstance); // instanciate the system /* NLMISC::TTicks end = NLMISC::CTime::getPerformanceTime(); nlinfo("instanciation time = %.2f", (float) (1000 * NLMISC::CTime::ticksToSecond(end - start))); */ myInstance->setScene(&scene); if (_CachedTex.empty() && scene.getDriver()) { //nlinfo("flushing texs"); // load && cache textures myInstance->enumTexs(_CachedTex, *scene.getDriver()); for(uint k = 0; k < _CachedTex.size(); ++k) { if (_CachedTex[k]) { _CachedTex[k]->setTextureCategory(CPSTextureCategory::get()); scene.getDriver()->setupTexture (*(ITexture *)_CachedTex[k]); } } } else { /* for(uint k = 0; k < _CachedTex.size(); ++k) { nlinfo(_CachedTex[k]->getShareName().c_str()); } */ } // tmp if (_Sharing) { _SharedSystem = myInstance; // set this as the first shared instance } #ifdef PS_FAST_ALLOC if (blockAllocator) { _NumBytesWanted = blockAllocator->getNumAllocatedBytes(); // now we know the number of wanted bytes, subsequent alloc can be much faster PSBlockAllocator = NULL; } #endif s_PSSMutex.leave(); /*NLMISC::TTicks end = NLMISC::CTime::getPerformanceTime(); nlinfo("instanciation time = %.2f", (float) (1000 * NLMISC::CTime::ticksToSecond(end - start))); */ return myInstance; }