stone.cpp 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. #include "stone.h"
  2. #include "../entity/registry.h"
  3. #include "../gl/mesh.h"
  4. #include "../gl/resources.h"
  5. #include "../scene_renderer.h"
  6. #include <QMatrix4x4>
  7. #include <QVector3D>
  8. #include <algorithm>
  9. #include <cmath>
  10. #include <numbers>
  11. #include <vector>
  12. namespace Render {
  13. namespace Geom {
  14. static auto create_stone_mesh() -> std::unique_ptr<GL::Mesh> {
  15. using GL::Vertex;
  16. std::vector<GL::Vertex> verts;
  17. std::vector<unsigned int> idx;
  18. constexpr int k_latitude_segments = 8;
  19. constexpr int k_longitude_segments = 10;
  20. constexpr float k_base_radius = 0.15F;
  21. for (int lat = 0; lat <= k_latitude_segments; ++lat) {
  22. float const theta = static_cast<float>(lat) / k_latitude_segments *
  23. std::numbers::pi_v<float>;
  24. float const sin_theta = std::sin(theta);
  25. float const cos_theta = std::cos(theta);
  26. for (int lon = 0; lon <= k_longitude_segments; ++lon) {
  27. float const phi = static_cast<float>(lon) / k_longitude_segments * 2.0F *
  28. std::numbers::pi_v<float>;
  29. float const sin_phi = std::sin(phi);
  30. float const cos_phi = std::cos(phi);
  31. float const noise = 1.0F + 0.15F * std::sin(phi * 3.0F + theta * 2.0F) +
  32. 0.1F * std::cos(phi * 5.0F - theta * 3.0F);
  33. float const radius = k_base_radius * noise;
  34. float const x = radius * sin_theta * cos_phi;
  35. float const y = radius * cos_theta;
  36. float const z = radius * sin_theta * sin_phi;
  37. QVector3D const normal =
  38. QVector3D(sin_theta * cos_phi, cos_theta, sin_theta * sin_phi)
  39. .normalized();
  40. float const u = static_cast<float>(lon) / k_longitude_segments;
  41. float const v = static_cast<float>(lat) / k_latitude_segments;
  42. verts.push_back(
  43. {{x, y, z}, {normal.x(), normal.y(), normal.z()}, {u, v}});
  44. }
  45. }
  46. for (int lat = 0; lat < k_latitude_segments; ++lat) {
  47. for (int lon = 0; lon < k_longitude_segments; ++lon) {
  48. int const first = lat * (k_longitude_segments + 1) + lon;
  49. int const second = first + k_longitude_segments + 1;
  50. idx.push_back(first);
  51. idx.push_back(second);
  52. idx.push_back(first + 1);
  53. idx.push_back(second);
  54. idx.push_back(second + 1);
  55. idx.push_back(first + 1);
  56. }
  57. }
  58. return std::make_unique<GL::Mesh>(verts, idx);
  59. }
  60. auto Stone::get() -> GL::Mesh * {
  61. static std::unique_ptr<GL::Mesh> const mesh = create_stone_mesh();
  62. return mesh.get();
  63. }
  64. } // namespace Geom
  65. } // namespace Render