diff --git a/include/Model.h b/include/Model.h index a3da35b..5016a30 100644 --- a/include/Model.h +++ b/include/Model.h @@ -11,6 +11,8 @@ #include +class Model genShpere(float radius, int sectorsCount, class Node* parent = NULL); // Генерирует сферу заданного радиуса с определенным количеством сегментов + // Класс узла сцены class Node { diff --git a/src/Model.cpp b/src/Model.cpp index 6b34f02..510a668 100644 --- a/src/Model.cpp +++ b/src/Model.cpp @@ -402,3 +402,77 @@ void Model::set_texture(Texture& texture) break; }; } + +// Генерирует сферу заданного радиуса с определенным количеством сегментов +Model genShpere(float radius, int sectorsCount, Node* parent) +{ + Model result(parent); + + std::vector vertices; + std::vector normals; + std::vector indices; + + float x, y, z, xy; // Позиция вершины + float nx, ny, nz, lengthInv = 1.0f / radius; // Нормаль вершины + float PI = 3.14159265; + float sectorStep = PI / sectorsCount; // Шаг сектора + float longAngle, latAngle; // Углы + + for(int i = 0; i <= sectorsCount; ++i) + { + latAngle = PI / 2 - i * sectorStep; // Начиная с pi/2 до -pi/2 + xy = radius * cos(latAngle); // r * cos(lat) + z = radius * sin(latAngle); // r * sin(lat) + + // добавляем (sectorCount+1) вершин на сегмент + // Последняя и первая вершины имеют одинаковые нормали и координаты + for(int j = 0; j <= sectorsCount; ++j) + { + longAngle = j * 2 * sectorStep; // Начиная с 0 до 2*pi + + // Положение вершины (x, y, z) + x = xy * cos(longAngle); // r * cos(lat) * cos(long) + y = xy * sin(longAngle); // r * cos(lat) * sin(long) + vertices.push_back({x, y, z}); + + // Нормали (nx, ny, nz) + nx = x * lengthInv; + ny = y * lengthInv; + nz = z * lengthInv; + normals.push_back({nx, ny, nz}); + } + } + int k1, k2; + for(int i = 0; i < sectorsCount; ++i) + { + k1 = i * (sectorsCount + 1); // начало текущего сегмента + k2 = k1 + sectorsCount + 1; // начало следующего сегмента + + for(int j = 0; j < sectorsCount; ++j, ++k1, ++k2) + { + // 2 треугольника на один сегмент + // k1, k2, k1+1 + if(i != 0) + { + indices.push_back(k1); + indices.push_back(k2); + indices.push_back(k1 + 1); + } + + // k1+1, k2, k2+1 + if(i != (sectorsCount-1)) + { + indices.push_back(k1 + 1); + indices.push_back(k2); + indices.push_back(k2 + 1); + } + + } + } + // Загрузка в модель + result.load_verteces(&vertices[0], vertices.size()); + result.load_normals(&normals[0], normals.size()); + result.load_indices(&indices[0], indices.size()); + + return result; +}