OpenGL:绘制B样条曲线

来源:互联网 发布:小仙女的网络意思 编辑:程序博客网 时间:2024/05/01 14:23

绘制B样条曲线:


#include <stdlib.h>#include <GL/glut.h>//#if 0/// the points of the curve - these are the same as the bezier curve/// points demonstrated in the bezier curve example.float Points[4][3] = {{ 10,10,0 },{  5,10,2 },{ -5,0,0 },{-10,5,-2}};#define NUM_POINTS 4//The following sets of 4 indices are the curves that need to//be drawn to create a clamped cubic b-spline. In total there//are 5 curve segments to draw.////0 0 0 1//    0 0 1 2//      0 1 2 3//        1 2 3 3//          2 3 3 3////Remember this when trying to understand knot vectors!!//#elsefloat Points[9][3] = {{ 10,5,0 },{  5,10,0 },{ -5,15,0 },{ -10,-5,0 },{ 4,-4,0 },{ 10,5,0 },{  5,10,0 },{ -5,15,0 },{ -10,-5,0 }};#define NUM_POINTS 9//若绘制过首尾控制点的曲线  //0 0 0 1//    0 0 1 2//      0 1 2 3//        1 2 3 4//          2 3 4 5//            3 4 5 6//              4 5 6 6//                5 6 6 6////Remember this when trying to understand knot vectors!!////若绘制首尾相接的平滑曲线 ,即为当前绘制//      0 1 2 3//        1 2 3 4//          2 3 4 5//            3 4 5 6#endif// the level of detail for the curveunsigned int LOD=20;///#define NUM_SEGMENTS (NUM_POINTS-3)//float* GetPoint(int i) {// return 1st pointif (i<0) {returnPoints[0];}if (i<NUM_POINTS)return Points[i];// return last pointreturn Points[NUM_POINTS-1];}//------------------------------------------------------------OnKeyPress()//void myIdle(void) {glutPostRedisplay();}//------------------------------------------------------------OnDraw()//void OnDraw() {// clear the screen & depth bufferglClear(GL_COLOR_BUFFER_BIT);// clear the previous transformglLoadIdentity();// set the camera position// gluLookAt(1,10,30,//eye pos// 0,0,0,//aim point// 0,1,0);//up direction// glColor3f(0.5,0.2,0); glPointSize(3);// // // draw curve hullglColor3f(0.3,0,0.5);glBegin(GL_LINE_STRIP);for(int i=0;i!=NUM_POINTS;++i) {glVertex3fv( Points[i] );}glEnd();glColor3f(0,1,0);// begin drawing our curveglBegin(GL_LINE_STRIP);for(int start_cv=0,j=0;j<NUM_SEGMENTS;j++,start_cv++){// for each section of curve, draw LOD number of divisionsfor(int i=0;i!=LOD;++i) {// use the parametric time value 0 to 1 for this curve// segment.float t = (float)i/LOD;// the t value invertedfloat it = 1.0f-t;// calculate blending functions for cubic bsplinefloat b0 = it*it*it/6.0f;float b1 = (3*t*t*t - 6*t*t +4)/6.0f;float b2 = (-3*t*t*t +3*t*t + 3*t + 1)/6.0f;float b3 =  t*t*t/6.0f;// calculate the x,y and z of the curve pointfloat x = b0 * GetPoint( start_cv + 0 )[0] +b1 * GetPoint( start_cv + 1 )[0] +b2 * GetPoint( start_cv + 2 )[0] +b3 * GetPoint( start_cv + 3 )[0] ;float y = b0 * GetPoint( start_cv + 0 )[1] +b1 * GetPoint( start_cv + 1 )[1] +b2 * GetPoint( start_cv + 2 )[1] +b3 * GetPoint( start_cv + 3 )[1] ;float z = b0 * GetPoint( start_cv + 0 )[2] +b1 * GetPoint( start_cv + 1 )[2] +b2 * GetPoint( start_cv + 2 )[2] +b3 * GetPoint( start_cv + 3 )[2] ;// specify the pointglVertex2f( x,y );}}// we need to specify the last point on the curve//glVertex3fv( Points[NUM_POINTS-1] );glEnd();// draw CV'sglBegin(GL_POINTS);for(int i=0;i!=NUM_POINTS;++i) {glVertex3fv( Points[i] );}glEnd();// currently we've been drawing to the back buffer, we need// to swap the back buffer with the front one to make the image visibleglutSwapBuffers();}//------------------------------------------------------------OnInit()//void OnInit() {//glClearColor(1,1,1,0);}//------------------------------------------------------------OnExit()//void OnExit() {}//------------------------------------------------------------OnReshape()//void OnReshape(int w, int h){// prevents division by zero when minimising windowif (h==0)h=1;// set the drawable region of the windowglViewport(0,0,w,h);// set up the projection matrixglMatrixMode(GL_PROJECTION);glLoadIdentity();// just use a perspective projection//gluPerspective(45,(float)w/h,0.1,100);if(w<=h)glOrtho(-20.0,20.0,-20.0*(GLfloat)h/(GLfloat)w,20.0*(GLfloat)h/(GLfloat)w,0.0,100.0);elseglOrtho(-20.0,20.0,-20.0*(GLfloat)h/(GLfloat)w,20.0*(GLfloat)h/(GLfloat)w,0.0,100.0);// go back to modelview matrix so we can move the objects aboutglMatrixMode(GL_MODELVIEW);glLoadIdentity();}//------------------------------------------------------------main()//int main(int argc,char** argv) {// initialise glutglutInit(&argc,argv);// request a depth buffer, RGBA display mode, and we want double bufferingglutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE);// set the initial window sizeglutInitWindowSize(640,480);// create the windowglutCreateWindow("Clamped B-Spline Curve");// run our custom initialisationOnInit();// set the function to use to draw our sceneglutDisplayFunc(OnDraw);// set the function to handle changes in screen sizeglutReshapeFunc(OnReshape);glutIdleFunc(&myIdle);// set the function to be called when we exitatexit(OnExit);// this function runs a while loop to keep the program running.glutMainLoop();return 0;}

