//max_points=80;

int res=10;lowres=10;medres=20;hires=40;vhires=50; // nurb resolution

enum knottype {open,periodic};
enum captype  {nurbFRONT,nurbBACK};

//float uknots[83];
//int numuknots;


void init_knots(int order,enum knottype  vector,int numcontrol,  int *numknots, float knots[])
{
	int i;
// #knots = #control points + order of NURB - assuming quadratic or cubic
	switch (vector) {
	case open:	if (order==3){
		     *numknots=numcontrol+3;
	         knots[0]=0.0;knots[1]=0.0;knots[2]=0.0;
	         for (i=3;i<=numcontrol-1;i++)
		          knots[i]=(i-2);
	         knots[numcontrol]=numcontrol-2;knots[numcontrol+1]=numcontrol-2;
		     knots[numcontrol+2]=numcontrol-2;
			}
	        else if (order==4){
            *numknots=numcontrol+4;
	        knots[0]=0.0;knots[1]=0.0;knots[2]=0.0;knots[3]=0.0;
	        for (i=4;i<=numcontrol-1;i++)
		      knots[i]=(i-3);
	        knots[numcontrol]=numcontrol-2;knots[numcontrol+1]=numcontrol-2;
		    knots[numcontrol+2]=numcontrol-2;knots[numcontrol+3]=numcontrol-2;
			}
			break;
	case periodic:if (order==3){
		      *numknots=numcontrol+5;
	  	      for (i=0;i<numcontrol+5;i++)
		       knots[i]=i;
		   }
		   else if (order==4){
			  *numknots=numcontrol+7;
	  	      for (i=0;i<numcontrol+7;i++)
		       knots[i]=i;
		   }
           break;
	}


}
       


void init_curve(int order,int last_index, float sil[][2] ,float curvectlpoints[][3])  // for surfaces of revolution
{
	int j;

	for (j=0;j<=last_index;j++)
	{       curvectlpoints[j][2] =0.0;
		    curvectlpoints[j][1] =sil[j][1];
            curvectlpoints[j][0] =sil[j][0];
    }

       
       
}

void init_periodic_curve(int order,int last_index, float sil[][2], float curvectlpoints[][3])  // for surfaces of revolution
{
	int j;

	for (j=0;j<=last_index;j++)
	{      curvectlpoints[j][2] =0.0;
		   curvectlpoints[j][1] =sil[j][1];
           curvectlpoints[j][0] =sil[j][0];
           			
	}
	if (order==4){
	 curvectlpoints[last_index+1][2] =0.0;
     curvectlpoints[last_index+1][1] =sil[0][1];
	 curvectlpoints[last_index+1][0] =sil[0][0];
	
	 curvectlpoints[last_index+2][2] =0.0;
     curvectlpoints[last_index+2][1] =sil[1][1];
	 curvectlpoints[last_index+2][0] =sil[1][0];

	 curvectlpoints[last_index+3][2] =0.0;
     curvectlpoints[last_index+3][1] =sil[2][1];
	 curvectlpoints[last_index+3][0] =sil[2][0];
	}
	
	else if (order==3){
     curvectlpoints[last_index+1][2] =0.0;
     curvectlpoints[last_index+1][1] =sil[0][1];
	 curvectlpoints[last_index+1][0] =sil[0][0];
	
	 curvectlpoints[last_index+2][2] =0.0;
     curvectlpoints[last_index+2][1] =sil[1][1];
	 curvectlpoints[last_index+2][0] =sil[1][0];
	 }
	    

        
}






void nurbSilhouette(int order,int vector,int last_index, float sil[][2])
{

	float uknots[83];  /////////////////test
    int numuknots;    //test
	float curvectlpoints[80][3];
    
	GLUnurbsObj *theNurb;
    
	if (last_index>2){

    init_knots(order,vector,last_index+1,&numuknots,&uknots[0]);
	if (vector==open) init_curve(order,last_index,&sil[0][0],&curvectlpoints[0][0]);
	 	else if (vector==periodic) 
			init_periodic_curve(order,last_index,&sil[0][0],&curvectlpoints[0][0]);
      
	
	   

    theNurb = gluNewNurbsRenderer();
	gluNurbsProperty(theNurb,GLU_SAMPLING_METHOD, GLU_DOMAIN_DISTANCE);
	gluNurbsProperty(theNurb,GLU_U_STEP,res);



 
     gluBeginCurve(theNurb);
	         gluNurbsCurve(theNurb, 
             numuknots,
			 uknots,    // number  and knots in u dir
             3,       // u stride
             &curvectlpoints[0][0],  //control points
             order,                // order of nurbs
             GL_MAP1_VERTEX_3);
	 gluEndCurve(theNurb);

 
	gluDeleteNurbsRenderer(theNurb);
    glFlush();
	}

} 



//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////     nurb functions         ////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////



