JMU
Scientific Visualization and Animation using Bezier Curves
An Introduction


Prof. David Bernstein
James Madison University

Computer Science Department
bernstdh@jmu.edu


Overview
Mathematical Representation
Bezier Curves in OpenGL
Bezier Curves in OpenGL (cont.)
Using an Evaluator
svaexamples/curves/draw.c (Fragment: curve)
           //
   // Create and draw the curves for every 4 points
   for (int i=0; (i+3)<numPoints; i+=3)
   {
      // The evaluator with a stride of 3 and an order of 4
      glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &points[i][0]);

      // Draw the curve
      glBegin(GL_POINTS);  // GL_LINE_STRIP fills the gaps
      {
         for (int i=0; i<100; i++)
         {
            glEvalCoord1f(((float)i)/100.0);             
         }
      }
      glEnd();
   }
        
A Curve Drawing Program
Adding Points
svaexamples/curves/draw.c (Fragment: onMouseClick)
        /**
 * The mouse callback (i.e., the function that is called
 * each time a mouse button is pressed or released).
 *
 * @param button The button (e.g., GLUT_LEFT_BUTTON)
 * @param state  The state (e.g., GLUT_UP or GLUT_DOWN)
 * @param x      The x-position of the mouse
 * @param y      The y-position of the mouse
 */
void onMouseClick(int button, int state, GLfloat x, GLfloat y)
{
   if(button == SVA_LEFT_BUTTON)
   {
      if (state == SVA_DOWN)
      {
         points[numPoints][0] = x;
         points[numPoints][1] = y;
         points[numPoints][2] = 0.;

         numPoints++;         
         
         svaRedisplay();         
      }
   }
   else if (button == SVA_RIGHT_BUTTON)
   {
      if (state == SVA_DOWN)
      {
         selectedPoint = closestPointTo(x, y, 0.0);         
      }
      else
      {
         selectedPoint = -1;         
      }

      svaRedisplay();         
   }
}
        
A Curve Drawing Program (cont.)
Moving Points
svaexamples/curves/draw.c (Fragment: onMouseDrag)
        /**
 * The mouse drag callback
 *
 * @param x      The x-position of the mouse
 * @param y      The y-position of the mouse
 */
void onMouseDrag(GLfloat x, GLfloat y)
{
   if (selectedPoint >= 0)
   {
      points[selectedPoint][0] = x;
      points[selectedPoint][1] = y;

      svaRedisplay();         
   }
}
        
A Curve Drawing Program (cont.)
Drawing the Points and the Curve
svaexamples/curves/draw.c (Fragment: onDisplay)
        /**
 * Display Callback
 */
void onDisplay()
{
   // Clear the screen
   glClear(GL_COLOR_BUFFER_BIT);

   // Set the color
   glColor3f(1.0, 0.0, 0.0);

   //
   // Create and draw the curves for every 4 points
   for (int i=0; (i+3)<numPoints; i+=3)
   {
      // The evaluator with a stride of 3 and an order of 4
      glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &points[i][0]);

      // Draw the curve
      glBegin(GL_POINTS);  // GL_LINE_STRIP fills the gaps
      {
         for (int i=0; i<100; i++)
         {
            glEvalCoord1f(((float)i)/100.0);             
         }
      }
      glEnd();
   }
   
         
   // Instead of:
   //
   //   glBegin(GL_POINTS);
   //   {
   //     for (int i=0; i<100; i++)
   //     {
   //       glEvalCoord1f(((float)i)/100.0);             
   //     }
   //   }
   //   glEnd();
   //
   // we could use:
   //
   //   glMapGrid1f(100, 0.0, 1.0 );         
   //   glEvalMesh1(GL_POINT, 0, 100);

       
    // Show the points
   glPointSize(3.);
   glBegin(GL_POINTS);
   {
      for (int i = 0; i<numPoints; i++)
      { 
         if (i == selectedPoint)  
         {
            glColor3f(1.0, 0.0, 1.0);
            glVertex3f(points[i][0], points[i][1], points[i][2]);   
         }
         else
         {
            glColor3f(0.0, 1.0, 0.0);
            glVertex3f(points[i][0], points[i][1], points[i][2]);   
         }
      }
      glEnd();
   }
   

   // Connect the points (using a piecewise linear curve)
   if (numPoints >= 2)
   {
      glColor3f(0.75, 0.75, 0.75);
      glBegin(GL_LINE_STRIP);
      {
         for (int i = 0; i < numPoints; i++)
         { 
            glVertex3f(points[i][0], points[i][1], points[i][2]);        
         }        
      }
      glEnd(); 
   }
}