TorusKnotGeometryTriangularWireframeFriendly function

GeometryBuilder TorusKnotGeometryTriangularWireframeFriendly({
  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 inside = false,
})

Like TorusKnotGeometryWireframeFriendly but with triangles rather than quads.

Implementation

GeometryBuilder TorusKnotGeometryTriangularWireframeFriendly(
    {double radius = 20.0,
    double tubeRadius = 4.0,
    int segmentsR = 128,
    int segmentsT = 16,
    int p = 2,
    int q = 3,
    double heightScale = 1.0,
    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);
  pointsAndTangents.add(pointsAndTangents[0]);
  pointsAndTangents.add(pointsAndTangents[1]);
  final int h = segmentsR + 1;
  assert(pointsAndTangents.length == 2 * h);
  final List<List<VM.Vector3>> bands =
      TubeHullBands(pointsAndTangents, segmentsT, tubeRadius);
  for (List<VM.Vector3> b in bands) {
    b.add(b[0]);
    b.add(b[1]);
  }
  assert(bands.length == h);

  final GeometryBuilder gb = GeometryBuilder();

  for (int i = 0; i < segmentsR; ++i) {
    for (int j = 0; j < segmentsT; j += 2) {
      final int jp = j + (i % 2) * 3;
      gb.AddFaces3(2, inside);
      VM.Vector3 b(int x, int y) => bands[x % segmentsR][(y % segmentsT) * 2];

      gb.AddVerticesTakeOwnership([b(i, jp + 2), b(i + 1, jp + 1), b(i, jp)]);

      gb.AddVerticesTakeOwnership(
          [b(i + 1, jp + 3), b(i + 1, jp + 1), b(i, jp + 2)]);
    }
  }

  return gb;
}