source: Revenant/geoworld/include/vmpdg.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: 19.8 KB
Line 
1#ifndef __GEOWORLDVMPDG_H__
2#define __GEOWORLDVMPDG_H__
3
4#include <mars_grids.h>
5#include <mars_ptr.h>
6#include <mars_util.h>
7
8#include <vector>
9#include <set>
10
11namespace geoworld
12{
13 template< typename T >
14 class MPDGVecType
15 {
16 public:
17 typedef T Precision;
18
19 T altitude;
20 unsigned short mindex;
21
22 MPDGVecType ()
23 : altitude(0), mindex(0) {}
24
25 MPDGVecType (const MPDGVecType & copy)
26 : altitude(copy.altitude), mindex(copy.mindex) {}
27 MPDGVecType (const T altitude, const unsigned short nIdx)
28 : altitude(altitude), mindex(nIdx) {}
29
30 inline MPDGVecType & operator += (const MPDGVecType & v)
31 { return operator += (v.altitude); }
32 inline MPDGVecType & operator -= (const MPDGVecType & v)
33 { return operator -= (v.altitude); }
34 inline MPDGVecType operator + (const MPDGVecType & v) const
35 { return operator + (v.altitude); }
36 inline MPDGVecType operator - (const MPDGVecType & v) const
37 { return operator - (v.altitude); }
38 inline MPDGVecType & operator += (const T & n)
39 {
40 altitude += n;
41 return *this;
42 }
43 inline MPDGVecType & operator -= (const T & n)
44 {
45 altitude -= n;
46 return *this;
47 }
48 inline MPDGVecType operator + (const T & n) const
49 {
50 return MPDGVecType(altitude + n, mindex);
51 }
52 inline MPDGVecType operator - (const T & n) const
53 {
54 return MPDGVecType(altitude - n, mindex);
55 }
56 inline MPDGVecType operator << (const unsigned short n) const
57 {
58 return MPDGVecType(altitude << n, mindex);
59 }
60 inline MPDGVecType operator >> (const unsigned short n) const
61 {
62 return MPDGVecType(altitude >> n, mindex);
63 }
64
65 inline bool operator < (const MPDGVecType & b) const
66 { return mindex < b.mindex || (mindex == b.mindex && altitude < b.altitude); }
67 inline bool operator > (const MPDGVecType & b) const
68 { return mindex > b.mindex || (mindex == b.mindex && altitude > b.altitude); }
69
70 inline bool operator <= (const MPDGVecType & b) const
71 { return mindex <= b.mindex || (mindex == b.mindex && altitude <= b.altitude); }
72 inline bool operator >= (const MPDGVecType & b) const
73 { return mindex >= b.mindex || (mindex == b.mindex && altitude >= b.altitude); }
74 };
75
76 template< typename T >
77 struct MPDGVecTypeNumerics
78 {
79 typedef long double UP;
80 typedef double POS;
81
82 static inline geoworld::MPDGVecType< T > zero () { return geoworld::MPDGVecType< T > (); }
83 static inline geoworld::MPDGVecType< T > step() { return geoworld::MPDGVecType< T > (mars::Numerics< T >::step(), 0); }
84 static inline geoworld::MPDGVecType< T > min () { return geoworld::MPDGVecType< T >(std::numeric_limits< T >::lowest(), std::numeric_limits< unsigned short >::lowest()); }
85 static inline geoworld::MPDGVecType< T > max () { return geoworld::MPDGVecType< T >(std::numeric_limits< T >::max(), std::numeric_limits< unsigned short >::max()); }
86 };
87
88 template< typename E, typename T >
89 class ElementalFieldView : public mars::ScalarFieldView< MPDGVecType< T >, MPDGVecTypeNumerics< T > >
90 {
91 public:
92 typedef std::vector< E > ElementList;
93
94 using ScalarFieldView = typename mars::ScalarFieldView< MPDGVecType< T >, MPDGVecTypeNumerics< T > >;
95 using Offset = typename ScalarFieldView::Offset;
96
97 private:
98 ElementList * _pElements;
99
100 protected:
101 ElementalFieldView (mars::MemoryBlock< MPDGVecType< T > > * pBlock, const mars::BBox< unsigned short > & bbox, ElementList * pElemList, const mars::GridType engt = mars::Normal)
102 : _pElements(pElemList), ScalarFieldView (pBlock, bbox, engt) {}
103 ElementalFieldView (mars::MemoryBlock< MPDGVecType< T > > * pBlock, const unsigned short nLeft, const unsigned short nTop, const unsigned short nWidth, const unsigned short nHeight, ElementList * pElemList, const mars::GridType engt = mars::Normal)
104 : _pElements(pElemList), ScalarFieldView (pBlock, nLeft, nTop, nWidth, nHeight, engt) {}
105
106 // Reserved for use by the ElementalField and subclasses, used to duplicate the memory block and element list
107 ElementalFieldView (const ElementalFieldView & copy, mars::MemoryBlock< E > * const pBlock, ElementList * const pElements)
108 : ScalarFieldView(copy, pBlock), _pElements(pElements) {}
109
110 // Copy constructor
111 ElementalFieldView (const ElementalFieldView & copy)
112 : ScalarFieldView(copy), _pElements(copy._pElements) {}
113
114 ElementList * elements() { return _pElements; }
115
116 static ElementalFieldView< E, T > createHosted (const unsigned short nWidth, const unsigned short nHeight, const mars::GridType engt)
117 { return ElementalFieldView< E, T > (new mars::MemoryBlock< MPDGVecType< T > > (nWidth, nHeight), 0, 0, nWidth, nHeight, new ElementList(), engt); }
118
119 mars::Range< MPDGVecType< T >, MPDGVecTypeNumerics< T > > rangeImpl (const int x0, const int y0, const int xN, const int yN) const
120 {
121 T
122 fAltMax = std::numeric_limits <T>::min(),
123 fAltMin = std::numeric_limits <T>::max();
124 unsigned short
125 nIdxMax = std::numeric_limits <unsigned short>::lowest(),
126 nIdxMin = std::numeric_limits <unsigned short>::max();
127
128 int x, y;
129 int iti;
130
131#ifdef _OPENMP
132#define RANGEIMPL_THREADCOUNT 4
133#else
134#define RANGEIMPL_THREADCOUNT 1
135#endif
136 unsigned short vnIdxMin4[RANGEIMPL_THREADCOUNT], vnIdxMax4[RANGEIMPL_THREADCOUNT];
137 T vfAltMin4[RANGEIMPL_THREADCOUNT], vfAltMax4[RANGEIMPL_THREADCOUNT];
138
139 for (iti = 0; iti < RANGEIMPL_THREADCOUNT; ++iti)
140 {
141 vfAltMin4[iti] = fAltMin;
142 vfAltMax4[iti] = fAltMax;
143 vnIdxMin4[iti] = nIdxMin;
144 vnIdxMax4[iti] = nIdxMax;
145 }
146
147#ifdef _OPENMP
148 #pragma omp parallel for private (x, y) num_threads(RANGEIMPL_THREADCOUNT)
149#endif
150 for (x = x0; x <= xN; ++x)
151 {
152 const int ti =
153#ifdef _OPENMP
154 omp_get_thread_num();
155#else
156 0;
157#endif
158 for (y = y0; y <= yN; ++y)
159 {
160 const MPDGVecType< T > & elem = ScalarFieldView::get(x, y);
161
162 if (elem.altitude > vfAltMax4[ti])
163 vfAltMax4[ti] = elem.altitude;
164 if (elem.altitude < vfAltMin4[ti])
165 vfAltMin4[ti] = elem.altitude;
166
167 if (elem.mindex > vnIdxMax4[ti])
168 vnIdxMax4[ti] = elem.mindex;
169 if (elem.mindex < vnIdxMin4[ti])
170 vnIdxMin4[ti] = elem.mindex;
171 }
172 }
173
174 for (iti = 0; iti < RANGEIMPL_THREADCOUNT; ++iti)
175 {
176 if (vfAltMax4[iti] > fAltMax)
177 fAltMax = vfAltMax4[iti];
178 if (vfAltMin4[iti] < fAltMin)
179 fAltMin = vfAltMin4[iti];
180
181 if (vnIdxMax4[iti] > nIdxMax)
182 nIdxMax = vnIdxMax4[iti];
183 if (vnIdxMin4[iti] < nIdxMin)
184 nIdxMin = vnIdxMin4[iti];
185 }
186
187 return mars::Range< MPDGVecType< T >, MPDGVecTypeNumerics < T > > (MPDGVecType< T >(fAltMin, nIdxMin), MPDGVecType< T >(fAltMax, nIdxMax));
188 }
189
190 friend class mars::ScalarFieldView< MPDGVecType< T >, MPDGVecTypeNumerics< T > >;
191
192 public:
193 typedef E Element;
194 typedef ElementalFieldView< E, T > View;
195 typedef T AltitudePrecision;
196
197 ElementalFieldView(ElementalFieldView && move) : ScalarFieldView(move), _pElements(move._pElements) {}
198
199 ElementalFieldView < E, T > * createView (const unsigned short nLeft, const unsigned short nTop, const unsigned short nRight, const unsigned short nBottom);
200 const ElementalFieldView < E, T > * createView (const unsigned short nLeft, const unsigned short nTop, const unsigned short nRight, const unsigned short nBottom) const;
201
202 inline const E & getElement (const signed int x, const signed int y) const
203 {
204 return _pElements->at(
205 ScalarFieldView::get(
206 x + static_cast< const ScalarFieldView * const > (this) ->left,
207 y + static_cast< const ScalarFieldView * const > (this) ->top
208 ).mindex
209 );
210 }
211 inline size_t elementCount () const
212 { return _pElements->size(); }
213 inline const E & getElement (const size_t nIdx) const
214 { return _pElements->at(nIdx); }
215 inline E & getElement (const size_t nIdx)
216 { return _pElements->at(nIdx); }
217
218 signed int findElementIndex (const E & elem) const
219 {
220 unsigned short nIdx = 0;
221 for (typename ElementList::const_iterator i = _pElements->begin(); i != _pElements->end(); ++i, ++nIdx)
222 if (*i == elem)
223 return nIdx;
224
225 return -1;
226 }
227
228 size_t countViewElements () const
229 {
230 std::set< unsigned short > setMIdx;
231
232 for (size_t j = 0; j < ScalarFieldView::height; ++j)
233 for (size_t i = 0; i < ScalarFieldView::width; ++i)
234 setMIdx.insert(ScalarFieldView::get(i, j).mindex);
235
236 return setMIdx.size();
237 }
238
239 void fetchViewElements (std::set< E > & st) const
240 {
241 for (size_t j = 0; j < ScalarFieldView::height; ++j)
242 for (size_t i = 0; i < ScalarFieldView::width; ++i)
243 st.insert(getElement(i, j));
244 }
245 void fetchViewIndices (std::set< unsigned short > & st) const
246 {
247 for (size_t j = 0; j < ScalarFieldView::height; ++j)
248 for (size_t i = 0; i < ScalarFieldView::width; ++i)
249 st.insert(ScalarFieldView::operator () (i, j) .mindex);
250 }
251
252 inline typename ElementalFieldView< E, T >::ElementList::const_iterator beginElements() const
253 { return _pElements->begin(); }
254 inline typename ElementalFieldView< E, T >::ElementList::const_iterator endElements() const
255 { return _pElements->end(); }
256
257 template< typename L >
258 inline void reg (const typename L::const_iterator iBegin, const typename L::const_iterator iEnd, const L * = NULL)
259 { _pElements->insert(_pElements->end(), iBegin, iEnd); }
260
261 inline void reg (const E & e)
262 { _pElements->push_back(e); }
263
264 inline void clearRegs ()
265 { _pElements->clear(); }
266
267 inline const T & altitude (const signed int x, const signed int y) const
268 { return ScalarFieldView::get(x, y).altitude; }
269 inline T & altitude (const signed int x, const signed int y)
270 { return ScalarFieldView::get(x, y).altitude; }
271
272 inline void operator += (const T & n)
273 { ScalarFieldView::operator += (MPDGVecType< T >(n, 0)); }
274 inline void operator -= (const T & n)
275 { ScalarFieldView::operator -= (MPDGVecType< T >(n, 0)); }
276
277 inline virtual mars::Range< MPDGVecType< T >, MPDGVecTypeNumerics< T > > range () const
278 { return rangeImpl (0, 0, ScalarFieldView::right - ScalarFieldView::left, ScalarFieldView::bottom - ScalarFieldView::top); }
279
280 inline void operator << (const ElementalFieldView< E, T > & copy)
281 {
282 _pElements->clear();
283 _pElements->insert(_pElements->end(), copy.beginElements(), copy.endElements());
284 ScalarFieldView::operator << (copy);
285 }
286 inline void operator >> (ElementalFieldView< E, T > & dest) const
287 { dest << *this; }
288
289 inline void operator >> (Offset & dest) const
290 { ScalarFieldView::operator >> (dest); }
291 inline void operator << (const Offset & src)
292 { ScalarFieldView::operator << (src); }
293 };
294
295 template< typename E, typename T >
296 ElementalFieldView < E, T > * ElementalFieldView< E, T >::createView (const unsigned short nLeft, const unsigned short nTop, const unsigned short nRight, const unsigned short nBottom)
297 { return ScalarFieldView::template createTypedView< ElementalFieldView< E, T > > (nLeft, nTop, nRight, nBottom, _pElements); }
298
299 template< typename E, typename T >
300 const ElementalFieldView < E, T > * ElementalFieldView< E, T >::createView (const unsigned short nLeft, const unsigned short nTop, const unsigned short nRight, const unsigned short nBottom) const
301 { return ScalarFieldView::template createTypedView< ElementalFieldView< E, T > > (nLeft, nTop, nRight, nBottom, _pElements); }
302
303 template <typename E, typename T> class VarriedMPDG;
304
305 template <typename E, typename T>
306 class ElementalField : public ElementalFieldView< E, T >
307 {
308 public:
309 using MemoryBlock = mars::MemoryBlock< MPDGVecType< T > >;
310 using ScalarFieldView = mars::ScalarFieldView< MPDGVecType< T >, MPDGVecTypeNumerics< T > >;
311 using VarriedMPDGType = VarriedMPDG< E, T >;
312 using ElementList = typename ElementalFieldView< E, T >::ElementList;
313
314 ElementalField (const unsigned short width, const unsigned short height, const mars::ScalarField< MPDGVecType< T > > & copy, const unsigned short x, const unsigned short y, const mars::GridType engt = mars::Normal)
315 : ElementalFieldView< E, T >(VarriedMPDGType::createHosted(width, height, engt))
316 { blitFrom (copy, x, y); }
317
318 ElementalField (const unsigned short width, const unsigned short height, const mars::GridType engt = mars::Normal)
319 : ElementalFieldView< E, T >(ElementalFieldView< E, T >::createHosted(width, height, engt))
320 { memset(this->data(), 0, this->block() -> bytesize); }
321 ElementalField (const ElementalFieldView< E, T > & copy)
322 : ElementalFieldView< E, T >(copy, new MemoryBlock (copy.getMemoryBlock()), new ElementList (*copy._pElements)) {}
323
324 virtual ~ElementalField()
325 { delete this->elements(); }
326
327 inline std::istream & operator << (std::istream & ins)
328 { return *this->block() << ins; }
329 inline std::ostream & operator >> (std::ostream & outs) const
330 { return *this->block() >> outs; }
331
332 inline void operator >> (typename ScalarFieldView::Offset & dest) const
333 { ElementalFieldView< E, T >::operator >> (dest); }
334 inline void operator << (const typename ScalarFieldView::Offset & src)
335 { ElementalFieldView< E, T >::operator << (src); }
336 };
337
338 template <typename E, typename T>
339 class VarriedMPDG : public mars::MidpointDisplacementGrid< MPDGVecType< T >, MPDGVecTypeNumerics< T > >, public ElementalFieldView< E, T >
340 {
341 private:
342 const enum StorageMode
343 {
344 Concrete,
345 Virtual
346 } _ensmStorageMode;
347
348 protected:
349 using MPDG = mars::MidpointDisplacementGrid< MPDGVecType< T >, MPDGVecTypeNumerics< T > >;
350 using Elems = ElementalFieldView< E, T >;
351
352 class SeedFunctor : public MPDG::PinkFn
353 {
354 private:
355 const unsigned short _maxidx;
356 float _base;
357
358 public:
359 inline SeedFunctor (unsigned short maxidx, const unsigned short nDim, const float fCoarseness)
360 : MPDG::PinkFn(nDim, fCoarseness), _maxidx(maxidx) {}
361
362 inline void iteration (const unsigned short nStride, const unsigned short c)
363 {
364 MPDG::PinkFn::iteration(nStride, c);
365 _base = this->computeRandomAmount(0) / 2;
366 }
367
368 inline MPDGVecType< T > operator () (int & state, const int x, const int y, const MPDGVecType< T > & a, const MPDGVecType< T > & b, const MPDGVecType< T > & c)
369 {
370 MPDGVecType< T > result;
371
372 result.mindex = mars::RAND(_maxidx);
373 result.altitude = static_cast< T > (this->applyFlux (_base));
374 return result;
375 }
376 inline MPDGVecType< T > operator () (int & state, const int x, const int y, const MPDGVecType< T > & a, const MPDGVecType< T > & b, const MPDGVecType< T > & c, const MPDGVecType< T > & d)
377 {
378 return operator() (state, x, y, a, b, c);
379 }
380 };
381
382 struct LocalFunctorState
383 {
384 T sumalt[3];
385 unsigned char ctalt[3];
386 MPDGVecType< T > result;
387 };
388
389 class LocalFunctor : public MPDG::template AbstractFunctor<LocalFunctorState>
390 {
391 public:
392 inline LocalFunctor (const unsigned short nDim, const float fCoarseness)
393 : MPDG::template AbstractFunctor<LocalFunctorState>(nDim, fCoarseness) {}
394
395 MPDGVecType< T > operator () (LocalFunctorState & state, const int x, const int y, const MPDGVecType< T > & a, const MPDGVecType< T > & b, const MPDGVecType< T > & c)
396 {
397 // Count cells matching 'a'
398 state.ctalt[0] = 0;
399 state.sumalt[0] = a.altitude;
400 if (a.mindex == b.mindex)
401 {
402 state.sumalt[0] += b.altitude;
403 ++state.ctalt[0];
404 }
405 if (a.mindex == c.mindex)
406 {
407 state.sumalt[0] += c.altitude;
408 ++state.ctalt[0];
409 }
410
411 // Count cells matching 'b'
412 state.ctalt[1] = 0;
413 state.sumalt[1] = b.altitude;
414 if (b.mindex == c.mindex)
415 {
416 state.sumalt[1] += c.altitude;
417 ++state.ctalt[1];
418 }
419
420 // Flip a coin to pick between a dominant alpha or auxiliary beta cell
421 const unsigned int pick = mars::RAND(3);
422
423 if (pick < 2)
424 state.result.altitude = this->applyFlux(state.sumalt[pick] / (state.ctalt[pick] + 1));
425 else
426 state.result.altitude = this->applyFlux(c.altitude);
427
428 switch (pick)
429 {
430 case 0:
431 state.result.mindex = a.mindex;
432 break;
433 case 1:
434 state.result.mindex = b.mindex;
435 break;
436 case 2:
437 state.result.mindex = c.mindex;
438 break;
439 }
440
441 return state.result;
442 }
443 MPDGVecType< T > operator () (LocalFunctorState & state, const int x, const int y, const MPDGVecType< T > & a, const MPDGVecType< T > & b, const MPDGVecType< T > & c, const MPDGVecType< T > & d)
444 {
445 // Count cells matching 'a'
446 state.ctalt[0] = 0;
447 state.sumalt[0] = a.altitude;
448 if (a.mindex == b.mindex)
449 {
450 state.sumalt[0] += b.altitude;
451 ++state.ctalt[0];
452 }
453 if (a.mindex == c.mindex)
454 {
455 state.sumalt[0] += c.altitude;
456 ++state.ctalt[0];
457 }
458 if (a.mindex == d.mindex)
459 {
460 state.sumalt[0] += d.altitude;
461 ++state.ctalt[0];
462 }
463
464 // Count cells matching 'b'
465 state.ctalt[1] = 0;
466 state.sumalt[1] = b.altitude;
467 if (b.mindex == c.mindex)
468 {
469 state.sumalt[1] += c.altitude;
470 ++state.ctalt[1];
471 }
472 if (b.mindex == d.mindex)
473 {
474 state.sumalt[1] += d.altitude;
475 ++state.ctalt[1];
476 }
477
478 // Count cells matching 'c'
479 state.ctalt[2] = 0;
480 state.sumalt[2] = c.altitude;
481 if (c.mindex == d.mindex)
482 {
483 state.sumalt[2] += d.altitude;
484 ++state.ctalt[2];
485 }
486
487 // Flip a coin to pick between a dominant alpha or auxiliary beta cell
488
489 const unsigned int pick = mars::RAND(4);
490
491 if (pick < 3)
492 state.result.altitude = this->applyFlux(state.sumalt[pick] / (state.ctalt[pick] + 1));
493 else
494 state.result.altitude = this->applyFlux(d.altitude);
495
496 switch (pick)
497 {
498 case 0:
499 state.result.mindex = a.mindex;
500 break;
501 case 1:
502 state.result.mindex = b.mindex;
503 break;
504 case 2:
505 state.result.mindex = c.mindex;
506 break;
507 case 3:
508 state.result.mindex = d.mindex;
509 break;
510 }
511
512 return state.result;
513 }
514 };
515
516 VarriedMPDG (const short nIterCount, ElementalFieldView< E, T > v, const StorageMode ensm)
517 : MPDG(nIterCount, v), ElementalFieldView<E, T>(v), _ensmStorageMode(ensm) {}
518
519 static VarriedMPDG * createHosted (const short nIterCount, const unsigned short nWidth, const unsigned short nHeight, const mars::GridType engt = mars::Normal)
520 { return new VarriedMPDG(nIterCount, ElementalFieldView< E, T >::createHosted(nWidth, nHeight, engt), Concrete); }
521
522 public:
523 using ScalarFieldView = typename mars::ScalarFieldView< MPDGVecType< T >, MPDGVecTypeNumerics< T > >;
524
525 virtual ~VarriedMPDG()
526 {
527 switch (_ensmStorageMode)
528 {
529 case Concrete: delete this->elements(); break;
530 }
531 }
532
533 inline static VarriedMPDG * createInstance (const unsigned short nMinWidth, const unsigned short nMinHeight, const mars::GridType engt)
534 {
535 assert(nMinHeight > 0 && nMinWidth > 0);
536 return createHosted (
537 MPDG::calcIterCount(std::min(nMinHeight, nMinWidth)),
538 MPDG::dimensionFor(nMinWidth, engt),
539 MPDG::dimensionFor(nMinHeight, engt),
540 engt
541 );
542 }
543 inline static VarriedMPDG * createInstance (Elems & view)
544 {
545 return new VarriedMPDG (
546 calcIterCount(std::min(view.width, view.height) - (view.gridtype == mars::Normal ? 1 : 0)),
547 view,
548 Virtual
549 );
550 }
551
552 inline virtual mars::Range< MPDGVecType< T >, MPDGVecTypeNumerics< T > > range () const
553 { return Elems::range(); }
554 inline virtual void clear()
555 { Elems::clear(); }
556 inline void stitch(const int nStitch)
557 { Elems::stitch(nStitch); }
558 void stitch(const int nStitch, const ScalarFieldView * pOther)
559 { Elems::stitch(nStitch, pOther); }
560 void stitchAll(const int nStitch)
561 { Elems::stitchAll(nStitch); }
562 inline void stitchAll(const int nStitch, const ScalarFieldView * pLeft, const ScalarFieldView * pTop, const ScalarFieldView * pRight, const ScalarFieldView * pBottom)
563 { Elems::stitchAll(nStitch, pLeft, pTop, pRight, pBottom); }
564
565 // TODO: Type hierarchy seems broken (bogus diamond pattern)
566 inline void operator -= (const T & n)
567 {
568 Elems::operator -= (n);
569 }
570
571 void seed (unsigned short nIterations, const float fCoarseNess, const signed int nFlux = -1)
572 {
573 SeedFunctor f (Elems::elementCount(), nFlux < 0 ? this->mindim : static_cast< unsigned short > (nFlux), fCoarseNess);
574
575 this->iterations(nIterations, f);
576 }
577
578 void run (const float fCoarseNess, const int nStitch = 0)
579 {
580 LocalFunctor f (this->mindim, fCoarseNess);
581
582 this->iterations (this->itercount - this->index(), f, nStitch);
583 }
584 };
585}
586
587#endif
Note: See TracBrowser for help on using the repository browser.