void nurbSurfRevOpen(int order,int numsilpts, float sil[][2])  // no dependencies
{
	GLUnurbsObj *theNurb;
	GLfloat uknots[12] = {0.0, 0.0, 0.0,0.25,0.25,0.5,0.5,0.75,0.75, 1.0,1.0, 1.0};
	float vknots[83];
	int numvknots;
	int last_index=numsilpts-1;
    float B[][3]= {   { 1.0, 0.0, 1.0},{ 0.707, 0.707, 0.707}
                 ,{ 0.0, 1.0, 1.0},{-0.707, 0.707, 0.707}
				 ,{-1.0, 0.0, 1.0},{-0.707,-0.707, 0.707}
				 ,{ 0.0,-1.0, 1.0},{ 0.707,-0.707, 0.707}
				 ,{ 1.0, 0.0, 1.0}};
    GLfloat ctlpoints[9][80][4];   //max_points
	GLfloat texctlpoints[9][80][2];
	int i,j,s;
    float len_sil,deltax,deltay,delta_length;
	float normalized_length[80];        //maxpoints
	   
    glEnable(GL_AUTO_NORMAL);
    glEnable(GL_NORMALIZE);

////////////////////////////// create knots  ////////////////////////  
	
    numvknots=numsilpts+order;
	if (order==4){
   	       vknots[0]=0.0;vknots[1]=0.0;vknots[2]=0.0;vknots[3]=0.0;
	       for (i=4;i<=numsilpts-1;i++)
	       vknots[i]=(i-3);
	       vknots[numsilpts]=numsilpts-3;vknots[numsilpts+1]=numsilpts-3;
	            vknots[numsilpts+2]=numsilpts-3;vknots[numsilpts+3]=numsilpts-3;
	}
	else if (order==3){
             vknots[0]=0.0;vknots[1]=0.0;vknots[2]=0.0;
	         for (i=3;i<=numsilpts-1;i++)
		          vknots[i]=(i-2);
	         vknots[numsilpts]=numsilpts-2;vknots[numsilpts+1]=numsilpts-2;
		         vknots[numsilpts+2]=numsilpts-2;
			}
	
///////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////// initialize control points ////////////////////////////////////
    
   	for (j=0;j<=last_index;j++)
	  for (i=0;i<9;i++) {
            ctlpoints[i][j][1] =sil[j][1]*B[8-i][2];
            ctlpoints[i][j][0] =sil[j][0]*B[8-i][0];
            ctlpoints[i][j][2] =sil[j][0]*B[8-i][1];
            ctlpoints[i][j][3] =B[8-i][2];
	   }
	
	
	
///////////////////////////////////////////////////////////////////
//            	generate texture coordinates                    //
///////////////////////////////////////////////////////////////////

	len_sil=0.0;normalized_length[0]=0.0;
	for (s = 0 ; s <= last_index - 1 ; s++) {
       deltax = (sil[s+1][0] - sil[s][0]);
	   deltay = (sil[s+1][1] - sil[s][1]);

	   delta_length = sqrt(deltax*deltax + deltay*deltay);
	   len_sil =len_sil+delta_length;
	   normalized_length[s+1]=len_sil;
	  };

	for (s=1 ; s<=last_index-1;s++) 
			normalized_length[s]=normalized_length[s]/len_sil;
	normalized_length[last_index]=1.0;

	
   	for (j=0;j<=last_index;j++)
	   for (i=0;i<9;i++) {
            texctlpoints[i][j][0] =(float)i/8.0;
            texctlpoints[i][j][1] =normalized_length[j];
	   }
	 
//////////////////////////////////////////////////////////////////////        
/////////////////////////// control points and knots finished ////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
    theNurb = gluNewNurbsRenderer();
//   gluNurbsProperty(theNurb, GLU_SAMPLING_TOLERANCE, 150.0);
	gluNurbsProperty(theNurb,GLU_SAMPLING_METHOD, GLU_DOMAIN_DISTANCE);
	gluNurbsProperty(theNurb,GLU_U_STEP,res);//120
	gluNurbsProperty(theNurb,GLU_V_STEP,res);//120
//    gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_OUTLINE_POLYGON);//GLU_FILL);
	gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_FILL);
    gluNurbsProperty(theNurb, GLU_CULLING, GLU_TRUE);
    
 
 

	
     
     gluBeginSurface(theNurb);
        gluNurbsSurface(theNurb, 
	   // #knots = #control points + order of NURB - using linear
            12, uknots,     // number  and knots in u dir
             numvknots, vknots,  //number and knots in v dir
            80* 2,       // u stride=#control points in v direction X size of data
            2,           //v stride
            &texctlpoints[0][0][0],  //texture coordinates
            3,order,                // order of  u nurbs and v nurbs
            GL_MAP2_TEXTURE_COORD_2);
        


        gluNurbsSurface(theNurb, 
            12, uknots,      // number  and knots in u dir
            numvknots, vknots,  //number and knots in v dir
            80 * 4,       // u stride=#control points in v direction X size of data
            4,           //v stride
            &ctlpoints[0][0][0],  //control points
            3,order,                // order of  u nurbs and v nurbs
            GL_MAP2_VERTEX_4);
		 
        gluEndSurface(theNurb);

    
	gluDeleteNurbsRenderer(theNurb);
    glFlush();
	 
	

} 


