[80a6a52] | 1 | #pragma once
|
---|
| 2 |
|
---|
| 3 | #include <mars_util.h>
|
---|
| 4 |
|
---|
| 5 | #include "gwutil.h"
|
---|
| 6 | #include "gmregistry.h"
|
---|
| 7 | #include "geomorph.h"
|
---|
| 8 |
|
---|
| 9 | namespace geoworld
|
---|
| 10 | {
|
---|
| 11 | class CraterGM : public HeightMapGeoMorph, public BoundedGeoMorph, public PersistentGeoMorph
|
---|
| 12 | {
|
---|
| 13 | private:
|
---|
| 14 | typedef mars::GaussianFn <float> CentralUpliftEq;
|
---|
| 15 | typedef mars::ParabolicFn <float, +1> BowlFn;
|
---|
| 16 | typedef mars::InvertedSquareFn <float, +1> PerimeterUpsideEq;
|
---|
| 17 | typedef mars::InvertedSquareFn <float, -1> PerimeterDownsideEq;
|
---|
| 18 |
|
---|
| 19 | class CraterZone : public CylindricalZone <CraterZone>
|
---|
| 20 | {
|
---|
| 21 | public:
|
---|
| 22 | const BowlFn bowl;
|
---|
| 23 | const float radius;
|
---|
| 24 |
|
---|
| 25 | inline CraterZone (const BowlFn & bowl)
|
---|
| 26 | : bowl(bowl), radius(mars::NewtonsMethod <float, BowlFn, 10>::solve(bowl, bowl.scale))
|
---|
| 27 | {}
|
---|
| 28 |
|
---|
| 29 | inline float outside () const { return radius; }
|
---|
| 30 | inline float inside () const { return 0; }
|
---|
| 31 | inline float downside (const float x, const float y) const { return bowl.f(x, y); }
|
---|
| 32 | inline float upside (const float x, const float y) const { return 0; }
|
---|
| 33 | inline float area () const { return bowl.f2(radius); }
|
---|
| 34 | };
|
---|
| 35 |
|
---|
| 36 | class SurfaceDensityZoneFn : public CylindricalZone <SurfaceDensityZoneFn>
|
---|
| 37 | {
|
---|
| 38 | private:
|
---|
| 39 | mars::GaussianFn <float> _fn;
|
---|
| 40 | float _fOutside;
|
---|
| 41 |
|
---|
| 42 | public:
|
---|
| 43 | SurfaceDensityZoneFn (const BowlFn & bowl) // HACK: Export constants, 25 makes it high, B * 11/32 makes it wide enough for the crater-rim
|
---|
| 44 | : _fn(bowl.scale, 25, bowl.broadness / 32 * 11, 0), _fOutside(bowl.scale * bowl.broadness)
|
---|
| 45 | {}
|
---|
| 46 |
|
---|
| 47 | inline float inside() const { return 0; }
|
---|
| 48 | inline float outside() const { return _fOutside; }
|
---|
| 49 | inline float upside(const float x, const float y) const { return _fn.f(x, y); }
|
---|
| 50 | inline float upsideGrad (const float x, const float y) const { return _fn.df(x); }
|
---|
| 51 | inline float downside(const float x, const float y) const { return 0; }
|
---|
| 52 | inline float area () const { return _fn.f2(_fOutside); }
|
---|
| 53 | };
|
---|
| 54 |
|
---|
| 55 | class DensityFieldBase
|
---|
| 56 | {
|
---|
| 57 | protected:
|
---|
| 58 | const GWCoords & _gcOrigin;
|
---|
| 59 | const SurfaceDensityZoneFn & _zone;
|
---|
| 60 |
|
---|
| 61 | public:
|
---|
| 62 | DensityFieldBase (const SurfaceDensityZoneFn & zone, const GWCoords & gcOrigin)
|
---|
| 63 | : _zone(zone), _gcOrigin(gcOrigin) {}
|
---|
| 64 | };
|
---|
| 65 |
|
---|
| 66 | class DensityGradientField : public GMGradientField, public DensityFieldBase
|
---|
| 67 | {
|
---|
| 68 | public:
|
---|
| 69 | DensityGradientField(const SurfaceDensityZoneFn & zone, const GWCoords & gcOrigin)
|
---|
| 70 | : DensityFieldBase(zone, gcOrigin) {}
|
---|
| 71 |
|
---|
| 72 | ResultType operator () (const IndexType x, const IndexType y, const IndexType z) const;
|
---|
| 73 | };
|
---|
| 74 |
|
---|
| 75 | class DensityScalarField : public GMScalarField, public DensityFieldBase
|
---|
| 76 | {
|
---|
| 77 | public:
|
---|
| 78 | DensityScalarField(const SurfaceDensityZoneFn & zone, const GWCoords & gcOrigin)
|
---|
| 79 | : DensityFieldBase(zone, gcOrigin) {}
|
---|
| 80 |
|
---|
| 81 | const GMGradientField * queryGradient() const { return new DensityGradientField(_zone, _gcOrigin); }
|
---|
| 82 | void releaseGradient (const GMGradientField * pGF) const { delete pGF; }
|
---|
| 83 |
|
---|
| 84 | ResultType operator () (const IndexType x, const IndexType y, const IndexType z) const;
|
---|
| 85 | };
|
---|
| 86 |
|
---|
| 87 | class CentralUpliftZone : public CylindricalZone <CentralUpliftZone>
|
---|
| 88 | {
|
---|
| 89 | private:
|
---|
| 90 | typedef mars::SolutionEquation <float, CentralUpliftEq, BowlFn > SolutionEq;
|
---|
| 91 | CentralUpliftEq _up;
|
---|
| 92 | BowlFn _bowl;
|
---|
| 93 | float _fOutside;
|
---|
| 94 |
|
---|
| 95 | public:
|
---|
| 96 | // FIXME: Gaussians are not configured right yet
|
---|
| 97 | inline CentralUpliftZone (const CentralUpliftEq & central, const BowlFn & bowl)
|
---|
| 98 | : _up (central), _bowl(bowl),
|
---|
| 99 | _fOutside (
|
---|
| 100 | mars::BisectMethod <float, SolutionEq >
|
---|
| 101 | ::solve(
|
---|
| 102 | SolutionEq(central, bowl),
|
---|
| 103 | 0,
|
---|
| 104 | mars::NewtonsMethod <float, BowlFn>
|
---|
| 105 | ::solve(
|
---|
| 106 | bowl,
|
---|
| 107 | bowl.scale
|
---|
| 108 | )
|
---|
| 109 | )
|
---|
| 110 | )
|
---|
| 111 | {}
|
---|
| 112 |
|
---|
| 113 | inline float outside () const { return _fOutside; }
|
---|
| 114 | inline float inside () const { return 0; }
|
---|
| 115 | inline float upside (const float x, const float y) const { return _up.f(x, y); }
|
---|
| 116 | inline float downside (const float x, const float y) const { return _bowl.f(x, y); }
|
---|
| 117 | inline float area () const { return _bowl.f2(_fOutside) - _up.f2(_fOutside); }
|
---|
| 118 | };
|
---|
| 119 |
|
---|
| 120 | class PerimiterUpliftZone : public CylindricalZone <PerimiterUpliftZone>
|
---|
| 121 | {
|
---|
| 122 | public:
|
---|
| 123 | const class OutsideSlope
|
---|
| 124 | {
|
---|
| 125 | public:
|
---|
| 126 | const mars::InvertedSquareFn< float, +1 > fn;
|
---|
| 127 | const mars::Magnitudinal< float > crest;
|
---|
| 128 | const float outside, falloff;
|
---|
| 129 |
|
---|
| 130 | const TaperFn taper;
|
---|
| 131 |
|
---|
| 132 | inline OutsideSlope (const mars::InvertedSquareFn< float, +1 > & fn, const mars::Magnitudinal< float > & crest, const float fSpallFalloffFactor)
|
---|
| 133 | : fn(fn), crest(crest), taper(TaperFn::createTaperFn(crest * fSpallFalloffFactor, crest)), outside(crest * fSpallFalloffFactor + crest), falloff(fSpallFalloffFactor) {}
|
---|
| 134 | } outslope;
|
---|
| 135 |
|
---|
| 136 | private:
|
---|
| 137 | const mars::InvertedSquareFn< float, -1 > _downside;
|
---|
| 138 | const float _fInside, _fBowlRadius;
|
---|
| 139 | BowlFn _bowl;
|
---|
| 140 |
|
---|
| 141 | inline static mars::Magnitudinal<float> solveBowl2Upside (const BowlFn & bowl, const PerimeterUpsideEq & upside)
|
---|
| 142 | {
|
---|
| 143 | using namespace mars;
|
---|
| 144 |
|
---|
| 145 | return NewtonsMethod <float, SolutionEquation <float, BowlFn, InvertedSquareFn <float, +1> > >
|
---|
| 146 | ::solve (
|
---|
| 147 | SolutionEquation <float, BowlFn, InvertedSquareFn <float, +1> > (
|
---|
| 148 | bowl,
|
---|
| 149 | upside
|
---|
| 150 | ),
|
---|
| 151 | bowl.scale * 2
|
---|
| 152 | );
|
---|
| 153 | }
|
---|
| 154 | inline static float solveBowl2Downside( const PerimeterDownsideEq & downside, const CraterZone & czone)
|
---|
| 155 | {
|
---|
| 156 | return mars::NewtonsMethod <float, mars::SolutionEquation <float, BowlFn, mars::InvertedSquareFn <float, -1> > >
|
---|
| 157 | ::solve (
|
---|
| 158 | mars::SolutionEquation <float, BowlFn, mars::InvertedSquareFn <float, -1> > (
|
---|
| 159 | czone.bowl,
|
---|
| 160 | downside
|
---|
| 161 | ),
|
---|
| 162 | czone.radius
|
---|
| 163 | );
|
---|
| 164 | }
|
---|
| 165 |
|
---|
| 166 | public:
|
---|
| 167 | inline PerimiterUpliftZone (const CraterZone & czone, const PerimeterUpsideEq & upside, const PerimeterDownsideEq & downside, const float fSpallFalloffFactor)
|
---|
| 168 | : _bowl(czone.bowl),
|
---|
| 169 | outslope(
|
---|
| 170 | upside,
|
---|
| 171 | solveBowl2Upside(czone.bowl, upside),
|
---|
| 172 | fSpallFalloffFactor
|
---|
| 173 | ),
|
---|
| 174 | _downside(downside),
|
---|
| 175 | _fInside ( solveBowl2Downside(downside, czone) ),
|
---|
| 176 | _fBowlRadius(czone.radius)
|
---|
| 177 | {
|
---|
| 178 | }
|
---|
| 179 |
|
---|
| 180 | inline float compareToCrest (const float x, const float y) const { return outslope.crest.compareTo(x, y); }
|
---|
| 181 |
|
---|
| 182 | inline float outside () const { return outslope.outside; }
|
---|
| 183 | inline float inside () const { return _fInside; }
|
---|
| 184 | inline float crest () const { return outslope.crest; }
|
---|
| 185 | inline float downside (const float x, const float y) const { return _downside.f(x, y); }
|
---|
| 186 | inline float upside (const float x, const float y) const { return outslope.crest.compareTo (x, y) > 0 ? outslope.fn.f(x, y) : _bowl.f(x, y); }
|
---|
| 187 |
|
---|
| 188 | // The most Newton-method-trigger-happy-intersection-routine currently on the planet
|
---|
| 189 | const float area () const
|
---|
| 190 | {
|
---|
| 191 | return
|
---|
| 192 | // Above the x-axis
|
---|
| 193 | ((outslope.fn.f2(outslope.outside) - outslope.fn.f2(outslope.crest)) + (_bowl.f2(outslope.crest) - _bowl.f2(_fBowlRadius)))
|
---|
| 194 | +
|
---|
| 195 | // Below the x-axis
|
---|
| 196 | _downside.f2(outslope.outside) - _downside.f2(_fInside) - (_bowl.f2(_fBowlRadius) - _bowl.f2(_fInside));
|
---|
| 197 | }
|
---|
| 198 | };
|
---|
| 199 |
|
---|
| 200 | class Zones
|
---|
| 201 | {
|
---|
| 202 | public:
|
---|
| 203 | const PerimiterUpliftZone puz;
|
---|
| 204 | const CentralUpliftZone central;
|
---|
| 205 | const CraterZone czone;
|
---|
| 206 | SurfaceDensityZoneFn density;
|
---|
| 207 |
|
---|
| 208 | inline Zones (const CraterZone & czone, const PerimeterUpsideEq & perimUp, const PerimeterDownsideEq & perimDown, const CentralUpliftEq & central, const float fSpallFalloffFactor)
|
---|
| 209 | : czone(czone), puz(czone, perimUp, perimDown, fSpallFalloffFactor), central(central, czone.bowl), density(czone.bowl) {}
|
---|
| 210 | } _zones;
|
---|
| 211 |
|
---|
| 212 | const GWSurfacePos _ptOrigin;
|
---|
| 213 | GWCoords _gcOrigin;
|
---|
| 214 |
|
---|
| 215 | const float
|
---|
| 216 | _fCentralUpliftDepthScale,
|
---|
| 217 | _fCentralUpliftBroadnessScale;
|
---|
| 218 |
|
---|
| 219 | const NoiseGenerator< float > _noise;
|
---|
| 220 |
|
---|
| 221 | public:
|
---|
| 222 | class CraterGMState
|
---|
| 223 | {
|
---|
| 224 | public:
|
---|
| 225 | float frScale, frBowlBroadness, fBowlDepth, fCentralUpliftBroadnessScale, fCentralUpliftDepthScale, fSpallFalloffFactor, frNoise;
|
---|
| 226 | GWSurfacePos ptOrigin;
|
---|
| 227 | GWCoords gcOrigin;
|
---|
| 228 |
|
---|
| 229 | virtual mars::ObjectStream & operator >> (mars::ObjectStream & outs) const;
|
---|
| 230 | virtual mars::ObjectStream & operator << (mars::ObjectStream & ins);
|
---|
| 231 | };
|
---|
| 232 |
|
---|
| 233 | CraterGM (const CraterGMState & state);
|
---|
| 234 |
|
---|
| 235 | CraterGM(
|
---|
| 236 | const VectorTag< GeoHeightMap::Precision >::V2 & ptOrigin,
|
---|
| 237 | const float frSample,
|
---|
| 238 | const float frScale,
|
---|
| 239 | const float frBowlBroadness,
|
---|
| 240 | const float fBowlDepth,
|
---|
| 241 | const float fSpallFalloffFactor,
|
---|
| 242 | const float frNoise,
|
---|
| 243 | const float fCentralUpliftDepthScale,
|
---|
| 244 | const float fCentralUpliftBroadnessScale
|
---|
| 245 | );
|
---|
| 246 |
|
---|
| 247 | virtual void init (SynthesisSession & manager, const IGeoWorldAccessor & accessor, const unsigned short nMaxWidth, const unsigned short nMaxHeight);
|
---|
| 248 | virtual void doMorph (LockedGWSection & section) const;
|
---|
| 249 | virtual mars::BBox< long > getBBox () const;
|
---|
| 250 | virtual GMScalarField * queryField (const FieldType enft, const GeoHeightMap & hm);
|
---|
| 251 | virtual void releaseField (const GMScalarField * pField);
|
---|
| 252 |
|
---|
| 253 | virtual mars::ptr< State > createState () const;
|
---|
| 254 | };
|
---|
| 255 |
|
---|
| 256 | class CraterGMFactory : public GeoMorphFactory, public ISurfaceBoundedGeoMorphFactory, public IPersistentGeoMorphFactory
|
---|
| 257 | {
|
---|
| 258 | private:
|
---|
| 259 | mars::RangeX< float >
|
---|
| 260 | _rngfrSample,
|
---|
| 261 | _rngfrScale,
|
---|
| 262 | _rngfrBowlBroadness,
|
---|
| 263 | _rngfBowlDepth;
|
---|
| 264 |
|
---|
| 265 | float
|
---|
| 266 | _fSpallFalloffFactor,
|
---|
| 267 | _frNoise,
|
---|
| 268 | _fCentralUpliftDepthScale,
|
---|
| 269 | _fCentralUpliftBroadnessScale;
|
---|
| 270 |
|
---|
| 271 | public:
|
---|
| 272 | GeoMorph * createRandomInstance(const long x, const long y) const;
|
---|
| 273 | void configure (IConfigGMFactory * pFactoryConfig, const IConfigGMFactory::Settings & settings );
|
---|
| 274 | void save (const GeoMorph * pGM, mars::ObjectStream & outs) const;
|
---|
| 275 | const GeoMorph * restore (mars::ObjectStream & ins) const;
|
---|
| 276 |
|
---|
| 277 | ~CraterGMFactory();
|
---|
| 278 | };
|
---|
| 279 | }
|
---|