#include "synthsession.h" #include #include #include #include #include #include #include #include #include namespace geoworld { SynthesisSession::SynthesisSession() : _pWorld(NULL), _pPgWorld(NULL), _pFile(NULL), _pDepSynth(NULL) {} SynthesisSession::~SynthesisSession() { delete _pPgWorld; delete _pWorld; delete _pFile; delete _pDepSynth; } void SynthesisSession::spawnRandomly( MorphList & outlist, const GeoMorphRegistry & registry, const size_t nCount, const unsigned long nWWidth, const unsigned long nWHeight, const unsigned short nLOD ) { using namespace mars; float fFrequencySum = 0; typedef std::list< std::pair< RangeX< float >, GeoMorphFactory * > > FactoryList; FactoryList factories; for (GeoMorphRegistry::GMFactorySet::const_iterator i = registry.beginGM(); i != registry.endGM(); ++i) { const float fFreq = (*i)->getFrequency(); factories.push_back( FactoryList::value_type ( RangeX< float > (fFrequencySum, fFrequencySum + fFreq), *i ) ); fFrequencySum += fFreq; } const unsigned long nLODWWidth = nWWidth >> nLOD, nLODHeight = nWHeight >> nLOD; ptr< GeoMorph > pMorph; for (size_t c = 0; c < nCount; ++c) { const float fRand = RANDf(fFrequencySum); for (FactoryList::const_iterator i = factories.begin(); i != factories.end(); ++i) { if (i->first.contains(fRand)) { const GeoMorphFactory * pFact = i->second; const ISurfaceBoundedGeoMorphFactory * pSBGMF = dynamic_cast< const ISurfaceBoundedGeoMorphFactory * > (pFact); if (pSBGMF != NULL) { pMorph = pSBGMF -> createRandomInstance( RAND(nLODWWidth), RAND(nLODHeight) ); } const IOpenGeoMorphFactory * pOGMF = dynamic_cast< const IOpenGeoMorphFactory * > (pFact); if (pOGMF != NULL) { pMorph = pOGMF->createRandomInstance(); } outlist.push_back(pMorph); } } } } void SynthesisSession::generate( const std::string & sFileName, const GeoMorphRegistry & registry, const unsigned long nWorldWidth, const unsigned long nWorldHeight, const unsigned short nWorldDepth) { using namespace mars; MorphList morphs, rejects; delete _pPgWorld; delete _pWorld; delete _pFile; delete _pDepSynth; _pFile = FileSource::create(sFileName, nWorldWidth, nWorldHeight, nWorldDepth, _config.tiledim, _config.macro.lod, _config.geohost.layercount); _pDepSynth = new DepositSynthesizer(&_mindb, _cfgdepsynth, _pFile->geohost.getWorldWidth(), _pFile->geohost.getWorldHeight(), _pFile->getWorldDepth(), _pFile->geohost.getLOD()); _pWorld = new GeoWorld(_pDepSynth, _config.macro.lod, 0, _pFile); fire(&ISynthesisSessionListener::onGenerate, _pWorld); fire(&ISynthesisSessionListener::onGenerateGeoHostLayers, _pWorld, _pDepSynth); _pDepSynth->generateStrata(); { MyMacroListener listener (this, _pWorld); _pWorld->addListener(&listener); for (GeoMorphRegistry::GTFactorySet::const_iterator i = registry.beginGT(GTP_Pre); i != registry.endGT(GTP_Pre); ++i) { const IOpenGeoMorphFactory * pOpenGMFact = dynamic_cast< IOpenGeoMorphFactory * > (*i); if (pOpenGMFact != NULL) { morphs.push_back(pOpenGMFact->createRandomInstance()); } } spawnRandomly(morphs, registry, _config.macro.morphcount, _pWorld->getWidth(), _pWorld->getHeight(), _pWorld->getLOD()); GeoWorldAccesser accessor0(_pWorld); const unsigned short nWidth = static_cast< unsigned short > (_pWorld->getMaxGeoMorphWidth()), nHeight = static_cast< unsigned short > (_pWorld->getMaxGeoMorphHeight()); for (MorphList::iterator i = morphs.begin(); i != morphs.end(); ++i) { (*i)->init(*this, accessor0, nWidth, nHeight); fire(&ISynthesisSessionListener::onInitMorph, _pWorld, i->pointer()); } fire(&ISynthesisSessionListener::onPrepareMorphs, _pWorld, morphs); _pWorld->addMorphs(morphs, rejects); fire(&ISynthesisSessionListener::onRaster, _pWorld); _pWorld->runMorphs(_mindb, rejects); if (!rejects.empty()) fire(&ISynthesisSessionListener::onRejects, _pWorld, rejects); _pWorld->removeListener(&listener); } fire(&ISynthesisSessionListener::onSpawnMinerals, _pWorld, _pDepSynth); _pDepSynth->generateMinerals(0); fire(&ISynthesisSessionListener::onCreateMiddleTier, _pWorld, sFileName); _pWorld->write(_config.macro.coarseness); _pPgWorld = new PagedGeoWorld (_pDepSynth, _pFile, _config.passes.count); generate(_pPgWorld, registry); *_pDepSynth >> _pFile->geohost; *_pDepSynth >> _pFile->minerals; _pFile->commit(); DEMDUMP << _pWorld->getLowHM(); DEMDUMP << _pDepSynth->getStratum().getBase(); } void SynthesisSession::generate( PagedGeoWorld * pPgWorld, const GeoMorphRegistry & registry ) { const unsigned short nWidth = static_cast< unsigned short > (pPgWorld->getMaxGeoMorphWidth()), nHeight = static_cast< unsigned short > (pPgWorld->getMaxGeoMorphHeight()); MorphList morphs, rejects; if (pPgWorld->getPassCount() > 0) fire(&ISynthesisSessionListener::onGenerate2, pPgWorld); for (unsigned int i = 0; i < pPgWorld->getPassCount(); ++i) { MyMicroListener listener (this, pPgWorld, i); pPgWorld->addListener(&listener); rejects.clear(); morphs.clear(); fire(&ISynthesisSessionListener::onPass2, pPgWorld, i); spawnRandomly(morphs, registry, _config.passes.morphcount.next(), pPgWorld->getWorldWidth(), pPgWorld->getWorldHeight(), pPgWorld->getLOD()); ReadOnlyPagedGeoWorldAccesser accessor1(pPgWorld); for (MorphList::iterator j = morphs.begin(); j != morphs.end(); ++j) { (*j)->init(*this, accessor1, nWidth, nHeight); fire(&ISynthesisSessionListener::onInitMorph2, pPgWorld, i, j->pointer()); } accessor1.releaseCache(); fire(&ISynthesisSessionListener::onPrepareMorphs2, pPgWorld, i, morphs); pPgWorld->addMorphs(morphs, rejects, i); fire(&ISynthesisSessionListener::onRaster2, pPgWorld, i); pPgWorld->runMorphs(i, rejects); if (!rejects.empty()) fire(&ISynthesisSessionListener::onRejects2, pPgWorld, i, rejects); pPgWorld->removeListener(&listener); fire(&ISynthesisSessionListener::onSpawnMinerals2, pPgWorld, i, _pDepSynth); _pDepSynth->generateMinerals(i + 1); } } bool SynthesisSession::init( IMineralsDBReader & minreader, IDepositSynthConfigReader & depsynthreader, ISynthesisSessionConfigReader & cfgreader) { bool bResult; bResult = minreader.load(&_mindb); if (bResult) _mindb.init(); bResult = cfgreader.load(_config) && bResult; bResult = depsynthreader.load(_cfgdepsynth) && bResult; return bResult; } const LockedGWSection & SynthesisSession::ReadOnlyPagedGeoWorldAccesser::acquireSection( const long x, const long y ) const { const unsigned short nTileDim = _pPgWld->getTileDimension(); const mars::BBox< long > bbox (x, y, x, y), bboxActual = LockedGWSection::computeLockedSection(bbox, nTileDim, false); assert(bboxActual.inside(x, y)); if (_mapLockedSections.find(bboxActual) == _mapLockedSections.end()) return *(_mapLockedSections[bboxActual] = _pPgWld->lockro(bbox, false)); else return *_mapLockedSections[bboxActual]; } SynthesisSession::ReadOnlyPagedGeoWorldAccesser::~ReadOnlyPagedGeoWorldAccesser() { for (LockedSectionsMap::const_iterator i = _mapLockedSections.begin(); i != _mapLockedSections.end(); ++i) _pPgWld->unlock(i->second); } SynthesisSession::ReadOnlyPagedGeoWorldAccesser::ReadOnlyPagedGeoWorldAccesser( const PagedGeoWorld * pPagedGeoWorld ) : BaseAccessor(pPagedGeoWorld->getAgentMaps()), _pPgWld (pPagedGeoWorld) {} geoworld::MorphList SynthesisSession::ReadOnlyPagedGeoWorldAccesser::compilePasses( const PagedGeoWorld * pPgGW ) { MorphList morphs; for (unsigned short i = 0; i < pPgGW->getPassCount(); ++i) morphs.insert(morphs.end(), pPgGW->beginPass(i), pPgGW->endPass(i)); return morphs; } void SynthesisSession::ReadOnlyPagedGeoWorldAccesser::releaseCache() { for (LockedSectionsMap::const_iterator i = _mapLockedSections.begin(); i != _mapLockedSections.end(); ++i) _pPgWld->unlock(i->second); _mapLockedSections.clear(); } SynthesisSession::GeoWorldAccesser::GeoWorldAccesser( GeoWorld * const pGeoWorld ) : BaseAccessor(pGeoWorld->getAgentMaps()), _pGeoWorld(pGeoWorld), _hm(pGeoWorld->getLowHM()) {} void SynthesisSession::MyMicroListener::runningMorphs( MorphList::const_iterator i0, MorphList::const_iterator iN, const size_t i, const size_t nCount, const size_t nTotal ) { size_t c = i; for (MorphList::const_iterator k = i0; k != iN; ++k) _pObservable->fire(&ISynthesisSessionListener::onDoMorph2, _pPgWorld, _nPass, *k, c++, nTotal); } SynthesisSession::MyMicroListener::~MyMicroListener() { if (!_rejects.empty()) _pObservable->fire(&ISynthesisSessionListener::onRejects2, _pPgWorld, _nPass, _rejects); } SynthesisSession::MyMicroListener::MyMicroListener( SynthesisSession * pObservable, PagedGeoWorld * const pPgWorld, const unsigned short nPass ) : _pObservable (pObservable), _pPgWorld(pPgWorld), _nPass(nPass) { } }