void nurbSurfRevPeriodic(int order,int numsilpts, float sil[][2])
{
	GLUnurbsObj *theNurb;
	GLfloat vknots[12] = {0.0, 0.0, 0.0,0.25,0.25,0.5,0.5,0.75,0.75, 1.0,1.0, 1.0};
	float uknots[83];
	int numuknots;
    float B[][3]= {   { 1.0, 0.0, 1.0},{ 0.707, 0.707, 0.707}
                 ,{ 0.0, 1.0, 1.0},{-0.707, 0.707, 0.707}
				 ,{-1.0, 0.0, 1.0},{-0.707,-0.707, 0.707}
				 ,{ 0.0,-1.0, 1.0},{ 0.707,-0.707, 0.707}
				 ,{ 1.0, 0.0, 1.0}};
    GLfloat ctlpoints[9][80][4];   //max_points
	GLfloat texctlpoints[9][80][2];
	int i,j,s;
    float len_sil,deltax,deltay,delta_length;
	float normalized_length[80];        //maxpoints
	int last_index=numsilpts-1;
	   
    glEnable(GL_AUTO_NORMAL);
    glEnable(GL_NORMALIZE);

////////////////////////////// create knots  //////////////////////// ;
	if (order==3){ 
       numuknots=numsilpts+2+order;
	   for (i=0;i<numuknots;i++)
		     uknots[i]=i;
	   }
	else if (order==4){
	  numuknots=numsilpts+3+order;
	  for (i=0;i<numuknots;i++)
		      uknots[i]=i;
	}
	
///////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////// initialize control points ////////////////////////////////////
    for (j=0;j<=last_index;j++)
	    for (i=0;i<9;i++) {
            ctlpoints[i][j][1] =sil[j][1]*B[8-i][2];
            ctlpoints[i][j][0] =sil[j][0]*B[8-i][0];
            ctlpoints[i][j][2] =sil[j][0]*B[8-i][1];
            ctlpoints[i][j][3] =B[8-i][2];
		}
	    
	 	
   for (i=0;i<9;i++) {
            ctlpoints[i][last_index+1][1] =ctlpoints[i][0][1];
            ctlpoints[i][last_index+1][0] =ctlpoints[i][0][0];
            ctlpoints[i][last_index+1][2] =ctlpoints[i][0][2];
            ctlpoints[i][last_index+1][3] =ctlpoints[i][0][3];
   }
  for (i=0;i<9;i++) {
            ctlpoints[i][last_index+2][1] =ctlpoints[i][1][1];
            ctlpoints[i][last_index+2][0] =ctlpoints[i][1][0];
            ctlpoints[i][last_index+2][2] =ctlpoints[i][1][2];
            ctlpoints[i][last_index+2][3] =ctlpoints[i][1][3];
  }
 if (order==4){ 
	       for (i=0;i<9;i++) {
            ctlpoints[i][last_index+3][1] =ctlpoints[i][2][1];
            ctlpoints[i][last_index+3][0] =ctlpoints[i][2][0];
            ctlpoints[i][last_index+3][2] =ctlpoints[i][2][2];
            ctlpoints[i][last_index+3][3] =ctlpoints[i][2][3];
		   }
 }
	   
		
	 
///////////////////////////////////////////////////////////////////
//            	generate texture coordinates                    //
///////////////////////////////////////////////////////////////////

    sil[last_index+1][0]=sil[0][0];
	sil[last_index+1][1]=sil[0][1];
	

 	len_sil=0.0;normalized_length[0]=0.0;
	for (s = 0 ; s <= last_index; s++) {
       deltax = (sil[s+1][0] - sil[s][0]);
	   deltay = (sil[s+1][1] - sil[s][1]);
   
	   delta_length = sqrt(deltax*deltax + deltay*deltay);
	   len_sil =len_sil+delta_length;
	   normalized_length[s+1]=len_sil;
	  };

	for (s=1 ; s<=last_index+1;s++) 
			normalized_length[s]=normalized_length[s]/len_sil;
    
	for (j=0;j<=last_index;j++)
	   for (i=0;i<9;i++) {
            texctlpoints[i][j][0] =(float)i/8.0;
            texctlpoints[i][j][1] =normalized_length[j];
	   }

   for (i=0;i<9;i++) {
       texctlpoints[i][last_index+1][0] =(float)i/8.0;
       texctlpoints[i][last_index+1][1] =1.0;
       texctlpoints[i][last_index+2][0] =(float)i/8.0;
       texctlpoints[i][last_index+2][1] =1.0+normalized_length[1];
	   if (order==4)
	   {
	   texctlpoints[i][last_index+3][0] =(float)i/8.0;
       texctlpoints[i][last_index+3][1] =1.0+normalized_length[2];
	   }
   }
	 
//////////////////////////////////////////////////////////////////////        
/////////////////////////// control points and knots finished ////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
    theNurb = gluNewNurbsRenderer();
//   gluNurbsProperty(theNurb, GLU_SAMPLING_TOLERANCE, 150.0);
	gluNurbsProperty(theNurb,GLU_SAMPLING_METHOD, GLU_DOMAIN_DISTANCE);
	gluNurbsProperty(theNurb,GLU_U_STEP,res);//120
	gluNurbsProperty(theNurb,GLU_V_STEP,res);//120
//    gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_OUTLINE_POLYGON);//GLU_FILL);
	gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_FILL);
    gluNurbsProperty(theNurb, GLU_CULLING, GLU_TRUE);
   
 
 

	
     
     gluBeginSurface(theNurb);
        gluNurbsSurface(theNurb, 
	   // #knots = #control points + order of NURB - using linear
            12, vknots,     // number  and knots in u dir
             numuknots, uknots,  //number and knots in v dir
            80* 2,       // u stride=#control points in v direction X size of data
            2,           //v stride
            &texctlpoints[0][0][0],  //control points
            3,order,                // order of nurbs
            GL_MAP2_TEXTURE_COORD_2);
        


        gluNurbsSurface(theNurb, 
            12, vknots,      // number  and knots in u dir
            numuknots, uknots,  //number and knots in v dir
            80 * 4,       // u stride=#control points in v direction X size of data
            4,           //v stride
            &ctlpoints[0][0][0],  //control points
            3,order,                // order of nurbs
            GL_MAP2_VERTEX_4);
		 
        gluEndSurface(theNurb);

    
	gluDeleteNurbsRenderer(theNurb);
    glFlush();
	 
	
 
} 




