| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697 |
- #include "worldGeneratorSettings.h"
- #include <FastNoiseSIMD.h>
- #include <magic_enum.hpp>
- #include <glm/glm.hpp>
- void WorldGenerator::init()
- {
- continentalnessNoise = FastNoiseSIMD::NewFastNoiseSIMD();
- peaksValiesNoise = FastNoiseSIMD::NewFastNoiseSIMD();
- oceansAndTerasesNoise = FastNoiseSIMD::NewFastNoiseSIMD();
- stone3Dnoise = FastNoiseSIMD::NewFastNoiseSIMD();
- vegetationNoise = FastNoiseSIMD::NewFastNoiseSIMD();
- whiteNoise = FastNoiseSIMD::NewFastNoiseSIMD();
- whiteNoise2 = FastNoiseSIMD::NewFastNoiseSIMD();
- spagettiNoise = FastNoiseSIMD::NewFastNoiseSIMD();
- temperatureNoise = FastNoiseSIMD::NewFastNoiseSIMD();
- humidityNoise = FastNoiseSIMD::NewFastNoiseSIMD();
- WorldGeneratorSettings s;
- applySettings(s);
- }
- void WorldGenerator::clear()
- {
- delete continentalnessNoise;
- delete peaksValiesNoise;
- delete oceansAndTerasesNoise;
- delete stone3Dnoise;
- delete vegetationNoise;
- delete whiteNoise;
- delete whiteNoise2;
- delete spagettiNoise;
- }
- void WorldGenerator::applySettings(WorldGeneratorSettings &s)
- {
- whiteNoise->SetSeed(s.seed);
- whiteNoise->SetNoiseType(FastNoiseSIMD::NoiseType::WhiteNoise);
- whiteNoise2->SetSeed(s.seed + 1);
- whiteNoise2->SetNoiseType(FastNoiseSIMD::NoiseType::WhiteNoise);
- auto apply = [&](FastNoiseSIMD *noise, int seed, NoiseSetting &s)
- {
- noise->SetSeed(seed);
- noise->SetNoiseType((FastNoiseSIMD::NoiseType)s.type);
- noise->SetAxisScales(s.scale, 1, s.scale);
- noise->SetFrequency(s.frequency);
- noise->SetFractalOctaves(s.octaves);
- noise->SetPerturbFractalOctaves(s.perturbFractalOctaves);
- };
- apply(continentalnessNoise, s.seed + 2, s.continentalnessNoiseSettings);
- continentalSplines = s.continentalnessNoiseSettings.spline;
- continentalPower = s.continentalnessNoiseSettings.power;
- apply(stone3Dnoise, s.seed + 3, s.stone3Dnoise);
- stone3DnoiseSplines = s.stone3Dnoise.spline;
- stone3Dpower = s.stone3Dnoise.power;
- densityBias = s.densityBias;
- densityBiasPower = s.densityBiasPower;
- apply(spagettiNoise, s.seed + 4, s.spagettiNoise);
- spagettiNoiseSplines = s.spagettiNoise.spline;
- spagettiNoisePower = s.spagettiNoise.power;
- spagettiNoiseBias = s.spagettiBias;
- spagettiNoiseBiasPower = s.spagettiBiasPower;
- apply(peaksValiesNoise, s.seed + 5, s.peaksAndValies);
- peaksValiesSplines = s.peaksAndValies.spline;
- peaksValiesPower = s.peaksAndValies.power;
- peaksValiesContributionSplines = s.peaksAndValiesContributionSpline;
- apply(oceansAndTerasesNoise, s.seed + 6, s.oceansAndTerases);
- oceansAndTerasesSplines = s.oceansAndTerases.spline;
- oceansAndTerasesPower = s.oceansAndTerases.power;
- oceansAndTerasesContributionSplines = s.oceansAndTerasesContributionSpline;
- apply(vegetationNoise, s.seed + 7, s.vegetationNoise);
- vegetationPower = s.vegetationNoise.power;
- vegetationSplines = s.vegetationNoise.spline;
- apply(temperatureNoise, s.seed + 8, s.temperatureNoise);
- temperaturePower = s.temperatureNoise.power;
- temperatureSplines = s.temperatureNoise.spline;
- apply(humidityNoise, s.seed + 9, s.humidityNoise);
- humidityPower = s.humidityNoise.power;
- humiditySplines = s.humidityNoise.spline;
- }
- std::string WorldGeneratorSettings::saveSettings()
- {
- std::string rez;
- rez.reserve(500);
- rez += "seed: "; rez += std::to_string(seed); rez += ";\n";
- rez += "continentalnessNoise:\n";
- rez += continentalnessNoiseSettings.saveSettings(1);
- rez += "peaksAndValies:\n";
- rez += peaksAndValies.saveSettings(1);
- rez += "peaksAndValiesContributionSpline:\n";
- rez += peaksAndValiesContributionSpline.saveSettings(1);
- rez += "oceansAndTerases:\n";
- rez += oceansAndTerases.saveSettings(1);
- rez += "oceansAndTerasesContributionSpline:\n";
- rez += oceansAndTerasesContributionSpline.saveSettings(1);
- rez += "vegetationNoise:\n";
- rez += vegetationNoise.saveSettings(1);
- rez += "stonetDnoise:\n";
- rez += stone3Dnoise.saveSettings(1);
- rez += "humidityNoise:\n";
- rez += humidityNoise.saveSettings(1);
- rez += "temperatureNoise:\n";
- rez += temperatureNoise.saveSettings(1);
- rez += "spagettiNoise:\n";
- rez += spagettiNoise.saveSettings(1);
- rez += "spagettiBias: "; rez += std::to_string(spagettiBias); rez += ";\n";
- rez += "spagettiBiasPower: "; rez += std::to_string(spagettiBiasPower); rez += ";\n";
- rez += "densityBias: "; rez += std::to_string(densityBias); rez += ";\n";
- rez += "densityBiasPower: "; rez += std::to_string(densityBiasPower); rez += ";\n";
- return rez;
- }
- void WorldGeneratorSettings::sanitize()
- {
- continentalnessNoiseSettings.sanitize();
- peaksAndValies.sanitize();
- oceansAndTerases.sanitize();
- stone3Dnoise.sanitize();
- humidityNoise.sanitize();
- temperatureNoise.sanitize();
- vegetationNoise.sanitize();
-
- peaksAndValiesContributionSpline.sanitize();
- oceansAndTerasesContributionSpline.sanitize();
- densityBias = glm::clamp(densityBias, 0.f, 1.f);
- densityBiasPower = glm::clamp(densityBiasPower, 0.1f, 10.f);
- spagettiNoise.sanitize();
- spagettiBias = glm::clamp(spagettiBias, 0.f, 10.f);
- spagettiBiasPower = glm::clamp(spagettiBiasPower, 0.1f, 10.f);
- }
- std::string NoiseSetting::saveSettings(int tabs, bool saveSpline)
- {
- std::string rez;
- rez.reserve(200);
- auto addTabs = [&]() { for (int i = 0; i < tabs; i++) { rez += '\t'; } };
- addTabs();
- rez += "{\n";
- addTabs();
- rez += "scale: "; rez += std::to_string(scale); rez += ";\n"; addTabs();
- rez += "type: "; rez += magic_enum::enum_name((FastNoiseSIMD::NoiseType)type); rez += ";\n"; addTabs();
- rez += "frequency: "; rez += std::to_string(frequency); rez += ";\n"; addTabs();
- rez += "octaves: "; rez += std::to_string(octaves); rez += ";\n"; addTabs();
- rez += "perturbFractalOctaves: "; rez += std::to_string(perturbFractalOctaves); rez += ";\n"; addTabs();
- rez += "power: "; rez += std::to_string(power); rez += ";\n";
- if (saveSpline)
- {
- addTabs();
- rez += "spline:\n";
- rez += spline.saveSettings(tabs + 1);
- }
-
- addTabs();
- rez += "}\n";
- return rez;
- }
- void NoiseSetting::sanitize()
- {
- spline.sanitize();
- scale = glm::clamp(scale, 0.001f, 100.f);
- type = glm::clamp(type, (int)FastNoiseSIMD::Value, (int)FastNoiseSIMD::CubicFractal);
- frequency = glm::clamp(frequency, 0.001f, 100.f);
- octaves = glm::clamp(octaves, 0, 8);
- perturbFractalOctaves = glm::clamp(perturbFractalOctaves, 0, 8);
- power = glm::clamp(power, 0.1f, 10.f);
- //todo the rest
- }
- bool WorldGeneratorSettings::loadSettings(const char *data)
- {
- *this = {};
- enum
- {
- TokenNone,
- TokenString,
- TokenNumber,
- TokenSymbol,
- };
- struct Token
- {
- int type = 0;
- std::string s = "";
- char symbol = 0;
- double number = 0;
- bool operator==(Token &other)
- {
- return type == other.type &&
- s == other.s &&
- symbol == other.symbol &&
- number == other.number;
- }
- };
- std::vector<Token> tokens;
- #pragma region tokenize
- {
- int lastPos = 0;
- for (int i = 0; data[i] != '\0';)
- {
- auto checkSymbol = [&]() -> bool
- {
- if (data[i] == ';' || data[i] == ':' || data[i] == '{' || data[i] == '}' || data[i] == ',')
- {
- tokens.push_back({Token{TokenSymbol, "", data[i], 0}});
- i++;
- return true;
- }
- return 0;
- };
- auto checkNumber = [&]() -> bool
- {
- if (std::isdigit(data[i]))
- {
- Token t;
- t.type = TokenNumber;
- t.s += data[i];
- i++;
- for (; data[i] != '\0'; i++)
- {
- if (std::isdigit(data[i]) || data[i] == '.')
- {
- t.s += data[i];
- }
- else
- {
- break;
- }
- }
- t.number = std::stod(t.s); //todo replace with something that reports errors
- if (!t.s.empty()) { tokens.push_back(t); }
- return true;
- }
- return 0;
- };
- auto consumeWhiteSpaces = [&]()
- {
- for (; data[i] != '\0'; i++)
- {
- if (data[i] != '\n' && data[i] != '\v' && data[i] != '\t' && data[i] != ' ' && data[i] != '\r')
- {
- break;
- }
- }
- };
- auto addString = [&]()
- {
- Token t;
- t.type = TokenString;
- for (; data[i] != '\0'; i++)
- {
- if (isalpha(data[i]))
- {
- t.s += data[i];
- }
- else
- {
- break;
- }
- }
- if (!t.s.empty()) { tokens.push_back(t); }
- };
- consumeWhiteSpaces();
- if (data[i] == '\0') { break; }
- if (checkSymbol())continue;
- if (checkNumber())continue;
- addString();
- if (lastPos == i)
- {
- return 0;
- }
- else
- {
- lastPos = i;
- }
- }
- }
- #pragma endregion
- #pragma region parse
- {
- for (int i = 0; i < tokens.size();)
- {
- auto isString = [&]() -> bool
- {
- return tokens[i].type == TokenString;
- };
- auto consume = [&](Token t) -> bool
- {
- if (i >= tokens.size()) { return false; }
- if (tokens[i] == t)
- {
- i++;
- return true;
- }
- else
- {
- return false;
- }
- };
-
- auto isEof = [&]() { return i >= tokens.size(); };
-
- auto isNumber = [&]()
- {
- return (tokens[i].type == TokenNumber);
- };
- auto consumeNumber = [&]() -> double
- {
- if (tokens[i].type == TokenNumber)
- {
- i++;
- return tokens[i-1].number;
- };
- assert(0);
- return 0;
- };
- auto consumeSpline = [&](Spline &spline) -> bool
- {
- spline.size = 0;
- if (!consume(Token{TokenSymbol, "", '{', 0})) { return 0; }
- while (!consume(Token{TokenSymbol, "", '}', 0}))
- {
- if (isEof()) { return 0; }
- float nrA = 0;
- float nrB = 0;
- if (!isNumber()) { return 0; }
- nrA = consumeNumber();
- if (!consume(Token{TokenSymbol, "", ',', 0})) { return 0; }
- if (!isNumber()) { return 0; }
- nrB = consumeNumber();
- if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
- if (spline.size >= MAX_SPLINES_COUNT)
- {
- return 0;
- }
- spline.points[spline.size] = glm::vec2(nrA, nrB);
- spline.size++;
- }
- return true;
- };
- auto consumeNoise = [&](NoiseSetting &settings) -> bool
- {
- if (!consume(Token{TokenSymbol, "", '{', 0})) { return 0; }
- while (!consume(Token{TokenSymbol, "", '}', 0}))
- {
- if (isEof()) { return 0; }
- if (isString())
- {
- auto s = tokens[i].s; //todo to lower
- i++;
- if (s == "scale")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!isNumber()) { return 0; }
- settings.scale = consumeNumber();
- if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
- }else if (s == "frequency")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!isNumber()) { return 0; }
- settings.frequency = consumeNumber();
- if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
- }
- else if (s == "octaves")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!isNumber()) { return 0; }
- settings.octaves = consumeNumber();
- if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
- }
- else if (s == "perturbFractalOctaves")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!isNumber()) { return 0; }
- settings.perturbFractalOctaves = consumeNumber();
- if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
- }
- else if (s == "power")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!isNumber()) { return 0; }
- settings.power = consumeNumber();
- if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
- }
- else if (s == "type")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
-
- if (!isString()) { return 0; }
-
- auto s = tokens[i].s; //todo to lower
- i++;
- settings.type = -1;
- const char *types[] = {
- "Value", "ValueFractal", "Perlin", "PerlinFractal", "Simplex",
- "SimplexFractal", "WhiteNoise", "Cellular", "Cubic", "CubicFractal"};
- for (int t = 0; t < sizeof(types) / sizeof(types[0]); t++)
- {
- if (s == types[t])
- {
- settings.type = t;
- break;
- }
- }
- if (settings.type < 0) { return 0; }
-
- if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
- }
- else if (s == "spline")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!consumeSpline(settings.spline)) { return 0; }
- }
- else
- {
- return 0;
- }
-
- }
- else if (consume(Token{TokenSymbol, "", ';', 0}))
- {
- }
- else
- {
- return 0;
- }
- }
- return true;
- };
- //if (isEof()) { break; }
- if (isString())
- {
- auto s = tokens[i].s; //todo to lower
- i++;
- if (s == "seed")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!isNumber()) { return 0; }
- seed = consumeNumber();
- if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
- }else if (s == "densityBias")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!isNumber()) { return 0; }
- densityBias = consumeNumber();
- if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
- }else if (s == "densityBiasPower")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!isNumber()) { return 0; }
- densityBiasPower = consumeNumber();
- if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
- }
- else if (s == "continentalnessNoise")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!consumeNoise(continentalnessNoiseSettings))
- {
- return 0;
- }
- }
- else if (s == "vegetationNoise")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!consumeNoise(vegetationNoise))
- {
- return 0;
- }
- }
- else if (s == "humidityNoise")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!consumeNoise(humidityNoise))
- {
- return 0;
- }
- }
- else if (s == "temperatureNoise")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!consumeNoise(temperatureNoise))
- {
- return 0;
- }
- }
- else if (s == "peaksAndValies")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!consumeNoise(peaksAndValies))
- {
- return 0;
- }
- }
- else if (s == "oceansAndTerases")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!consumeNoise(oceansAndTerases))
- {
- return 0;
- }
- }
- else if (s == "stonetDnoise")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!consumeNoise(stone3Dnoise))
- {
- return 0;
- }
- }
- else if (s == "spagettiNoise")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!consumeNoise(spagettiNoise))
- {
- return 0;
- }
- }
- else if (s == "spagettiBias")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!isNumber()) { return 0; }
- spagettiBias = consumeNumber();
- if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
- }
- else if (s == "spagettiBiasPower")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!isNumber()) { return 0; }
- spagettiBiasPower = consumeNumber();
- if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
- }
- else if (s == "peaksAndValiesContributionSpline")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!consumeSpline(peaksAndValiesContributionSpline))
- {
- return 0;
- }
- }
- else if (s == "oceansAndTerasesContributionSpline")
- {
- if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
- if (isEof()) { return 0; }
- if (!consumeSpline(oceansAndTerasesContributionSpline))
- {
- return 0;
- }
- }
- else
- {
- return 0;
- }
- }
- else if (consume(Token{TokenSymbol, "", ';', 0}))
- {
- }else
- {
- return 0;
- }
- }
- }
- #pragma endregion
- sanitize();
- return true;
- }
|