anchor.diff:    for (int i = 0; i < radialSubdivisions; i++) {
       double u = i / radialSubdivisions;
   
  -    double xposTop = radiusTop * Math.sin(u * Math.PI * 2);
  -    double zposTop = radiusTop * Math.cos(u * Math.PI * 2);
  -    double xposBot = radiusBot * Math.sin(u * Math.PI * 2);
  -    double zposBot = radiusBot * Math.cos(u * Math.PI * 2);
  +    double x = Math.sin(u * Math.PI * 2);
  +    double z = Math.cos(u * Math.PI * 2);
   
  -    vertices.add(new VM.Vector3(xposTop, halfHeight, zposTop));
  -    uvs.add(new VM.Vector2(u, u));
  -    vertices.add(new VM.Vector3(xposBot, -halfHeight, zposBot));
  -    uvs.add(new VM.Vector2(1.0, u));
  +    vertices.add(new VM.Vector3(x * radTop, halfHeight, z * radTop));
  +    uvs.add(new VM.Vector2(u, 1.0));
  +    vertices.add(new VM.Vector3(x * radBot, -halfHeight, z * radBot));
  +    uvs.add(new VM.Vector2(u, 0.0));
  +  }
  +  assert (vertices.length == 2 + 2 * radialSubdivisions);
   
  -    if (i > 0) {
  -      int p = (i * 2) + 2; // add offset for "top center" and "bottom center"
  -      // triangle in top circle
  -      md.AddFace3(0, p - 2, p);
  -      // triangle in bottom circle
  -      md.AddFace3(1, p - 1, p + 1);
  -      // triangle from two verts top to one vert bottom
  -      md.AddFace3(p - 2, p, p + 1);
  -      // triangle from two verts bottom to one vert top
  -      md.AddFace3(p - 1, p + 1, p - 2);
  -    }
  -  }
  -
  -  // close the last gap
  -  if (true) {
  -    var i = radialSubdivisions;
  -    var p = (i * 2) + 2;
  +  // 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
  -    md.AddFace3(0, p - 2, 2);
  +    md.AddFace3(0, t, tnext);
       // triangle in bottom circle
  -    md.AddFace3(1, p - 1, 3);
  +    md.AddFace3(1, b, bnext);
       // triangle from two verts top to one vert bottom
  -    md.AddFace3(p - 2, 2, 3);
  +    md.AddFace3(tnext, t, b);
       // triangle from two verts bottom to one vert top
  -    md.AddFace3(p - 1, 3, p - 2);
  +    md.AddFace3(b, bnext, tnext);
     }
   
     md.AddVertices(vertices);
  
positive.code: // uv mapping is weird to help with debugging
  
  MeshData createCylinderInternal(
      double radiusTop, double radiusBot, double height, int radialSubdivisions) {
    MeshData md = new MeshData();
    md.name = "cylinder";
    md.EnableAttribute(aTextureCoordinates);
  
negative.code: 
    md.AddFaces4(radialSubdivisions);
    for (int i = 0; i < radialSubdivisions; i++) {
      md.AddVertices([top[i + 1], top[i], bot[i], bot[i + 1]]);
      // TODO: fix these
      md.AddAttributesVector2(aTextureCoordinates, [zero, zero, zero, zero]);
    }
  