文章目錄
- 3.1 一維求值器
- 3.2 一維均勻求值器
- 3.3 二維求值器
- 4.1 選擇渲染屬性
- 4.2 建立並繪製曲線曲面
作者: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 coordinatesGL_MAP1_VERTEX_4 //x, y, z, wvertex coordinatesGL_MAP1_INDEX //color indexGL_MAP1_COLOR_4 //R, G, B, AGL_MAP1_NORMAL //normal coordinatesGL_MAP1_TEXTURE_COORD_1 //stexture coordinatesGL_MAP1_TEXTURE_COORD_2 //s, ttexture coordinatesGL_MAP1_TEXTURE_COORD_3 //s, t, rtexture coordinatesGL_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_PATCHGLU_NURBS_MODE, // GLU_NURBS_RENDERER, GL_NURBS_TESSELLATORGLU_CULLING, //GLU_SAMPLING_METHOD, // GLU_PATH_LENTH, GLU_PARAMETRIC_ERROR, GLU_DOMAIN_DISTANCEGLU_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);