CylinderGeometry constructor

CylinderGeometry([
  1. dynamic radiusTop = 1,
  2. dynamic radiusBottom = 1,
  3. dynamic height = 1,
  4. dynamic radialSegments = 8,
  5. dynamic heightSegments = 1,
  6. bool openEnded = false,
  7. dynamic thetaStart = 0,
  8. dynamic thetaLength = Math.pi * 2,
])

Implementation

CylinderGeometry([
  radiusTop = 1,
  radiusBottom = 1,
  height = 1,
  radialSegments = 8,
  heightSegments = 1,
  bool openEnded = false,
  thetaStart = 0,
  thetaLength = Math.pi * 2,
]) : super() {
  type = "CylinderGeometry";
  parameters = {
    "radiusTop": radiusTop,
    "radiusBottom": radiusBottom,
    "height": height,
    "radialSegments": radialSegments,
    "heightSegments": heightSegments,
    "openEnded": openEnded,
    "thetaStart": thetaStart,
    "thetaLength": thetaLength
  };

  var scope = this;

  radialSegments = Math.floor(radialSegments);
  heightSegments = Math.floor(heightSegments);

  // buffers

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

  // helper variables

  var index = 0;
  var indexArray = [];
  var halfHeight = height / 2;
  var groupStart = 0;

  // generate geometry

  generateTorso() {
    var normal = Vector3.init();
    var vertex = Vector3.init();

    var groupCount = 0;

    // this will be used to calculate the normal
    var slope = (radiusBottom - radiusTop) / height;

    // generate vertices, normals and uvs

    for (var y = 0; y <= heightSegments; y++) {
      var indexRow = [];

      var v = y / heightSegments;

      // calculate the radius of the current row

      var radius = v * (radiusBottom - radiusTop) + radiusTop;

      for (var x = 0; x <= radialSegments; x++) {
        var u = x / radialSegments;

        var theta = u * thetaLength + thetaStart;

        var sinTheta = Math.sin(theta);
        var cosTheta = Math.cos(theta);

        // vertex

        vertex.x = radius * sinTheta;
        vertex.y = -v * height + halfHeight;
        vertex.z = radius * cosTheta;
        vertices.addAll([vertex.x.toDouble(), vertex.y.toDouble(), vertex.z.toDouble()]);

        // normal

        normal.set(sinTheta, slope, cosTheta).normalize();
        normals.addAll([normal.x.toDouble(), normal.y.toDouble(), normal.z.toDouble()]);

        // uv

        uvs.addAll([u, 1 - v]);

        // save index of vertex in respective row

        indexRow.add(index++);
      }

      // now save vertices of the row in our index array

      indexArray.add(indexRow);
    }

    // generate indices

    for (var x = 0; x < radialSegments; x++) {
      for (var y = 0; y < heightSegments; y++) {
        // we use the index array to access the correct indices

        var a = indexArray[y][x];
        var b = indexArray[y + 1][x];
        var c = indexArray[y + 1][x + 1];
        var d = indexArray[y][x + 1];

        // faces

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

        // update group counter

        groupCount += 6;
      }
    }

    // add a group to the geometry. this will ensure multi material support

    scope.addGroup(groupStart, groupCount, 0);

    // calculate new start value for groups

    groupStart += groupCount;
  }

  generateCap(top) {
    // save the index of the first center vertex
    var centerIndexStart = index;

    var uv = Vector2(null, null);
    var vertex = Vector3.init();

    var groupCount = 0;

    var radius = (top == true) ? radiusTop : radiusBottom;
    var sign = (top == true) ? 1 : -1;

    // first we generate the center vertex data of the cap.
    // because the geometry needs one set of uvs per face,
    // we must generate a center vertex per face/segment

    for (var x = 1; x <= radialSegments; x++) {
      // vertex

      vertices.addAll([0, halfHeight * sign, 0]);

      // normal

      normals.addAll([0, sign.toDouble(), 0]);

      // uv

      uvs.addAll([0.5, 0.5]);

      // increase index

      index++;
    }

    // save the index of the last center vertex
    var centerIndexEnd = index;

    // now we generate the surrounding vertices, normals and uvs

    for (var x = 0; x <= radialSegments; x++) {
      var u = x / radialSegments;
      var theta = u * thetaLength + thetaStart;

      var cosTheta = Math.cos(theta);
      var sinTheta = Math.sin(theta);

      // vertex

      vertex.x = radius * sinTheta;
      vertex.y = halfHeight * sign;
      vertex.z = radius * cosTheta;
      vertices.addAll([vertex.x.toDouble(), vertex.y.toDouble(), vertex.z.toDouble()]);

      // normal

      normals.addAll([0, sign.toDouble(), 0]);

      // uv

      uv.x = (cosTheta * 0.5) + 0.5;
      uv.y = (sinTheta * 0.5 * sign) + 0.5;
      uvs.addAll([uv.x.toDouble(), uv.y.toDouble()]);

      // increase index

      index++;
    }

    // generate indices

    for (var x = 0; x < radialSegments; x++) {
      var c = centerIndexStart + x;
      var i = centerIndexEnd + x;

      if (top == true) {
        // face top

        indices.addAll([i, i + 1, c]);
      } else {
        // face bottom

        indices.addAll([i + 1, i, c]);
      }

      groupCount += 3;
    }

    // add a group to the geometry. this will ensure multi material support

    scope.addGroup(groupStart, groupCount, top == true ? 1 : 2);

    // calculate new start value for groups

    groupStart += groupCount;
  }

  generateTorso();

  if (openEnded == false) {
    if (radiusTop > 0) generateCap(true);
    if (radiusBottom > 0) generateCap(false);
  }

  // build geometry

  setIndex(indices);
  setAttribute('position', Float32BufferAttribute(Float32Array.from(vertices), 3, false));
  setAttribute('normal', Float32BufferAttribute(Float32Array.from(normals), 3, false));
  setAttribute('uv', Float32BufferAttribute(Float32Array.from(uvs), 2, false));
}