float polygon_sides_length(float sides_count) { return 2.0 * sin(M_PI / sides_count); } /* Returns intersection ratio between the radius edge at theta and the polygon edge. */ float circle_to_polygon_radius(float sides_count, float theta) { /* From Graphics Gems from CryENGINE 3 (Siggraph 2013) by Tiago Sousa (slide 36). */ float side_angle = M_2PI / sides_count; return cos(side_angle * 0.5) / cos(theta - side_angle * floor((sides_count * theta + M_PI) / M_2PI)); } /* Remap input angle to have homogenous spacing of points along a polygon edge. * Expect theta to be in [0..2pi] range. * Outputs corrected theta. */ float circle_to_polygon_angle(float sides_count, float theta) { float side_angle = M_2PI / sides_count; float side = floor(theta / side_angle); float halfside_angle = side_angle * 0.5; /* Length of segment from center to the middle of polygon side. */ float adjacent = circle_to_polygon_radius(sides_count, halfside_angle); /* This is the relative position of the sample on the polygon half side. */ float local_theta = theta - side * side_angle; float ratio = (local_theta - halfside_angle) / halfside_angle; float halfside_len = polygon_sides_length(sides_count) * 0.5; float oposite = ratio * halfside_len; float final_local_theta = halfside_angle + (atan(oposite / adjacent)); return side * side_angle + final_local_theta; }