void nurbExtSidesOpen(int order,int numsilpts, float sil[][2])  
{
	GLUnurbsObj *theNurb;
    GLfloat vknots[4] = {0.0,0.0,1.0, 1.0};
	int i,j;
	float uknots[83];  
    int numuknots; 
    int last_index=numsilpts-1;
    GLfloat ctlpoints[80][2][3];
	GLfloat texctlpoints[80][2][2];
	int s;
    float len_sil,deltax,deltay,delta_length;
	float normalized_length[80];        //maxpoints

    glEnable(GL_AUTO_NORMAL);
    glEnable(GL_NORMALIZE);
////////////////////////////// create knots  ////////////////////////  
	
    numuknots=numsilpts+order;
	if (order==4){
   	       uknots[0]=0.0;uknots[1]=0.0;uknots[2]=0.0;uknots[3]=0.0;
	       for (i=4;i<=numsilpts-1;i++)
	       uknots[i]=(i-3);
	       uknots[numsilpts]=numsilpts-3;uknots[numsilpts+1]=numsilpts-3;
	            uknots[numsilpts+2]=numsilpts-3;uknots[numsilpts+3]=numsilpts-3;
	}
	else if (order==3){
             uknots[0]=0.0;uknots[1]=0.0;uknots[2]=0.0;
	         for (i=3;i<=numsilpts-1;i++)
		          uknots[i]=(i-2);
	         uknots[numsilpts]=numsilpts-2;uknots[numsilpts+1]=numsilpts-2;
		         uknots[numsilpts+2]=numsilpts-2;
			}
	
///////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////// initialize control points ////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////

	 for (j=0;j<=last_index;j++)
	{
            ctlpoints[j][0][1] =sil[j][1];
            ctlpoints[j][0][0] =sil[j][0];
            ctlpoints[j][0][2] =-5.0;
			          		
			ctlpoints[j][1][1] =sil[j][1];
            ctlpoints[j][1][0] =sil[j][0];
            ctlpoints[j][1][2] =5.0;
	}
/////////////////////////////////////////////////////////////////////
//////////////////////////  texture control points  /////////////////
 	len_sil=0.0;normalized_length[0]=0.0;
	for (s = 0 ; s <= last_index - 1 ; s++) {
       deltax = (sil[s+1][0] - sil[s][0]);
	   deltay = (sil[s+1][1] - sil[s][1]);

	   delta_length = sqrt(deltax*deltax + deltay*deltay);
	   len_sil =len_sil+delta_length;
	   normalized_length[s+1]=len_sil;
	  };

	for (s=1 ; s<=last_index-1;s++) 
			normalized_length[s]=normalized_length[s]/len_sil;
	normalized_length[last_index]=1.0;

	
   	for (j=0;j<=last_index;j++)
	    {
            texctlpoints[j][0][0] =normalized_length[j];
            texctlpoints[j][0][1] =0.0;
			texctlpoints[j][1][0] =normalized_length[j];
            texctlpoints[j][1][1] =1.0;
	   }
	   
////////////////////////////////////////////////////////////////////
    theNurb = gluNewNurbsRenderer();
	gluNurbsProperty(theNurb,GLU_SAMPLING_METHOD, GLU_DOMAIN_DISTANCE);
	gluNurbsProperty(theNurb,GLU_U_STEP,res);//120
	gluNurbsProperty(theNurb,GLU_V_STEP,res);//120
	gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_FILL);
    gluNurbsProperty(theNurb, GLU_CULLING, GLU_TRUE);
    
   gluBeginSurface(theNurb);

           gluNurbsSurface(theNurb, 
	   // #knots = #control points + order of NURB - using linear
            numuknots, uknots,     // number  and knots in u dir
            4, vknots,  //number and knots in v dir
            2* 2,       // u stride=#control points in v direction X size of data
            2,           //v stride
            &texctlpoints[0][0][0],  //texture coordinates
            order,2,                // order of  u nurbs and v nurbs
            GL_MAP2_TEXTURE_COORD_2);

         gluNurbsSurface(theNurb, 
            numuknots, uknots,    // number  and knots in u dir
            4, vknots,    //number and knots in v dir
          2*3 ,       // u stride
            3,           //v stride
   
            &ctlpoints[0][0][0],  //control points
            order, 2,                // order of nurbs
            GL_MAP2_VERTEX_3);
		 
        gluEndSurface(theNurb);

    gluDeleteNurbsRenderer(theNurb);
    glFlush();

} 





