source: Revenant/geoworld/src/gwmorphs/volcano.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: 15.8 KB
Line 
1#include "volcano.h"
2
3#include <mars_ptr.h>
4
5#include "geoworld.h"
6
7namespace geoworld
8{
9 void VolcanoGM::init(SynthesisSession & manager, const IGeoWorldAccessor & accessor, const unsigned short nMaxWidth, const unsigned short nMaxHeight)
10 {
11 using namespace mars;
12
13 const int nOutside = RNDi(_czone.outside());
14 _bbox = BBox< long > (
15 -nOutside, -nOutside,
16 +nOutside, +nOutside
17 );
18
19 const GWCoords gcOrigin = GWCoords(0, 0, accessor.mean(_ptOrigin.x, _ptOrigin.y));
20 for (unsigned int i = 0; i < _nNumLavaFlows; ++i)
21 {
22 const VectorTag< float >::V3 vc = _czone.random(gcOrigin);
23
24 _chans.addStartPoint (vc, PolarCoords< float > (vc).azimuth);
25 }
26
27 const float
28 nNewHalfWidth = static_cast< float > (nMaxWidth) / 2,
29 nNewHalfHeight = static_cast< float > (nMaxHeight) / 2;
30
31 _chans.init(
32 new FluiDynQueryBridge(&accessor, _ptOrigin), // TODO: Is it right to use ptOrigin with a local bbox?
33 _mmnLevels.next(),
34 mars::BBox< float > (
35 -nNewHalfWidth + 1,
36 -nNewHalfHeight + 1,
37 +nNewHalfWidth - 1,
38 +nNewHalfHeight - 1
39 )
40 );
41
42 _bbox.add (static_cast< BBox< long > > (_chans.getBBox()));
43 _bbox += _ptOrigin;
44 }
45
46 void VolcanoGM::doMorph( LockedGWSection & section ) const
47 {
48 using namespace mars;
49
50 const unsigned short
51 nDim = static_cast <unsigned short> (_czone.outside() * 2.0f),
52 nInnerDim = static_cast< unsigned short > (_czone.getIntersect());
53
54 const unsigned short
55 nVolcHalfDim = static_cast< unsigned short > (ceil (_czone.outside()));
56
57 const GWCoords gcOrigin = section.createCoordsRVN(_ptOrigin, nVolcHalfDim / 2);
58 LockedGWSection::View * pView = section.createView(
59 gcOrigin.x - nVolcHalfDim,
60 gcOrigin.y - nVolcHalfDim,
61 gcOrigin.x + nVolcHalfDim,
62 gcOrigin.y + nVolcHalfDim
63 );
64
65 ptr< NoiseGenerator< float >::NoiseMap >
66 mpgrid = _noise.compute(nDim, nDim),
67 mpcones = _noise.compute(nInnerDim, nInnerDim);
68
69 for (ConeZone::UpsideDEMIterator <ConeZone> it = _czone.walkUpside(GWCoords(0, 0, gcOrigin.z)); it; ++it)
70 {
71 const VectorTag< short > ::V2
72 i2d = it->v2D(),
73 a = i2d + nVolcHalfDim;
74
75 (*pView->getHeightMap())(a.x, a.y) =
76 blend(
77 (*pView->getHeightMap())(a.x, a.y),
78 it->z + (*mpgrid)(i2d.x, i2d.y),
79 _czone.taper(i2d.x, i2d.y)
80 );
81 }
82
83 // TODO: Verify use of RNDi
84 const GWCoords::Precision
85 fFull = static_cast< GWCoords::Precision > (mars::RNDi(_czone.full(_frCalderaFull)));
86
87 for (std::vector< ConeZone >::const_iterator i = _inners.begin(); i != _inners.end(); ++i)
88 {
89 const ConeZone & ic = *i;
90
91 ADDCROSS_GLOBALDEM(
92 static_cast< unsigned short > (ic.delta.x + gcOrigin.x),
93 static_cast< unsigned short > (ic.delta.y + gcOrigin.y)
94 );
95 INCCROSS_GLOBALDEM();
96
97 const GWCoords::Precision
98 ic_delta_x = static_cast< GWCoords::Precision > (mars::RNDi(ic.delta.x)),
99 ic_delta_y = static_cast< GWCoords::Precision > (mars::RNDi(ic.delta.y)),
100 x = gcOrigin.x + ic_delta_x, // TODO: Verify use of RNDi
101 y = gcOrigin.y + ic_delta_y; // TODO: Verify use of RNDi
102
103 const GWCoords gcInner(
104 x,
105 y,
106 std::max(
107 section.getSurfaceMean(x, y),
108 static_cast<GeoHeightMap::Precision> (fFull + gcOrigin.z + (*mpgrid)(0, 0))
109 )
110 );
111
112 for (ConeZone::UpsideDEMIterator< ConeZone > j = ic.walkUpside(gcInner); j; ++j)
113 {
114 const VectorTag< short > ::V2
115 j2d = j->v2D(),
116 r = j2d - static_cast< GWSurfacePos > (gcInner),
117 a = j2d - _ptOrigin + nVolcHalfDim;
118
119 (*pView->getHeightMap())(a.x, a.y) =
120 blend(
121 (*pView->getHeightMap())(a.x, a.y),
122 std::max(
123 (*pView->getHeightMap())(a.x, a.y),
124 static_cast< GeoHeightMap::Precision > (
125 j->z
126 + (*mpcones)(j->x + ic_delta_x, j->y + ic_delta_y)
127 )
128 ),
129 ic.taper(r.x, r.y)
130 );
131 }
132 }
133
134 section.releaseView(pView);
135
136 mars::BBox< long > bbox = getBBox();
137 pView = section.createView(bbox.left, bbox.top, bbox.right, bbox.bottom);
138 _chans.run(pView);
139 section.releaseView(pView);
140 }
141
142 VolcanoGM::VolcanoGM
143 (
144 const GWSurfacePos & ptOrigin,
145 const float frNoise,
146 const float fScale,
147 const float fConeBroadness,
148 const float fConeAmplitude,
149 const float fCalderaBroadness,
150 const float frCalderaDepthRatio,
151 const float frCalderaFull,
152 const float fConeFalloffFactor,
153 const unsigned int nNumInnerCones,
154 const mars::RangeX< float > & mmfInnerConeRelativeScale,
155 const mars::RangeX< float > & mmfInnerConeBroadness,
156 const mars::RangeX< float > & mmfInnerConeAmplitude,
157 const mars::RangeX< float > & mmfInnerCalderaBroadness,
158 const mars::RangeX< float > & mmfrInnerCalderaDepthRatio,
159 const mars::RangeX< float > & mmfrInnerConeDisplaceRatio,
160 // Lava flow configs
161 // TODO: Sort out this mess of parameters, way too many!
162 const unsigned int nNumLavaFlows,
163 const float fLavaWaveScale,
164 const float fLavaWavePhase,
165 const float fLavaWaveAmplitude,
166 const float fLavaViscosity,
167 const float frLavaWavePerturbance,
168 const float fLavaFlowHeight,
169 // FluiDyn configs
170 const mars::RangeX< float > & mmfBendZenith,
171 const unsigned short nBendZenithSteps,
172 const unsigned short nCandidateSampleAmt,
173 const mars::RangeX< float > & mmfSplineSeg,
174 const float fGravitySlopeGrace,
175 const float frSnapToGuide,
176 const mars::RangeX< float > & mmfFlowLineWidth,
177 const mars::RangeX< unsigned int > & mmnLevels,
178 const mars::RangeX< unsigned int > & mmnKidsPerLevel,
179 const float fwStraightness,
180 const float fwElevationInfluence,
181 const float fwDensityInfluence,
182 const float fwChaosInfluence
183 ) : _czone(
184 ConeFn(fScale, fConeAmplitude, fConeBroadness, 0),
185 CalderaFn(fScale, fCalderaBroadness, fConeAmplitude * frCalderaDepthRatio),
186 fConeFalloffFactor
187 ),
188 _frCalderaFull(frCalderaFull),
189 _mmfInnerConeRelativeScale(mmfInnerConeRelativeScale),
190 _mmfInnerConeBroadness(mmfInnerConeBroadness),
191 _mmfInnerConeAmplitude(mmfInnerConeAmplitude),
192 _mmfrInnerCalderaDepthRatio(mmfrInnerCalderaDepthRatio),
193 _mmfInnerCalderaBroadness(mmfInnerCalderaBroadness),
194 _mmfrInnerConeDisplaceRatio(mmfrInnerConeDisplaceRatio),
195 _ptOrigin(ptOrigin),
196 _nNumLavaFlows (nNumLavaFlows),
197 _mmnLevels(mmnLevels),
198 _chans(
199 mmfBendZenith, nBendZenithSteps, nCandidateSampleAmt, mmfSplineSeg,
200 fGravitySlopeGrace, frSnapToGuide, mmfFlowLineWidth, mmnKidsPerLevel,
201 fwStraightness, fwElevationInfluence, fwDensityInfluence, fwChaosInfluence,
202 fLavaFlowHeight, fLavaWaveScale, fLavaWavePhase, fLavaWaveAmplitude, fLavaViscosity, frLavaWavePerturbance, 1.0f
203 ),
204 _noise(0.4f, frNoise)
205 {
206 for (unsigned int i = 0; i < nNumInnerCones; ++i)
207 addInner(
208 _mmfInnerConeRelativeScale.next(),
209 _mmfInnerConeAmplitude.next(),
210 _mmfInnerConeBroadness.next(),
211 _mmfInnerCalderaBroadness.next(),
212 _mmfrInnerCalderaDepthRatio.next(),
213 fConeFalloffFactor,
214 VectorTag< float > ::PC
215 (
216 _mmfrInnerConeDisplaceRatio.next(),
217 mars::RANDf(static_cast< float > (mars::PI * 2.0))
218 )
219 );
220 }
221
222 VolcanoGM::VolcanoGM()
223 : _frCalderaFull(0), _nNumLavaFlows (0), _noise(0.4f, 0) {}
224
225 VolcanoGM * VolcanoGM::createInstance( mars::ObjectStream & ins )
226 {
227 VolcanoGM * pVGM = new VolcanoGM ();
228
229 ins
230 >> pVGM->_ptOrigin
231 >> pVGM->_bbox
232 >> pVGM->_mmnLevels
233 >> pVGM->_nNumLavaFlows
234 >> pVGM->_mmfInnerConeRelativeScale
235 >> pVGM->_mmfInnerConeBroadness
236 >> pVGM->_mmfInnerConeAmplitude
237 >> pVGM->_mmfrInnerCalderaDepthRatio
238 >> pVGM->_mmfInnerCalderaBroadness
239 >> pVGM->_mmfrInnerConeDisplaceRatio
240 >> pVGM->_frCalderaFull
241 >> pVGM->_noise.noise;
242
243 size_t nInnerCount;
244 ins >> nInnerCount;
245 pVGM->_inners.clear();
246 pVGM->_inners.reserve(nInnerCount);
247 ConeZone inner;
248 for (size_t c = 0; c < nInnerCount; ++c)
249 {
250 inner << ins;
251 pVGM->_inners.push_back(inner);
252 }
253
254 pVGM->_czone << ins;
255 pVGM->_chans << ins;
256 return pVGM;
257 }
258
259 mars::ObjectStream & VolcanoGM::operator >> ( mars::ObjectStream & outs ) const
260 {
261 outs
262 << _ptOrigin
263 << _bbox
264 << _mmnLevels
265 << _nNumLavaFlows
266 << _mmfInnerConeRelativeScale
267 << _mmfInnerConeBroadness
268 << _mmfInnerConeAmplitude
269 << _mmfrInnerCalderaDepthRatio
270 << _mmfInnerCalderaBroadness
271 << _mmfrInnerConeDisplaceRatio
272 << _frCalderaFull
273 << _noise.noise;
274
275 outs << static_cast< size_t > (_inners.size());
276 for (InnersList::const_iterator i = _inners.begin(); i != _inners.end(); ++i)
277 *i >> outs;
278
279 _czone >> outs;
280 _chans >> outs;
281 return outs;
282 }
283
284 void VolcanoGM::MyChannelSet::applyFlowLine( const FlowLineType & fl, VolcanoGM::LavaFlowData * pData ) const
285 {
286 const mars::ptr< FlowPerturbation > ppert = _ngenPert.compute
287 (
288 static_cast< short > (mars::RNDi(fl.radius * 2)), // TODO: Verify use of RNDi
289 static_cast< short > (mars::RNDi(fl.getLength())) // TODO: Verify use of RNDi
290 );
291
292 for (MyChannelSet::FlowLineType::Iterator<GeoHeightMap::Precision, EaseInFn, EaseOutFn> it = fl.iterate<GeoHeightMap::Precision, EaseInFn, EaseOutFn>(_fnEaseIn, _fnEaseOut); it; ++it)
293 {
294 const mars::vector2D <short> & pos = *it;
295 const float
296 fTotalRadius = static_cast <float> (it.crad()),
297 fRad = it.trad(),
298 fBevel = fTotalRadius * _pfnBevel->f(fRad);
299
300 pData->hmbb(pos.x, pos.y) =
301 std::max(
302 static_cast< GeoHeightMap::Precision >
303 (
304 pData->view.mean5(pos.x, pos.y) +
305 _fnWave.f(static_cast< float > (it.sradius()), it.distance(), fTotalRadius, *ppert) * fBevel +
306 fBevel
307 ),
308 pData->hmbbb(pos.x, pos.y)
309 );
310 }
311 pData->hmbb >> pData->hmbbb;
312 }
313
314 void VolcanoGM::MyChannelSet::run( LockedGWSection::View * pView ) const
315 {
316 LavaFlowData data(pView->getHeightMap());
317 VolcanoGM::ChannelSetType::run(&data);
318 }
319
320 void VolcanoGM::MyChannelSet::init( const mars::ptr< FluiDynQueryBridge > & pQuery, const unsigned int nLevels, const mars::BBox< float > & bboxSearch )
321 {
322 using namespace mars;
323
324 ChannelSetType::init(pQuery, bboxSearch, nLevels);
325
326 const BBox< long > bbox = getBBox();
327 const GWCoords pos3d = GWCoords(-bbox.left, -bbox.top, 0);
328
329 for (MyChannelSet::GuideList::iterator i = begin(); i != end(); ++i)
330 (*i)->offsetBy(pos3d);
331 }
332
333 mars::ObjectStream & VolcanoGM::MyChannelSet::operator >> ( mars::ObjectStream & outs ) const
334 {
335 ChannelSetType::operator >> (outs);
336
337 outs << _ngenPert.noise << _pfnBevel->amplitude << _pfnBevel->getResolution();
338 _fnWave >> outs;
339 return outs;
340 }
341
342 mars::ObjectStream & VolcanoGM::MyChannelSet::operator << ( mars::ObjectStream & ins )
343 {
344 ChannelSetType::operator << (ins);
345
346 unsigned short nFlowBevelResolution;
347 float fFlowBevelAmplitude;
348
349 ins >> _ngenPert.noise >> fFlowBevelAmplitude >> nFlowBevelResolution;
350 _fnWave << ins;
351
352 delete _pfnBevel;
353 _pfnBevel = new FlowBevelFn(nFlowBevelResolution, fFlowBevelAmplitude);
354
355 return ins;
356 }
357
358 VolcanoGM::MyChannelSet::MyChannelSet
359 (
360 const mars::RangeX< float > & mmfBendZenith,
361 const unsigned int nBendZenithSteps,
362 const unsigned int nCandidateSampleAmt,
363 const mars::RangeX< float > & mmfSplineSeg,
364 const float fGravitySlopeGrace,
365 const float frSnapToGuide,
366 const mars::RangeX< float > & mmfFlowLineWidth,
367 const mars::RangeX< unsigned int > & mmnKidsPerLevel,
368 const float fwStraightness,
369 const float fwElevationInfluence,
370 const float fwDensityInfluence,
371 const float fwChaosInfluence,
372 const float fLavaFlowHeight,
373 const float fWaveScale,
374 const float fPhase,
375 const float fAmplitude,
376 const float fViscosity,
377 const float fPerturbance,
378 const float fPertNoise
379 )
380 : ChannelSet(
381 mmfBendZenith,
382 nBendZenithSteps,
383 nCandidateSampleAmt,
384 mmfSplineSeg,
385 fGravitySlopeGrace,
386 frSnapToGuide,
387 mmfFlowLineWidth,
388 mmnKidsPerLevel,
389 fwStraightness,
390 fwElevationInfluence,
391 fwDensityInfluence,
392 fwChaosInfluence
393 ),
394 _fnEaseOut(createEaseOutFn()),
395 _fnEaseIn(createEaseInFn()),
396 _pfnBevel(new FlowBevelFn(
397 mmfFlowLineWidth.maximum,
398 fLavaFlowHeight
399 )),
400 _fnWave(
401 fPhase,
402 fAmplitude,
403 fViscosity,
404 fPerturbance,
405 fWaveScale
406 ),
407 _ngenPert(0.8f, fPertNoise)
408 {}
409
410 VolcanoGM::MyChannelSet::MyChannelSet()
411 :
412 _fnEaseOut(createEaseOutFn()),
413 _fnEaseIn(createEaseInFn()),
414 _pfnBevel(NULL),
415 _ngenPert(0.8f, 0) {}
416
417 VolcanoGM::MyChannelSet::~MyChannelSet()
418 {
419 delete _pfnBevel;
420 }
421
422 GeoMorph * VolcanoGMFactory::createRandomInstance( const long x, const long y ) const
423 {
424 return new VolcanoGM(
425 GWSurfacePos (x, y),
426 _frNoise,
427 _mmfScale.next(),
428 _mmfConeBroadness.next(),
429 _mmfConeAmplitude.next(),
430 _mmfCalderaBroadness.next(),
431 _mmfrCalderaDepthRatio.next(),
432 _mmfrCalderaFull.next(),
433 _fConeFalloffFactor,
434 _mmnNumInnerCones.next(),
435 _mmfInnerConeRelativeScale,
436 _mmfInnerConeBroadness,
437 _mmfInnerConeAmplitude,
438 _mmfInnerCalderaBroadness,
439 _mmfrInnerCalderaDepthRatio,
440 _mmfrInnerConeDisplaceRatio,
441 _mmnNumLavaFlows.next(),
442 _mmfLavaWaveScale.next(),
443 _mmfLavaWavePhase.next(),
444 _mmfLavaWaveAmplitude.next(),
445 _mmfLavaViscosity.next(),
446 _frLavaWavePerturbance,
447 _mmfLavaFlowHeight.next(),
448 _mmfBendZenith,
449 _nBendZenithSteps,
450 _nCandidateSampleAmt,
451 _mmfSplineSeg,
452 _fGravitySlopeGrace,
453 _frSnapToGuide,
454 _mmfFlowLineWidth,
455 _mmnLevels,
456 _mmnKidsPerLevel,
457 _fwStraightness,
458 _fwElevationInfluence,
459 _fwDensityInfluence,
460 _fwChaosInfluence
461 );
462 }
463
464 void VolcanoGMFactory::configure( IConfigGMFactory * pFactoryConfig, const IConfigGMFactory::Settings & settings )
465 {
466 geoworld::IConfigSection
467 & section = *pFactoryConfig->getSection(),
468 & sectCone = *section.getmap("cone"),
469 & sectCaldera = *section.getmap("caldera"),
470 & sectInnerCones = *section.getmap("innercones"),
471 & sectInnerConesCalderas = *sectInnerCones.getmap("caldera"),
472 & sectLava = *section.getmap("lavaflows"),
473 & sectLavaWaves = *sectLava.getmap("waves"),
474 & sectLavaCandidates = *sectLava.getmap("candidates"),
475 & sectLavaFlowlines = *sectLava.getmap("flowlines"),
476 & sectLavaWeights = *sectLava.getmap("weights");
477
478 *section["noise"] >> _frNoise;
479 *section["scale"] >> _mmfScale;
480 *sectCone["broadness"] >> _mmfConeBroadness;
481 *sectCone["amplitude"] >> _mmfConeAmplitude;
482 *sectCone["falloff"] >> _fConeFalloffFactor;
483 *sectCaldera["broadness"] >> _mmfCalderaBroadness;
484 *sectCaldera["fullness"] >> _mmfrCalderaFull;
485 *sectCaldera["depth"] >> _mmfrCalderaDepthRatio;
486 *sectInnerCones["amount"] >> _mmnNumInnerCones;
487 *sectInnerCones["scale"] >> _mmfInnerConeRelativeScale;
488 *sectInnerCones["broadness"] >> _mmfInnerConeBroadness;
489 *sectInnerCones["amplitude"] >> _mmfInnerConeAmplitude;
490 *sectInnerConesCalderas["broadness"] >> _mmfInnerCalderaBroadness;
491 *sectInnerConesCalderas["depth"] >> _mmfrInnerCalderaDepthRatio;
492 *sectInnerCones["displacement"] >> _mmfrInnerConeDisplaceRatio;
493 *sectLavaCandidates["bend_zenith"] >> _mmfBendZenith;
494 *sectLavaCandidates["zenith_steps"] >> _nBendZenithSteps;
495 *sectLavaCandidates["samples"] >> _nCandidateSampleAmt;
496 *sectLava["segment"] >> _mmfSplineSeg;
497 *sectLava["slope_grace"] >> _fGravitySlopeGrace;
498 *sectLava["guide_snap"] >> _frSnapToGuide;
499 *sectLava["amount"] >> _mmnNumLavaFlows;
500 *sectLava["height"] >> _mmfLavaFlowHeight;
501 *sectLavaWaves["scale"] >> _mmfLavaWaveScale;
502 *sectLavaWaves["frequency"] >> _mmfLavaWavePhase;
503 *sectLavaWaves["amplitude"] >> _mmfLavaWaveAmplitude;
504 *sectLavaWaves["viscosity"] >> _mmfLavaViscosity;
505 *sectLavaWaves["perturbation"] >> _frLavaWavePerturbance;
506 *sectLavaFlowlines["width"] >> _mmfFlowLineWidth;
507 *sectLavaFlowlines["levels"] >> _mmnLevels;
508 *sectLavaFlowlines["children"] >> _mmnKidsPerLevel;
509 *sectLavaWeights["straightness"] >> _fwStraightness;
510 *sectLavaWeights["elevation"] >> _fwElevationInfluence;
511 *sectLavaWeights["density"] >> _fwDensityInfluence;
512 *sectLavaWeights["chaos"] >> _fwChaosInfluence;
513 }
514
515 void VolcanoGMFactory::save( const GeoMorph * pGM, mars::ObjectStream & outs ) const
516 {
517 const VolcanoGM * pVGM = dynamic_cast< const VolcanoGM * > (pGM);
518
519 assert(pVGM != NULL);
520 *pVGM >> outs;
521 }
522
523 const GeoMorph * VolcanoGMFactory::restore( mars::ObjectStream & ins ) const
524 {
525 VolcanoGM * pVGM;
526
527 pVGM << ins;
528 return pVGM;
529 }
530}
Note: See TracBrowser for help on using the repository browser.