closed-B样条:


Reference:

B样条详细说明:

http://blog.csdn.net/tuqu/article/details/5366701

绘制closed-B样条曲线

http://blog.csdn.net/tuqu/article/details/5386215


OpenGL绘制DDA、Hermite、Bezier、B样条:

http://blog.163.com/zhou_ghui/blog/static/177580120132159441827/

<1>DDA直线:(两点确定一条曲线,即用鼠标点两点);

 #include <windows.h> #include <gl/glut.h> #include <gl/gl.h> #include <stdio.h> #include <math.h>  GLfloat x_coord[2], y_coord[2];  int nPoints = 0;  inline GLfloat x_convert (int x)  {  return -8.0+x/499.0*16;  }  inline GLfloat y_convert (int y)  {  return 8.0 - y/499.0*16;  }  void init(){    glClearColor(1,1,1,0);  }  void myReshape(int w,int h)  {  glViewport(0,0,(GLsizei)w,(GLsizei)h);  glMatrixMode(GL_PROJECTION);  glLoadIdentity();  //gluPerspective(45.0,(GLfloat)w/(GLfloat)h,1.0,50.0);  if(w<=h)  glOrtho(-8.0,8.0,-8.0*(GLfloat)h/(GLfloat)w,8.0*(GLfloat)h/(GLfloat)w,-8.0,8.0);  else  glOrtho(-8.0*(GLfloat)h/(GLfloat)w,8.0*(GLfloat)h/(GLfloat)w,-8.0,8.0,-8.0,8.0);   glMatrixMode(GL_MODELVIEW);  glLoadIdentity();  }  int round ( float a){    return int (a+0.5);  }  void DDA(int x0,int xEnd,int y0, int yEnd)  //DDA画线算法  {     int dx= xEnd - x0 ;     int dy= yEnd - y0 ;     int steps ;     float xIncrement , yIncrement , x=x0, y=y0;     if(fabs(dx) > fabs(dy) )    steps = fabs (dx);     else steps = fabs(dy);      xIncrement = (float) dx/steps;     yIncrement = (float) dy/steps;      glBegin(GL_POINTS);     glPointSize(100);     glVertex2i( round (x), round (y));     for(int i=0; i        x+=xIncrement;   y+=yIncrement;   glVertex2i( round (x), round (y));     }     glEnd();  }  void display(){      glClear(GL_COLOR_BUFFER_BIT);          glColor3f(0,1,0);                //画两点之间的直线    glBegin(GL_LINE_STRIP);    for (int i = 0; i < nPoints; i++)  glVertex3f (x_coord[i], y_coord[i], 0.0);    glEnd();         glColor3f (1.0, 0, 0);            //调用DDA画线算法   glPointSize(5);     if (nPoints == 2)  DDA(x_coord[0],x_coord[1], y_coord[0] , y_coord[1]);   glFlush();   }  void handle_mouseclick (int button, int state, int x, int y){  if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {  if (nPoints == 2) nPoints = 0;   printf("%d (%d, %d) ==> (%f, %f)\n", nPoints, x, y, x_convert(x), y_convert(y));   x_coord[nPoints] = x_convert(x);  y_coord[nPoints] = y_convert(y);  nPoints++;  glutPostRedisplay();  }  } int main(int argc, char** argv)  {     glutInit(&argc, argv);     glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB |GLUT_DEPTH);     glutInitWindowSize (500, 500);     glutInitWindowPosition (100, 100);     glutCreateWindow ("hello");     init ();     glutDisplayFunc( display );      glutReshapeFunc(myReshape);     glutMouseFunc(handle_mouseclick);     glutMainLoop();     return 0;  }

