mathgeometryglm-mathtesselation

Tesselation of the circle in OpenGL


I'm having trouble understanding the math behind this function. I would like to hear the logic behind the formulas (especially what is this tangential and radial factor) written here to create points which later (when it send the vec3 array to a function) form a circle in OpenGL.

void doTesselate(const Arc& arc, int slices, std::vector<glm::vec3>& vertices)
{
  double dang = (arc.endAngle() - arc.startAngle()) * Deg2Rad;

  double radius = arc.radius();
  double angIncr = dang / slices;

  double tangetial_factor = tan(angIncr);
  double radial_factor = 1 - cos(angIncr);

  double startAngle = arc.startAngle() * Deg2Rad;
  const glm::vec3& center = arc.center();

  double x = center.x - radius * cos(startAngle);
  double y = center.y - radius * sin(startAngle);

  ++slices;
  for (int ii = 0; ii < slices; ii++) {
    vertices.push_back(glm::vec3(x, y, center.z));

    double tx = center.y - y;
    double ty = x - center.x;

    x += tx * tangetial_factor;
    y += ty * tangetial_factor;

    double rx = center.x - x;
    double ry = center.y - y;

    x += rx * radial_factor;
    y += ry * radial_factor;
  }
}

Solution

  • The idea is the following:

    Visualization

    Starting from the current point, you go a bit in tangential direction and then back towards the center.

    The vector (tx, ty) is the tangent at the current point with length equal to the radius. In order to get to the new angle, you have to move tan(angle) * radius along the tangent. radius is already incorporated in the tangent vector and tan(angle) is the tangetial_factor (you get that directly from tangent's definition).

    After that, (rx, ry) is the vector towards the center. This vector has the length l:

    cos(angle) = radius / l
    l = radius / cos(angle)
    

    We need to find a multiple m of this vector, such that the corrected point lies on the circle with the given radius again. If we just inspect the lengths, then we want to find:

    target distance = current distance    - m * length of (rx, ry)
             radius = radius / cos(angle) - m * radius / cos(angle)
                  1 = (1 - m) / cos(angle)
         cos(angle) = 1 - m
     1 - cos(angle) = m
    

    And this multiple is exactly the radial_factor (the amount which you need to move towards the center to get onto the circle).