source: Revenant/geoworld/src/gwmorphs/winderode.cpp@ 8125274

port/mars-tycoon
Last change on this file since 8125274 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: 4.8 KB
Line 
1#include "winderode.h"
2
3#include <omp.h>
4
5#include "geoworld.h"
6
7namespace geoworld
8{
9 void WindErosionGM::init(SynthesisSession & manager, const IGeoWorldAccessor & accessor, const unsigned short nMaxWidth, const unsigned short nMaxHeight)
10 {
11 _psfDensity = accessor.queryField(FT_Density);
12 }
13
14 void WindErosionGM::doMorph( LockedGWSection & section ) const
15 {
16 using namespace mars;
17 using namespace geoworld;
18
19 LockedGWSection::View
20 * pView = section.createView(section.bbox.left, section.bbox.top, section.bbox.right, section.bbox.bottom);
21
22 ScalarField< RationalType >
23 hmf(pView->width, pView->height, Wrap),
24 hmdf(pView->width, pView->height, Wrap);
25
26 const RangeX< GeoHeightMap::Precision > rnghm = pView->getHeightMap() ->range();
27 GaussianFn< RationalType >
28 gauss(1.0, 1.0, rnghm.delta * _frDecayLevel, 0);
29 signed int i, j, k, g;
30 VectorTag< RationalType >::V2 vgr;
31
32 ptr< NoiseGen::NoiseMap > pnm = _ngen.compute(pView->width, pView->height);
33 const NoiseGen::NoiseMap & nm = *pnm;
34 const RangeX< NoiseGen::NoiseMap::Precision > rngnm = nm.range();
35 const signed int len = static_cast< signed int > (pView->getHeightMap() ->length); // It's ok, HeightMap.length is never more than the positive maximum of a signed-integer
36
37 // Copy integral-precision field to rational-precision field
38 hmf << *pView->getHeightMap();
39
40 for (unsigned int c = 0; c < _iterations; ++c)
41 {
42 for (j = 0; j < hmf.height; ++j)
43 for (i = 0; i < hmf.width; ++i)
44 {
45 const RationalType mh = hmf.mean5(i, j);
46 // This ensures that pits and gullies are ignored
47 if (mh - hmf(i, j) < 0)
48 {
49 const RationalType // Get the noise map ratio at i,j as a ratio to the noise map range
50 nr = static_cast< RationalType > ((nm(i,j) - rngnm.minimum) / rngnm.delta);
51
52 // Obtain gradient into vgr, sampling distance of 5
53 grad5(hmf, i, j, vgr);
54
55 const RationalType
56 // Sample density half-way down at current spot
57 fp = static_cast< RationalType > (1) /
58 static_cast< RationalType > (
59 (*_psfDensity) (i, j, static_cast< GeoHeightMap::Precision > (hmf(i,j) * 0.5f))
60 ),
61 pgr = MAG(vgr),
62
63 // Amount of material to remove
64 rdh = pgr * fp * nr;
65
66 // If the displacement is zero or the volume of material to move is zero then skip
67 if (rdh > 0.0)
68 {
69 // Remove a smooth pile of material from the source site
70 for (k = i - 2; k <= i + 2; ++k)
71 for (g = j - 2; g <= j + 2; ++g)
72 hmdf(k, g) -= gaussblur(k - i, g - j) * rdh;
73
74 const RationalType
75 rddh = rdh * gauss.f(pgr); // TODO: Export gauss fn to pre-init tables state
76
77 // Scale-up the displacement by a random amount, makes a very pleasing result
78 vgr *= RANDf(mh) + static_cast< RationalType > (1);
79
80 const signed int
81 x0 = i - RNDi(vgr.x),
82 y0 = j - RNDi(vgr.y);
83
84 // Deposits "alluvium" into a smooth pile
85 for (k = x0 - 2; k <= x0 + 2; ++k)
86 for (g = y0 - 2; g <= y0 + 2; ++g)
87 hmdf(k, g) += gaussblur(k - x0, g - y0) * rddh;
88 }
89 }
90 }
91
92 hmf += hmdf;
93 hmdf.clear();
94 }
95
96 if (_bSmoothPost)
97 {
98 #pragma omp parallel for private(i, j)
99 for (j = 0; j < hmf.height; ++j)
100 for (i = 0; i < hmf.width; ++i)
101 (*pView->getHeightMap())(i, j) = static_cast< GeoHeightMap::Precision > (
102 hmf(i,j) + (
103 static_cast< RationalType > (hmf.meanVN(i, j) - hmf(i, j))
104 )
105 * (nm(i, j) - rngnm.minimum) / rngnm.delta
106 );
107 } else
108 *pView->getHeightMap() << hmf;
109
110 section.releaseView(pView);
111 }
112
113 WindErosionGM::~WindErosionGM()
114 {
115 // HACK: Use releaseField
116 delete _psfDensity;
117 }
118
119 WindErosionGM::WindErosionGM( const unsigned int nIterations /*= 8*/, const float frDecayLevel /*= 0.1f*/, const bool bSmoothPost /*= true */ ) : _iterations(nIterations), _frDecayLevel(frDecayLevel), _ngen(0.3f, 0.5f), _bSmoothPost(bSmoothPost), _pAccessor(NULL), _psfDensity(NULL)
120 {
121 using namespace mars;
122 GaussianFn< RationalType > gauss(
123 static_cast< RationalType > (1),
124 static_cast< RationalType > (1) / sqrt (
125 static_cast< RationalType > (2) * static_cast< RationalType > (PI)
126 ),
127 1,
128 0
129 ); // TODO: Export to pre-init tables API
130
131 for (signed int x = -2; x <= +2; ++x)
132 for (signed int y = -2; y <= +2; ++y)
133 gaussblur(x, y) = gauss.f(static_cast< RationalType > (x), static_cast< RationalType > (y));
134 }
135
136 GeoMorph * WindErosionGTFactory::createRandomInstance() const
137 { return new WindErosionGM(_mmnIterations.next(), _frDecayLevel, _bSmoothPost); }
138
139 void WindErosionGTFactory::configure( IConfigGTFactory * pFactoryConfig, const IConfigGTFactory::Settings & settings )
140 {
141 const geoworld::IConfigSection & section = *pFactoryConfig->getSection();
142
143 *section["iterations"] >> _mmnIterations;
144 *section["decay"] >> _frDecayLevel;
145 *section["smooth"] >> _bSmoothPost;
146 }
147}
Note: See TracBrowser for help on using the repository browser.