OpenGL method of drawing Bezier curves

  • 2020-08-22 22:18:15
  • OfStack

The example of this paper shares the specific code of OpenGL drawing Bezier curve for your reference. The specific content is as follows

Project requirements:

Any control points on the screen can be set with the mouse and curves can be generated

Curve modification is accomplished using mouse and keyboard interaction.

Project Overview

This project USES Bezier curve generation algorithm to generate user-defined curves. The core functions can be realized as follows:

1. User can click anywhere on the screen with the mouse to generate recording points.

2. The Bezier curve is generated from any previous number of record points and their sequence when the mouse right clicks on any part of the screen.

Additional auxiliary input functions:

1. Press 'C' to clear all the record points.

2. Press 'R' to clear the last record point.

3, press the keyboard 'Q' key to launch the program.

Project design idea

1. Introduction to Bezier Curve:

The Bessel curve is one such curve, which is a smooth curve drawn according to the coordinates of four arbitrary points. Historically, people who study Bessel curves originally designed this vector curve drawing method based on the idea of determining four points by known parametric equation of the curve. In 1962, French mathematician Pierre Bezier was the first to study the method of drawing curves by vectors, and gave a detailed calculation formula, so the curve drawn by such a formula was named Bessel curve after his family name.

2. Generation formula:

(1) Linear formula (only two points)

At the given points P0 and P1, the linear Bates curve is just a line between two points. This line is given by the following formula:

And this is equivalent to linear interpolation.

(2) Formula to the power of 2 (3 points)

The path of baez curve to the power 2 is traced by the function B (t) of P0, P1 and P2 at the given points:

The TrueType typeface USES a two-order Baez curve composed of Baez splines.

(3) Formula to the third power (4 points)

P0, P1, P2, P34 points define the third power Baez curve in plane or in 3d space. The curve starts from P0 to P1 and goes from P2 to P3. 1 it will not go through P1 or P2; These two points are just giving direction information there. The distance between P0 and P1 determines the "length" of the curve towards P2 before turning towards P3.

The parametric form of the curve is as follows:

Modern imaging systems, such as PostScript, Asymptote, and Metafont, employ three Baez curves composed of Baez splines to depict the contours of the curves.

(4) 1 General parameter formula (n points)

The order Bates curve can be deduced as follows. P0, P1... , Pn, whose Baez curve is:

The baez curve of order N, i.e. the interpolation between the Baez curves of order N-1.


#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#include<GL/glut.h>
// Defines the maximum value for control points 
#define MAX_CPTX 25 
int ncpts=0;// Number of actual control points 
static int width=600,height=600;// The window size 
typedef struct
{
 GLfloat x,y;
} POINT;
POINT cpts[MAX_CPTX];// Store control point coordinates 
// o n!
int JieCheng(int n)
{
 if(n==1||n==0)
 {
 return 1;
 }
 else
 {
 return n*JieCheng(n-1);
 }
}
// Combinatorial permutation 
double C(int n,int i)
{
 return ((double)JieCheng(n))/((double)(JieCheng(i)*JieCheng(n-i)));
}
// o 1 The number of u the num To the power 
double N(double u,int n)
{
 double sum=1.0;
 if (n==0)
 {
 return 1;
 }
 for(int i=0;i<n;i++)
 {
 sum*=u;
 }
 return sum;
}
 
// draw bezier curve 
void drawBezier(POINT *p)
{ 
 void display();
 if(ncpts<=0) return; 
 
 POINT *p1;
 p1=new POINT[1000];
 GLfloat u=0,x,y;
 int i,num=1;
 p1[0]=p[0];
 for(u=0;u<=1;u=u+0.001)
 { 
 x=0;
 y=0;
 for(i=0;i<ncpts;i++)
 { 
  x+=C(ncpts-1,i)*N(u,i)*N((1-u),(ncpts-1-i))*p[i].x;
  y+=C(ncpts-1,i)*N(u,i)*N((1-u),(ncpts-1-i))*p[i].y;
 }
 p1[num].x=x;
 p1[num].y=y;
 num++;
 } 
 
  glPointSize(4.0);
  glColor3f(0.0,0.0,0.0);
  glBegin(GL_LINE_STRIP);
  for(int k=0;k<1000;k++)
 glVertex2f(p1[k].x,p1[k].y);
  glEnd();
  glFlush();
 return;
}
 
 
 
// Enter a new control point 
static void mouse(int button, int state,int x,int y)
{
void display();
float wx,wy;
// The mouse does not press the left button, does not respond 
if(state!=GLUT_DOWN)
 return;
else 
 {if(button==GLUT_LEFT_BUTTON)
 {
// Conversion coordinates 
wx=(2.0*x)/(float)(width-1)-1.0;
wy=(2.0*(height-1-y))/(float)(height-1)-1.0;
// Determine if the number of control points exceeds the maximum 
if(ncpts==MAX_CPTX)
 return;
// Storage control point 
cpts[ncpts].x=wx;
cpts[ncpts].y=wy;
ncpts++;
// Draw control points 
glColor3f(0.0,0.0,0.0);
glPointSize(5.0);
glBegin(GL_POINTS);
glVertex2f(wx,wy);
glEnd();
glFlush();
}
if(button==GLUT_RIGHT_BUTTON)
{
display();
drawBezier(cpts);
}
}
}
void display(void)
{
 int i;
 glClear(GL_COLOR_BUFFER_BIT);
 glColor3f(0.0,0.0,0.0);
 glPointSize(5.0);
 glBegin(GL_POINTS);
 for (i = 0; i < ncpts; i++)
  glVertex2f(cpts[i].x,cpts[i].y);
 glEnd();
 glFlush();
 
}
// Keyboard callback function 
void keyboard(unsigned char key,int x,int y)
{
 switch (key)
 {
  case 'q': case 'Q':
   exit(0);
   break;
  case 'c': case 'C':
 ncpts = 0;
 glutPostRedisplay();
   break;
 case 'r': case 'R':
 ncpts--;
 glutPostRedisplay();
 break;
 }
}
 
// Redraw function 
void reshape(int w,int h)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0,1.0,-1.0,1.0,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
glViewport(0,0,w,h);// Adjust the viewport 
width=w;
height=h;
}
int main(int argc, char **argv)
{
// Initialize the 
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB);
glutInitWindowSize(width,height);
glutCreateWindow("zjc2012211763");
// Register the callback function 
glutDisplayFunc(display);
glutMouseFunc(mouse);
glutKeyboardFunc(keyboard);
glutReshapeFunc(reshape);
glClearColor(1.0,1.0,1.0,1.0);
glColor3f(0.0,0.0,0.0);
glutMainLoop();
}

Related articles: