source: Revenant/geoworld/src/oregen.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: 10.2 KB
Line 
1#include "oregen.h"
2
3#include <iterator>
4#include <mars_log.h>
5
6namespace geoworld
7{
8 const float DepositSynthesizer::FREQUENCY_MULTIPLIER = 1000;
9
10 DepositSynthesizer::DepositSynthesizer(const MineralsDB * pMinDB, const DepositSynthesizerSettings & settings, const WorldUnit nWidth, const WorldUnit nHeight, const WorldUnit nDepth, const unsigned short nDEMLOD)
11 : _pMinDB(pMinDB), _nAbsWidth(nWidth), _nAbsHeight(nHeight), _stratum(settings.layers.count, nWidth, nHeight, nDepth, nDEMLOD, mars::Wrap), _settings(settings),
12 _otOre(std::max(nWidth, nHeight), 4),
13 _factBubbleGum(
14 settings.minerals.spherepack.limit,
15 settings.minerals.spherepack.minimum,
16 settings.minerals.spherepack.maxtier,
17 settings.minerals.spherepack.sizeflux,
18 settings.minerals.spherepack.kidflux,
19 settings.minerals.deposit.vein.detail,
20 settings.minerals.deposit.vein.erratic
21 ),
22 _pbsAbundance(settings.minerals.abundance.curve),
23 _pbsDepositSize(settings.minerals.deposit.curve),
24 _pbsThickness(settings.layers.count, settings.layers.thickness.curve, settings.layers.thickness.scale)
25 {
26 assert(((_nAbsWidth - 1) & _nAbsWidth) == 0 && ((_nAbsHeight - 1) & _nAbsHeight) == 0); // Must be a power of 2
27 }
28
29 DepositSynthesizer::~DepositSynthesizer()
30 {
31 }
32
33 DepositSynthesizerSettings DepositSynthesizer::loadSettings( IDepositSynthConfigReader & cfgreader )
34 {
35 DepositSynthesizerSettings settings;
36 cfgreader.load(settings);
37 return settings;
38 }
39
40 Silica DepositSynthesizer::selectSilica( const float fRatio )
41 {
42 if (fRatio < 0.16f)
43 return Silica_NA;
44 else if (fRatio < 0.17f * 2.0f)
45 return Silica_UltraMafic;
46 else if (fRatio < 0.17f * 3.0f)
47 return Silica_Mafic;
48 else if (fRatio < 0.17f * 4.0f)
49 return Silica_Intermediate;
50 else if (fRatio < 0.17f * 5.0f)
51 return Silica_InterFelsic;
52 else
53 return Silica_Felsic;
54 }
55
56 Origin DepositSynthesizer::selectOrigin( const float fRatio )
57 {
58 if (fRatio < 0.2f)
59 return Origin_NA;
60 else if (fRatio < 0.2f * 2.0f)
61 return Origin_Plutonic;
62 else if (fRatio < 0.2f * 3.0f)
63 return Origin_Subvolcanic;
64 else if (fRatio < 0.2f * 4.0f)
65 return Origin_Volcanic;
66 else
67 return Origin_Meteoritic;
68 }
69
70 void DepositSynthesizer::generateStrata()
71 {
72 using namespace mars;
73 typedef std::vector< MineralsDB::ClassesSet::value_type > ClassList;
74
75 ClassList lstSilicaClassSelection;
76
77 for (unsigned char s = _settings.layers.silica.minimum; s <= _settings.layers.silica.maximum; ++s)
78 {
79 MineralsDB::ClassesSetFacade facade = _pMinDB->getClassesBySilica(static_cast< Silica > (s));
80
81 lstSilicaClassSelection.insert(lstSilicaClassSelection.end(), facade.begin(), facade.end());
82 }
83
84 ptr< GeoStratumMPDG > pVMPDG =
85 GeoStratumMPDG::createInstance(
86 static_cast< unsigned short > (_nAbsWidth >> _stratum.lod),
87 static_cast< unsigned short > (_nAbsHeight >> _stratum.lod),
88 mars::Wrap
89 );
90
91 for (size_t c = 0; c < _stratum.size(); ++c)
92 {
93 const size_t nClassCount = _settings.layers.classes.next();
94 for (size_t j = 0; j < nClassCount; ++j)
95 pVMPDG->reg(lstSilicaClassSelection[mars::RAND(lstSilicaClassSelection.size())]);
96
97 pVMPDG->seed(1, _settings.layers.coarseness, static_cast< signed int > (_settings.layers.thickness.base + _pbsThickness[c]));
98 pVMPDG->run(_settings.layers.coarseness);
99
100 const GeoStratumMPDG::Precision
101 min = pVMPDG->range().minimum;
102
103 *pVMPDG -= min.altitude - GeoStratumField::ScalarTraits::step().altitude;
104
105 _stratum[c] << *pVMPDG;
106
107 assert(_stratum[c].range().minimum.altitude >= 0);
108
109 pVMPDG->reset();
110 pVMPDG->clearRegs();
111 }
112
113 // TODO: Automate
114 _stratum.updateIndexMap();
115 }
116
117 void DepositSynthesizer::generateMinerals(const unsigned int nPass)
118 {
119 using namespace mars;
120 typedef std::set< ptr< MineralDef > > MineralSet;
121 const mars::RangeX< WorldUnit > rngStrata = _stratum.getRange();
122
123 const size_t
124 nMineralCount = static_cast< size_t > (
125 _settings.minerals.frequency *
126 static_cast< float > (_nAbsWidth) / FREQUENCY_MULTIPLIER *
127 static_cast< float > (_nAbsHeight) / FREQUENCY_MULTIPLIER *
128 static_cast< float > (rngStrata.delta) / FREQUENCY_MULTIPLIER
129 );
130
131 size_t c = 0;
132 MineralDepositList lstAssociations, lstProtoliths;
133 MineralSet setSelections;
134
135 while (c < nMineralCount)
136 {
137 OctTreeOreInstance::VECTOR ptChosenSpot (RAND(_nAbsWidth), RAND(_nAbsHeight), rngStrata.next());
138 const size_t nNestCount = _settings.minerals.deposit.nesting.next();
139
140 for (size_t j = 0; j <= nNestCount; ++j, ++c) // j <= x: Nesting value is number of nested hosted minerals not number of minerals total
141 {
142 const MinClassPtr pEnvironment = _stratum.getDominantElementVN3(ptChosenSpot.x, ptChosenSpot.y, ptChosenSpot.z);
143
144 for (
145 OctTreeOreInstance::const_EntityRadialIterator
146 i = const_cast< const OctTreeOreInstance & > (_otOre).contents(
147 OctTreeOreInstance::MyRadialRegion(
148 ptChosenSpot,
149 _settings.minerals.neighborhood.next()
150 )
151 );
152 i;
153 ++i
154 )
155 {
156 if (i->pass < nPass)
157 {
158 MineralsDB::PetrogenyMineralSetFacade facminIncubated = _pMinDB->getIncubatedMinerals(i->deposit.mineral);
159
160 lstProtoliths.push_back(i->deposit);
161 for (MineralsDB::PetrogenyMineralSet::const_iterator k = facminIncubated.begin(); k != facminIncubated.end(); ++k)
162 setSelections.insert(k->mineral);
163 }
164 else
165 {
166 MineralsDB::PetrogenyMineralSetFacade facminAssociated = _pMinDB->getAssociatedMinerals(i->deposit.mineral);
167
168 lstAssociations.push_back(i->deposit);
169 for (MineralsDB::PetrogenyMineralSet::const_iterator k = facminAssociated.begin(); k != facminAssociated.end(); ++k)
170 setSelections.insert(k->mineral);
171 }
172 }
173
174 MineralsDB::PetrogenyClassSetFacade facminEnvironment = _pMinDB->getMineralsByEnvironment(pEnvironment);
175
176 for (MineralsDB::PetrogenyClassSet::const_iterator k = facminEnvironment.begin(); k != facminEnvironment.end(); ++k)
177 setSelections.insert(k->mineral);
178
179 if (!setSelections.empty())
180 {
181 const size_t nSelection = RAND(setSelections.size());
182 MineralSet::const_iterator iMin = setSelections.begin();
183 std::vector< MineralDef::GenesisList::const_iterator > lstGeneses;
184 MineralDeposit depHost;
185
186 std::advance(iMin, nSelection);
187 (*iMin)->intersectGeneses(lstGeneses, lstAssociations, lstProtoliths, depHost, pEnvironment);
188 if (!lstGeneses.empty())
189 {
190 const size_t nGenSelection = RAND(lstGeneses.size());
191 const PetrogenyDef & petrogeny = *lstGeneses[nGenSelection];
192 const std::pair< BubbleGumFactory::PackPtr, DepositDistribution > pairDeposit = depositMineral(petrogeny, ptChosenSpot, *iMin, nPass);
193 const BubbleGumFactory::PackPtr & pSpherePack = pairDeposit.first;
194 const DepositDistribution & enddDepositDistrib = pairDeposit.second;
195 const size_t nSphereCount = pSpherePack->count();
196 const size_t nSelectedHostSphere = RAND(nSphereCount);
197
198 size_t k = 0;
199 for (BubbleGumFactory::PackPtr::Type::const_iterator iPack = pSpherePack->iterate(); iPack; ++iPack, ++k)
200 {
201 if (k == nSelectedHostSphere)
202 {
203 ptChosenSpot = iPack->p;
204 depHost = MineralDeposit(*iMin, enddDepositDistrib);
205 break;
206 }
207 }
208 }
209 }
210 }
211 lstAssociations.clear();
212 lstProtoliths.clear();
213 setSelections.clear();
214 }
215 }
216
217 std::pair< DepositSynthesizer::BubbleGumFactory::PackPtr, DepositDistribution >
218 DepositSynthesizer::depositMineral( const PetrogenyDef & petrogeny, const OctTreeOreInstance::VECTOR & ptChosenSpot, const mars::ptr< MineralDef > & pMin, const size_t nPass )
219 {
220 using namespace mars;
221
222 const PointScale enpsAbundance = _pbsAbundance(RANDf(1.0f));
223 const float fDepositSize = _pbsDepositSize[petrogeny.size] * _settings.minerals.deposit.base;
224 const size_t nSelDistOff = RAND(petrogeny.distributions.count());
225 size_t c = 0;
226 for (size_t i = 0; c < petrogeny.distributions.size() && i < nSelDistOff; petrogeny.distributions[c] && ++i, ++c);
227 const DepositDistribution enddDistrib = static_cast< DepositDistribution > (c);
228
229 BubbleGumFactory::PackPtr pSpherePack;
230
231 switch (enddDistrib)
232 {
233 case Dist_Cluster:
234 pSpherePack = _factBubbleGum.createCluster(ptChosenSpot, fDepositSize);
235 break;
236 case Dist_Vein:
237 {
238 const OctTreeOreInstance::VECTOR::Precision
239 nScale = static_cast< OctTreeOreInstance::VECTOR::Precision > (fDepositSize),
240 nHalfScale = nScale / 2;
241
242 OctTreeOreInstance::VECTOR off (RAND(nScale) - nHalfScale, RAND(nScale) - nHalfScale, RAND(nScale) - nHalfScale);
243
244 off *= nHalfScale;
245 off /= MAG(off);
246 pSpherePack = _factBubbleGum.createVein(ptChosenSpot - off, ptChosenSpot + off, fDepositSize, _settings.minerals.deposit.vein.deviation.next());
247 }
248 break;
249 case Dist_Dike:
250 {
251 const OctTreeOreInstance::VECTOR::Precision
252 nScale = static_cast< OctTreeOreInstance::VECTOR::Precision > (fDepositSize),
253 nHalfScale = nScale / 2;
254
255 OctTreeOreInstance::VECTOR off (
256 (RAND(nScale) - nHalfScale) / static_cast< OctTreeOreInstance::VECTOR::Precision > (1.0f / (1.0f - _settings.minerals.deposit.dike.orthogonality.next())),
257 RAND(nScale) - nHalfScale,
258 (RAND(nScale) - nHalfScale) / static_cast< OctTreeOreInstance::VECTOR::Precision > (1.0f / (1.0f - _settings.minerals.deposit.dike.orthogonality.next()))
259 );
260
261 off *= nHalfScale;
262 off /= MAG(off);
263 pSpherePack = _factBubbleGum.createVein(ptChosenSpot - off, ptChosenSpot + off, fDepositSize, _settings.minerals.deposit.dike.deviation.next());
264 }
265 break;
266 case Dist_Laccolith:
267 pSpherePack = _factBubbleGum.createLaccolith(ptChosenSpot, fDepositSize, _settings.minerals.deposit.laccolith.tail.next());
268 break;
269 case Dist_Sill:
270 case Dist_Layer:
271 LOG(mars::Log::Warn) << "Distribution of type sill/layer not implemented, mineral petrogeny dropped";
272 break;
273 }
274
275 if (pSpherePack != NULL)
276 pSpherePack->store(_otOre, ptr< OreInstance > (new OreInstance(pMin, nPass, enddDistrib)));
277
278 return std::pair< BubbleGumFactory::PackPtr, DepositDistribution > (pSpherePack, enddDistrib);
279 }
280
281 void DepositSynthesizer::operator>>( FileSource::MineralMap & dest ) const
282 {
283 for (OctTreeOreInstance::const_EntityAllIterator i = const_cast< const OctTreeOreInstance & > (_otOre).contents(); i; ++i)
284 dest.add(i->deposit.mineral, FileSource::MineralMap::QuadTreeSpherePacks::MyCylindricalRegion (i.region()));
285 }
286}
Note: See TracBrowser for help on using the repository browser.