source: Revenant/geoworld/include/gwmorphs/crater.h@ 7ef8ec4

port/mars-tycoon
Last change on this file since 7ef8ec4 was 80a6a52, checked in by Jonathan Neufeld <support@…>, 3 years ago

Get to a compile state for terrain procedural generation

  • Property mode set to 100644
File size: 9.3 KB
Line 
1#pragma once
2
3#include <mars_util.h>
4
5#include "gwutil.h"
6#include "gmregistry.h"
7#include "geomorph.h"
8
9namespace 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}
Note: See TracBrowser for help on using the repository browser.