void nurbExtSidesPeriodic(int order,int numsilpts, float sil[][2])  
{
	GLUnurbsObj *theNurb;
    GLfloat vknots[4] = {0.0,0.0,1.0, 1.0};
	int i,j;
	float uknots[83];   /////////////////test
    int numuknots;   /////test
	int last_index=numsilpts-1;
    GLfloat ctlpoints[80][2][3];/// test
	GLfloat texctlpoints[80][2][2];
	int s;
    float len_sil,deltax,deltay,delta_length;
	float normalized_length[80];        //maxpoints

    glEnable(GL_AUTO_NORMAL);
    glEnable(GL_NORMALIZE);

////////////////////////////// create knots  //////////////////////// ;
	if (order==3){ 
       numuknots=numsilpts+2+order;
	   for (i=0;i<numuknots;i++)
		     uknots[i]=i;
	   }
	else if (order==4){
	  numuknots=numsilpts+3+order;
	  for (i=0;i<numuknots;i++)
		      uknots[i]=i;
	}
	
//////////////////////////////////////////////////////////////////////  
////////////////////////////////////////////////////////////////////
	 for (j=0;j<=last_index;j++)
	{
            ctlpoints[j][0][1] =sil[j][1];
            ctlpoints[j][0][0] =sil[j][0];
            ctlpoints[j][0][2] =-5.0;
			          		
			ctlpoints[j][1][1] =sil[j][1];
            ctlpoints[j][1][0] =sil[j][0];
            ctlpoints[j][1][2] =5.0;
	}

    for (i=0;i<2;i++) {
            ctlpoints[last_index+1][i][1] =ctlpoints[0][i][1];
            ctlpoints[last_index+1][i][0] =ctlpoints[0][i][0];
            ctlpoints[last_index+1][i][2] =ctlpoints[0][i][2];
            ctlpoints[last_index+1][i][3] =ctlpoints[0][i][3];
		   }
    for (i=0;i<2;i++) {
            ctlpoints[last_index+2][i][1] =ctlpoints[1][i][1];
            ctlpoints[last_index+2][i][0] =ctlpoints[1][i][0];
            ctlpoints[last_index+2][i][2] =ctlpoints[1][i][2];
            ctlpoints[last_index+2][i][3] =ctlpoints[1][i][3];
		   }
	if (order==4) 
		for (i=0;i<9;i++) {
            ctlpoints[last_index+3][i][1] =ctlpoints[2][i][1];
            ctlpoints[last_index+3][i][0] =ctlpoints[2][i][0];
            ctlpoints[last_index+3][i][2] =ctlpoints[2][i][2];
            ctlpoints[last_index+3][i][3] =ctlpoints[2][i][3];
		   }
////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
//////////////////////////  texture control points  /////////////////
    sil[last_index+1][0]=sil[0][0];
	sil[last_index+1][1]=sil[0][1];
	

 	len_sil=0.0;normalized_length[0]=0.0;
	for (s = 0 ; s <= last_index; s++) {
       deltax = (sil[s+1][0] - sil[s][0]);
	   deltay = (sil[s+1][1] - sil[s][1]);
   
	   delta_length = sqrt(deltax*deltax + deltay*deltay);
	   len_sil =len_sil+delta_length;
	   normalized_length[s+1]=len_sil;
	  };

	

	for (s=1 ; s<=last_index+1;s++) 
			normalized_length[s]=normalized_length[s]/len_sil;
		
	

	
   for (j=0;j<=last_index;j++)
	    {
            texctlpoints[j][0][0] =normalized_length[j];
            texctlpoints[j][0][1] =0.0;
			texctlpoints[j][1][0] =normalized_length[j];
            texctlpoints[j][1][1] =1.0;
	   }

	texctlpoints[last_index+1][0][0] =1.0;
    texctlpoints[last_index+1][0][1] =0.0;
	texctlpoints[last_index+1][1][0] =1.0;
    texctlpoints[last_index+1][1][1] =1.0;
	   
	texctlpoints[last_index+2][0][0] =1.0+normalized_length[1];
    texctlpoints[last_index+2][0][1] =0.0;
	texctlpoints[last_index+2][1][0] =1.0+normalized_length[1];
    texctlpoints[last_index+2][1][1] =1.0;



	if (order==4)
	{
	texctlpoints[last_index+3][0][0] =1.0+normalized_length[2];
    texctlpoints[last_index+3][0][1] =0.0;
    texctlpoints[last_index+3][1][0] =1.0+normalized_length[2];
    texctlpoints[last_index+3][1][1] =1.0;  
   	   
	}
/////////////////////// end texture control points  ///////////////////	   
////////////////////////////////////////////////////////////////////
    theNurb = gluNewNurbsRenderer();
	gluNurbsProperty(theNurb,GLU_SAMPLING_METHOD, GLU_DOMAIN_DISTANCE);
	gluNurbsProperty(theNurb,GLU_U_STEP,res);
	gluNurbsProperty(theNurb,GLU_V_STEP,res);
	gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_FILL);
    gluNurbsProperty(theNurb, GLU_CULLING, GLU_TRUE);
   
	gluBeginSurface(theNurb);
  
        gluNurbsSurface(theNurb, 
	   // #knots = #control points + order of NURB - using linear
            numuknots, uknots,     // number  and knots in u dir
            4, vknots,  //number and knots in v dir
            2* 2,       // u stride=#control points in v direction X size of data
            2,           //v stride
            &texctlpoints[0][0][0],  //texture coordinates
            order,2,                // order of  u nurbs and v nurbs
            GL_MAP2_TEXTURE_COORD_2);

         gluNurbsSurface(theNurb, 
            numuknots, uknots,    // number  and knots in u dir
            4, vknots,    //number and knots in v dir
            2*3 ,       // u stride
            3,           //v stride
   
            &ctlpoints[0][0][0],  //control points
            order, 2,                // order of nurbs
            GL_MAP2_VERTEX_3);
		 
        gluEndSurface(theNurb);

    gluDeleteNurbsRenderer(theNurb);
    glFlush();

} 







