source: Revenant/geoworld/include/geometry.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: 5.0 KB
Line 
1#pragma once
2
3#include "sphpack.h"
4#include "mars_geometry.h"
5#include "mars_ptr.h"
6#include "mars_splines.h"
7#include "mars_util.h"
8
9namespace geoworld
10{
11 template < typename T >
12 class SpherePackFactory
13 {
14 public:
15 typedef typename RandomSpherePack<T>::VECTOR VECTOR;
16 typedef mars::ptr< RandomSpherePack <T> > PackPtr;
17
18 private:
19 const mars::RangeX <float> _sizeflux;
20 const mars::RangeX <unsigned short> _kidflux, _viter;
21 const T _minimum, _maxtier, _limit;
22 const float _verratic, _fminimum, _fpihalf;
23
24 class VeinGuide : public mars::BasicGuide <VECTOR, T>
25 {
26 private:
27 inline VECTOR randomV (const T delta) const
28 {
29 using namespace mars;
30 return vector3D <T> (
31 RAND(delta) - delta / 2,
32 RAND(delta) - delta / 2,
33 RAND(delta) - delta / 2
34 );
35 }
36
37 public:
38 typedef mars::BasicGuide <VECTOR, T> super;
39
40 inline VeinGuide (const typename super::Point & a, const typename super::Point & b)
41 : super::BasicGuide(a, b) {}
42
43 void subdivide (const float factor)
44 {
45 typename super::PointList::const_iterator itFollow, itLeading;
46
47 itLeading = super::begin();
48 itFollow = itLeading++;
49
50 while (itLeading != super::end())
51 {
52 const VECTOR g = this->grad(itFollow);
53 const VECTOR p2 = *itFollow + g / 2 + randomV(static_cast< T > (static_cast< float > (MAG(g)) * factor));
54
55 super::_points.insert(itLeading, p2);
56
57 itFollow = itLeading++;
58 }
59 }
60 };
61
62 public:
63 inline SpherePackFactory (
64 const T limit, // Smallest-visible sphere radius before descendant generation ceases
65 const T minimum, // Absolute smallest sphere radius, any generated spheres with radii below this value are discarded
66 const T maxtier, // The maximum number depth-iterations (as opposed to breadth), this also affects the level of detail
67 const mars::RangeX <float> & sizeflux, // Flux of size of spheres at starting tier
68 const mars::RangeX <unsigned short> & kidflux, // Flux of number of breadth-iterations (as opposed to depth)
69 const mars::RangeX <unsigned short> & viter, // Range of allowed number of vein-subdivision iterations (0 = perfectly straight vein, 2^N -> INF = hopelessly crooked)
70 const float verratic // Amount of angular erratic placement of spheres in a vein
71 )
72 : _sizeflux(sizeflux), _kidflux(kidflux), _limit(limit), _minimum(minimum), _fminimum(static_cast< float > (minimum)), _maxtier(maxtier), _viter(viter), _verratic(verratic), _fpihalf(static_cast< float > (mars::PI / 2)) {}
73
74 PackPtr createLaccolith (const VECTOR & at, const float scale, const float tail) const
75 {
76 using namespace mars;
77
78 PackPtr pPack = new RandomSpherePack<T> (_limit, _minimum, _maxtier, _sizeflux, _kidflux);
79 float size = scale * tail;
80
81 pPack->spawn(at, static_cast< T > (scale));
82 if (size > _fminimum)
83 {
84 pPack->spawn(_fpihalf, _fpihalf, static_cast< T > (size));
85 size *= tail;
86
87 if (size > _fminimum)
88 pPack->spawn(_fpihalf, _fpihalf, static_cast< T > (size));
89 }
90
91 pPack->generateDescendants();
92
93 return pPack;
94 }
95
96 PackPtr createCluster (const VECTOR & at, const float scale) const
97 {
98 using namespace mars;
99
100 PackPtr pPack = new RandomSpherePack<T> (_limit, _minimum, _maxtier, _sizeflux, _kidflux);
101
102 pPack->spawn(at, static_cast< T > (scale));
103 pPack->generateDescendants();
104
105 return pPack;
106 }
107
108 PackPtr createVein (const VECTOR & a, const VECTOR & b, const float scale, const float deviation) const
109 {
110 using namespace mars;
111
112 VeinGuide guide (a, b);
113 const unsigned short iterations = _viter.next();
114
115 for (unsigned short c = 0; c < iterations; ++c)
116 guide.subdivide(deviation);
117
118 PackPtr pPack = new RandomSpherePack<T> (_limit, _minimum, _maxtier, _sizeflux, _kidflux);
119
120 typename RandomSpherePack< T >::Sphere region = pPack->createEmptySphere();
121 typename VeinGuide::SegmentType i = guide.begin(), ip;
122 SphericalCoords< T > spc = guide.grad (i);
123 const float fSQScale = SQ(scale);
124 const RangeX <float> rrarc(-_fpihalf * _verratic, _fpihalf * _verratic, 0.02f);
125
126 region = pPack->spawn(a, static_cast< T > (scale));
127 while (MAGSQ(guide.back() - region.p) > fSQScale)
128 {
129 ip = guide.nearestPoint(i, region.p);
130 spc = guide.tail(ip) - region.p;
131 region = pPack->spawn(spc.zenith + rrarc.next(), spc.azimuth + rrarc.next(), static_cast< T > (scale));
132 i = ip;
133 }
134
135 pPack->generateDescendants();
136
137 return pPack;
138 }
139
140 template< typename SB >
141 PackPtr createSpline (const mars::Spline< SB > & spline, const float scale, const float deviation) const
142 {
143 using namespace mars;
144
145 typedef typename mars::Spline< SB >::real real;
146
147 PackPtr pPack = new RandomSpherePack<T> (_limit, _minimum, _maxtier, _sizeflux, _kidflux);
148
149 for (unsigned int c = 0; c < spline.segCount(); ++c)
150 {
151 const real
152 fLen = spline.len(c);
153 const unsigned int
154 nCount = static_cast< unsigned int > (fLen / scale * 2);
155
156 for (unsigned int i = 0; i < nCount; ++i)
157 pPack->spawn(spline.compute(c, static_cast< real > (i) / static_cast< real > (nCount)), static_cast< T > (scale));
158 }
159
160 pPack->generateDescendants();
161
162 return pPack;
163 }
164 };
165}
Note: See TracBrowser for help on using the repository browser.