Advertisement
Guest User

SoA Icosphere Generator

a guest
Apr 12th, 2015
2,162
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.21 KB | None | 0 0
  1. /// Seed of Andromeda Icosphere Generator
  2. /// Written by Frank McCoy
  3. /// Use it for whatever, but remember where you got it from.
  4.  
  5. #include <cstdint>
  6. #include <unordered_map>
  7. #include <vector>
  8. #include <glm/glm.hpp>
  9. // GLM is awesome ^ ^ ^
  10.  
  11. const static float GOLDEN_RATIO = 1.61803398875f;
  12.  
  13. const static int NUM_ICOSOHEDRON_VERTICES = 12;
  14. const static glm::vec3 ICOSOHEDRON_VERTICES[12] = {
  15.     glm::vec3(-1.0f, GOLDEN_RATIO, 0.0f),
  16.     glm::vec3(1.0f, GOLDEN_RATIO, 0.0f),
  17.     glm::vec3(-1.0f, -GOLDEN_RATIO, 0.0f),
  18.     glm::vec3(1.0f, -GOLDEN_RATIO, 0.0f),
  19.  
  20.     glm::vec3(0.0f, -1.0f, GOLDEN_RATIO),
  21.     glm::vec3(0.0f, 1.0f, GOLDEN_RATIO),
  22.     glm::vec3(0.0f, -1.0, -GOLDEN_RATIO),
  23.     glm::vec3(0.0f, 1.0f, -GOLDEN_RATIO),
  24.  
  25.     glm::vec3(GOLDEN_RATIO, 0.0f, -1.0f),
  26.     glm::vec3(GOLDEN_RATIO, 0.0f, 1.0f),
  27.     glm::vec3(-GOLDEN_RATIO, 0.0f, -1.0f),
  28.     glm::vec3(-GOLDEN_RATIO, 0.0, 1.0f)
  29. };
  30.  
  31. const static int NUM_ICOSOHEDRON_INDICES = 60;
  32. const static uint32_t ICOSOHEDRON_INDICES[60] = {
  33.     0, 11, 5,
  34.     0, 5, 1,
  35.     0, 1, 7,
  36.     0, 7, 10,
  37.     0, 10, 11,
  38.  
  39.     1, 5, 9,
  40.     5, 11, 4,
  41.     11, 10, 2,
  42.     10, 7, 6,
  43.     7, 1, 8,
  44.  
  45.     3, 9, 4,
  46.     3, 4, 2,
  47.     3, 2, 6,
  48.     3, 6, 8,
  49.     3, 8, 9,
  50.  
  51.     4, 9, 5,
  52.     2, 4, 11,
  53.     6, 2, 10,
  54.     8, 6, 7,
  55.     9, 8, 1
  56. };
  57.  
  58. // Hash functions for the unordered map
  59. class Vec3KeyFuncs {
  60. public:
  61.     size_t operator()(const glm::vec3& k)const {
  62.         return std::hash<float>()(k.x) ^ std::hash<float>()(k.y) ^ std::hash<float>()(k.z);
  63.     }
  64.  
  65.     bool operator()(const glm::vec3& a, const glm::vec3& b)const {
  66.         return a.x == b.x && a.y == b.y && a.z == b.z;
  67.     }
  68. };
  69.  
  70. inline glm::vec3 findMidpoint(glm::vec3 vertex1, glm::vec3 vertex2) {
  71.     return glm::normalize(glm::vec3((vertex1.x + vertex2.x) / 2.0f, (vertex1.y + vertex2.y) / 2.0f, (vertex1.z + vertex2.z) / 2.0f));
  72. }
  73.  
  74. /// Generates an icosphere with radius 1.0f.
  75. /// @param lod: Number of subdivisions
  76. /// @param indices: Resulting indices for use with glDrawElements
  77. /// @param positions: Resulting vertex positions
  78. void generateIcosphereMesh(size_t lod, std::vector<uint32_t>& indices, std::vector<glm::vec3>& positions) {
  79.     std::vector<uint32_t> newIndices;
  80.     newIndices.reserve(256);
  81.  
  82.     std::unordered_map<glm::vec3, uint32_t, Vec3KeyFuncs, Vec3KeyFuncs> vertexLookup;
  83.    
  84.     indices.resize(NUM_ICOSOHEDRON_INDICES);
  85.     for (uint32_t i = 0; i < NUM_ICOSOHEDRON_INDICES; i++) {
  86.         indices[i] = ICOSOHEDRON_INDICES[i];
  87.     }
  88.     positions.resize(NUM_ICOSOHEDRON_VERTICES);
  89.     for (uint32_t i = 0; i < NUM_ICOSOHEDRON_VERTICES; i++) {
  90.         positions[i] = glm::normalize(ICOSOHEDRON_VERTICES[i]);
  91.         vertexLookup[glm::normalize(ICOSOHEDRON_VERTICES[i])] = i;
  92.     }
  93.  
  94.     for (size_t i = 0; i < (size_t)lod; i++) {
  95.         for (size_t j = 0; j < indices.size(); j += 3) {
  96.             /*
  97.             j
  98.             mp12   mp13
  99.             j+1    mp23   j+2
  100.             */
  101.             // Defined in counter clockwise order
  102.             glm::vec3 vertex1 = positions[indices[j + 0]];
  103.             glm::vec3 vertex2 = positions[indices[j + 1]];
  104.             glm::vec3 vertex3 = positions[indices[j + 2]];
  105.  
  106.             glm::vec3 midPoint12 = findMidpoint(vertex1, vertex2);
  107.             glm::vec3 midPoint23 = findMidpoint(vertex2, vertex3);
  108.             glm::vec3 midPoint13 = findMidpoint(vertex1, vertex3);
  109.  
  110.             uint32_t mp12Index;
  111.             uint32_t mp23Index;
  112.             uint32_t mp13Index;
  113.  
  114.             auto iter = vertexLookup.find(midPoint12);
  115.             if (iter != vertexLookup.end()) { // It is in the map
  116.                 mp12Index = iter->second;
  117.             } else { // Not in the map
  118.                 mp12Index = (uint32_t)positions.size();
  119.                 positions.push_back(midPoint12);
  120.                 vertexLookup[midPoint12] = mp12Index;
  121.             }
  122.  
  123.             iter = vertexLookup.find(midPoint23);
  124.             if (iter != vertexLookup.end()) { // It is in the map
  125.                 mp23Index = iter->second;
  126.             } else { // Not in the map
  127.                 mp23Index = (uint32_t)positions.size();
  128.                 positions.push_back(midPoint23);
  129.                 vertexLookup[midPoint23] = mp23Index;
  130.             }
  131.  
  132.             iter = vertexLookup.find(midPoint13);
  133.             if (iter != vertexLookup.end()) { // It is in the map
  134.                 mp13Index = iter->second;
  135.             } else { // Not in the map
  136.                 mp13Index = (uint32_t)positions.size();
  137.                 positions.push_back(midPoint13);
  138.                 vertexLookup[midPoint13] = mp13Index;
  139.             }
  140.  
  141.             newIndices.push_back(indices[j]);
  142.             newIndices.push_back(mp12Index);
  143.             newIndices.push_back(mp13Index);
  144.  
  145.             newIndices.push_back(mp12Index);
  146.             newIndices.push_back(indices[j + 1]);
  147.             newIndices.push_back(mp23Index);
  148.  
  149.             newIndices.push_back(mp13Index);
  150.             newIndices.push_back(mp23Index);
  151.             newIndices.push_back(indices[j + 2]);
  152.  
  153.             newIndices.push_back(mp12Index);
  154.             newIndices.push_back(mp23Index);
  155.             newIndices.push_back(mp13Index);
  156.         }
  157.         indices.swap(newIndices);
  158.         newIndices.clear();
  159.     }
  160. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement