#include "crater.h" #include "mars_ptr.h" #include "geoworld.h" namespace geoworld { void CraterGM::init(SynthesisSession & manager, const IGeoWorldAccessor & accessor, const unsigned short nMaxWidth, const unsigned short nMaxHeight) { _gcOrigin = accessor.createCoords(_ptOrigin); } void CraterGM::doMorph (LockedGWSection & section) const { using namespace mars; using namespace geoworld; const unsigned short nDim = static_cast (_zones.puz.outside() * 2.0f); mars::ptr< NoiseGenerator< float >::NoiseMap > pMPField = _noise.compute(nDim, nDim); for (PerimiterUpliftZone::UpsideDEMIterator it = _zones.puz.walkUpside (_gcOrigin); it; ++it) { section.heightmap(it->x, it->y) = blend( section.heightmap(it->x, it->y), it->z + (*pMPField)(it->x, it->y), _zones.puz.outslope.taper.f ( static_cast< float > (it->x - _ptOrigin.x), static_cast< float > (it->y - _ptOrigin.y) ) ); } // TODO: Why are we walking the downside? is this an inverted function? for (CraterZone::DownsideDEMIterator it = _zones.czone.walkDownside (_gcOrigin); it; ++it) { section.heightmap(it->x, it->y) = static_cast< GeoHeightMap::Precision > (mars::RNDi(it->z + pMPField->getw(it->x, it->y))); // TODO: Verify use of RNDi } for (CentralUpliftZone::UpsideDEMIterator it = _zones.central.walkUpside (_gcOrigin); it; ++it) { section.heightmap(it->x, it->y) = static_cast< GeoHeightMap::Precision > (mars::RNDi(it->z + pMPField->getw(it->x, it->y))); // TODO: Verify use of RNDi } } GMScalarField * CraterGM::queryField( const FieldType enft, const GeoHeightMap & hm ) { switch (enft) { case FT_Density: return new DensityScalarField(_zones.density, _gcOrigin); default: return NULL; } } void CraterGM::releaseField( const GMScalarField * pField ) { delete pField; } mars::BBox< long > CraterGM::getBBox() const { return mars::BBox< long > ( _ptOrigin - static_cast< long > (floor (_zones.puz.outside())), _ptOrigin + static_cast< long > (ceil (_zones.puz.outside())) ); } mars::ptr< PersistentGeoMorph::State > CraterGM::createState() const { CraterGMState * pState = new CraterGMState(); pState->fBowlDepth = -_zones.czone.bowl.depth; pState->fCentralUpliftBroadnessScale = _fCentralUpliftBroadnessScale; pState->fCentralUpliftDepthScale = _fCentralUpliftDepthScale; pState->frBowlBroadness = _zones.czone.bowl.broadness; pState->frNoise = _noise.noise; pState->frScale = _zones.czone.bowl.scale; pState->fSpallFalloffFactor = _zones.puz.outslope.falloff; pState->gcOrigin = _gcOrigin; pState->ptOrigin = _ptOrigin; return dynamic_cast< PersistentGeoMorph::State * > (pState); } CraterGM::CraterGM( const VectorTag< GeoHeightMap::Precision >::V2 & ptOrigin, const float frSample, const float frScale, const float frBowlBroadness, const float fBowlDepth, const float fSpallFalloffFactor, const float frNoise, const float fCentralUpliftDepthScale, const float fCentralUpliftBroadnessScale ) : _zones( CraterZone( BowlFn( frScale, frBowlBroadness, -fBowlDepth ) ), PerimeterUpsideEq( frScale, frBowlBroadness, 0.0f ), PerimeterDownsideEq( frScale, frBowlBroadness / 4.0f * mars::SQ(-fBowlDepth), 0.0f ), CentralUpliftEq( frScale, 1.0f, fCentralUpliftBroadnessScale * frBowlBroadness, -fBowlDepth * fCentralUpliftDepthScale ), fSpallFalloffFactor ), _fCentralUpliftDepthScale(fCentralUpliftDepthScale), _fCentralUpliftBroadnessScale(fCentralUpliftBroadnessScale), _noise (0.4f, frNoise), // TODO: Messy redundant EqSet instantiation to satisfy constructor member initialization limitations _ptOrigin(ptOrigin) {} CraterGM::CraterGM( const CraterGMState & state ) : _zones( CraterZone( BowlFn( state.frScale, state.frBowlBroadness, -state.fBowlDepth ) ), PerimeterUpsideEq( state.frScale, state.frBowlBroadness, 0.0f ), PerimeterDownsideEq( state.frScale, state.frBowlBroadness / 4.0f * mars::SQ(-state.fBowlDepth), 0.0f ), CentralUpliftEq( state.frScale, 1.0f, state.fCentralUpliftBroadnessScale * state.frBowlBroadness, -state.fBowlDepth * state.fCentralUpliftDepthScale ), state.fSpallFalloffFactor ), _fCentralUpliftDepthScale(state.fCentralUpliftDepthScale), _fCentralUpliftBroadnessScale(state.fCentralUpliftBroadnessScale), _noise (0.4f, state.frNoise), // TODO: Messy redundant EqSet instantiation to satisfy constructor member initialization limitations _ptOrigin(state.ptOrigin), _gcOrigin(state.gcOrigin) {} CraterGM::DensityScalarField::ResultType CraterGM::DensityScalarField::operator () (const IndexType x, const IndexType y, const IndexType z) const { return std::max(1.0f, _zone.upside(static_cast< float > (x), static_cast< float > (y))); } CraterGM::DensityGradientField::ResultType CraterGM::DensityGradientField::operator () (const IndexType x, const IndexType y, const IndexType z) const { using namespace mars; const vector3Df dir ( static_cast< float > (_gcOrigin.x - x), static_cast< float > (_gcOrigin.y - y), static_cast< float > (_gcOrigin.z - z) ); const float fMag = MAG(dir); return fMag > _zone.outside() ? vector3Df() : -mars::U(dir) * _zone.upsideGrad(static_cast< float > (x), static_cast< float > (y)); } CraterGMFactory::~CraterGMFactory() {} GeoMorph * CraterGMFactory::createRandomInstance( const long x, const long y ) const { return new CraterGM( GWSurfacePos(x, y), _rngfrSample.next(), _rngfrScale.next(), _rngfrBowlBroadness.next(), _rngfBowlDepth.next(), _fSpallFalloffFactor, _frNoise, _fCentralUpliftDepthScale, _fCentralUpliftBroadnessScale ); } void CraterGMFactory::configure( IConfigGMFactory * pFactoryConfig, const IConfigGMFactory::Settings & settings ) { const geoworld::IConfigSection & section = *pFactoryConfig->getSection(); *section["sample"] >> _rngfrSample; *section["scale"] >> _rngfrScale; *section["broadness"] >> _rngfrBowlBroadness; *section["depth"] >> _rngfBowlDepth; *section["falloff"] >> _fSpallFalloffFactor; *section["noise"] >> _frNoise; *section["uplift_depth"] >> _fCentralUpliftDepthScale; *section["uplift_broadness"] >> _fCentralUpliftBroadnessScale; } void CraterGMFactory::save( const GeoMorph * pGM, mars::ObjectStream & outs ) const { const CraterGM * pCraterGM = dynamic_cast< const CraterGM * > (pGM); assert(pCraterGM != NULL); *(pCraterGM->createState()) >> outs; } const GeoMorph * CraterGMFactory::restore( mars::ObjectStream & ins ) const { CraterGM::CraterGMState state; state << ins; return new CraterGM(state); } mars::ObjectStream & CraterGM::CraterGMState::operator >> ( mars::ObjectStream & outs ) const { outs << frScale << frBowlBroadness << fBowlDepth << fCentralUpliftBroadnessScale << fCentralUpliftDepthScale << fSpallFalloffFactor << frNoise << ptOrigin << gcOrigin; return outs; } mars::ObjectStream & CraterGM::CraterGMState::operator << ( mars::ObjectStream & ins ) { ins >> frScale >> frBowlBroadness >> fBowlDepth >> fCentralUpliftBroadnessScale >> fCentralUpliftDepthScale >> fSpallFalloffFactor >> frNoise >> ptOrigin >> gcOrigin; return ins; } }