source: Revenant/geoworld/src/gwmorphs/outflowchannels.cpp

port/mars-tycoon
Last change on this file 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: 11.1 KB
RevLine 
[80a6a52]1#include "outflowchannels.h"
2
3#include <mars_util.h>
4#include <mars_lookup.h>
5#include <mars_ptr.h>
6
7using namespace mars;
8using namespace geoworld::ofc;
9
10namespace geoworld
11{
12 void OutflowChannelGM::init(SynthesisSession & manager, const IGeoWorldAccessor & accessor, const unsigned short nMaxWidth, const unsigned short nMaxHeight)
13 {
14 using namespace mars;
15
16 const mars::RangeX< float > mmfDirs(_fGeneralDir - _fSourceSpread / 2.0f, _fGeneralDir + _fSourceSpread / 2.0f);
17
18 for (unsigned int i = 0; i < _nSourcePoints; ++i)
19 {
20 const float fDir = mmfDirs.next();
21
22 _chans.addStartPoint(
23 accessor.createCoords(
24 static_cast< GWSurfacePos::Precision > (_mmfSourceDisplacement.next() * cosf(fDir + static_cast< float > (mars::PI))),
25 static_cast< GWSurfacePos::Precision > (_mmfSourceDisplacement.next() * sinf(fDir + static_cast< float > (mars::PI)))
26 ),
27 fDir
28 );
29 }
30
31 const float
32 nNewHalfWidth = static_cast< float > (nMaxWidth) / 2,
33 nNewHalfHeight = static_cast< float > (nMaxHeight) / 2;
34
35 _chans.init(
36 new FluiDynQueryBridge (&accessor, _ptStart),
37 _mmnLevels.next(),
38 mars::BBox< float > (
39 -nNewHalfWidth + 1,
40 -nNewHalfHeight + 1,
41 +nNewHalfWidth - 1,
42 +nNewHalfHeight - 1
43 )
44 );
45
46 const BBox< long > bbox = _chans.getBBox();
47
48 if (!bbox.empty())
49 _bbox = _chans.getBBox() + _ptStart;
50 else
51 _bbox = BBox< long >();
52 }
53
54 void OutflowChannelGM::doMorph (LockedGWSection & section) const
55 {
56 mars::BBox< long > bbox = getBBox();
57 LockedGWSection::View * pView = section.createView(bbox.left, bbox.top, bbox.right, bbox.bottom);
58
59 _chans.run(pView->getHeightMap());
60
61 section.releaseView(pView);
62 }
63
64 OutflowChannelGM::~OutflowChannelGM()
65 {
66 }
67
68 OutflowChannelGM::OutflowChannelGM(
69 const GWSurfacePos & ptStart,
70 const float fGeneralDir,
71 const unsigned int nSourcePoints,
72 const mars::RangeX< float > & mmfSourceDisplacement,
73 const float fSourceSpread,
74 const mars::RangeX< float > & mmfBendZenith,
75 const unsigned int nBendZenithSteps,
76 const unsigned int nCandidateSampleAmt,
77 const mars::RangeX< float > & mmfSplineSeg,
78 const float fGravitySlopeGrace,
79 const float fCarveWeight,
80 const float frSnapToGuide,
81 const mars::RangeX< float > & mmfFlowLineWidth,
82 const mars::RangeX< unsigned int > & mmnLevels,
83 const mars::RangeX< unsigned int > & mmnKidsPerLevel,
84 const float fwStraightness,
85 const float fwElevationInfluence,
86 const float fwDensityInfluence,
87 const float fwChaosInfluence,
88 const unsigned int nSedimentHistorySize
89 ) :
90 _mmfFlowLineWidth(mmfFlowLineWidth),
91 _mmnLevels(mmnLevels),
92 _chans(
93 mmfBendZenith, nBendZenithSteps, nCandidateSampleAmt, mmfSplineSeg,
94 fGravitySlopeGrace, fCarveWeight, frSnapToGuide, mmfFlowLineWidth, mmnKidsPerLevel,
95 fwStraightness, fwElevationInfluence, fwDensityInfluence, fwChaosInfluence,
96 nSedimentHistorySize
97 ),
98 _ptStart(ptStart),
99 _fGeneralDir(fGeneralDir),
100 _nSourcePoints(nSourcePoints),
101 _mmfSourceDisplacement(mmfSourceDisplacement),
102 _fSourceSpread(fSourceSpread)
103 {}
104
105 OutflowChannelGM::OutflowChannelGM()
106 :
107 _fGeneralDir(0),
108 _nSourcePoints(0),
109 _fSourceSpread(0)
110 {}
111
112 OutflowChannelGM * OutflowChannelGM::createInstance( mars::ObjectStream & ins )
113 {
114 OutflowChannelGM * pOFCGM = new OutflowChannelGM();
115
116 ins
117 >> pOFCGM->_mmfFlowLineWidth
118 >> pOFCGM->_mmnLevels
119 >> pOFCGM->_ptStart
120 >> pOFCGM->_fGeneralDir
121 >> pOFCGM->_nSourcePoints
122 >> pOFCGM->_mmfSourceDisplacement
123 >> pOFCGM->_fSourceSpread
124 >> pOFCGM->_bbox;
125
126 pOFCGM->_chans << ins;
127 return pOFCGM;
128 }
129
130 mars::ObjectStream & OutflowChannelGM::operator >> ( mars::ObjectStream & outs ) const
131 {
132 outs
133 << _mmfFlowLineWidth
134 << _mmnLevels
135 << _ptStart
136 << _fGeneralDir
137 << _nSourcePoints
138 << _mmfSourceDisplacement
139 << _fSourceSpread
140 << _bbox;
141
142 _chans >> outs;
143 return outs;
144 }
145
146 void OutflowChannelGM::MyChannelSet::applyFlowLine( const FlowLineType & fl, OutflowChannelData * pData ) const
147 {
148 unsigned int nSplNum = 0;
149 mars::RingBuffer< HMPrec > & rbSediment = *_prbSediment;
150
151 for (ChannelFinderType::FlowLineType::Iterator<GeoHeightMap::Precision, EaseInFn, EaseOutFn> it = fl.iterate<GeoHeightMap::Precision, EaseInFn, EaseOutFn>(_fnEaseIn, _fnEaseOut); it; ++it)
152 {
153 const VectorTag< unsigned short > ::V2 pos = *it;
154 // Reset sediment history if wrap-around to new spline
155 if (nSplNum != it.splineNum())
156 {
157 rbSediment.clear();
158 nSplNum = it.splineNum();
159 }
160
161 // Total width
162 const float fTotalRadius = static_cast <float> (it.crad());
163
164 // The radius as a ratio to the total width
165 const float frRadius = it.trad();
166
167 // Perturbation value obtained from map
168 const float per = _perturb->getw(it.radius(), it.index());
169
170 // Obtain the height at the current spot
171 const GeoHeightMap::Precision s = pData->view(pos.x, pos.y);
172
173 // Diffused perturbed sediment index based on distance from spline spine
174 const unsigned int ips =
175 std::min(
176 static_cast< unsigned int > (_prbSediment->count - 1),
177 static_cast< unsigned int > (per * _fnBevel.rforce(frRadius) * fTotalRadius)
178 );
179
180 // If the sediment value at the sediment index is empty/null
181 if (rbSediment[ips] == 0)
182 rbSediment[ips] = s;
183 else
184 rbSediment[ips] = (rbSediment[ips] + s) / 2;
185
186 //const VectorTag< float > ::V3 T = it.stress();
187
188 const GeoHeightMap::Precision
189 he = rbSediment[0],
190 h = static_cast <GeoHeightMap::Precision> (
191 (he == 0 ? s : (he + s) / 2)
192 + (_fnBevel.f(frRadius))
193 * getWidthRange().maximum
194 //* std::max(0.0f, T.z / 4.0f) // HACK: Scale down the stress tensor, its scale is unvalidated // HACK: Add the stress tensor to the bevel ratio, scale unvalidated
195 );
196 ++rbSediment;
197
198 pData->hmbb(pos.x, pos.y) =
199 std::min(
200 pData->view(pos.x, pos.y),
201 std::min(s, h)
202 );
203 }
204 pData->view << pData->hmbb;
205 }
206
207 void OutflowChannelGM::MyChannelSet::init( const mars::ptr< FluiDynQueryBridge > & pQuery, const unsigned int nLevels, const mars::BBox< float > & bboxSearch )
208 {
209 using namespace mars;
210
211 OutflowChannelGM::ChannelSetType::init(pQuery, bboxSearch, nLevels);
212
213 const BBox< long > bbox = getBBox();
214
215 if (!bbox.empty()) // Sometimes the finder algorithm fails to find any suitable paths, so we ditch this GeoMorph instance
216 {
217 const GWCoords pos3d = GWCoords(-bbox.left, -bbox.top, 0);
218
219 for (MyChannelSet::GuideList::iterator i = begin(); i != end(); ++i)
220 (*i)->offsetBy(pos3d);
221
222 _perturb =
223 PerturbMapType::createInstance(
224 static_cast< HMPrec >(getWidthRange().maximum),
225 static_cast< HMPrec >(sqrt(static_cast <float> (SQ(bbox.getWidth()) + SQ(bbox.getHeight())))),
226 mars::Wrap
227 );
228
229 for (PerturbMapType::EdgeSeedIterator it = _perturb->edgeSeedIterator(); it; ++it)
230 {
231 it = static_cast <short> (RAND(_prbSediment->count));
232 }
233 _perturb->run(0.25f);
234 }
235 }
236
237 void OutflowChannelGM::MyChannelSet::run( GeoHeightMap::View * pView ) const
238 {
239 OutflowChannelData data(pView);
240 OutflowChannelGM::ChannelSetType::run(&data);
241 }
242
243 mars::ObjectStream & OutflowChannelGM::MyChannelSet::operator >> (mars::ObjectStream & outs) const
244 {
245 ChannelSetType::operator >> (outs);
246 outs << _fnBevel.getBevelDepth() << (_prbSediment == NULL ? 0 : _prbSediment->count);
247 return outs;
248 }
249 mars::ObjectStream & OutflowChannelGM::MyChannelSet::operator << (mars::ObjectStream & ins)
250 {
251 using namespace mars;
252
253 ChannelSetType::operator << (ins);
254
255 float fCarveWeight;
256 unsigned int nSedimentCount;
257
258 ins >> fCarveWeight >> nSedimentCount;
259 _fnBevel = BevelFn(fCarveWeight);
260 delete _prbSediment;
261 _prbSediment = (nSedimentCount > 0 ? new RingBuffer< HMPrec >(nSedimentCount) : NULL);
262 return ins;
263 }
264
265 OutflowChannelGM::MyChannelSet::MyChannelSet(
266 const mars::RangeX< float > & mmfBendZenith,
267 const unsigned int nBendZenithSteps,
268 const unsigned int nCandidateSampleAmt,
269 const mars::RangeX< float > & mmfSplineSeg,
270 const float fGravitySlopeGrace,
271 const float fCarveWeight,
272 const float frSnapToGuide,
273 const mars::RangeX< float > & mmfFlowLineWidth,
274 const mars::RangeX< unsigned int > & mmnKidsPerLevel,
275 const float fwStraightness,
276 const float fwElevationInfluence,
277 const float fwDensityInfluence,
278 const float fwChaosInfluence,
279 const unsigned int nSedimentHistorySize
280 )
281 : ChannelSet(
282 mmfBendZenith,
283 nBendZenithSteps,
284 nCandidateSampleAmt,
285 mmfSplineSeg,
286 fGravitySlopeGrace,
287 frSnapToGuide,
288 mmfFlowLineWidth,
289 mmnKidsPerLevel,
290 fwStraightness,
291 fwElevationInfluence,
292 fwDensityInfluence,
293 fwChaosInfluence
294 ),
295 _fnEaseOut(ofc::EASE_IN_FN),
296 _fnEaseIn(ofc::EASE_OUT_FN),
297 _fnBevel(fCarveWeight),
298 _prbSediment(new RingBuffer< HMPrec > (nSedimentHistorySize)),
299 _perturb(NULL)
300 {}
301
302 OutflowChannelGM::MyChannelSet::MyChannelSet()
303 :
304 _fnEaseOut(ofc::EASE_IN_FN),
305 _fnEaseIn(ofc::EASE_OUT_FN),
306 _fnBevel(0),
307 _prbSediment(NULL),
308 _perturb(NULL)
309 {}
310
311 OutflowChannelGM::MyChannelSet::~MyChannelSet()
312 {
313 delete _perturb;
314 delete _prbSediment;
315 }
316
317 GeoMorph * OutflowChannelGMFactory::createRandomInstance( const long x, const long y ) const
318 {
319 return new OutflowChannelGM(
320 GWSurfacePos(x, y),
321 mars::RANDf(static_cast< float > (2 * mars::PI)),
322 _mmnSourcePoints.next(),
323 _mmfSourceDisplacement,
324 _mmfSourceSpread.next(),
325 _mmfBendZenith,
326 _nBendZenithSteps,
327 _nCandidateSampleAmount,
328 _mmfSplineSeg,
329 _fGravitySlopeGrace,
330 _fCarveWeight,
331 _frSnapToGuide,
332 _mmfFlowLineWidth,
333 _mmnLevels,
334 _mmnKidsPerLevel,
335 _fwStraightness,
336 _fwElevationInfluence,
337 _fwDensityInfluence,
338 _fwChaosInfluence,
339 _nSedimentHistorySize
340 );
341 }
342
343 void OutflowChannelGMFactory::configure( IConfigGMFactory * pFactoryConfig, const IConfigGMFactory::Settings & settings )
344 {
345 geoworld::IConfigSection
346 & section = *pFactoryConfig->getSection(),
347 & sectCandidates = *section.getmap("candidates"),
348 & sectFlowlines = *section.getmap("flowlines"),
349 & sectWeights = *section.getmap("weights");
350
351 *section["num_sources"] >> _mmnSourcePoints;
352 *section["displacement"] >> _mmfSourceDisplacement;
353 *section["spread"] >> _mmfSourceSpread;
354 *sectCandidates["bend_zenith"] >> _mmfBendZenith;
355 *sectCandidates["zenith_steps"] >> _nBendZenithSteps;
356 *sectCandidates["samples"] >> _nCandidateSampleAmount;
357 *section["segment"] >> _mmfSplineSeg;
358 *section["slope_grace"] >> _fGravitySlopeGrace;
359 *section["carve"] >> _fCarveWeight;
360 *section["guide_snap"] >> _frSnapToGuide;
361 *sectFlowlines["width"] >> _mmfFlowLineWidth;
362 *sectFlowlines["levels"] >> _mmnLevels;
363 *sectFlowlines["children"] >> _mmnKidsPerLevel;
364 *sectWeights["straightness"] >> _fwStraightness;
365 *sectWeights["elevation"] >> _fwElevationInfluence;
366 *sectWeights["density"] >> _fwDensityInfluence;
367 *sectWeights["chaos"] >> _fwChaosInfluence;
368 *section["sediment_memory"] >> _nSedimentHistorySize;
369 }
370
371 void OutflowChannelGMFactory::save( const GeoMorph * pGM, mars::ObjectStream & outs ) const
372 {
373 const OutflowChannelGM * pOFCGM = dynamic_cast< const OutflowChannelGM * > (pGM);
374
375 assert(pOFCGM != NULL);
376 *pOFCGM >> outs;
377 }
378
379 const GeoMorph * OutflowChannelGMFactory::restore( mars::ObjectStream & ins ) const
380 {
381 OutflowChannelGM * pOFCGM;
382
383 pOFCGM << ins;
384 return pOFCGM;
385 }
386}
Note: See TracBrowser for help on using the repository browser.