http://blog.csdn.net/yangtrees/article/details/9026411
绘制B样条曲线:
#include <stdlib.h>
#include <GL/glut.h>
#pragma comment(lib,"glut32.lib")
//
#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!!
//
#else
float 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 curve
unsigned int LOD=20;
#define NUM_SEGMENTS (NUM_POINTS-3)
//
float* GetPoint(int i)
{
// return 1st point
if (i<0)
{
return Points[0];
}
if (i<NUM_POINTS)
{
return Points[i];
}
// return last point
return Points[NUM_POINTS-1];
}
//------------------------------------------------------------ OnKeyPress()
void myIdle(void)
{
glutPostRedisplay();
}
//------------------------------------------------------------ OnDraw()
void OnDraw()
{
// clear the screen & depth buffer
glClear(GL_COLOR_BUFFER_BIT);
// clear the previous transform
glLoadIdentity();
// 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 hull
glColor3f(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 curve
glBegin(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 divisions
for(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 inverted
float it = 1.0f-t;
// calculate blending functions for cubic bspline
float 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 point
float 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 point
glVertex2f( x,y );
}
}
// we need to specify the last point on the curve
//glVertex3fv( Points[NUM_POINTS-1] );
glEnd();
// draw CV's
glBegin(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 visible
glutSwapBuffers();
}
//------------------------------------------------------------ OnInit()
void OnInit()
{
//glClearColor(1,1,1,0);
}
//------------------------------------------------------------ OnExit()
void OnExit()
{
}
//------------------------------------------------------------ OnReshape()
void OnReshape(int w, int h)
{
// prevents division by zero when minimising window
if (h==0)
{
h=1;
}
// set the drawable region of the window
glViewport(0,0,w,h);
// set up the projection matrix
glMatrixMode(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);
}
else
{
glOrtho(-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 about
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
//------------------------------------------------------------ main()
int main(int argc,char** argv)
{
// initialise glut
glutInit(&argc,argv);
// request a depth buffer, RGBA display mode, and we want double buffering
glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE);
// set the initial window size
glutInitWindowSize(640,480);
// create the window
glutCreateWindow("Clamped B-Spline Curve");
// run our custom initialisation
OnInit();
// set the function to use to draw our scene
glutDisplayFunc(OnDraw);
// set the function to handle changes in screen size
glutReshapeFunc(OnReshape);
glutIdleFunc(&myIdle);
// set the function to be called when we exit
atexit(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 <stdio.h>
#include <math.h>
#include <gl/glut.h>
#pragma comment(lib,"glut32.lib")
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画线算法
{
float dx= xEnd - x0 ;
float 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 < steps; 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 <stdio.h>
#include <math.h>
#include <gl/glut.h>
#pragma comment(lib,"glut32.lib")
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 <min; 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;
}