Download presentation
Presentation is loading. Please wait.
1
OpenGL (7) 靜宜大學資工系 蔡奇偉 副教授
2
多面體模型 多邊形 OpenGL 相關函式
3
多邊形 何謂多邊形? 多邊形的種類 多邊形的正面與反面 填滿多邊形 OpenGL 多邊形相關函式
4
何謂多邊形? n 邊的多邊形(polygon)是由 n 個共平面的端點 v1, v2, …, vn 和 n 條邊線 (v1, v2),(v2, v3), …, (vn-1, vn), (vn, v1) 所組成。 v1 v2 v3 v4 v1 v2 v3 v1 v2 v3 v4 v5 v6 v7 v1 v2 v3 v4 v5
5
多邊形的種類 簡單多邊形(simple polygon) 邊線都不相交而且沒有洞的多邊形。又可分成:
凸多邊形(convex polygon) 假定 a 和 b 是多邊形中任意的兩點。線段 ab 上所有的點也都在多邊形中。 凹多邊形(concave polygon) 不是凸的簡單多邊形即為凹多邊形。 非簡單多邊形(non-simple polygon) 邊線相交或有洞的多邊形。
6
凸多邊形 凹多邊形 非簡單的多邊形
7
多邊形的正面與反面 在三度空間中,多邊形有正反兩面。端點順序符合逆時針方向的那一面稱為正面,另一面即為反面。 v3 v2 反面 正面 v4
8
OpenGL 多邊形相關函式 glRect*() glBegin() …glEnd() glPolygonMode()
glFrontFace() glCullFace() glPolygonStipple()
9
glRect{sifd} (TYPE x1, TYPE y1, TYPE x2, TYPE y2)
在 z = 0 的平面上,畫一個以 (x1, y1) 和 (x2, y2) 為對角端點的矩形。 (x1, y1) (x2, y2) (x1, y1) (x2, y2) glRect{sifd}v (TYPE *v1, TYPE *v2) v1: 用來存第一個端點的陣列 v2: 用來存第二個端點的陣列
10
glBegin(type) /* 一連串的 glVertex*() 呼叫 */ glEnd() 參數 type 可以是下面的常數值: GL_TRIANGLES GL_TRIANGLE_STRIP GL_TRIANGLE_FAN GL_QUADS GL_QUAD_STRIP GL_POLYGON
11
glPolygonMode (GLenum face, GLenum mode)
控制多邊形的繪製的方式。 參數 face 設定繪製多邊形的正面或反面,其值可為: GL_FRONT_AND_BACK 正反面都畫(此為預設值) GL_FRONT 只畫正面 GL_BACK 只畫反面 參數 mode 設定繪製的模式,其值可為: GL_FILL 填滿多邊形內部(此為預設的模式) GL_LINE 只畫多邊形的框線 GL_POINT 只畫多邊形的端點
12
GL_FILL GL_LINE GL_POINT
13
glFrontFace (GLenum mode) 設定多邊形正面的決定方式。 參數 mode 設定正面的方向,其值可為:
GL_CCW 逆時針方向為正面(此為預設值) GL_CW 順時針方向為正面 v3 v3 v2 v2 正面 GL_CCW GL_CW 正面 v4 v4 v1 v1
14
glCullFace (GLenum mode)
GL_FRONT 正面 GL_BACK 反面 GL_FRONT_AND_BACK 正面和反面 呼叫此函式之前,你必須已經呼叫 glEnable(GL_CULL_FACE) 來啟動此 OpenGL 的剔除功能。 若要關閉此功能,則可呼叫: glDisable(GL_CULL_FACE)
15
繪製曲面的線框圖 typedef double (*UVFuncPtr) (double, double); class Mesh {
public: Mesh (); void set_XYZFunc (UVFuncPtr xfp, UVFuncPtr yfp, UVFuncPtr zfp); void compute (float umin, float umax, float vmin, float vmax, int m, int n); void set_foreground (float r, float g, float b) { fgRed = r; fgGreen = g; fgBlue = b; } void set_background (float r, float g, float b) { bgRed = r; bgGreen = g; bgBlue = b; } void draw (int mode, bool bHiddenLineRemoval = false); protected: float *vertex (int i, int j) { return data + (i*uSize+j)*3; } void drawObj (); private: void alloc (int m, int n); UVFuncPtr x, y, z; int uSize, vSize; float bgRed, bgGreen, bgBlue; float fgRed, fgGreen, fgBlue; float *data; };
16
static double stdXFunc (double u, double v)
{ return u; } static double stdYFunc (double u, double v) return v; static double stdZFunc (double u, double v) return u+v; Mesh::Mesh () : uSize(0), vSize(0), data(0), x(stdXFunc), y(stdYFunc), z(stdZFunc)
17
void Mesh::set_XYZFunc (UVFuncPtr xfp, UVFuncPtr yfp, UVFuncPtr zfp)
{ if (xfp) x = xfp; if (yfp) y = yfp; if (zfp) z = zfp; } void Mesh::alloc (int m, int n) uSize = n + 1; vSize = m + 1; data = new float[uSize*vSize*3];
18
void Mesh::compute (float umin, float umax, float vmin, float vmax,
int m, int n) { if (data) delete [] data; alloc(m, n); double u, v, du = (umax-umin)/n, dv = (vmax-vmin)/m; int i, j; float *dp = data; for (i = 0, v = vmin; i <= n; i++, v += dv) for (j = 0, u = umin; j <= m; j++, u += du) { *dp++ = x(u,v); *dp++ = y(u,v); *dp++ = z(u,v); }
19
virtual void Mesh::drawObj ()
{ for (int i = 0; i < vSize-1; i++) { glBegin(GL_QUAD_STRIP); for (int j = 0; j < uSize; j++) { glVertex3fv(vertex(i+1, j)); glVertex3fv(vertex(i, j)); } glEnd();
20
void Mesh::draw (int mode, bool bHiddenLineRemoval)
{ glPolygonMode(GL_FRONT_AND_BACK, mode); glColor3f( fgRed, fgGreen, fgBlue); drawObj(); if (bHiddenLineRemoval) { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.0, 1.0); glColor3f(bgRed, bgGreen, bgBlue); glDisable(GL_POLYGON_OFFSET_FILL); }
21
用法: Mesh mesh; double z (double u, double v) {
return 2.0*exp(-u*u-v*v); } … void init () glEnable(GL_DEPTH_TEST); mesh.set_XYZFunc(0, 0, z); mesh.set_foreground(1.0, 0.0, 0.0); mesh.set_background(0.0, 0.0, 0.0); mesh.compute(-1, 1, -1, 1, 10, 10);
22
void display(void) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); mesh.draw(GL_LINE, true); glutSwapBuffers(); }
23
端點陣列 我們可以用 OpenGL 的端點陣列 (vertex array) 來預先儲存參數式的計算值。然後,用端點陣列中的資料來繪製曲線。這樣一來,就可以避免參數式的重新計算。
24
使用端點陣列的步驟 啟動端點陣列的功能。 建立端點陣列及儲存資料於其中。 運用端點陣列中的資料來繪製圖形。
25
啟動端點陣列的功能 void glEnableClientState (GLenum array) 參數 array 可以是以下的常數值:
GL_VERTEX_ARRAY GL_COLOR_ARRAY GL_SECONDARY_COLOR_ARRAY GL_INDEX_ARRAY GL_NORMAL_ARRAY GL_FOG_COORDINATE_ARRAY GL_TEXTURE_COORD_ARRAY GL_EDGE_FLAG_ARRAY
26
關閉端點陣列的功能 void glDisableClientState (GLenum array) 參數 array 的值如前一頁所示。
27
建立端點陣列 void glVertexPointer ( Glint size, // 端點的維度
GLenum type, // 端點座標值的資料型態 GLsizei stride, // 兩端點資料的間隔 byte 數 const GLvoid *pointer // 端點資料的儲存位置 ) 例: float vlist3[3*100]; glVertexPointer(3, GL_FLOAT, 0, vlist3);
28
運用端點陣列 void glArrayElement (GLint ith) 輸出所有開啟陣列的第 i 個元素。
29
void glDrawElements (GLenum mode, GLsizei count,
GLenum type, void *indices) vertex arrays index array
30
1 2 3 4 5 6 7 front back vertex array 1 2 3 4 5 6 7 GLubyte Front[] = {4,5,6,7}; GLubyte Right[] = {1,2,6,5}; GLubyte Bottom[] = {0,1,5,4}; GLubyte Back[] = {0,3,2,1}; GLubyte Left[] = {0,4,7,3}; GLubyte Top[] = {2,3,7,6}; glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, Front); glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, Right); glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, Bottom); glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, Back); glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, Left); glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, Top);
31
GLubyte allIndices[] = {4,5,6,7, 1,2,6,5, 0,1,5,4,
0,3,2,1, 0,4,7,3, 2,3,7,6}; glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, allIndices);
32
Normal Vectors(法向量) 垂直於曲面上一點的單位向量,稱為該點的法向量,如下圖所示:
在 OpenGL 中,你只能在端點上指定其法向量。法向量會決定端點所接受的光量。我們以後再來討論這個主題。 N
33
法向量的計算 平滑曲面 我們先計算 u 方向與 v 方向的切向量: 則法向量為:
34
範例 當 u = 1 和 v = 2 時,垂直於該點上的向量為 (-24, 2, 24)。 除以此向量的長度 34 之後,我們得到法向量為:
( , , )
35
平面多邊形(flat polygon) 我們知道平面上每一點的法向量都相同。假定 v1, v2, 和 v3 是平面上不共線的三點。 v3 N
36
範例 glNormal3{bsidf} (Type nx, Type ny, Type nz)
glNormal3{bsidf}v (const Type *v) 設定目前的法向量,成為下一個 glVertex*() 定義之端點的法向量。 範例 glBegin(GL_POLYGON); glNormal3fv(n0); glVertex3fv(v0); glNormal3fv(n1); glVertex3fv(v1); glNormal3fv(n2); glVertex3fv(v2); glNormal3fv(n3); glVertex3fv(v3); glEnd();
Similar presentations