worldGeneratorSettings.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. #include "worldGeneratorSettings.h"
  2. #include <FastNoiseSIMD.h>
  3. #include <magic_enum.hpp>
  4. #include <glm/glm.hpp>
  5. void WorldGenerator::init()
  6. {
  7. continentalnessNoise = FastNoiseSIMD::NewFastNoiseSIMD();
  8. peaksValiesNoise = FastNoiseSIMD::NewFastNoiseSIMD();
  9. oceansAndTerasesNoise = FastNoiseSIMD::NewFastNoiseSIMD();
  10. stone3Dnoise = FastNoiseSIMD::NewFastNoiseSIMD();
  11. vegetationNoise = FastNoiseSIMD::NewFastNoiseSIMD();
  12. whiteNoise = FastNoiseSIMD::NewFastNoiseSIMD();
  13. whiteNoise2 = FastNoiseSIMD::NewFastNoiseSIMD();
  14. spagettiNoise = FastNoiseSIMD::NewFastNoiseSIMD();
  15. temperatureNoise = FastNoiseSIMD::NewFastNoiseSIMD();
  16. humidityNoise = FastNoiseSIMD::NewFastNoiseSIMD();
  17. WorldGeneratorSettings s;
  18. applySettings(s);
  19. }
  20. void WorldGenerator::clear()
  21. {
  22. delete continentalnessNoise;
  23. delete peaksValiesNoise;
  24. delete oceansAndTerasesNoise;
  25. delete stone3Dnoise;
  26. delete vegetationNoise;
  27. delete whiteNoise;
  28. delete whiteNoise2;
  29. delete spagettiNoise;
  30. }
  31. void WorldGenerator::applySettings(WorldGeneratorSettings &s)
  32. {
  33. whiteNoise->SetSeed(s.seed);
  34. whiteNoise->SetNoiseType(FastNoiseSIMD::NoiseType::WhiteNoise);
  35. whiteNoise2->SetSeed(s.seed + 1);
  36. whiteNoise2->SetNoiseType(FastNoiseSIMD::NoiseType::WhiteNoise);
  37. auto apply = [&](FastNoiseSIMD *noise, int seed, NoiseSetting &s)
  38. {
  39. noise->SetSeed(seed);
  40. noise->SetNoiseType((FastNoiseSIMD::NoiseType)s.type);
  41. noise->SetAxisScales(s.scale, 1, s.scale);
  42. noise->SetFrequency(s.frequency);
  43. noise->SetFractalOctaves(s.octaves);
  44. noise->SetPerturbFractalOctaves(s.perturbFractalOctaves);
  45. };
  46. apply(continentalnessNoise, s.seed + 2, s.continentalnessNoiseSettings);
  47. continentalSplines = s.continentalnessNoiseSettings.spline;
  48. continentalPower = s.continentalnessNoiseSettings.power;
  49. apply(stone3Dnoise, s.seed + 3, s.stone3Dnoise);
  50. stone3DnoiseSplines = s.stone3Dnoise.spline;
  51. stone3Dpower = s.stone3Dnoise.power;
  52. densityBias = s.densityBias;
  53. densityBiasPower = s.densityBiasPower;
  54. apply(spagettiNoise, s.seed + 4, s.spagettiNoise);
  55. spagettiNoiseSplines = s.spagettiNoise.spline;
  56. spagettiNoisePower = s.spagettiNoise.power;
  57. spagettiNoiseBias = s.spagettiBias;
  58. spagettiNoiseBiasPower = s.spagettiBiasPower;
  59. apply(peaksValiesNoise, s.seed + 5, s.peaksAndValies);
  60. peaksValiesSplines = s.peaksAndValies.spline;
  61. peaksValiesPower = s.peaksAndValies.power;
  62. peaksValiesContributionSplines = s.peaksAndValiesContributionSpline;
  63. apply(oceansAndTerasesNoise, s.seed + 6, s.oceansAndTerases);
  64. oceansAndTerasesSplines = s.oceansAndTerases.spline;
  65. oceansAndTerasesPower = s.oceansAndTerases.power;
  66. oceansAndTerasesContributionSplines = s.oceansAndTerasesContributionSpline;
  67. apply(vegetationNoise, s.seed + 7, s.vegetationNoise);
  68. vegetationPower = s.vegetationNoise.power;
  69. vegetationSplines = s.vegetationNoise.spline;
  70. apply(temperatureNoise, s.seed + 8, s.temperatureNoise);
  71. temperaturePower = s.temperatureNoise.power;
  72. temperatureSplines = s.temperatureNoise.spline;
  73. apply(humidityNoise, s.seed + 9, s.humidityNoise);
  74. humidityPower = s.humidityNoise.power;
  75. humiditySplines = s.humidityNoise.spline;
  76. }
  77. std::string WorldGeneratorSettings::saveSettings()
  78. {
  79. std::string rez;
  80. rez.reserve(500);
  81. rez += "seed: "; rez += std::to_string(seed); rez += ";\n";
  82. rez += "continentalnessNoise:\n";
  83. rez += continentalnessNoiseSettings.saveSettings(1);
  84. rez += "peaksAndValies:\n";
  85. rez += peaksAndValies.saveSettings(1);
  86. rez += "peaksAndValiesContributionSpline:\n";
  87. rez += peaksAndValiesContributionSpline.saveSettings(1);
  88. rez += "oceansAndTerases:\n";
  89. rez += oceansAndTerases.saveSettings(1);
  90. rez += "oceansAndTerasesContributionSpline:\n";
  91. rez += oceansAndTerasesContributionSpline.saveSettings(1);
  92. rez += "vegetationNoise:\n";
  93. rez += vegetationNoise.saveSettings(1);
  94. rez += "stonetDnoise:\n";
  95. rez += stone3Dnoise.saveSettings(1);
  96. rez += "humidityNoise:\n";
  97. rez += humidityNoise.saveSettings(1);
  98. rez += "temperatureNoise:\n";
  99. rez += temperatureNoise.saveSettings(1);
  100. rez += "spagettiNoise:\n";
  101. rez += spagettiNoise.saveSettings(1);
  102. rez += "spagettiBias: "; rez += std::to_string(spagettiBias); rez += ";\n";
  103. rez += "spagettiBiasPower: "; rez += std::to_string(spagettiBiasPower); rez += ";\n";
  104. rez += "densityBias: "; rez += std::to_string(densityBias); rez += ";\n";
  105. rez += "densityBiasPower: "; rez += std::to_string(densityBiasPower); rez += ";\n";
  106. return rez;
  107. }
  108. void WorldGeneratorSettings::sanitize()
  109. {
  110. continentalnessNoiseSettings.sanitize();
  111. peaksAndValies.sanitize();
  112. oceansAndTerases.sanitize();
  113. stone3Dnoise.sanitize();
  114. humidityNoise.sanitize();
  115. temperatureNoise.sanitize();
  116. vegetationNoise.sanitize();
  117. peaksAndValiesContributionSpline.sanitize();
  118. oceansAndTerasesContributionSpline.sanitize();
  119. densityBias = glm::clamp(densityBias, 0.f, 1.f);
  120. densityBiasPower = glm::clamp(densityBiasPower, 0.1f, 10.f);
  121. spagettiNoise.sanitize();
  122. spagettiBias = glm::clamp(spagettiBias, 0.f, 10.f);
  123. spagettiBiasPower = glm::clamp(spagettiBiasPower, 0.1f, 10.f);
  124. }
  125. std::string NoiseSetting::saveSettings(int tabs, bool saveSpline)
  126. {
  127. std::string rez;
  128. rez.reserve(200);
  129. auto addTabs = [&]() { for (int i = 0; i < tabs; i++) { rez += '\t'; } };
  130. addTabs();
  131. rez += "{\n";
  132. addTabs();
  133. rez += "scale: "; rez += std::to_string(scale); rez += ";\n"; addTabs();
  134. rez += "type: "; rez += magic_enum::enum_name((FastNoiseSIMD::NoiseType)type); rez += ";\n"; addTabs();
  135. rez += "frequency: "; rez += std::to_string(frequency); rez += ";\n"; addTabs();
  136. rez += "octaves: "; rez += std::to_string(octaves); rez += ";\n"; addTabs();
  137. rez += "perturbFractalOctaves: "; rez += std::to_string(perturbFractalOctaves); rez += ";\n"; addTabs();
  138. rez += "power: "; rez += std::to_string(power); rez += ";\n";
  139. if (saveSpline)
  140. {
  141. addTabs();
  142. rez += "spline:\n";
  143. rez += spline.saveSettings(tabs + 1);
  144. }
  145. addTabs();
  146. rez += "}\n";
  147. return rez;
  148. }
  149. void NoiseSetting::sanitize()
  150. {
  151. spline.sanitize();
  152. scale = glm::clamp(scale, 0.001f, 100.f);
  153. type = glm::clamp(type, (int)FastNoiseSIMD::Value, (int)FastNoiseSIMD::CubicFractal);
  154. frequency = glm::clamp(frequency, 0.001f, 100.f);
  155. octaves = glm::clamp(octaves, 0, 8);
  156. perturbFractalOctaves = glm::clamp(perturbFractalOctaves, 0, 8);
  157. power = glm::clamp(power, 0.1f, 10.f);
  158. //todo the rest
  159. }
  160. bool WorldGeneratorSettings::loadSettings(const char *data)
  161. {
  162. *this = {};
  163. enum
  164. {
  165. TokenNone,
  166. TokenString,
  167. TokenNumber,
  168. TokenSymbol,
  169. };
  170. struct Token
  171. {
  172. int type = 0;
  173. std::string s = "";
  174. char symbol = 0;
  175. double number = 0;
  176. bool operator==(Token &other)
  177. {
  178. return type == other.type &&
  179. s == other.s &&
  180. symbol == other.symbol &&
  181. number == other.number;
  182. }
  183. };
  184. std::vector<Token> tokens;
  185. #pragma region tokenize
  186. {
  187. int lastPos = 0;
  188. for (int i = 0; data[i] != '\0';)
  189. {
  190. auto checkSymbol = [&]() -> bool
  191. {
  192. if (data[i] == ';' || data[i] == ':' || data[i] == '{' || data[i] == '}' || data[i] == ',')
  193. {
  194. tokens.push_back({Token{TokenSymbol, "", data[i], 0}});
  195. i++;
  196. return true;
  197. }
  198. return 0;
  199. };
  200. auto checkNumber = [&]() -> bool
  201. {
  202. if (std::isdigit(data[i]))
  203. {
  204. Token t;
  205. t.type = TokenNumber;
  206. t.s += data[i];
  207. i++;
  208. for (; data[i] != '\0'; i++)
  209. {
  210. if (std::isdigit(data[i]) || data[i] == '.')
  211. {
  212. t.s += data[i];
  213. }
  214. else
  215. {
  216. break;
  217. }
  218. }
  219. t.number = std::stod(t.s); //todo replace with something that reports errors
  220. if (!t.s.empty()) { tokens.push_back(t); }
  221. return true;
  222. }
  223. return 0;
  224. };
  225. auto consumeWhiteSpaces = [&]()
  226. {
  227. for (; data[i] != '\0'; i++)
  228. {
  229. if (data[i] != '\n' && data[i] != '\v' && data[i] != '\t' && data[i] != ' ' && data[i] != '\r')
  230. {
  231. break;
  232. }
  233. }
  234. };
  235. auto addString = [&]()
  236. {
  237. Token t;
  238. t.type = TokenString;
  239. for (; data[i] != '\0'; i++)
  240. {
  241. if (isalpha(data[i]))
  242. {
  243. t.s += data[i];
  244. }
  245. else
  246. {
  247. break;
  248. }
  249. }
  250. if (!t.s.empty()) { tokens.push_back(t); }
  251. };
  252. consumeWhiteSpaces();
  253. if (data[i] == '\0') { break; }
  254. if (checkSymbol())continue;
  255. if (checkNumber())continue;
  256. addString();
  257. if (lastPos == i)
  258. {
  259. return 0;
  260. }
  261. else
  262. {
  263. lastPos = i;
  264. }
  265. }
  266. }
  267. #pragma endregion
  268. #pragma region parse
  269. {
  270. for (int i = 0; i < tokens.size();)
  271. {
  272. auto isString = [&]() -> bool
  273. {
  274. return tokens[i].type == TokenString;
  275. };
  276. auto consume = [&](Token t) -> bool
  277. {
  278. if (i >= tokens.size()) { return false; }
  279. if (tokens[i] == t)
  280. {
  281. i++;
  282. return true;
  283. }
  284. else
  285. {
  286. return false;
  287. }
  288. };
  289. auto isEof = [&]() { return i >= tokens.size(); };
  290. auto isNumber = [&]()
  291. {
  292. return (tokens[i].type == TokenNumber);
  293. };
  294. auto consumeNumber = [&]() -> double
  295. {
  296. if (tokens[i].type == TokenNumber)
  297. {
  298. i++;
  299. return tokens[i-1].number;
  300. };
  301. assert(0);
  302. return 0;
  303. };
  304. auto consumeSpline = [&](Spline &spline) -> bool
  305. {
  306. spline.size = 0;
  307. if (!consume(Token{TokenSymbol, "", '{', 0})) { return 0; }
  308. while (!consume(Token{TokenSymbol, "", '}', 0}))
  309. {
  310. if (isEof()) { return 0; }
  311. float nrA = 0;
  312. float nrB = 0;
  313. if (!isNumber()) { return 0; }
  314. nrA = consumeNumber();
  315. if (!consume(Token{TokenSymbol, "", ',', 0})) { return 0; }
  316. if (!isNumber()) { return 0; }
  317. nrB = consumeNumber();
  318. if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
  319. if (spline.size >= MAX_SPLINES_COUNT)
  320. {
  321. return 0;
  322. }
  323. spline.points[spline.size] = glm::vec2(nrA, nrB);
  324. spline.size++;
  325. }
  326. return true;
  327. };
  328. auto consumeNoise = [&](NoiseSetting &settings) -> bool
  329. {
  330. if (!consume(Token{TokenSymbol, "", '{', 0})) { return 0; }
  331. while (!consume(Token{TokenSymbol, "", '}', 0}))
  332. {
  333. if (isEof()) { return 0; }
  334. if (isString())
  335. {
  336. auto s = tokens[i].s; //todo to lower
  337. i++;
  338. if (s == "scale")
  339. {
  340. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  341. if (isEof()) { return 0; }
  342. if (!isNumber()) { return 0; }
  343. settings.scale = consumeNumber();
  344. if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
  345. }else if (s == "frequency")
  346. {
  347. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  348. if (isEof()) { return 0; }
  349. if (!isNumber()) { return 0; }
  350. settings.frequency = consumeNumber();
  351. if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
  352. }
  353. else if (s == "octaves")
  354. {
  355. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  356. if (isEof()) { return 0; }
  357. if (!isNumber()) { return 0; }
  358. settings.octaves = consumeNumber();
  359. if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
  360. }
  361. else if (s == "perturbFractalOctaves")
  362. {
  363. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  364. if (isEof()) { return 0; }
  365. if (!isNumber()) { return 0; }
  366. settings.perturbFractalOctaves = consumeNumber();
  367. if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
  368. }
  369. else if (s == "power")
  370. {
  371. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  372. if (isEof()) { return 0; }
  373. if (!isNumber()) { return 0; }
  374. settings.power = consumeNumber();
  375. if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
  376. }
  377. else if (s == "type")
  378. {
  379. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  380. if (isEof()) { return 0; }
  381. if (!isString()) { return 0; }
  382. auto s = tokens[i].s; //todo to lower
  383. i++;
  384. settings.type = -1;
  385. const char *types[] = {
  386. "Value", "ValueFractal", "Perlin", "PerlinFractal", "Simplex",
  387. "SimplexFractal", "WhiteNoise", "Cellular", "Cubic", "CubicFractal"};
  388. for (int t = 0; t < sizeof(types) / sizeof(types[0]); t++)
  389. {
  390. if (s == types[t])
  391. {
  392. settings.type = t;
  393. break;
  394. }
  395. }
  396. if (settings.type < 0) { return 0; }
  397. if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
  398. }
  399. else if (s == "spline")
  400. {
  401. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  402. if (isEof()) { return 0; }
  403. if (!consumeSpline(settings.spline)) { return 0; }
  404. }
  405. else
  406. {
  407. return 0;
  408. }
  409. }
  410. else if (consume(Token{TokenSymbol, "", ';', 0}))
  411. {
  412. }
  413. else
  414. {
  415. return 0;
  416. }
  417. }
  418. return true;
  419. };
  420. //if (isEof()) { break; }
  421. if (isString())
  422. {
  423. auto s = tokens[i].s; //todo to lower
  424. i++;
  425. if (s == "seed")
  426. {
  427. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  428. if (isEof()) { return 0; }
  429. if (!isNumber()) { return 0; }
  430. seed = consumeNumber();
  431. if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
  432. }else if (s == "densityBias")
  433. {
  434. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  435. if (isEof()) { return 0; }
  436. if (!isNumber()) { return 0; }
  437. densityBias = consumeNumber();
  438. if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
  439. }else if (s == "densityBiasPower")
  440. {
  441. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  442. if (isEof()) { return 0; }
  443. if (!isNumber()) { return 0; }
  444. densityBiasPower = consumeNumber();
  445. if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
  446. }
  447. else if (s == "continentalnessNoise")
  448. {
  449. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  450. if (isEof()) { return 0; }
  451. if (!consumeNoise(continentalnessNoiseSettings))
  452. {
  453. return 0;
  454. }
  455. }
  456. else if (s == "vegetationNoise")
  457. {
  458. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  459. if (isEof()) { return 0; }
  460. if (!consumeNoise(vegetationNoise))
  461. {
  462. return 0;
  463. }
  464. }
  465. else if (s == "humidityNoise")
  466. {
  467. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  468. if (isEof()) { return 0; }
  469. if (!consumeNoise(humidityNoise))
  470. {
  471. return 0;
  472. }
  473. }
  474. else if (s == "temperatureNoise")
  475. {
  476. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  477. if (isEof()) { return 0; }
  478. if (!consumeNoise(temperatureNoise))
  479. {
  480. return 0;
  481. }
  482. }
  483. else if (s == "peaksAndValies")
  484. {
  485. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  486. if (isEof()) { return 0; }
  487. if (!consumeNoise(peaksAndValies))
  488. {
  489. return 0;
  490. }
  491. }
  492. else if (s == "oceansAndTerases")
  493. {
  494. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  495. if (isEof()) { return 0; }
  496. if (!consumeNoise(oceansAndTerases))
  497. {
  498. return 0;
  499. }
  500. }
  501. else if (s == "stonetDnoise")
  502. {
  503. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  504. if (isEof()) { return 0; }
  505. if (!consumeNoise(stone3Dnoise))
  506. {
  507. return 0;
  508. }
  509. }
  510. else if (s == "spagettiNoise")
  511. {
  512. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  513. if (isEof()) { return 0; }
  514. if (!consumeNoise(spagettiNoise))
  515. {
  516. return 0;
  517. }
  518. }
  519. else if (s == "spagettiBias")
  520. {
  521. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  522. if (isEof()) { return 0; }
  523. if (!isNumber()) { return 0; }
  524. spagettiBias = consumeNumber();
  525. if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
  526. }
  527. else if (s == "spagettiBiasPower")
  528. {
  529. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  530. if (isEof()) { return 0; }
  531. if (!isNumber()) { return 0; }
  532. spagettiBiasPower = consumeNumber();
  533. if (!consume(Token{TokenSymbol, "", ';', 0})) { return 0; }
  534. }
  535. else if (s == "peaksAndValiesContributionSpline")
  536. {
  537. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  538. if (isEof()) { return 0; }
  539. if (!consumeSpline(peaksAndValiesContributionSpline))
  540. {
  541. return 0;
  542. }
  543. }
  544. else if (s == "oceansAndTerasesContributionSpline")
  545. {
  546. if (!consume(Token{TokenSymbol, "", ':', 0})) { return 0; }
  547. if (isEof()) { return 0; }
  548. if (!consumeSpline(oceansAndTerasesContributionSpline))
  549. {
  550. return 0;
  551. }
  552. }
  553. else
  554. {
  555. return 0;
  556. }
  557. }
  558. else if (consume(Token{TokenSymbol, "", ';', 0}))
  559. {
  560. }else
  561. {
  562. return 0;
  563. }
  564. }
  565. }
  566. #pragma endregion
  567. sanitize();
  568. return true;
  569. }