<2>Bezier曲线(三次:四点确定一条曲线)

 #include <windows.h> #include <gl/glut.h> #include <gl/gl.h> #include <stdio.h> #include <math.h> GLfloat x_coord[4], y_coord[4]; int nPoints = 0;  inline GLfloat x_convert (int x) {  return -5.0+x/249.0*10; }  inline GLfloat y_convert (int y) {  return 5.0 - y/249.0*10; }  void init(){   glClearColor(1,1,1,0);  } void myReshape(int w,int h) {  glViewport(0,0,(GLsizei)w,(GLsizei)h);  glMatrixMode(GL_PROJECTION);  glLoadIdentity();  //gluPerspective(45.0,(GLfloat)w/(GLfloat)h,1.0,50.0);  if(w<=h)  glOrtho(-5.0,5.0,-5.0*(GLfloat)h/(GLfloat)w,5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0);  else  glOrtho(-5.0*(GLfloat)h/(GLfloat)w,5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0,-5.0,5.0);   glMatrixMode(GL_MODELVIEW);  glLoadIdentity(); }  //P(t)= B0,3(t)P0 + B1,3(t)P1+ B2,3(t)P2﹢B3,3(t)P3    //  B0,3(t)﹦(1-t)3    // B1,3(t)﹦3t(1-t)2     //B2,3(t)﹦3t2(1-t)     //B3,3(t)﹦t3  void Bezier(int n)  //Bezier曲线 {     float t, dt, t2, t3, f1, f2, f3, f4;      dt = 1.0/n;      // t runs from 0 to 1.      glBegin(GL_LINE_STRIP);  for (t = 0.0; t <= 1.0; t += dt) {         t2 = (1-t) *(1- t);         t3 = t2 * (1-t);       // t3 =(1-t)*(1-t)*(1-t)          f1 = t3;         f2 = 3*t*t2;         f3 = 3*t*t*(1-t);         f4 = t*t*t;          glVertex2f( f1*x_coord[0] + f2*x_coord[1] + f3*x_coord[2] + f4*x_coord[3],                          f1*y_coord[0] + f2*y_coord[1] + f3*y_coord[2] + f4*y_coord[3]);     }     glEnd(); } void display(){     glClear(GL_COLOR_BUFFER_BIT);          glColor3f (1, 0, 0);    glBegin(GL_LINE_STRIP);    for (int i = 0; i < nPoints; i++)  glVertex3f (x_coord[i], y_coord[i], 0.0);    glEnd();          glColor3f (0, 1, 0);     if (nPoints == 4)  Bezier(20);   glFlush();  }  void handle_mouseclick (int button, int state, int x, int y) {  if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {  if (nPoints == 4) nPoints = 0;   printf("%d (%d, %d) ==> (%f, %f)\n", nPoints, x, y, x_convert(x), y_convert(y));   x_coord[nPoints] = x_convert(x);  y_coord[nPoints] = y_convert(y);  nPoints++;  glutPostRedisplay();  } } int  main(int argc, char** argv) {    glutInit(&argc, argv);    glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB |GLUT_DEPTH);    glutInitWindowSize (250, 250);    glutInitWindowPosition (100, 100);    glutCreateWindow ("hello");    init ();     glutDisplayFunc( display );     glutReshapeFunc(myReshape);    glutMouseFunc(handle_mouseclick);     glutMainLoop();    return 0; }

