#pragma once #include #include #include #include "gwutil.h" #include "fluidyn.h" #include "geomorph.h" #include "synthsession.h" #include "gmregistry.h" namespace geoworld { namespace ofc { typedef mars::ParabolicFn EaseInFn; // Used for tapering the flow line typedef mars::ParabolicFn EaseOutFn; // Used for tapering the flow line const static EaseInFn EASE_IN_FN (1, 1.1f, -1.001f); const static EaseOutFn EASE_OUT_FN (1, 1.1f, -1.001f); } class OutflowChannelGM : public HeightMapGeoMorph, public BoundedGeoMorph { private: class OutflowChannelData { public: GeoHeightMap::View & view; GeoHeightMap hmbb; OutflowChannelData (GeoHeightMap::View * pView) : view(*pView), hmbb(*pView) {} }; class FluiDynQueryBridge : public fldyn::IQueryBridge { private: const IGeoWorldAccessor * _pAccessor; const GMScalarField * _pfsDensity; const GWSurfacePos _ptOffset; public: inline FluiDynQueryBridge (const IGeoWorldAccessor * pAccessor, const GWSurfacePos & ptOffset) : _pAccessor (pAccessor), _pfsDensity(pAccessor->queryField(FT_Density)), _ptOffset(ptOffset) {} inline DensityPrecision density (const GeoHeightMap::Precision x, const GeoHeightMap::Precision y, const GeoHeightMap::Precision z) const { return (*_pfsDensity) (x + _ptOffset.x, y + _ptOffset.y, z); } inline DensityPrecision density (const GeoHeightMap::Precision x, const GeoHeightMap::Precision y) const { return (*_pfsDensity) (x + _ptOffset.x, y + _ptOffset.y, (*_pAccessor)(x + _ptOffset.x, y + _ptOffset.y)); } inline GeoHeightMap::Precision elevation (const unsigned int x, const unsigned int y) const { return _pAccessor->mean(x + _ptOffset.x, y + _ptOffset.y); } }; public: typedef mars::MidpointDisplacementGrid< typename GeoHeightMap::Precision > PerturbMapType; typedef mars::vector2D< float > PointType; typedef fldyn::ChannelSet ChannelSetType; typedef fldyn::PathFinder ChannelFinderType; typedef ChannelFinderType::FlowLineType::Iterator RasterIteratorType; private: class MyChannelSet : public ChannelSetType { private: class BevelFn : public mars::GaussianFn< float, -1 > { private: float _frDepth; public: BevelFn (const float frDepth) : GaussianFn(1.0f, frDepth, 1.0f / 3.0f, 0.0f), _frDepth(frDepth) {} BevelFn & operator = (const BevelFn & copy) { mars::GaussianFn< float, -1 >::operator = (copy); _frDepth = copy._frDepth; return *this; } inline float getBevelDepth () const { return _frDepth; } inline const float rforce (const float t) const { return -f(t) / _frDepth; } inline const float bevel (const float t) const { return f(t) / _frDepth; } } _fnBevel; const ofc::EaseInFn _fnEaseIn; const ofc::EaseOutFn _fnEaseOut; PerturbMapType * _perturb; mars::RingBuffer< HMPrec > * _prbSediment; protected: virtual void applyFlowLine (const FlowLineType & fl, OutflowChannelData * pData) const; public: MyChannelSet (); MyChannelSet( const mars::RangeX< float > & mmfBendZenith, const unsigned int nBendZenithSteps, const unsigned int nCandidateSampleAmt, const mars::RangeX< float > & mmfSplineSeg, const float fGravitySlopeGrace, const float fCarveWeight, const float frSnapToGuide, const mars::RangeX< float > & mmfFlowLineWidth, const mars::RangeX< unsigned int > & mmnKidsPerLevel, const float fwStraightness, const float fwElevationInfluence, const float fwDensityInfluence, const float fwChaosInfluence, const unsigned int nSedimentHistorySize ); void init ( const mars::ptr< FluiDynQueryBridge > & pQuery, const unsigned int nLevels, const mars::BBox< float > & bboxSearch ); void run ( GeoHeightMap::View * pView ) const; mars::ObjectStream & operator >> (mars::ObjectStream & outs) const; mars::ObjectStream & operator << (mars::ObjectStream & ins); ~MyChannelSet(); } _chans; GWSurfacePos _ptStart; mars::RangeX< float > _mmfFlowLineWidth, _mmfSourceDisplacement; mars::RangeX< unsigned int> _mmnLevels; mars::BBox< long > _bbox; float _fSourceSpread, _fGeneralDir; unsigned int _nSourcePoints; OutflowChannelGM(); public: OutflowChannelGM( const GWSurfacePos & ptStart, const float fGeneralDir, const unsigned int nSourcePoints, const mars::RangeX< float > & mmfSourceDisplacement, const float fSourceSpread, const mars::RangeX< float > & mmfBendZenith, const unsigned int nBendZenithSteps, const unsigned int nCandidateSampleAmt, const mars::RangeX< float > & mmfSplineSeg, const float fGravitySlopeGrace, const float fCarveWeight, const float frSnapToGuide, const mars::RangeX< float > & mmfFlowLineWidth, const mars::RangeX< unsigned int > & mmnLevels, const mars::RangeX< unsigned int > & mmnKidsPerLevel, const float fwStraightness, const float fwElevationInfluence, const float fwDensityInfluence, const float fwChaosInfluence, const unsigned int nSedimentHistorySize ); ~OutflowChannelGM(); virtual void init (SynthesisSession & manager, const IGeoWorldAccessor & accessor, const unsigned short nMaxWidth, const unsigned short nMaxHeight); virtual mars::BBox< long > getBBox() const { return _bbox; } virtual void doMorph (LockedGWSection & section) const; static OutflowChannelGM * createInstance (mars::ObjectStream & ins); mars::ObjectStream & operator >> (mars::ObjectStream & outs) const; }; inline mars::ObjectStream & operator << (OutflowChannelGM *& pGM, mars::ObjectStream & ins) { pGM = OutflowChannelGM::createInstance(ins); return ins; } class OutflowChannelGMFactory : public GeoMorphFactory, public IPersistentGeoMorphFactory, public ISurfaceBoundedGeoMorphFactory { private: mars::RangeX< float > _mmfBendZenith, _mmfSplineSeg, _mmfFlowLineWidth, _mmfSourceSpread, _mmfSourceDisplacement; mars::RangeX< unsigned int> _mmnSourcePoints, _mmnLevels, _mmnKidsPerLevel; unsigned int _nBendZenithSteps, _nCandidateSampleAmount, _nSedimentHistorySize; float _fGravitySlopeGrace, _fCarveWeight, _frSnapToGuide, _fwStraightness, _fwElevationInfluence, _fwDensityInfluence, _fwChaosInfluence; public: virtual GeoMorph * createRandomInstance(const long x, const long y) const; virtual void configure( IConfigGMFactory * pFactoryConfig, const IConfigGMFactory::Settings & settings ); virtual void save (const GeoMorph * pGM, mars::ObjectStream & outs) const; virtual const GeoMorph * restore (mars::ObjectStream & ins) const; }; }