#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include "geomorph.h" #include "gmregistry.h" #include "gwtypes.h" #include "geoworld.h" #include "gwconfig.h" #include "oregen.h" namespace geoworld { class GeoMorph; class AgentMapGradientFieldAdapter : public GMGradientField { private: const AgentMap & _amap; public: AgentMapGradientFieldAdapter (const AgentMap & amap) : _amap(amap) {} inline ResultType operator () (const IndexType x, const IndexType y, const IndexType z) const { return _amap.gradient(x, y, z); } }; class AgentMapScalarFieldAdapter : public GMScalarField { private: const AgentMap & _amap; public: AgentMapScalarFieldAdapter (const AgentMap & amap) : _amap (amap) {} inline ResultType operator () (const IndexType x, const IndexType y, const IndexType z) const { return _amap.sample(x, y, z); } inline const GMGradientField * queryGradient() const { return new AgentMapGradientFieldAdapter (_amap); } inline void releaseGradient(const GMGradientField * pGF) const { delete pGF; } }; class GeoMorphRegistry; class ISynthesisSessionListener { public: virtual void onGenerate (GeoWorld * const pWorld) {} virtual void onGenerateGeoHostLayers (GeoWorld * const pWorld, DepositSynthesizer * const pDepSynth) {} virtual void onCreateMiddleTier(GeoWorld * const pWorld, const std::string & sFileName) {} virtual void onPrepareMorphs (GeoWorld * const pWorld, const MorphList & morphs) {} virtual void onInitMorph (GeoWorld * const pWorld, const GeoMorph * pMorph) {} virtual void onRaster (GeoWorld * const pWorld) {} virtual void onDoMorph (GeoWorld * const pWorld, mars::ptr< GeoMorph > & pGM, const size_t i, const size_t nTotal) {} virtual void onRejects (GeoWorld * const pWorld, const MorphList & rejects) {} virtual void onSpawnMinerals (GeoWorld * const pWorld, DepositSynthesizer * const pDepSynth) {} virtual void onGenerate2 (PagedGeoWorld * const pPgWorld) {} virtual void onPass2 (PagedGeoWorld * const pPgWorld, const unsigned short nPass) {} virtual void onPrepareMorphs2 (PagedGeoWorld * const pPgWorld, const unsigned short nPass, const MorphList & morphs) {} virtual void onInitMorph2 (PagedGeoWorld * const pPgWorld, const unsigned short nPass, const GeoMorph * pMorph) {} virtual void onRaster2 (PagedGeoWorld * const pPgWorld, const unsigned short nPass) {} virtual void onDoMorph2 (PagedGeoWorld * const pPgWorld, const unsigned short nPass, mars::ptr< GeoMorph > & pGM, const size_t i, const size_t nTotal) {} virtual void onRejects2 (PagedGeoWorld * const pPgWorld, const unsigned short nPass, const MorphList & rejects) {} virtual void onSpawnMinerals2 (PagedGeoWorld * const pPgWorld, const unsigned short nPass, DepositSynthesizer * const pDepSynth) {} }; class SynthesisSession : public mars::Observable< ISynthesisSessionListener > { public: SynthesisSession(); ~SynthesisSession(); bool init(IMineralsDBReader & minreader, IDepositSynthConfigReader & depsynthreader, ISynthesisSessionConfigReader & cfgreader); bool init(IMetaConfigReader & cfgreader, GeoMorphRegistry & registry); inline void setTileDim (const unsigned short nDim) { _config.tiledim = nDim; } void generate ( const std::string & sFileName, const GeoMorphRegistry & registry, const unsigned long nWorldWidth, const unsigned long nWorldHeight, const unsigned short nWorldDepth ); inline const PagedGeoWorld & getWorld () const { return *_pPgWorld; } protected: class MyMacroListener : public IGeoWorldListener { private: SynthesisSession * _pObservable; GeoWorld * const _pWorld; public: MyMacroListener (SynthesisSession * pObservable, GeoWorld * const pWorld) : _pObservable (pObservable), _pWorld(pWorld) {} void runningMorph (const mars::ptr< GeoMorph > & pGM, const size_t i, const size_t nTotal) { _pObservable->fire(&ISynthesisSessionListener::onDoMorph, _pWorld, pGM, i, nTotal); }; }; class MyMicroListener : public IGeoWorldListener { private: SynthesisSession * _pObservable; PagedGeoWorld * const _pPgWorld; unsigned short _nPass; MorphList _rejects; public: MyMicroListener (SynthesisSession * pObservable, PagedGeoWorld * const pPgWorld, const unsigned short nPass); void runningMorph (const mars::ptr< GeoMorph > & pGM, const size_t i, const size_t nTotal) { _pObservable->fire(&ISynthesisSessionListener::onDoMorph2, _pPgWorld, _nPass, pGM, i, nTotal); } virtual void runningMorphs (MorphList::const_iterator i0, MorphList::const_iterator iN, const size_t i, const size_t nCount, const size_t nTotal); virtual void rejectedMorph (const mars::ptr< GeoMorph > & pGM) { _rejects.push_back(pGM); } ~MyMicroListener(); }; private: class BaseAccessor : public IGeoWorldAccessor { private: const AllAgentMaps & _amaps; public: inline BaseAccessor (const AllAgentMaps & amaps) : _amaps(amaps) {} inline const GMScalarField * queryField (const FieldType enft) const { return new AgentMapScalarFieldAdapter(_amaps[enft]); } }; class ReadOnlyPagedGeoWorldAccesser : public BaseAccessor { private: class BBoxComparator : public std::binary_function< mars::BBox< long >, mars::BBox< long >, bool > { private: unsigned long _nMaxScanLine; public: BBoxComparator () : _nMaxScanLine(FileSource::MAX_AXIS_TILES * FileSource::MAX_TILE_DIM) {} bool operator() (const mars::BBox< long > & lval, const mars::BBox< long > & rval) const { if (lval.top == rval.top) if (lval.left == rval.left) if (lval.bottom == rval.bottom) if (lval.right == rval.right) return false; else return lval.right < rval.right; else return lval.bottom < rval.bottom; else return lval.left < rval.left; else return lval.top < rval.top; } }; typedef std::map< mars::BBox< long >, const LockedGWSection *, BBoxComparator > LockedSectionsMap; mutable LockedSectionsMap _mapLockedSections; const PagedGeoWorld * _pPgWld; const LockedGWSection & acquireSection (const long x, const long y) const; static MorphList compilePasses (const PagedGeoWorld * pPgGW); public: ReadOnlyPagedGeoWorldAccesser (const PagedGeoWorld * pPagedGeoWorld); ~ReadOnlyPagedGeoWorldAccesser(); void releaseCache (); inline const GeoHeightMap::Precision operator () (const long x, const long y) const { return acquireSection(x, y).heightmap(x, y); } inline const GeoHeightMap::Precision mean (const long x, const long y) const { return static_cast ( ( static_cast (operator () (x - 1, y - 1)) + static_cast (operator () (x + 1, y - 1)) + static_cast (operator () (x - 1, y + 1)) + static_cast (operator () (x + 1, y + 1)) ) / 4 ); // TODO: Automatically select precision type for "mean" calculations } inline VectorTag< long >::V3 createCoords (const long x, const long y) const { return VectorTag< long >::V3 ( x, y, mean(x, y) ); } }; class GeoWorldAccesser : public BaseAccessor { private: GeoWorld * const _pGeoWorld; const GeoHeightMap & _hm; public: GeoWorldAccesser (GeoWorld * const pGeoWorld); inline const GeoHeightMap::Precision operator () (const long x, const long y) const { return _hm(x, y); } inline const GeoHeightMap::Precision mean (const long x, const long y) const { return _hm.meanVN (x, y); } inline VectorTag< long >::V3 createCoords (const long x, const long y) const { return VectorTag< long >::V3(x, y, _hm.meanVN (x, y)); } }; FileSource * _pFile; GeoWorld * _pWorld; PagedGeoWorld * _pPgWorld; DepositSynthesizer * _pDepSynth; DepositSynthesizerSettings _cfgdepsynth; MineralsDB _mindb; SynthesisSessionConfig _config; void spawnRandomly (MorphList & outlist, const GeoMorphRegistry & registry, const size_t nCount, const unsigned long nWWidth, const unsigned long nWHeight, const unsigned short nLOD); void generate ( PagedGeoWorld * pPgWorld, const GeoMorphRegistry & registry ); }; }