source: Revenant/geoworld/include/gwmorphs/volcano.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: 15.1 KB
Line 
1#pragma once
2
3#include <mars_calc.h>
4
5#include "geomorph.h"
6#include "gwutil.h"
7#include "linalgadapt.h"
8#include "gmregistry.h"
9#include "fluidyn.h"
10#include "geoworld.h"
11
12namespace geoworld
13{
14 class VolcanoGM : public HeightMapGeoMorph, public BoundedGeoMorph
15 {
16 private:
17 typedef mars::GaussianFn <float> ConeFn;
18 typedef mars::ParabolicFn <float, +1> CalderaFn;
19 typedef mars::MidpointDisplacementGrid< float > FlowPerturbation;
20
21 typedef mars::SolutionEquation< float, ConeFn, CalderaFn > ConeCalderaSolnEq;
22 typedef mars::BisectMethod <float, ConeCalderaSolnEq, 10> ConeCalderaSolver;
23 typedef VectorTag< float >::V3 Vector3;
24 typedef VectorTag< float >::V2 Vector2;
25
26 typedef mars::ParabolicFn<float, -1> EaseInFn; // Used for tapering the flow line
27 typedef mars::ParabolicFn<float, -1> EaseOutFn; // Used for tapering the flow line
28
29 class ConeZone : public geoworld::CylindricalZone <ConeZone>
30 {
31 private:
32 class Intersect
33 {
34 public:
35 const mars::Magnitudinal< float > val;
36 const geoworld::TaperFn taper;
37 const float outside;
38
39 Intersect ()
40 : val(0), outside(0) {}
41 Intersect (const mars::Magnitudinal< float > & val, const float fScale, const float fFalloff)
42 : val(val), taper(geoworld::TaperFn::createTaperFn(fFalloff * fScale, val)), outside(fFalloff * fScale + val) {}
43
44 inline Intersect & operator = (const Intersect & copy)
45 {
46 const_cast< mars::Magnitudinal< float > & > (val) = copy.val;
47 const_cast< geoworld::TaperFn & > (taper) = copy.taper;
48 const_cast< float & > (outside) = copy.outside;
49 return *this;
50 }
51 } _intersect;
52
53 inline float area (const float fUntil) const
54 { return cone.f2(fUntil) - cone.f2(_intersect.val) + caldera.f2(_intersect.val); }
55
56 inline static Intersect createIntersect (const ConeFn & cone, const CalderaFn & caldera, const float fFalloffFactor)
57 { return Intersect(ConeCalderaSolver ::solve(ConeCalderaSolnEq(cone, caldera), 0, cone.scale *2), cone.scale, fFalloffFactor); }
58
59 public:
60 const ConeFn cone;
61 const CalderaFn caldera;
62 const Vector2 delta;
63 const float falloff;
64
65 ConeZone () : falloff(0) {}
66 ConeZone (const ConeFn & cone, const CalderaFn & caldera, const float fFalloffFactor, const Vector2 & delta = Vector2())
67 : cone(cone), caldera(caldera), delta(delta), falloff(fFalloffFactor),
68 _intersect(createIntersect(cone, caldera, fFalloffFactor))
69 {}
70
71 inline ConeZone & operator = (const ConeZone & copy)
72 {
73 const_cast< ConeFn & > (cone) = copy.cone;
74 const_cast< CalderaFn & > (caldera) = copy.caldera;
75 const_cast< Vector2 & > (delta) = copy.delta;
76 const_cast< float & > (falloff) = copy.falloff;
77 _intersect = copy._intersect;
78 return *this;
79 }
80 inline mars::ObjectStream & operator << (mars::ObjectStream & ins)
81 {
82 float fScale, fConeAmplitude, fConeBroadness, fCalderaBroadness, fCalderaDepth;
83
84 ins >> fScale >> fConeAmplitude >> fConeBroadness >> fCalderaBroadness >> fCalderaDepth
85 >> const_cast< float & > (falloff)
86 >> const_cast< Vector2 & > (delta);
87 const_cast< ConeFn & > (cone) = ConeFn(fScale, fConeAmplitude, fConeBroadness);
88 const_cast< CalderaFn & > (caldera) = CalderaFn(fScale, fCalderaBroadness, fCalderaDepth);
89 _intersect = createIntersect(cone, caldera, falloff);
90 return ins;
91 }
92 inline mars::ObjectStream & operator >> (mars::ObjectStream & outs) const
93 {
94 outs << cone.scale << cone.amplitude << cone.broadness << caldera.broadness << caldera.depth << falloff << delta;
95 return outs;
96 }
97
98 inline float taper (const float x, const float y) const
99 { return _intersect.taper.f(x, y); }
100
101 inline const mars::Magnitudinal< float > & getIntersect() const
102 { return _intersect.val; }
103
104 inline float full (const float frDepth) const
105 { return caldera.f(0) + (cone.f(0) - caldera.f(0)) * frDepth; }
106 inline float outside () const { return _intersect.outside; }
107 inline float inside () const { return 0; }
108 inline float downside (const float x, const float y) const { return 0; }
109 inline float upside (const float x, const float y) const { return std::min(cone.f(x, y), caldera.f(x, y)); }
110 inline float area () const { return area(_intersect.outside); }
111 } _czone;
112
113 GWSurfacePos
114 _ptOrigin;
115 float _frCalderaFull;
116 mars::RangeX< float >
117 _mmfInnerConeRelativeScale,
118 _mmfInnerConeBroadness,
119 _mmfInnerConeAmplitude,
120 _mmfInnerCalderaBroadness,
121 _mmfrInnerCalderaDepthRatio,
122 _mmfrInnerConeDisplaceRatio;
123
124 mars::BBox< long > _bbox;
125
126 typedef std::vector< ConeZone > InnersList;
127 InnersList _inners;
128
129 class FluiDynQueryBridge : public fldyn::IQueryBridge <FluiDynQueryBridge, FieldReal, GeoHeightMap::Precision>
130 {
131 private:
132 const IGeoWorldAccessor * _pAccessor;
133 const GMScalarField * _pfsDensity;
134 const GWSurfacePos _ptOffset;
135
136 public:
137 inline FluiDynQueryBridge (const IGeoWorldAccessor * pAccessor, const GWSurfacePos & ptOffset)
138 : _pAccessor (pAccessor), _pfsDensity(pAccessor->queryField(FT_Density)), _ptOffset(ptOffset) {}
139
140 inline DensityPrecision density (const GeoHeightMap::Precision x, const GeoHeightMap::Precision y, const GeoHeightMap::Precision z) const
141 { return (*_pfsDensity) (x + _ptOffset.x, y + _ptOffset.y, z); }
142 inline DensityPrecision density (const GeoHeightMap::Precision x, const GeoHeightMap::Precision y) const
143 { return (*_pfsDensity) (x + _ptOffset.x, y + _ptOffset.y, (*_pAccessor)(x + _ptOffset.x, y + _ptOffset.y)); }
144 inline GeoHeightMap::Precision elevation (const unsigned int x, const unsigned int y) const
145 { return _pAccessor->mean(x + _ptOffset.x, y + _ptOffset.y); }
146 };
147
148 class LavaFlowData
149 {
150 public:
151 GeoHeightMap::View & view;
152 GeoHeightMap hmbb, hmbbb;
153
154 LavaFlowData (GeoHeightMap::View * pView)
155 : view(*pView), hmbb(*pView), hmbbb(*pView) {}
156 ~LavaFlowData()
157 { view << hmbbb; }
158 };
159
160 typedef fldyn::ChannelSet <FluiDynQueryBridge, float, typename GeoHeightMap::Precision, LavaFlowData> ChannelSetType;
161
162 class MyChannelSet : public ChannelSetType
163 {
164 private:
165 class HumpyBevelFn
166 {
167 private:
168 const float _fBL2;
169
170 inline static float createBL2 () { return 1-(1/exp(1.0f)); }
171
172 public:
173 const float amplitude;
174
175 HumpyBevelFn ()
176 : _fBL2(createBL2()), amplitude(0) {}
177 HumpyBevelFn(const float amplitude)
178 : _fBL2(createBL2()), amplitude(amplitude) {}
179
180 inline const float f (const float x) const
181 {
182 using namespace mars;
183 return GaussianFn< float >::f(x, 1.0f, 0.5f * GaussianFn< float >::f(x, 1.0f, _fBL2, amplitude, 0.0f), amplitude, 0.0f);
184 }
185 };
186
187 class FlowBevelFn : public mars::CacheFnProxy< float, HumpyBevelFn >
188 {
189 private:
190 static inline CacheFnProxy createCacheFnProxy (const float fAmplitude, const unsigned short nResolution)
191 { return CacheFnProxy(HumpyBevelFn(fAmplitude), 0, 1, nResolution); }
192
193 public:
194 const float amplitude;
195
196 FlowBevelFn (const unsigned short nResolution, const float fAmplitude)
197 : CacheFnProxy(createCacheFnProxy(fAmplitude, nResolution)), amplitude(fAmplitude) {}
198 FlowBevelFn (const float fMaxRadius, const float fAmplitude)
199 : CacheFnProxy(createCacheFnProxy(fAmplitude, static_cast< unsigned short > (ceil(fMaxRadius)))), amplitude(fAmplitude) {}
200 } * _pfnBevel;
201
202 class WaveFn : private mars::GaussianFn< float >
203 {
204 private:
205 float _fScale;
206
207 inline static GaussianFn< float > createGaussian (const float fViscosity)
208 { return GaussianFn(1.0f, 1.0f / fViscosity, 1.0f/3.0f, 0.0f); }
209
210 public:
211 const float waves, wavesize, perturbance, waveamplitude, viscosity;
212
213 WaveFn ()
214 : waves(0), wavesize(0), perturbance(0), waveamplitude(0), viscosity(0), _fScale(0) {}
215 WaveFn (
216 const float frWaveSize,
217 const float fWaveAmplitude,
218 const float fViscosity,
219 const float frPerturbance,
220 const float fScale = 1.0f
221 )
222 : GaussianFn(createGaussian(fViscosity)), viscosity(fViscosity), _fScale(fScale), waves(1.0f / frWaveSize), wavesize(frWaveSize),
223 perturbance (frPerturbance), waveamplitude(fWaveAmplitude)
224 {}
225
226 // r : Distance from spine (radi)
227 // t : The total distance traveled thus-far in the current spline
228 // rT : The total radius of the flow
229 inline float f (const float r, const float t, const float rT, const FlowPerturbation & perturb) const
230 {
231 // TODO: Externalize a wave amplitude parameter, right now depends on pre-configured scale
232 // TODO: Scale parameter isn't used, always 1.0, causes perturbance to become dependent on actual scale to have any real effect
233 return cosf(
234 (
235 (
236 t
237 - GaussianFn::f(r / rT) * rT // Cancels broadness feature of Gaussian
238 + perturb(
239 mars::RNDi(r), // TODO: Verify use of RNDi
240 mars::RNDi(t)
241 ) * perturbance
242 ) / static_cast< float > (mars::PI) * waves
243 ) / _fScale
244 ) * waveamplitude / 2.0f * _fScale;
245 }
246
247 mars::ObjectStream & operator >> (mars::ObjectStream & outs) const
248 { return outs << _fScale << waves << wavesize << perturbance << waveamplitude << viscosity; }
249
250 mars::ObjectStream & operator << (mars::ObjectStream & ins)
251 {
252 ins
253 >> _fScale
254 >> const_cast< float & > (waves)
255 >> const_cast< float & > (wavesize)
256 >> const_cast< float & > (perturbance)
257 >> const_cast< float & > (waveamplitude)
258 >> const_cast< float & > (viscosity);
259
260 GaussianFn::operator = (createGaussian(viscosity));
261 return ins;
262 }
263 } _fnWave;
264
265 const EaseInFn _fnEaseIn;
266 const EaseOutFn _fnEaseOut;
267 geoworld::NoiseGenerator< float > _ngenPert;
268
269 inline static EaseInFn createEaseInFn () { return EaseInFn(1, 1.1f, -1.001f); }
270 inline static EaseOutFn createEaseOutFn () { return EaseOutFn(1, 1.1f, -1.001f); }
271
272 protected:
273 virtual void applyFlowLine (const FlowLineType & fl, LavaFlowData * pData) const;
274
275 public:
276 MyChannelSet();
277 MyChannelSet(
278 const mars::RangeX< float > & mmfBendZenith,
279 const unsigned int nBendZenithSteps,
280 const unsigned int nCandidateSampleAmt,
281 const mars::RangeX< float > & mmfSplineSeg,
282 const float fGravitySlopeGrace,
283 const float frSnapToGuide,
284 const mars::RangeX< float > & mmfFlowLineWidth,
285 const mars::RangeX< unsigned int > & mmnKidsPerLevel,
286 const float fwStraightness,
287 const float fwElevationInfluence,
288 const float fwDensityInfluence,
289 const float fwChaosInfluence,
290 const float fLavaFlowHeight,
291 const float fWaveScale,
292 const float fPhase,
293 const float fAmplitude,
294 const float fViscosity,
295 const float fPerturbance,
296 const float fPertNoise
297 );
298
299 ~MyChannelSet();
300
301 void init ( const mars::ptr< FluiDynQueryBridge > & pQuery, const unsigned int nLevels, const mars::BBox< float > & bboxSearch );
302 void run ( LockedGWSection::View * pView ) const;
303
304 mars::ObjectStream & operator >> (mars::ObjectStream & outs) const;
305 mars::ObjectStream & operator << (mars::ObjectStream & ins);
306
307 } _chans;
308
309 unsigned int _nNumLavaFlows;
310 geoworld::NoiseGenerator< float > _noise;
311 mars::RangeX< unsigned int > _mmnLevels;
312
313 inline void addInner (
314 const float frdScale,
315 const float fAmplitude,
316 const float fConeBroadness,
317 const float fCaldBroadness,
318 const float frCaldDepthRatio,
319 const float fFalloffFactor,
320 VectorTag< float >::PC dpc
321 )
322 {
323 const float fScale = _czone.caldera.scale * frdScale;
324 dpc.p *= _czone.caldera.scale;
325 const Vector2 dpos = dpc;
326
327 _inners.push_back(
328 ConeZone(
329 ConeFn(
330 fScale,
331 fAmplitude,
332 fConeBroadness,
333 -ConeFn(
334 fScale,
335 fAmplitude,
336 fConeBroadness,
337 0
338 ).f(_czone.getIntersect() + mars::MAG(dpos)) / fScale
339 ),
340 CalderaFn(
341 fScale,
342 fCaldBroadness,
343 fAmplitude * frCaldDepthRatio
344 ),
345 fFalloffFactor,
346 dpos
347 )
348 );
349 }
350
351 VolcanoGM ();
352
353 public:
354 VolcanoGM (
355 const GWSurfacePos & ptOrigin,
356 const float frNoise,
357 const float fScale,
358 const float fConeBroadness,
359 const float fConeAmplitude,
360 const float fCalderaBroadness,
361 const float frCalderaDepthRatio,
362 const float frCalderaFull,
363 const float fConeFalloffFactor,
364 const unsigned int nNumInnerCones,
365 const mars::RangeX< float > & mmfInnerConeRelativeScale,
366 const mars::RangeX< float > & mmfInnerConeBroadness,
367 const mars::RangeX< float > & mmfInnerConeAmplitude,
368 const mars::RangeX< float > & mmfInnerCalderaBroadness,
369 const mars::RangeX< float > & mmfrInnerCalderaDepthRatio,
370 const mars::RangeX< float > & mmfrInnerConeDisplaceRatio,
371 // Lava flow configs
372 // TODO: Sort out this mess of parameters, way too many!
373 const unsigned int nNumLavaFlows,
374 const float fLavaWaveScale,
375 const float fLavaWavePhase,
376 const float fLavaWaveAmplitude,
377 const float fLavaViscosity,
378 const float frLavaWavePerturbance,
379 const float fLavaFlowHeight,
380 // FluiDyn configs
381 const mars::RangeX< float > & mmfBendZenith,
382 const unsigned short nBendZenithSteps,
383 const unsigned short nCandidateSampleAmt,
384 const mars::RangeX< float > & mmfSplineSeg,
385 const float fGravitySlopeGrace,
386 const float frSnapToGuide,
387 const mars::RangeX< float > & mmfFlowLineWidth,
388 const mars::RangeX< unsigned int > & mmnLevels,
389 const mars::RangeX< unsigned int > & mmnKidsPerLevel,
390 const float fwStraightness,
391 const float fwElevationInfluence,
392 const float fwDensityInfluence,
393 const float fwChaosInfluence
394 );
395
396 virtual void init (SynthesisSession & manager, const IGeoWorldAccessor & accessor, const unsigned short nMaxWidth, const unsigned short nMaxHeight);
397 virtual void doMorph (LockedGWSection & section) const;
398 virtual mars::BBox< long > getBBox () const { return _bbox; }
399
400 static VolcanoGM * createInstance (mars::ObjectStream & ins);
401 mars::ObjectStream & operator >> (mars::ObjectStream & outs) const;
402 };
403
404 inline mars::ObjectStream & operator << (VolcanoGM *& pGM, mars::ObjectStream & ins)
405 {
406 pGM = VolcanoGM::createInstance(ins);
407 return ins;
408 }
409
410 class VolcanoGMFactory : public GeoMorphFactory, public IPersistentGeoMorphFactory, public ISurfaceBoundedGeoMorphFactory
411 {
412 private:
413 float
414 _frNoise,
415 _fConeFalloffFactor,
416
417 _frLavaWavePerturbance,
418
419 _fGravitySlopeGrace,
420 _frSnapToGuide,
421
422 _fwStraightness,
423 _fwElevationInfluence,
424 _fwDensityInfluence,
425 _fwChaosInfluence;
426
427 mars::RangeX< float >
428 _mmfScale,
429 _mmfConeBroadness,
430 _mmfConeAmplitude,
431 _mmfCalderaBroadness,
432 _mmfrCalderaDepthRatio,
433 _mmfrCalderaFull,
434
435 _mmfInnerConeRelativeScale,
436 _mmfInnerConeBroadness,
437 _mmfInnerConeAmplitude,
438 _mmfInnerCalderaBroadness,
439 _mmfrInnerCalderaDepthRatio,
440 _mmfrInnerConeDisplaceRatio,
441
442 _mmfLavaWaveScale,
443 _mmfLavaWavePhase,
444 _mmfLavaWaveAmplitude,
445 _mmfLavaViscosity,
446 _mmfLavaFlowHeight,
447
448 _mmfBendZenith,
449 _mmfSplineSeg,
450 _mmfFlowLineWidth;
451
452 mars::RangeX< unsigned int >
453 _mmnLevels,
454 _mmnKidsPerLevel,
455 _mmnNumInnerCones,
456
457 _mmnNumLavaFlows;
458
459 unsigned short
460 _nBendZenithSteps,
461 _nCandidateSampleAmt;
462
463 public:
464 virtual GeoMorph * createRandomInstance(const long x, const long y) const;
465 virtual void configure( IConfigGMFactory * pFactoryConfig, const IConfigGMFactory::Settings & settings );
466 virtual void save (const GeoMorph * pGM, mars::ObjectStream & outs) const;
467 virtual const GeoMorph * restore (mars::ObjectStream & ins) const;
468 };
469}
Note: See TracBrowser for help on using the repository browser.