#include<GL/glut.h>
#include<GL/glu.h>
#include<GL/gl.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

GLUnurbsObj *pNurb = NULL;
int nCtrlPoints = 7;    
GLfloat ctrlPoints[7][4];
GLfloat pointsWeights[7][4]  = {    
    {0,-.5, 0, 1},
    {.5,-.5, 0, 0.5},
    {0.25, -0.0669873, 0, 1},
    {0, 0.3880254, 0, 0.5},
    {-.25,  -0.0669873, 0, 1},
    {-.5,-.5, 0, 0.5},
    {0,-.5, 0, 1}};

    
    // Knot vector
    int order = 3;
    int nKnots = 10;
    GLfloat Knots[10] = {0,0,0,1,1,2,2,3,3,3};




#define kStride 4
    
    // Called to draw scene
    void RenderScene(void)
    {
        int i, j;
        
        // Clear the window with current clearing color
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
        // Render the NURB
        
        // make sure we are setup
        if (!pNurb)
        {
            // Setup the Nurbs object
            pNurb = gluNewNurbsRenderer();
            gluNurbsProperty(pNurb, GLU_SAMPLING_TOLERANCE, 5.0f);
            //gluNurbsProperty(pNurb, GLU_DISPLAY_MODE, GLU_OUTLINE_POLYGON);
            //gluNurbsProperty(pNurb, GLU_DISPLAY_MODE, (GLfloat)GLU_FILL);
            
            // make the NURBS control points from the points & weights
            for(i = 0; i < nCtrlPoints; i++)
            {
                ctrlPoints[i][3] = pointsWeights[i][3];
                for (j = 0; j < 3; j++)
                {
                    ctrlPoints[i][j] = pointsWeights[i][j]*ctrlPoints[i][3];
                }
            }
        }
        
        glColor3f(1,0,1);
        
        // Begin the NURB definition
        gluBeginCurve(pNurb);
        
        // Send the Non Uniform Rational BSpline
        gluNurbsCurve(pNurb, nKnots, Knots, kStride, 
            &ctrlPoints[0][0], order, GL_MAP1_VERTEX_4);
        
        gluEndCurve(pNurb);
        
        // Draw the control points in red
        glPointSize(3.0f);
        glColor3f(1,0,0);
        glBegin(GL_POINTS);
        for(i = 0; i < nCtrlPoints; i++)
            glVertex3fv(pointsWeights[i]);  
        glEnd();
        
        // Flush drawing commands
        glFlush();
    }

void reshape(int w, int h)
{
   glViewport(0, 0, (GLsizei) w, (GLsizei) h);
   
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   //glTranslatef (0.0, 0.0, -1.0);
}



int main(int argc, char** argv)
{
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
   glutInitWindowSize (500, 500);
   glutInitWindowPosition (100, 100);
   glutCreateWindow(argv[0]);
   glutReshapeFunc(reshape);
   glutDisplayFunc(RenderScene);
   glutMainLoop();
   return 0; 
}
    