void nurbCapOpen(int order,int numsilpts, float sil[][2],enum captype face,float rz)
{
	GLUnurbsObj *theNurb;
	GLfloat rectangle[2][2][3];
	GLfloat normal[2][2][3];
	GLfloat texctlpoints[2][2][2];
	GLfloat trimctlpoints[80][2];
    GLfloat rectknots[4] = {0.0,0.0, 1.0,1.0};
	float nz;

	int i,j;
	float xmin=1000.0,xmax=-1000.0,ymin=1000.0,ymax=-1000.0;
	float trimknots[83]; 
    int numtrimknots;    
	int last_index=numsilpts-1;
   
    glEnable(GL_NORMALIZE);
	 glDisable(GL_AUTO_NORMAL);
   if (face==nurbBACK) glFrontFace(GL_CW);

    for(i=0;i<=last_index;i++){
		if (sil[i][0]>xmax) xmax=sil[i][0];
		if (sil[i][0]<xmin) xmin=sil[i][0];
		if (sil[i][1]>ymax) ymax=sil[i][1];
        if (sil[i][1]<ymin) ymin=sil[i][1];
	}


    rectangle[0][0][1] =ymin;
    rectangle[0][0][0] =xmin;
    rectangle[0][0][2] =rz;
			
	rectangle[0][1][1] =ymax;
    rectangle[0][1][0] =xmin;
    rectangle[0][1][2] =rz;
			
	rectangle[1][0][1] =ymin;
    rectangle[1][0][0] =xmax;
    rectangle[1][0][2] =rz;
			
	rectangle[1][1][1] =ymax;
    rectangle[1][1][0] =xmax;
    rectangle[1][1][2] =rz;
	
   if (face==nurbFRONT) nz=1.0; else nz=-1.0;
   normal[0][0][1] =0;
   normal[0][0][0] =0;
   normal[0][0][2] =nz;
			
   normal[0][1][1] =0;
   normal[0][1][0] =0;
   normal[0][1][2] =nz;
			
   normal[1][0][1] =0;
   normal[1][0][0] =0;
   normal[1][0][2] =nz;
			
   normal[1][1][1] =0;
   normal[1][1][0] =0;
   normal[1][1][2] =nz;
 ////////////////////////////////////// create texture coordinates /////////////////////// 
   if (face==nurbFRONT){
   texctlpoints[0][0][1] =0;
   texctlpoints[0][0][0] =0;

   texctlpoints[0][1][1] =1;
   texctlpoints[0][1][0] =0;

   texctlpoints[1][0][1] =0;
   texctlpoints[1][0][0] =1;

   texctlpoints[1][1][1] =1;
   texctlpoints[1][1][0] =1;
   }
   
   else if (face==nurbBACK){
   texctlpoints[0][0][1] =0;
   texctlpoints[0][0][0] =1;

   texctlpoints[1][0][1] =0;
   texctlpoints[1][0][0] =0;

   texctlpoints[0][1][1] =1;
   texctlpoints[0][1][0] =1;

   texctlpoints[1][1][1] =1;
   texctlpoints[1][1][0] =0;
   }
  
 /////////////////////////////////////////////////////////////////////////////////////
////////////////////////////// create knots for trim curve  //////////////////////// 
	
    numtrimknots=numsilpts+order;
	if (order==4){
   	       trimknots[0]=0.0;trimknots[1]=0.0;trimknots[2]=0.0;trimknots[3]=0.0;
	       for (i=4;i<=numsilpts-1;i++)
	       trimknots[i]=(i-3);
	       trimknots[numsilpts]=numsilpts-3;trimknots[numsilpts+1]=numsilpts-3;
	            trimknots[numsilpts+2]=numsilpts-3;trimknots[numsilpts+3]=numsilpts-3;
	}
	else if (order==3){
             trimknots[0]=0.0;trimknots[1]=0.0;trimknots[2]=0.0;
	         for (i=3;i<=numsilpts-1;i++)
		          trimknots[i]=(i-2);
	         trimknots[numsilpts]=numsilpts-2;trimknots[numsilpts+1]=numsilpts-2;
		         trimknots[numsilpts+2]=numsilpts-2;
			}
	
///////////////////////////////////////////////////////////////////////////////////
////////////           create trim control points   ///////////////////////////////
	for (j=0;j<=last_index-1;j++)
	{       
		    trimctlpoints[j][1] =(sil[j][1]-ymin)/(ymax-ymin);
            trimctlpoints[j][0] =(sil[j][0]-xmin)/(xmax-xmin);
           	
	}
            trimctlpoints[last_index][1] =trimctlpoints[0][1];
            trimctlpoints[last_index][0] =trimctlpoints[0][0];
///////////////////////////////////////////////////////////////////////////////////

	  
    theNurb = gluNewNurbsRenderer();
	gluNurbsProperty(theNurb,GLU_SAMPLING_METHOD, GLU_DOMAIN_DISTANCE);
	gluNurbsProperty(theNurb,GLU_U_STEP,res);//120
	gluNurbsProperty(theNurb,GLU_V_STEP,res);//120
	gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_FILL);
    gluNurbsProperty(theNurb, GLU_CULLING, GLU_TRUE);
 
        
	    
	    
       

       gluBeginSurface(theNurb);
		 gluNurbsSurface(theNurb, 
	   // #knots = #control points + order of NURB - using linear
            4, rectknots,    // number  and knots in u dir
            4, rectknots,    //number and knots in v dir
            2*2 ,       // u stride
            2,           //v stride
            &texctlpoints[0][0][0],  //control points
            2, 2,                // order of nurbs
            GL_MAP2_TEXTURE_COORD_2);

         gluNurbsSurface(theNurb, 
	   // #knots = #control points + order of NURB - using linear
            4, rectknots,    // number  and knots in u dir
            4, rectknots,    //number and knots in v dir
            2*3 ,       // u stride
            3,           //v stride
            &normal[0][0][0],  //control points
            2, 2,                // order of nurbs
            GL_MAP2_NORMAL);
         gluNurbsSurface(theNurb, 
	   // #knots = #control points + order of NURB - using linear
            4, rectknots,    // number  and knots in u dir
            4, rectknots,    //number and knots in v dir
            2*3 ,       // u stride
            3,           //v stride
            &rectangle[0][0][0],  //control points
            2, 2,                // order of nurbs
            GL_MAP2_VERTEX_3);
	
		 gluBeginTrim(theNurb);
		   gluNurbsCurve(theNurb, 
            numtrimknots,
			trimknots,    // number  and knots for trim curve
            2,       // u stride
            &trimctlpoints[0][0],  //control points for trim curve
            order,                // order of trim curve
            GLU_MAP1_TRIM_2);
         gluEndTrim(theNurb);
        gluEndSurface(theNurb);
	   
	gluDeleteNurbsRenderer(theNurb);
	glFrontFace(GL_CCW);

    glFlush();

} 



