CylinderGeometry function

GeometryBuilder CylinderGeometry(
  1. double radTop,
  2. double radBot,
  3. double height,
  4. int radialSubdivisions,
  5. bool computeNormals,
)

Implementation

GeometryBuilder CylinderGeometry(double radTop, double radBot, double height,
    int radialSubdivisions, bool computeNormals) {
  assert (radialSubdivisions >2, "must have at least 3 divisions");
  double halfHeight = height / 2;

  List<VM.Vector3> vertices = [];
  List<VM.Vector2> uvs = [];
  List<VM.Vector3> normal = [];
  // top center
  vertices.add(VM.Vector3(0.0, halfHeight, 0.0));
  uvs.add(VM.Vector2(0.0, 0.0));
  if (computeNormals) normal.add(VM.Vector3(0.0, 1.0, 0.0));
  // bottom center
  vertices.add(VM.Vector3(0.0, -halfHeight, 0.0));
  uvs.add(VM.Vector2(1.0, 1.0));
  if (computeNormals) normal.add(VM.Vector3(0.0, -1.0, 0.0));

  // First round for disks
  for (int i = 0; i < radialSubdivisions; i++) {
    double u = i / radialSubdivisions;

    double x = Math.sin(u * Math.pi * 2);
    double z = Math.cos(u * Math.pi * 2);

    vertices.add(VM.Vector3(x * radTop, halfHeight, z * radTop));
    uvs.add(VM.Vector2(u, 1.0));
    if (computeNormals) normal.add(VM.Vector3(0.0, 1.0, 0.0));
    vertices.add(VM.Vector3(x * radBot, -halfHeight, z * radBot));
    uvs.add(VM.Vector2(u, 0.0));
    if (computeNormals) normal.add(VM.Vector3(0.0, -1.0, 0.0));
  }

  if (computeNormals) {
    assert(vertices.length == 2 + 2 * radialSubdivisions);
    assert(uvs.length == 2 + 2 * radialSubdivisions);
    // Second set of vertices for walls with different normals
    for (int i = 0; i < 2 * radialSubdivisions; i += 2) {
      vertices.add(vertices[i + 2]);
      vertices.add(vertices[i + 3]);
      uvs.add(uvs[i + 2]);
      uvs.add(uvs[i + 3]);
      // Now compute normals
      VM.Vector3 a = vertices[i + 2];
      VM.Vector3 b = vertices[i + 3];
      // note: we added vertices so we will not access out  of bounds
      VM.Vector3 c = vertices[i + 4];
      VM.Vector3 temp = VM.Vector3.zero();
      VM.Vector3 norm = VM.Vector3.zero();
      NormalFromPoints(a, b, c, temp, norm);
      normal.add(norm);
      normal.add(norm);
    }
    assert(vertices.length == 2 + 4 * radialSubdivisions);
  } else {
    assert(vertices.length == 2 + 2 * radialSubdivisions);
  }
  GeometryBuilder gb = GeometryBuilder();
  gb.EnableAttribute(aTexUV);
  gb.AddVertices(vertices);
  gb.AddAttributesVector2(aTexUV, uvs);
  if (computeNormals) {
    gb.EnableAttribute(aNormal);
    gb.AddAttributesVector3(aNormal, normal);
  }
  // triangles for top and bottom
  for (int i = 0; i < radialSubdivisions; i++) {
    final int t = (i * 2) + 2; // top node
    final int b = t + 1; // bot node
    int j = i + 1;
    if (j == radialSubdivisions) j = 0;
    final int tnext = (j * 2) + 2;
    final int bnext = tnext + 1;
    // triangle in top circle
    gb.AddFace3(0, t, tnext);
    // triangle in bottom circle
    gb.AddFace3(1, bnext, b);

    // Wall
    int o = computeNormals ? radialSubdivisions * 2 : 0;
    gb.AddFace4(o + tnext, o + t, o + b, o + bnext);
  }
  return gb;
}