作者:yurunsun@gmail.com 新浪微博@孙雨润 新浪博客 CSDN博客
日期: 2013-6-13
本章内容:
- 凹多边形分格化
- 二次方程表面
- 求值器
- NURBS
1. 凹多边形分格化
OpenGL显示凹多边形时必须先分解为简单凸多边形,这种划分方法称为多边形分格化(tesselation),glu提供一组函数接受复杂多边形轮廓线,返回一些三角形、三角形网、三角形扇以及直线的组合。
-
创建一个新的分格化对象
GLUtesselator* gluNewTess(void);
-
注册回调函数
void gluTessCallback(GLUtesselator *tessobj, GLenum type, void (*fn)());
-
指定分格化属性,例如环绕规则来确定哪些区域填充、哪些不该着色
void gluTessProperty(GLUtesselator *tessobj, GLenum property, GLdouble value); void gluTessNormal(GLUtesselator *tessobj, GLdouble x, GLdouble y, GLdouble z);
-
指定一个或多个闭合多边形的轮廓线来渲染经过分格化的多边形,最好将分格化后的多边形放入显示列表中
void gluTessBeginPolygon(GLUtesselator *tessobj, void *user_data); void gluNextContour(GLUtriangulatorObj *tessobj, GLenum type); void gluTessEndPolygon(GLUtesselator *tessobj); void gluTessBeginContour(GLUtesselator *tessobj); void gluNextContour(GLUtriangulatorObj *tessobj, GLenum type); void gluTessEndContour(GLUtesselator *tessobj); void gluTessVertex(GLUtesselator *tessobj, GLdouble coords[3], void *vertex_data);
-
继续使用此分格化对象,或者删除
void gluDeleteTess(GLUtesselator *tessobj);
2. 二次方程表面
使用glu创建和渲染二次方程表面步骤如下:
gluNewQuadric()
函数创建一个二次方程对象- 指定这个二次方程对象的属性
gluQuadricOrientation()
函数控制环绕方向,区分内部外部区域gluQuadricDrawStyle()
函数选择把物体渲染成点、直线、填充多边形gluQuadricNormal()
函数为每个顶点或每个面指定一条法线gluQuadricTexture()
函数生成纹理坐标
gluQuadricCallback()
函数注册一个错误处理函数-
根据需要调用相应二次方程表面渲染函数:
gluSphere(); gluCylinder(); gluDisk(); gluPartialDisk();
-
gluDeleteQuadric()
销毁二次方程对象
3. 求值器
3.1 一维求值器
GLfloat ctrlpoints[4][3] = {{ -4.0, -4.0, 0.0}, { -2.0, 4.0, 0.0},
{2.0, -4.0, 0.0}, {4.0, 4.0, 0.0}};
void init(void) {
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);
glEnable(GL_MAP1_VERTEX_3);
}
void display(void) {
glBegin(GL_LINE_STRIP);
for (int i = 0; i <= 30; i++)
glEvalCoord1f((GLfloat) i/30.0);
glEnd();
}
使用下面函数定义一维求值器:
void glMap1f(GLenum target, float u1, float u2, GLint stride, GLint order, const float *points);
GL_MAP1_VERTEX_3 //x, y, zvertex coordinates
GL_MAP1_VERTEX_4 //x, y, z, wvertex coordinates
GL_MAP1_INDEX //color index
GL_MAP1_COLOR_4 //R, G, B, A
GL_MAP1_NORMAL //normal coordinates
GL_MAP1_TEXTURE_COORD_1 //stexture coordinates
GL_MAP1_TEXTURE_COORD_2 //s, ttexture coordinates
GL_MAP1_TEXTURE_COORD_3 //s, t, rtexture coordinates
GL_MAP1_TEXTURE_COORD_4 //s, t, r, qtexture coordinates
- target: GLMAP1VERTEX_3表示指定了应用程序提供的三维控制点以及应该产生的三维顶点
- u1: 0.0表示参数u的低值
- u2: 1.0表示参数u的高值
- stride: 3表示从一个控制点跳到下一个控制点时应该推进多少浮点值
- order: 4表示样条的阶数
- points: &ctrlpoints[0][0]表示指向第一个控制点的数据的指针
下面函数对已启用的求值器执行计算:
void glEvalCoord1{fd}(TYPE u);
void glEvalCoord1{fd}v(const TYPE *u);
可以一次使用多个求值器进行计算,即如果定义并启用了GL_MAP1_VERTEX_3
和一个GL_MAP1_COLOR_4
,就可以调用`glEvalCoord1()函数同时生成一个位置和一种颜色。
3.2 一维均匀求值器
在上例中课件使用了i/30,即使u值均匀分布。更方便的方法是调用glMapGrid1f()
函数定义一个一维网格,然后使用glEvalMesh1()
函数应用这个网格。
void glMapGrid1{fd}(GLint n, TYPE u1, TYPE u2);
void glEvalMesh1(GLenum mode, GLint p1, GLint p2);
第二个函数相当于
glBegin(GL_POINTS);
for (i = p1; i <= p2; i++)
glEvalCoord1(u1 + i*(u2-u1)/n);
glEnd();
3.3 二维求值器
与一维求值器的区别就是需要考虑两个参数u和v.
void glMap2{fd}(GLenum target, TYPE u1, TYPE u2, GLint ustride,
GLint uorder,TYPE v1, TYPE v2, GLint vstride,
GLint vorder, TYPE points);
void glEvalCoord2{fd}(TYPE u, TYPE v);
void glEvalCoord2{fd}v(const TYPE *values);
同样有二维均匀求值器:
void glMapGrid2{fd}(GLint nu,TYPE u1, TYPE u2, GLint nv,TYPE v1, TYPE v2);
void glEvalMesh2(GLenummode, GLint i1, GLint i2, GLint j1, GLint j2);
4. NURBS接口
GLU建立在OpenGL求值器函数的基础上提供了NURBS接口。使用步骤如下:
glEnable(GL_AUTO_NORMAL)
自动生成法线(也可以自己计算)gluNewNurbsRENDERER()
创建指向NURBS对象的指针gluNurbsProperty()
选择渲染属性gluNurbsCallback()
注册错误回调函数gluBeginCurve()/gluBeginSurface()
声明开始绘制曲线曲面gluNurbsCurve()/gluNurbsSurface()
生成和渲染曲线曲面gluEndCurve()/gluEndSurface()
声明结束绘制曲线曲面
下面重点解释其中几个步骤:
4.1 选择渲染属性
voidgluNurbsProperty(GLUnurbsObj *nobj, GLenum property, GLfloat value);
GLU_DISPLAY_MODE, // GLU_FILL, GLU_OUTLINE_POLYGON, GLU_OUTLINE_PATCH
GLU_NURBS_MODE, // GLU_NURBS_RENDERER, GL_NURBS_TESSELLATOR
GLU_CULLING, //
GLU_SAMPLING_METHOD, // GLU_PATH_LENTH, GLU_PARAMETRIC_ERROR, GLU_DOMAIN_DISTANCE
GLU_SAMPLING_TOLERANCE,
GLU_PARAMETRIC_TOLERANCE,
GLU_U_STEP, GLU_V_STEP,
GLU_AUTO_LOAD_MATRIX // 是否需要从openGL服务器下载投影矩阵、模视矩阵和视口 否则使用:
void gluLoadSamplingMatrices(GLUnurbsObj *nobj,
const GLfloat modelMatrix[16],
const GLfloat projMatrix[16],
const GLint viewport[4]);
4.2 创建并绘制曲线曲面
void gluNurbsSurface(GLUnurbsObj *nobj, GLint uknot_count,
GLfloat *uknot, GLint vknot_count, GLfloat *vknot,
GLint u_stride, GLint v_stride, GLfloat *ctlarray,
GLint uorder, GLint vorder, GLenum type);
gluBeginSurface(nobj);
gluNurbsSurface(nobj, ..., GL_MAP2_TEXTURE_COORD_2);
gluNurbsSurface(nobj, ..., GL_MAP2_NORMAL);
gluNurbsSurface(nobj, ..., GL_MAP2_VERTEX_3);
gluEndSurface(nobj);
- 如果这篇文章对您有帮助,请到CSDN博客留言;
- 转载请注明:来自雨润的技术博客 http://blog.csdn.net/sunyurun