// Sphere class
//
// # of vertexes(quality=0): 5
// # of faces(triangle): 6
//
// UV mapping:
// 0      0.5      1
// +-------+-------+
// |       |       |
// | bottom|       |
// |       | top   |
// |       |       |
// |       |       |
// |       |       |
// |       |       |
// |       |       |
// +-------+-------+
//
//  (dead space will exist on corners)

class Sphere3D extends Polygon {
  public function new( ?r:Float = 1.0,
                       ?quality:Int = 3 ) {
    super();
    var q3:Int = quality + 3;
    var pi2:Float = Math.PI * 2.0;

    // vertexes
    var v:Array< Point3D > = new Array< Point3D >();
    for ( i in 0 ... q3 ) {
      var x:Float = pi2 * i / q3;
      addVertexPos( new Point3D( r * Math.sin( x ), 0.0, r * Math.cos( x ) ) );
    }
    addVertexPos( new Point3D( 0.0, 0.0, r ) );
    addVertexPos( new Point3D( 0, -r, 0 ) );
    addVertexPos( new Point3D( 0, r, 0 ) );

    // uv
    var uh:Float = 1.0 / cast( q3, Float );
    var uvm:Array< UVCoord > = new Array< UVCoord >();
    for ( i in 0 ... q3 + 1 ) {
      uvm.push( new UVCoord( 0.5, 1.0 - uh * i ) );
    }
    var uvb:Array< UVCoord > = new Array< UVCoord >();
    for ( i in 0 ... q3 ) {
      uvb.push( new UVCoord( 0.0, 1.0 - ( 0.5 + i ) / q3 ) );
    }
    var uvt:Array< UVCoord > = new Array< UVCoord >();
    for ( i in 0 ... q3 ) {
      uvt.push( new UVCoord( 1.0, 1.0 - ( 0.5 + i ) / q3 ) );
    }
    var tp = q3 + 1;
    var o:Point3D = new Point3D( 0, 0, 0 );
    for ( i in 0 ... q3 ) {
      addFaceRecursively0( quality,
                           new Face( tp, i + 1, i,
                                     uvb[i], uvm[i+1], uvm[i] ), r, o );
    }
    tp = tp + 1;
    for ( i in 0 ... q3 ) {
      addFaceRecursively0( quality,
                           new Face( tp, i, i + 1,
                                     uvt[i], uvm[i], uvm[i+1] ), r, o );
    }
  }

  public override function addVertexNormals():Void {
    for ( vert in verts ) {
      var v:Point3D = Point3D.getSub( vert.pos, origin );
      v.normalize();
      vert.normal = v;
    }
  }
}
