💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

216 lines
5.6 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. /*
  2. * Copyright (C) 2017 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper Source Code.
  5. *
  6. * Antkeeper Source Code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper Source Code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "nest.hpp"
  20. #include <algorithm>
  21. #include <cmath>
  22. #undef min
  23. #undef max
  24. Vector3 Shaft::getHelixPosition(float depth) const
  25. {
  26. Vector3 position;
  27. position.x = entrance.x + std::cos(initialHelixAngle + depth / helixPitch) * helixRadius;
  28. position.y = entrance.y + depth;
  29. position.z = entrance.z + std::sin(initialHelixAngle + depth / helixPitch) * helixRadius;
  30. return position;
  31. }
  32. float Shaft::getHelixAngle(float depth) const
  33. {
  34. return initialHelixAngle + depth / helixPitch;
  35. }
  36. Nest::Nest():
  37. root(nullptr)
  38. {}
  39. Nest::~Nest()
  40. {
  41. if (root != nullptr)
  42. {
  43. free(root);
  44. }
  45. }
  46. void Nest::generate()
  47. {
  48. if (root != nullptr)
  49. {
  50. // Delete existing shafts and chambers
  51. free(root);
  52. }
  53. // Seed random number generator
  54. rng.seed(parameters.randomSeed);
  55. // Generate shafts and chambers
  56. root = dig(nullptr);
  57. // Merge intersecting chambers
  58. // Create nest map
  59. map();
  60. }
  61. Shaft* Nest::dig(Chamber* parent) const
  62. {
  63. Shaft* shaft = new Shaft();
  64. // Set child's parent
  65. shaft->parent = parent;
  66. if (parent != nullptr)
  67. {
  68. // Set parent's child to this shaft
  69. parent->child = shaft;
  70. // Increment generation
  71. shaft->generation = parent->parent->generation + 1;
  72. // Determine initial helix angle
  73. shaft->initialHelixAngle = parent->parent->getHelixAngle(parent->relativeDepth);
  74. }
  75. else
  76. {
  77. // Shaft is root shaft
  78. shaft->generation = 0;
  79. shaft->entrance = Vector3(0.0f);
  80. // Choose initial helix angle
  81. }
  82. shaft->initialHelixAngle = random(glm::radians(-180.0f), glm::radians(180.0f));
  83. if (parent == nullptr)
  84. {
  85. // Choose initial random parameters
  86. shaft->shaftRadius = random(parameters.minShaftRadius, parameters.maxShaftRadius);
  87. shaft->helixRadius = random(parameters.minShaftHelixRadius, parameters.maxShaftHelixRadius);
  88. shaft->helixPitch = random(parameters.minShaftHelixPitch, parameters.maxShaftHelixPitch);
  89. }
  90. else
  91. {
  92. // Copy initial random parameters from grandparent
  93. shaft->shaftRadius = parent->parent->shaftRadius;
  94. shaft->helixRadius = parent->parent->helixRadius;
  95. shaft->helixPitch = parent->parent->helixPitch;
  96. }
  97. // Choose random depth
  98. shaft->shaftDepth = random(parameters.minShaftDepth, parameters.maxShaftDepth);
  99. // Calculate entrance position
  100. if (parent != nullptr)
  101. {
  102. Vector3 helixPosition = parent->parent->getHelixPosition(parent->relativeDepth);
  103. float helixAngle = parent->parent->getHelixAngle(parent->relativeDepth);
  104. shaft->entrance.x = helixPosition.x + std::cos(helixAngle) * (parent->outerRadius - parent->innerRadius) - std::cos(shaft->initialHelixAngle) * shaft->helixRadius;
  105. shaft->entrance.y = helixPosition.y;
  106. shaft->entrance.z = helixPosition.z + std::sin(helixAngle) * (parent->outerRadius - parent->innerRadius) - std::sin(shaft->initialHelixAngle) * shaft->helixRadius;
  107. }
  108. // Determine potential child count (may be less, according to spacing between chambers)
  109. int maxChildCount = std::max<int>(1, random(parameters.minShaftChamberCount, parameters.maxShaftChamberCount));
  110. // Generate chambers, starting with final chamber (shaft must end with a chamber)
  111. for (float depth = shaft->shaftDepth; depth >= 0.0f;)
  112. {
  113. Chamber* chamber = new Chamber();
  114. shaft->children.push_back(chamber);
  115. chamber->parent = shaft;
  116. chamber->child = nullptr;
  117. chamber->relativeDepth = depth;
  118. chamber->absoluteDepth = shaft->entrance.y + chamber->relativeDepth;
  119. chamber->innerRadius = random(parameters.minChamberInnerRadius, parameters.maxChamberInnerRadius);
  120. chamber->outerRadius = random(parameters.minChamberOuterRadius, parameters.maxChamberOuterRadius);
  121. chamber->centralAngle = random(parameters.minChamberCentralAngle, parameters.maxChamberCentralAngle);
  122. // Check if maximum child count has been reached
  123. if (shaft->children.size() >= maxChildCount)
  124. {
  125. break;
  126. }
  127. // Decrease depth by random amount
  128. depth -= random(parameters.minShaftChamberPitch, parameters.maxShaftChamberPitch);
  129. }
  130. // Generate subshafts from chambers
  131. if (shaft->generation < parameters.maxShaftGeneration)
  132. {
  133. for (Chamber* chamber: shaft->children)
  134. {
  135. dig(chamber);
  136. }
  137. }
  138. return shaft;
  139. }
  140. void Nest::merge()
  141. {
  142. }
  143. void Nest::map()
  144. {
  145. }
  146. void Nest::free(Shaft* shaft)
  147. {
  148. for (Chamber* chamber: shaft->children)
  149. {
  150. if (chamber->child != nullptr)
  151. {
  152. free(chamber->child);
  153. }
  154. delete chamber;
  155. }
  156. delete shaft;
  157. }
  158. inline float Nest::random(float minValue, float maxValue) const
  159. {
  160. std::uniform_real_distribution<float> distribution(minValue, std::nextafter(maxValue, std::numeric_limits<float>::max()));
  161. return distribution(rng);
  162. }
  163. inline int Nest::random(int minValue, int maxValue) const
  164. {
  165. std::uniform_int_distribution<int> distribution(minValue, std::nextafter(maxValue, std::numeric_limits<int>::max()));
  166. return distribution(rng);
  167. }
  168. void Nest::setParameters(const NestParameters& parameters)
  169. {
  170. this->parameters = parameters;
  171. }
  172. const NestParameters& Nest::getParameters() const
  173. {
  174. return parameters;
  175. }