TorusKnotGeometry function

GeometryBuilder TorusKnotGeometry({
  1. double radius = 20.0,
  2. double tubeRadius = 4.0,
  3. int segmentsR = 128,
  4. int segmentsT = 16,
  5. int p = 2,
  6. int q = 3,
  7. double heightScale = 1.0,
  8. bool wrap = false,
  9. bool computeUVs = true,
  10. bool computeNormals = true,
  11. bool inside = false,
})

q == 0 and p == 1 results in a torus

Implementation

GeometryBuilder TorusKnotGeometry(
    {double radius = 20.0,
    double tubeRadius = 4.0,
    int segmentsR = 128,
    int segmentsT = 16,
    int p = 2,
    int q = 3,
    double heightScale = 1.0,
    // wrap false => start and end node are separate vertices
    bool wrap = false,
    bool computeUVs = true,
    bool computeNormals = true,
    bool inside = false}) {
  void curveFunc(double u, VM.Vector3 out) {
    TorusKnotGetPos(u, q, p, radius, heightScale, out);
  }

  final List<VM.Vector3> pointsAndTangents = ParametricCurvePointsAndTangents(
      curveFunc, 0.0, 2.0 * Math.pi, segmentsR,
      halfOpen: true);
  if (!wrap) {
    pointsAndTangents.add(pointsAndTangents[0]);
    pointsAndTangents.add(pointsAndTangents[1]);
  }
  final int h = segmentsR + (wrap ? 0 : 1);
  assert(pointsAndTangents.length == 2 * h);

  final List<List<VM.Vector3>> bands =
      TubeHullBands(pointsAndTangents, segmentsT, tubeRadius);
  if (!wrap) {
    for (List<VM.Vector3> b in bands) {
      b.add(b[0]);
      b.add(b[1]);
    }
  }
  assert(bands.length == h);
  final int w = segmentsT + (wrap ? 0 : 1);

  assert(bands[0].length == 2 * w);

  final GeometryBuilder gb = GeometryBuilder();

  for (List<VM.Vector3> lst in bands) {
    for (int i = 0; i < lst.length; i += 2) {
      gb.AddVertexTakeOwnership(lst[i]);
    }
  }
  assert(gb.vertices.length == w * h);

  gb.GenerateRegularGridFaces(w, h, wrap, inside);

  if (computeUVs) {
    assert(!wrap, "uvs do not work well with wrapping");
    gb.GenerateRegularGridUV(w, h);
    assert(gb.attributes[aTexUV]?.length == gb.vertices.length);
  }

  if (computeNormals) {
    gb.EnableAttribute(aNormal);
    for (List<VM.Vector3> lst in bands) {
      for (int i = 0; i < lst.length; i += 2) {
        gb.AddAttributeVector3(aNormal, lst[i + 1]);
      }
    }
    assert(gb.attributes[aNormal]?.length == gb.vertices.length);
  }
  return gb;
}