.. _program_listing_file_Source_Math_Src_Icosphere.cpp: Program Listing for File Icosphere.cpp ====================================== |exhale_lsh| :ref:`Return to documentation for file ` (``Source\Math\Src\Icosphere.cpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #include "Math/Icosphere.h" #include #include #include #include "Math/Transform.h" #include "Core/RawStorageFormat.h" namespace Azura { namespace Math { namespace { // Source Ref: https://schneide.blog/2016/07/15/generating-an-icosphere-in-c/ const float X = 0.525731112119133606f; const float Z = 0.850650808352039932f; const float N = 0.0f; const RawStorageFormat VERTEX_FORMAT = RawStorageFormat::R32G32B32A32_FLOAT; const RawStorageFormat NORMAL_FORMAT = RawStorageFormat::R32G32B32_FLOAT; const RawStorageFormat INDEX_FORMAT = RawStorageFormat::R32_UINT; using Lookup = std::map, U32>; const std::array BASE_VERTICES = { Vector4f{-X, N, Z, 1.0f}, Vector4f{X, N, Z, 1.0f}, Vector4f{-X, N, -Z, 1.0f}, Vector4f{X, N, -Z, 1.0f}, Vector4f{N, Z, X, 1.0f}, Vector4f{N, Z, -X, 1.0f}, Vector4f{N, -Z, X, 1.0f}, Vector4f{N, -Z, -X, 1.0f}, Vector4f{Z, X, N, 1.0f}, Vector4f{-Z, X, N, 1.0f}, Vector4f{Z, -X, N, 1.0f}, Vector4f{-Z, -X, N, 1.0f} }; const std::array BASE_TRIANGLES = { Vector3u{0, 4, 1}, Vector3u{0, 9, 4}, Vector3u{9, 5, 4}, Vector3u{4, 5, 8}, Vector3u{4, 8, 1}, Vector3u{8, 10, 1}, Vector3u{8, 3, 10}, Vector3u{5, 3, 8}, Vector3u{5, 2, 3}, Vector3u{2, 7, 3}, Vector3u{7, 10, 3}, Vector3u{7, 6, 10}, Vector3u{7, 11, 6}, Vector3u{11, 0, 6}, Vector3u{0, 1, 6}, Vector3u{6, 1, 10}, Vector3u{9, 0, 11}, Vector3u{9, 11, 2}, Vector3u{9, 2, 5}, Vector3u{7, 2, 11} }; U32 VertexForEdge(Lookup& lookup, std::vector& vertices, U32 first, U32 second) { Lookup::key_type key(first, second); if (key.first > key.second) { std::swap(key.first, key.second); } const auto inserted = lookup.insert({key, U32(vertices.size())}); if (inserted.second) { auto& edge0 = vertices[first]; auto& edge1 = vertices[second]; const Vector3f data = Transform::Downgrade(edge0 + edge1); const auto point = mathfu::NormalizedHelper(data); vertices.emplace_back(point, 1.0f); } return inserted.first->second; } std::vector SubDivide(std::vector& vertices, std::vector triangles) { Lookup lookup; std::vector result; result.reserve(triangles.size() * 4); for (auto&& each : triangles) { Vector3u mid; for (int edge = 0; edge < 3; ++edge) { mid[edge] = VertexForEdge(lookup, vertices, each[edge], each[(edge + 1) % 3]); } result.emplace_back(each[0], mid[0], mid[2]); result.emplace_back(each[1], mid[1], mid[0]); result.emplace_back(each[2], mid[2], mid[1]); result.emplace_back(mid[0], mid[1], mid[2]); } return result; } } // namespace IcoSphere::IcoSphere(U32 subDivisions) : m_vertices(BASE_VERTICES.begin(), BASE_VERTICES.end()), m_triangles(BASE_TRIANGLES.begin(), BASE_TRIANGLES.end()) { m_vertices.reserve(10 * U32(std::pow(4, subDivisions))); m_normals.reserve(10 * U32(std::pow(4, subDivisions))); m_triangles.reserve(10 * U32(std::pow(4, subDivisions))); for (U32 idx = 0; idx < subDivisions; ++idx) { m_triangles = SubDivide(m_vertices, m_triangles); } for (const auto& vertex: m_vertices) { m_normals.push_back(Transform::Downgrade(vertex).Normalized()); } } U32 IcoSphere::VertexDataSize() const { return U32(m_vertices.size() * GetFormatSize(VERTEX_FORMAT)); } U32 IcoSphere::IndexDataSize() const { return U32(m_triangles.size() * GetFormatSize(INDEX_FORMAT) * 3); } U32 IcoSphere::NormalDataSize() const { return U32(m_normals.size() * GetFormatSize(NORMAL_FORMAT)); } const U8* IcoSphere::VertexData() const { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) return reinterpret_cast(m_vertices.data()); } const U8* IcoSphere::IndexData() const { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) return reinterpret_cast(m_triangles.data()); } const U8* IcoSphere::NormalData() const { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) return reinterpret_cast(m_normals.data()); } RawStorageFormat IcoSphere::GetVertexFormat() const { return VERTEX_FORMAT; } RawStorageFormat IcoSphere::GetIndexFormat() const { return INDEX_FORMAT; } RawStorageFormat IcoSphere::GetNormalFormat() const { return NORMAL_FORMAT; } U32 IcoSphere::UVDataSize() const { // TODO(vasumahesh1): Not Implemented return 0; } const U8* IcoSphere::UVData() const { // TODO(vasumahesh1): Not Implemented return nullptr; } RawStorageFormat IcoSphere::GetUVFormat() const { // TODO(vasumahesh1): Not Implemented return RawStorageFormat::UNKNOWN; } U32 IcoSphere::GetVertexCount() const { return U32(m_vertices.size()); } U32 IcoSphere::GetIndexCount() const { return U32(m_triangles.size() * 3); } U32 IcoSphere::TotalDataSize() const { return VertexDataSize() + IndexDataSize() + NormalDataSize(); } } // namespace Math } // namespace Azura