<3>Hermit曲线(三次,三点确定一条曲线)

 #include <windows.h> #include <gl/glut.h> #include <gl/gl.h> #include <stdio.h> #include <math.h>  GLfloat x_coord[3], y_coord[3];  int nPoints = 0;  inline GLfloat x_convert (int x)  {  return -8.0+x/499.0*16;  }  inline GLfloat y_convert (int y)  {  return 8.0 - y/499.0*16;  }  void init(){    glClearColor(1,1,1,0);  }  void myReshape(int w,int h)  {  glViewport(0,0,(GLsizei)w,(GLsizei)h);  glMatrixMode(GL_PROJECTION);  glLoadIdentity();  //gluPerspective(45.0,(GLfloat)w/(GLfloat)h,1.0,50.0);  if(w<=h)  glOrtho(-8.0,8.0,-8.0*(GLfloat)h/(GLfloat)w,8.0*(GLfloat)h/(GLfloat)w,-8.0,8.0);  else  glOrtho(-8.0*(GLfloat)h/(GLfloat)w,8.0*(GLfloat)h/(GLfloat)w,-8.0,8.0,-8.0,8.0);   glMatrixMode(GL_MODELVIEW);  glLoadIdentity();  }   void Hermit(int n)  //  {    float t, dt, t2, t3, f1, f2, f3, f4;      dt = 1.0/n;      // t runs from 0 to 1.     GLfloat PT0_x = x_coord[1] - x_coord[0];     GLfloat PT0_y = y_coord[1] - y_coord[0];     GLfloat PT1_x = x_coord[2] - x_coord[1];  GLfloat PT1_y = y_coord[2] - y_coord[1];     glBegin(GL_LINE_STRIP);  for (t = 0.0; t <= 1.0; t += dt) {         t2 = t * t;         t3 = t2 * t;       // t3 = t * t * t         f1 = 2.0*t3 - 3.0*t2 + 1.0;         f2 = -2.0*t3 + 3.0*t2;         f3 = t3 - 2.0*t2 + t;         f4 = t3 - t2;         glVertex2f( f1*x_coord[0] + f2*x_coord[2] + f3*PT0_x + f4*PT1_x,                          f1*y_coord[0] + f2*y_coord[2] + f3*PT0_y + f4*PT1_y );     }     glEnd();  }  void display(){      glClear(GL_COLOR_BUFFER_BIT);          glColor3f(0,1,0);                //画两点之间的直线    glBegin(GL_LINE_STRIP);    for (int i = 0; i < nPoints; i++)  glVertex3f (x_coord[i], y_coord[i], 0.0);    glEnd();         glColor3f (1.0, 0, 0);            //调用DDA画线算法     if (nPoints == 3)  Hermit(20);   glFlush();   }  void handle_mouseclick (int button, int state, int x, int y){  if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {  if (nPoints == 3) nPoints = 0;   printf("%d (%d, %d) ==> (%f, %f)\n", nPoints, x, y, x_convert(x), y_convert(y));   x_coord[nPoints] = x_convert(x);  y_coord[nPoints] = y_convert(y);  nPoints++;  glutPostRedisplay();  }  } int main(int argc, char** argv)  {     glutInit(&argc, argv);     glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB |GLUT_DEPTH);     glutInitWindowSize (500, 500);     glutInitWindowPosition (100, 100);     glutCreateWindow ("hello");     init ();     glutDisplayFunc( display );      glutReshapeFunc(myReshape);     glutMouseFunc(handle_mouseclick);     glutMainLoop();     return 0;  }