void nurbCapPeriodic(int order,int numsilpts, float sil[][2],enum captype face,float rz)
{
	GLUnurbsObj *theNurb;
	GLfloat rectangle[2][2][3];
	GLfloat normal[2][2][3];
	GLfloat texctlpoints[2][2][2];
	GLfloat trimctlpoints[80][2];
    GLfloat rectknots[4] = {0.0,0.0, 1.0,1.0};
	float nz;

	int i,j;
	float xmin=1000.0,xmax=-1000.0,ymin=1000.0,ymax=-1000.0;
	float trimknots[83]; 
    int numtrimknots;    
	int last_index=numsilpts-1;
   
    glEnable(GL_NORMALIZE);
	 glDisable(GL_AUTO_NORMAL);

   if (face==nurbBACK) glFrontFace(GL_CW);

    for(i=0;i<=last_index;i++){
		if (sil[i][0]>xmax) xmax=sil[i][0];
		if (sil[i][0]<xmin) xmin=sil[i][0];
		if (sil[i][1]>ymax) ymax=sil[i][1];
        if (sil[i][1]<ymin) ymin=sil[i][1];
	}


    rectangle[0][0][1] =ymin;
    rectangle[0][0][0] =xmin;
    rectangle[0][0][2] =rz;
			
	rectangle[0][1][1] =ymax;
    rectangle[0][1][0] =xmin;
    rectangle[0][1][2] =rz;
			
	rectangle[1][0][1] =ymin;
    rectangle[1][0][0] =xmax;
    rectangle[1][0][2] =rz;
			
	rectangle[1][1][1] =ymax;
    rectangle[1][1][0] =xmax;
    rectangle[1][1][2] =rz;
	
   if (face==nurbFRONT) nz=1.0; else nz=-1.0;
   normal[0][0][1] =0;
   normal[0][0][0] =0;
   normal[0][0][2] =nz;
			
   normal[0][1][1] =0;
   normal[0][1][0] =0;
   normal[0][1][2] =nz;
			
   normal[1][0][1] =0;
   normal[1][0][0] =0;
   normal[1][0][2] =nz;
			
   normal[1][1][1] =0;
   normal[1][1][0] =0;
   normal[1][1][2] =nz;

/////////////////////////////////////////////////////////////////////////////////////
///                        create texture coordinates                            /// 
////////////////////////////////////////////////////////////////////////////////////   
   if (face==nurbFRONT){
   texctlpoints[0][0][1] =0;
   texctlpoints[0][0][0] =0;

   texctlpoints[0][1][1] =1;
   texctlpoints[0][1][0] =0;

   texctlpoints[1][0][1] =0;
   texctlpoints[1][0][0] =1;

   texctlpoints[1][1][1] =1;
   texctlpoints[1][1][0] =1;
   }
   
   else if (face==nurbBACK){                       /// reverse texture for backface
   texctlpoints[0][0][1] =0;
   texctlpoints[0][0][0] =1;

   texctlpoints[1][0][1] =0;
   texctlpoints[1][0][0] =0;

   texctlpoints[0][1][1] =1;
   texctlpoints[0][1][0] =1;

   texctlpoints[1][1][1] =1;
   texctlpoints[1][1][0] =0;
   }
  
 ////////////////////////////////////////////////////////////////////////////////////
////////////////////////////// create knots for trim curve  //////////////////////// 
////////////////////////////////////////////////////////////////////////////////////
	if (order==3){ 
       numtrimknots=numsilpts+2+order;
	   for (i=0;i<numtrimknots;i++)
		     trimknots[i]=i;
	   }
	else if (order==4){
	  numtrimknots=numsilpts+3+order;
	  for (i=0;i<numtrimknots;i++)
		      trimknots[i]=i;
	}	
  

	
///////////////////////////////////////////////////////////////////////////////////
////////////           create trim control points   ///////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
	for (j=0;j<=last_index;j++)
	{       
		    trimctlpoints[j][1] =(sil[j][1]-ymin)/(ymax-ymin);
            trimctlpoints[j][0] =(sil[j][0]-xmin)/(xmax-xmin);
           	
	}

      trimctlpoints[last_index+1][1] =(sil[0][1]-ymin)/(ymax-ymin);
	  trimctlpoints[last_index+1][0] =(sil[0][0]-xmin)/(xmax-xmin);
	
	  
      trimctlpoints[last_index+2][1] =(sil[1][1]-ymin)/(ymax-ymin);
	  trimctlpoints[last_index+2][0] =(sil[1][0]-xmin)/(xmax-xmin);

	  if (order==4){
      trimctlpoints[last_index+3][1] =(sil[2][1]-ymin)/(ymax-ymin);
	  trimctlpoints[last_index+3][0] =(sil[2][0]-xmin)/(xmax-xmin);
	  }

	    
///////////////////////////////////////////////////////////////////////////////////

	  
    theNurb = gluNewNurbsRenderer();
	gluNurbsProperty(theNurb,GLU_SAMPLING_METHOD, GLU_DOMAIN_DISTANCE);
	gluNurbsProperty(theNurb,GLU_U_STEP,res);//120
	gluNurbsProperty(theNurb,GLU_V_STEP,res);//120
	gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_FILL);
    gluNurbsProperty(theNurb, GLU_CULLING, GLU_TRUE);
 
        
	    
	    
       

       gluBeginSurface(theNurb);
		 gluNurbsSurface(theNurb, 
	   // #knots = #control points + order of NURB - using linear
            4, rectknots,    // number  and knots in u dir
            4, rectknots,    //number and knots in v dir
            2*2 ,       // u stride
            2,           //v stride
            &texctlpoints[0][0][0],  //control points
            2, 2,                // order of nurbs
            GL_MAP2_TEXTURE_COORD_2);

         gluNurbsSurface(theNurb, 
	   // #knots = #control points + order of NURB - using linear
            4, rectknots,    // number  and knots in u dir
            4, rectknots,    //number and knots in v dir
            2*3 ,       // u stride
            3,           //v stride
            &normal[0][0][0],  //control points
            2, 2,                // order of nurbs
            GL_MAP2_NORMAL);
         gluNurbsSurface(theNurb, 
	   // #knots = #control points + order of NURB - using linear
            4, rectknots,    // number  and knots in u dir
            4, rectknots,    //number and knots in v dir
            2*3 ,       // u stride
            3,           //v stride
            &rectangle[0][0][0],  //control points
            2, 2,                // order of nurbs
            GL_MAP2_VERTEX_3);
	
		 gluBeginTrim(theNurb);
		   gluNurbsCurve(theNurb, 
            numtrimknots,
			trimknots,    // number  and knots for trim curve
            2,       // u stride
            &trimctlpoints[0][0],  //control points for trim curve
            order,                // order of trim curve
            GLU_MAP1_TRIM_2);
         gluEndTrim(theNurb);
        gluEndSurface(theNurb);
	   
	gluDeleteNurbsRenderer(theNurb);

	glFrontFace(GL_CCW);
    glFlush();

} 
/////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////  end new functions  ////////////////////////////////////

