LatheGeometry constructor

LatheGeometry(
  1. List<Vector2> points, {
  2. int segments = 12,
  3. double phiStart = 0,
  4. double phiLength = math.pi * 2,
})

points — Array of Vector2s. The x-coordinate of each point must be greater than zero. Default is an array with (0,-0.5), (0.5,0) and (0,0.5) which creates a simple diamond shape.

segments — the number of circumference segments to generate. Default is 12.

phiStart — the starting angle in radians. Default is 0.

phiLength — the radian (0 to 2PI) range of the lathed section 2PI is a closed lathe, less than 2PI is a portion. Default is 2PI.

Implementation

LatheGeometry(List<Vector2> points,{int segments = 12, double phiStart = 0, double phiLength = math.pi * 2}): super() {
  type = 'LatheGeometry';
  parameters = {
    "points": points,
    "segments": segments,
    "phiStart": phiStart,
    "phiLength": phiLength
  };

  segments = segments.floor();

  // clamp phiLength so it's in range of [ 0, 2PI ]

  phiLength = MathUtils.clamp(phiLength, 0, math.pi * 2);

  // buffers

  final indices = [];
  List<double> vertices = [];
  List<double> uvs = [];
  final initNormals = [];
  List<double> normals = [];

  // helper variables

  final inverseSegments = 1.0 / segments;
  final vertex = Vector3.zero();
  final uv = Vector2.zero();
  final normal = Vector3.zero();
  final curNormal = Vector3.zero();
  final prevNormal = Vector3.zero();
  double dx = 0;
  double dy = 0;

  // pre-compute normals for initial "meridian"

  for (int j = 0; j <= (points.length - 1); j++) {
    // special handling for 1st vertex on path
    if (j == 0) {
      dx = points[j + 1].x - points[j].x;
      dy = points[j + 1].y - points[j].y;

      normal.x = dy * 1.0;
      normal.y = -dx;
      normal.z = dy * 0.0;

      prevNormal.setFrom(normal);

      normal.normalize();

      initNormals.addAll([normal.x, normal.y, normal.z]);
    } else if (j == points.length - 1) {
      // special handling for last Vertex on path
      initNormals.addAll([prevNormal.x, prevNormal.y, prevNormal.z]);
    } else {
      // default handling for all vertices in between
      dx = points[j + 1].x - points[j].x;
      dy = points[j + 1].y - points[j].y;

      normal.x = dy * 1.0;
      normal.y = -dx;
      normal.z = dy * 0.0;

      curNormal.setFrom(normal);

      normal.x += prevNormal.x;
      normal.y += prevNormal.y;
      normal.z += prevNormal.z;

      normal.normalize();

      initNormals.addAll([normal.x, normal.y, normal.z]);

      prevNormal.setFrom(curNormal);
    }
  }

  // generate vertices, uvs and normals

  // generate vertices and uvs

  for (int i = 0; i <= segments; i++) {
    final phi = phiStart + i * inverseSegments * phiLength;

    final sin = math.sin(phi);
    final cos = math.cos(phi);

    for (int j = 0; j <= (points.length - 1); j++) {
      // vertex

      vertex.x = points[j].x * sin;
      vertex.y = points[j].y;
      vertex.z = points[j].x * cos;

      vertices.addAll(
          [vertex.x.toDouble(), vertex.y.toDouble(), vertex.z.toDouble()]);

      // uv

      uv.x = i / segments;
      uv.y = j / (points.length - 1);

      uvs.addAll([uv.x.toDouble(), uv.y.toDouble()]);

      // normal

      final x = initNormals[3 * j + 0] * sin;
      final y = initNormals[3 * j + 1];
      final z = initNormals[3 * j + 0] * cos;

      normals.addAll([x, y, z]);
    }
  }

  // indices

  for (int i = 0; i < segments; i++) {
    for (int j = 0; j < (points.length - 1); j++) {
      final base = j + i * points.length;

      final a = base;
      final b = base + points.length;
      final c = base + points.length + 1;
      final d = base + 1;

      // faces

      indices.addAll([a, b, d]);
      indices.addAll([c, d, b]);
    }
  }

  // build geometry

  setIndex(indices);
  setAttribute(Attribute.position, Float32BufferAttribute.fromList(vertices, 3, false));
  setAttribute(Attribute.uv, Float32BufferAttribute.fromList(uvs, 2, false));
  setAttribute(Attribute.normal,Float32BufferAttribute.fromList(normals, 3, false));
}