One neat trick I’ve learned is that you can use the points on a Fibonacci sphere to optimally compress unit vectors, for things like normal textures. For example, if you have an array of 1024 points representing a Fibonacci sphere, you can compress unit vectors into lg(1024)=10 bits with a nearest neighbor search and decompress with an O(1) table lookup. In fact, the general strategy works for higher dimensions as we…
What you're saying sounds promising but I have no idea how to implement it - any articles about it that contain algorithms?
import math
def fibonacci_sphere_point(idx, num_points):
i = idx + 0.5
phi = math.acos(1 - 2 * i / num_points)
golden_ratio = (1 + 5 ** 0.5) / 2
theta = 2 * math.pi * i / golden_ratio
sin_phi = math.sin(phi)
cos_phi = math.cos(phi)
sin_theta = math.sin(theta)
cos_theta = math.cos(theta)
return (
cos_theta * sin_phi,
sin_theta * sin_phi,
cos_phi,
)
table = [fibonacci_sphere_point(i, 1024) for i in range(1024)]
def sqr_dist(a, b):
return (a[0]-b[0])**2 + (a[1]-b[1])**2 + (a[2]-b[2])**2
def decode(value):
return table[value]
def encode(point):
closest_idx = 0
closest_dist2 = sqr_dist(point, table[closest_idx])
for i in range(1, len(table)):
curr_dist2 = sqr_dist(point, table[i])
if closest_dist2 > curr_dist2:
closest_dist2 = curr_dist2
closest_idx = i
return closest_idx