Skip to content

Commit

Permalink
[Math/MathUtils] Added a Fibonacci sphere points computation
Browse files Browse the repository at this point in the history
- This allows computing evenly distributed points around a unit sphere, and will be useful for some algorithms
  • Loading branch information
Razakhel committed Feb 2, 2024
1 parent 7b999ca commit e96b218
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 0 deletions.
19 changes: 19 additions & 0 deletions include/RaZ/Math/MathUtils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
#ifndef RAZ_MATHUTILS_HPP
#define RAZ_MATHUTILS_HPP

#include "RaZ/Math/Constants.hpp"
#include "RaZ/Math/Vector.hpp"

#include <algorithm>
#include <cassert>
#include <type_traits>
#include <vector>

namespace Raz::MathUtils {

Expand Down Expand Up @@ -162,6 +164,23 @@ void computeOrthonormalBasis(const Vec3<T>& input, Vec3<T>& axis2, Vec3<T>& axis
axis3 = Vec3<T>(b, sign + input.y() * input.y() * a, -input.y());
}

/// Computes points on the Fibonacci sphere, giving evenly distributed points around a unit sphere.
/// \param pointCount Number of points to compute.
/// \return Points on the Fibonacci sphere. All vectors are of length 1.
inline std::vector<Vec3f> computeFibonacciSpherePoints(std::size_t pointCount) {
std::vector<Vec3f> fiboPoints(pointCount);

for (std::size_t i = 0; i < pointCount; ++i) {
const float theta = 2.f * Pi<float> * static_cast<float>(i) / GoldenRatio<float>;
const float cosPhi = 1.f - 2.f * (static_cast<float>(i) + 0.5f) / static_cast<float>(pointCount);
const float sinPhi = std::sqrt(1.f - cosPhi * cosPhi);

fiboPoints[i] = Vec3f(std::cos(theta) * sinPhi, cosPhi, std::sin(theta) * sinPhi);
}

return fiboPoints;
}

} // namespace Raz::MathUtils

#endif // RAZ_MATHUTILS_HPP
35 changes: 35 additions & 0 deletions tests/src/RaZ/Math/MathUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,38 @@ TEST_CASE("MathUtils orthonormal basis") {
CHECK(axis3 == Raz::Vec3f(0.211324856f, -0.788675f, 0.577350259f));
CHECK(axis2.dot(axis3) == 0.f);
}

TEST_CASE("MathUtils Fibonacci sphere") {
std::vector<Raz::Vec3f> fiboPoints = Raz::MathUtils::computeFibonacciSpherePoints(0);
CHECK(fiboPoints.empty());

fiboPoints = Raz::MathUtils::computeFibonacciSpherePoints(1);
REQUIRE(fiboPoints.size() == 1);
CHECK_THAT(fiboPoints[0], IsNearlyEqualToVector(Raz::Vec3f(1.f, 0.f, 0.f)));

fiboPoints = Raz::MathUtils::computeFibonacciSpherePoints(2);
REQUIRE(fiboPoints.size() == 2);
CHECK_THAT(fiboPoints[0], IsNearlyEqualToVector(Raz::Vec3f(0.8660253f, 0.5f, 0.f)));
CHECK_THAT(fiboPoints[1], IsNearlyEqualToVector(Raz::Vec3f(-0.6385802f, -0.5, -0.5849917f)));

fiboPoints = Raz::MathUtils::computeFibonacciSpherePoints(3);
REQUIRE(fiboPoints.size() == 3);
CHECK_THAT(fiboPoints[0], IsNearlyEqualToVector(Raz::Vec3f(0.745356f, 0.6666666f, 0.f)));
CHECK_THAT(fiboPoints[1], IsNearlyEqualToVector(Raz::Vec3f(-0.7373688f, 0.f, -0.6754903f)));
CHECK_THAT(fiboPoints[2], IsNearlyEqualToVector(Raz::Vec3f(0.0651632f, -0.6666666f, 0.742502f)));

fiboPoints = Raz::MathUtils::computeFibonacciSpherePoints(4);
REQUIRE(fiboPoints.size() == 4);
CHECK_THAT(fiboPoints[0], IsNearlyEqualToVector(Raz::Vec3f(0.6614378f, 0.75f, 0.f)));
CHECK_THAT(fiboPoints[1], IsNearlyEqualToVector(Raz::Vec3f(-0.7139543f, 0.25f, -0.6540406f)));
CHECK_THAT(fiboPoints[2], IsNearlyEqualToVector(Raz::Vec3f(0.0846495f, -0.25f, 0.9645385f)));
CHECK_THAT(fiboPoints[3], IsNearlyEqualToVector(Raz::Vec3f(0.4024442f, -0.75f, -0.5249176f)));

fiboPoints = Raz::MathUtils::computeFibonacciSpherePoints(5);
REQUIRE(fiboPoints.size() == 5);
CHECK_THAT(fiboPoints[0], IsNearlyEqualToVector(Raz::Vec3f(0.6f, 0.8f, 0.f)));
CHECK_THAT(fiboPoints[1], IsNearlyEqualToVector(Raz::Vec3f(-0.6758097f, 0.3999999f, -0.619097f)));
CHECK_THAT(fiboPoints[2], IsNearlyEqualToVector(Raz::Vec3f(0.0874256f, 0.f, 0.996171f)));
CHECK_THAT(fiboPoints[3], IsNearlyEqualToVector(Raz::Vec3f(0.5576431f, -0.3999999f, -0.7273473f)));
CHECK_THAT(fiboPoints[4], IsNearlyEqualToVector(Raz::Vec3f(-0.5908281f, -0.7999999f, 0.104509f)));
}

0 comments on commit e96b218

Please sign in to comment.