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 | }
|
---|