// --------------------------------------------------------------------
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// --------------------------------------------------------------------

package tinylib.primitives;

// Cone
//
// # of vertexes (quality=0; tetrahedron ): 4
// # of faces (quality=0): 4
//
// UV mapping(quality=0): .. i gave up to write mapping ... orz
// 0      0.5      1
// +-------+-------+
// |       |       |
// | bottom|       |
// |       | cone  |
// |   face|       |
// |       |       |
// |       |       |
// |       |       |
// |       |       |
// +-------+-------+

/**
  Cone
**/

class Cone3D extends Cylinder {
  public function new( ?r:Float,
                       ?h:Float,
                       ?quality:Int = 0 ) {
    super( 0.0, 0.0 );
    h *= 0.5;
    var qr3:Int = quality + 3;
    var pi2:Float = Math.PI * 2.0;
    var v:Array< Point3D > = new Array< Point3D >();
    for ( i in 0 ... qr3 ) {
      var x:Float = pi2 * i / qr3;
      v.push( new Point3D( r * Math.sin( x ), -h, r * Math.cos( x ) ) );
    }
    v.push( new Point3D( 0, h, 0 ) );

    var idx:Array< Int > = new Array< Int >();
    for ( i in 0 ... qr3 ) idx.push( i );
    idx.push( qr3 );
    for ( i in 0 ... qr3 ) idx.push( i ); // for bottom face
    for ( i in idx ) addVertexPos( v[i] );

    // UV
    var uh:Float = 1.0 / cast( qr3, Float );
    var uvm:Array< UVCoord > = new Array< UVCoord >();
    var uvl:Array< UVCoord > = new Array< UVCoord >();
    for ( i in 0 ... qr3 + 1 ) {
      uvm.push( new UVCoord( 0.5, 1.0 - uh * i ) );
      if ( i != qr3 ) {
        uvl.push( new UVCoord( 0.0, 1.0 - uh * ( i + 0.5 ) ) );
      }
    }
    var uvm2:Array< UVCoord > = new Array< UVCoord >();
    var uvt:Array< UVCoord > = new Array< UVCoord >();
    uh = 1.0 / ( quality + 1 );
    for ( i in 0 ... quality + 2 ) {
      uvm2.push( new UVCoord( 0.5, 1.0 - uh * i ) );
      if ( i != quality + 1 ) uvt.push( new UVCoord( 1.0, 1.0 - uh * ( i + 0.5 ) ) );
    }

    // Faces
    var tp = qr3;
    for ( i in 0 ... qr3 ) {
      var toi1 = (i==qr3-1) ? 0 : i + 1;
      addFace( new Face( tp, i, toi1, uvl[i], uvm[i], uvm[i+1] ) );
    }
    tp = qr3 + 1;
    for ( i in 0 ... quality + 1 ) {
      var toi = tp + 1 + i;
      addFace( new Face( tp, toi+1, toi, uvt[i], uvm2[i+1], uvm2[i] ) );
    }
  }
}
