/*
nurbs.cpp
*/
#include "nurbs.h"
#pragma comment(lib,"glu32.lib")
#pragma comment(lib,"glaux.lib")
#pragma comment(lib,"opengl32.lib")
/*
只要将前p个控制点和最后p个控制点重合,就能实现闭合。其中,p为次数,不是阶数。
一:初始化
1、先定义控制点
2、定义NURBS对象
GLUnurbsObj *theNurb;
theNurb = gluNewNurbsRenderer();
3、设置NURBS属性
void gluNurbsProperty(GLUnurbsObj* nobj, GLenum property, GLfloat value)
nobj: 指向NURBS对象的指针。
property: 需设置的属性。
value: 设置指定属性的值。
gluNurbsProperty( theNurb, GLU_SAMPLING_TOLERANCE, 25.0 ) ;
二:绘制Draw
绘制NURBS曲线的函数:gluNurbsCurve:
void gluNurbsCurve(
GLUnurbsObj *nobj, 指向NURBS对象的指针
GLint nknots, 节点数,节点数=控制点数+阶数
GLfloat *knot, nknots数组非递减节点值
Glint stride, 跨度,相邻控制点的偏移量,即:单个控制点的坐标元素个数
GLfloat *ctlarray, 指向NURBS的控制点数组的指针
GLint order, NURBS曲线的阶数,阶数=次数+1
GLenum type 曲线、面类型
);
在glBeginCurve、glEndCurve之间。
*/
CNurbs::CNurbs():m_theNurbs(NULL)
{
initNURBS();
}
CNurbs::~CNurbs()
{
if (m_theNurbs!=NULL) {
gluDeleteNurbsRenderer(m_theNurbs);
m_theNurbs = NULL;
}
}
void CNurbs::initNURBS()
{
//创建NURBS对象m_theNurbs
m_theNurbs = gluNewNurbsRenderer();
//设置采样容差
gluNurbsProperty( m_theNurbs, GLU_SAMPLING_TOLERANCE, 25.0 ) ;
}
// 2阶bizer绘制1/4圆
void CNurbs::DrawQuarterCircleDegree2()
{
int ptCount = 3;
// 1/4圆控制点
// w=sqrt(2)/2,中间的控制点w*[1,1,0,1]=[sin(45),sin(45),0,sin(45)]
float w = sqrt(2)/2.0;
GLfloat ctrlPoints[3][4] = {
{ 4, 0, 0 , 1}, { 4.0*w, 4.0*w, 0 , 1*w }, { 0, 4, 0 , 1}
};
GLfloat circleColors[3][4]= { {1.0,0.0,0.0,1.0}, {1.0,1.0,0.0,1.0}, {1.0,0.5,0.0,1.0} };
GLfloat knots[6] = { 0, 0, 0, 1, 1, 1 };
glPushMatrix();
glTranslatef(-26,0,0);
// 绘制1/4圆曲线
int degree = 2; //阶数(度数)
int order_number = degree+1; //u(v)方向控制点的个数,=曲线度数+1
gluBeginCurve( m_theNurbs ) ;
gluNurbsCurve( m_theNurbs, 6, knots, 4, &ctrlPoints[0][0], order_number, GL_MAP1_VERTEX_4 ) ;
gluNurbsCurve( m_theNurbs, 6, knots, 4, &circleColors[0][0], order_number, GL_MAP1_COLOR_4 );
gluEndCurve(m_theNurbs);
// 画控制点
glPointSize( 8.0f );
glColor3f( 0.0f, 0.0f, 1.0f );
glBegin( GL_POINTS );
for( int i = 0; i < ptCount; i++ ) {
glVertex3fv( &ctrlPoints[i][0] );
}
glEnd();
glPopMatrix();
glFlush();
}
// 4阶bizer绘制1/4圆
void CNurbs::DrawQuarterCircleDegree4()
{
int ptCount = 5;
float const x1 = 4.0f;
float const y1 = 2.0f / sqrt(2);
float const x2 = 4.0f - sqrt(2)/2.0f;
// 1/4圆控制点
float w = 2.0*sqrt(2)/3.0;
GLfloat ctrlPoints[5][4] = {
{ 4, 0, 0 , 1}, { x1, y1, 0 , 1 }, { x2*w, x2*w, 0 , 1*w},
{ y1, x1, 0 , 1 }, { 0, 4, 0 , 1}
};
GLfloat circleColors[5][4]= { {1.0,0.0,0.0,1.0}, {1.0,1.0,0.0,1.0}, {1.0,0.5,0.0,1.0}, {0.8,0.0,0.6,1.0}, {0.7,0.3,0.6,1.0} };
// 10=控制点数5+(阶数+1)
GLfloat knots[10] = { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 };
glPushMatrix();
glTranslatef(-20,0,0);
// 绘制1/4圆曲线
int degree = 4; //阶数(度数)
int order_number = degree+1; //u(v)方向控制点的个数,=曲线度数+1
gluBeginCurve( m_theNurbs ) ;
gluNurbsCurve( m_theNurbs, 10, knots, 4, &ctrlPoints[0][0], order_number, GL_MAP1_VERTEX_4 ) ;
gluNurbsCurve( m_theNurbs, 10, knots, 4, &circleColors[0][0], order_number, GL_MAP1_COLOR_4 );
gluEndCurve(m_theNurbs);
// 画控制点
glPointSize( 8.0f );
glColor3f( 0.0f, 0.0f, 1.0f );
glBegin( GL_POINTS );
for( int i = 0; i < ptCount; i++ ) {
glVertex3fv( &ctrlPoints[i][0] );
}
glEnd();
glPopMatrix();
glFlush();
}
// 3阶bizer绘制1/2圆
void CNurbs::DrawHalfCircleDegree3()
{
int ptCount = 4;
// 1/2圆控制点
float w = 1/3.0f;
GLfloat ctrlPoints[4][4] = {
{ 4, 0, 0 , 1}, { 4*w, 8*w, 0 , 1*w }, { -4*w, 8*w, 0 , 1*w},
{ -4, 0, 0 , 1 }
};
GLfloat circleColors[4][4]= { {1.0,0.0,0.0,1.0}, {1.0,1.0,0.0,1.0}, {1.0,0.5,0.0,1.0}, {0.8,0.0,0.6,1.0} };
GLfloat knots[8] = { 0, 0, 0, 0, 1, 1, 1, 1 };
glPushMatrix();
glTranslatef(-10,0,0);
// 绘制半圆曲线
int degree = 3; //阶数(度数)
int order_number = degree+1; //u(v)方向控制点的个数,=曲线度数+1
gluBeginCurve( m_theNurbs ) ;
gluNurbsCurve( m_theNurbs, 8, knots, 4, &ctrlPoints[0][0], order_number, GL_MAP1_VERTEX_4 ) ;
gluNurbsCurve( m_theNurbs, 8, knots, 4, &circleColors[0][0], order_number, GL_MAP1_COLOR_4 );
gluEndCurve(m_theNurbs);
// 绘制四周的由控制点连接生成的直线
glLineWidth( 8.0f );
glBegin(GL_LINE_STRIP);
for (int i = 0; i < ptCount; i++ ) {
glColor3f( 1.0f, 0.0f, 0.0f );
glVertex3fv( ctrlPoints[i] ) ;
}
glEnd();
// 画控制点
glPointSize( 8.0f );
glColor3f( 0.0f, 0.0f, 1.0f );
glBegin( GL_POINTS );
for( i = 0; i < ptCount; i++ ) {
glVertex3fv( &ctrlPoints[i][0] );
}
glEnd();
glPopMatrix();
glFlush();
}
// 2阶Bizer由3个控制点控制一段曲线
// 通过9个控制点,绘制4段Bizer曲线,组成一个Nurbs圆
void CNurbs::DrawCircleDegree2_9Point()
{
if (m_theNurbs==NULL)
return;
// 圆控制点
int ptCount = 9;
float w = sqrt(2)/2.0f;
GLfloat ctrlPoints[9][4] = {
{ 0, -4, 0 , 1}, { -4*w, -4*w, 0 , 1*w }, { -4, 0, 0 , 1},
{ -4*w, 4*w, 0 , 1*w}, { 0, 4, 0 , 1}, { 4*w, 4*w, 0 , 1*w},
{ 4, 0, 0 , 1}, { 4*w, -4*w, 0 , 1*w}, { 0, -4, 0 , 1}
};
GLfloat circleColors[9][4]= { {1.0,0.0,0.0,1.0}, {1.0,1.0,0.0,1.0}, {1.0,0.5,0.0,1.0}, {0.8,0.0,0.6,1.0},
{0.7,0.3,0.6,1.0}, {0.5,0.7,0.6,1.0}, {0.3,1.0,0.6,1.0}, {0.3,1.0,0.6,1.0}, {0.0,1.0,1.0,1.0}
};
// 画圆节点序列
// 节点数 = 控制点数9+分段曲线的控制点个数3
GLfloat knots[12] = { 0, 0, 0, 0.25, 0.25, 0.5, 0.5, 0.75, 0.75, 1, 1, 1 };
glPushMatrix();
// 绘制圆曲线
int degree = 2; //阶数(度数)
int order_number = degree+1; //u(v)方向控制点的个数,=曲线度数+1
gluBeginCurve( m_theNurbs ) ;
gluNurbsCurve( m_theNurbs, 12, knots, 4, &ctrlPoints[0][0], order_number, GL_MAP1_VERTEX_4 ) ;
gluNurbsCurve( m_theNurbs, 12, knots, 4, &circleColors[0][0], order_number, GL_MAP1_COLOR_4 );
gluEndCurve(m_theNurbs);
// 绘制四周的由控制点连接生成的直线
glLineWidth( 3.0f );
glBegin(GL_LINE_STRIP);
for (int i = 0; i < ptCount; i++ ) {
glColor3f( 1.0f, 0.0f, 0.0f );
glVertex3fv( ctrlPoints[i] ) ;
}
glEnd();
// 画控制点
glPointSize( 8.0f );
glColor3f( 0.0f, 0.0f, 1.0f );
glBegin( GL_POINTS );
for( i = 0; i < ptCount; i++ ) {
glVertex3fv( &ctrlPoints[i][0] );
}
glEnd();
glPopMatrix();
glFlush();
}
// 2阶Bizer由3个控制点控制一段曲线
// 通过7个控制点,绘制4段Bizer曲线,组成一个Nurbs圆
void CNurbs::DrawCircleDegree2_7Point()
{
if (m_theNurbs==NULL)
return;
// 圆控制点
int ptCount = 7;
float w = 0.5f;
GLfloat ctrlPoints[7][4] = {
{ 0, -4, 0 , 1}, { -4*sqrt(3)*w, -4*w, 0 , w }, { -2*sqrt(3), 2, 0 , 1},
{ 0, 8*w, 0 , w}, { 2*sqrt(3), 2, 0 , 1}, { 4*sqrt(3)*w, -4*w, 0 , w},
{ 0, -4, 0 , 1}
};
GLfloat circleColors[7][4]= { {1.0,0.0,0.0,1.0}, {1.0,1.0,0.0,1.0}, {1.0,0.5,0.0,1.0}, {0.8,0.0,0.6,1.0},
{0.7,0.3,0.6,1.0}, {0.5,0.7,0.6,1.0}, {0.3,1.0,0.6,1.0}
};
// 画圆节点序列
// 节点数 = 控制点数7+分段曲线的控制点个数3
GLfloat knots[10] = { 0, 0, 0, 1/3.0, 1/3.0, 2/3.0, 2/3.0, 1, 1, 1 };
glPushMatrix();
glTranslatef(10,0,0);
// 绘制圆曲线
int degree = 2; //阶数(度数)
int order_number = degree+1; //u(v)方向控制点的个数,=曲线度数+1
gluBeginCurve( m_theNurbs ) ;
gluNurbsCurve( m_theNurbs, 10, knots, 4, &ctrlPoints[0][0], order_number, GL_MAP1_VERTEX_4 ) ;
gluNurbsCurve( m_theNurbs, 10, knots, 4, &circleColors[0][0], order_number, GL_MAP1_COLOR_4 );
gluEndCurve(m_theNurbs);
// 绘制四周的由控制点连接生成的直线
glLineWidth( 3.0f );
glBegi