<4>B样条曲线(实现鼠标右键在屏幕中选点,左键可拖动点)(三次,四点确定一条曲线)

 #include <windows.h> #include <gl/glut.h> #include <gl/gl.h> #include <stdio.h>#include <math.h> GLfloat x_coord[100], y_coord[100];  int nPoints = 0;  int j=0;  inline GLfloat x_convert (int x) {  return -5.0+x/249.0*10; }  inline GLfloat y_convert (int y) {  return 5.0 - y/249.0*10; }  void init(){   glClearColor(1,1,1,0);  } void myReshape(int w,int h) {  glViewport(0,0,(GLsizei)w,(GLsizei)h);  glMatrixMode(GL_PROJECTION);  glLoadIdentity();  //gluPerspective(45.0,(GLfloat)w/(GLfloat)h,1.0,50.0);  if(w<=h)  glOrtho(-5.0,5.0,-5.0*(GLfloat)h/(GLfloat)w,5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0);  else  glOrtho(-5.0*(GLfloat)h/(GLfloat)w,5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0,-5.0,5.0);   glMatrixMode(GL_MODELVIEW);  glLoadIdentity(); }  //  (1/2)*(t-1)*(t-1) //  (1/2)*(-2*t*t+2*t+1) //   (1/2)*t*t  void B2(int n)  //B样条3次曲线 {     float t, dt, t2, t3, f1, f2, f3, f4;      dt = 1.0/n;      // t runs from 0 to 1.      glBegin(GL_LINE_STRIP);   for(int j=0; j< (nPoints - 2 ); j++ ) for (t = 0.0; t <= 1.0; t += dt) {          f1 = (1.0/6)*((-1)*t*t*t+3*t*t-3*t+1);         f2 = (1.0/6)*(3*t*t*t-6*t*t+4);         f3 = (1.0/6)*((-3)*t*t*t+3*t*t +3*t +1);  f4= (1.0/6)*(t*t*t);          glVertex2f( f1*x_coord[j] + f2*x_coord[j+1] + f3*x_coord[j+2]+ f4*x_coord[j+3],                          f1*y_coord[j] + f2*y_coord[j+1] + f3*y_coord[j+2] + f4*y_coord[j+3]);     }     glEnd(); }  void display(){     glClear(GL_COLOR_BUFFER_BIT);     glBegin(GL_LINE_STRIP);        glColor3f (0, 1, 0);    for (int i = 0; i < nPoints; i++) {  glVertex3f (x_coord[i], y_coord[i], 0.0);    }    glEnd();   glColor3f (1.0, 0, 0);  if (nPoints >=4)  {  B2(20);    }  glFlush();  }  void handle_mouseclick (int button, int state, int x, int y) {  if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {   if( nPoints >=4 )  j++;   printf("%d (%d, %d) ==> (%f, %f)\n", nPoints, x, y, x_convert(x), y_convert(y));   x_coord[nPoints] = x_convert(x);  y_coord[nPoints] = y_convert(y);   nPoints++;   glutPostRedisplay();  } }  void mousemotion(int x, int y) {  float min =99999999;  int index;  x = x_convert(x);         y = y_convert(y);  int i ;  for(i=0; i  if(min > (x-x_coord[i])*(x-x_coord[i]) + (y-y_coord[i])*(y-y_coord[i]) ){  min=(x-x_coord[i])*(x-x_coord[i]) + (y-y_coord[i])*(y-y_coord[i]) ;  index=i;  }  x_coord[index] = x;  y_coord[index] = y;   glutPostRedisplay(); }  int main(int argc, char** argv) {    glutInit(&argc, argv);    glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB |GLUT_DEPTH);    glutInitWindowSize (250, 250);    glutInitWindowPosition (100, 100);    glutCreateWindow ("hello");    init ();     glutDisplayFunc( display );     glutReshapeFunc(myReshape);    glutMouseFunc(handle_mouseclick);    glutMotionFunc(mousemotion);     glutMainLoop();    return 0; }




原创粉丝点击