Presentation is loading. Please wait.

Presentation is loading. Please wait.

Modeling 靜宜大學資工系 蔡奇偉副教授. 大綱  何謂多邊形?  多邊形的種類  多邊形的正面與反面  填滿多邊形  OpenGL 多邊形相關函式  範例.

Similar presentations


Presentation on theme: "Modeling 靜宜大學資工系 蔡奇偉副教授. 大綱  何謂多邊形?  多邊形的種類  多邊形的正面與反面  填滿多邊形  OpenGL 多邊形相關函式  範例."— Presentation transcript:

1 Modeling 靜宜大學資工系 蔡奇偉副教授

2 大綱  何謂多邊形?  多邊形的種類  多邊形的正面與反面  填滿多邊形  OpenGL 多邊形相關函式  範例

3 何謂多邊形? n 邊的多邊形( polygon )是由 n 個共平面的端點 v 1, v 2, …, v n 和 n 條邊線 (v 1, v 2 ) , (v 2, v 3 ), …, (v n-1, v n ), (v n, v 1 ) 所組成。 v1v1 v2v2 v3v3 v1v1 v2v2 v3v3 v4v4 v1v1 v2v2 v3v3 v4v4 v5v5 v6v6 v7v7 v1v1 v2v2 v3v3 v4v4 v5v5

4 多邊形的種類 簡單多邊形( simple polygon ) 邊線都不相交而且沒有洞的多邊形。又可分成: 凸多邊形( convex polygon ) 假定 a 和 b 是多邊形中任意的兩點。線段 ab 上所有 的點也都在多邊形中。 凹多邊形( concave polygon ) 不是凸的簡單多邊形即為凹多邊形。 非簡單多邊形( non-simple polygon ) 邊線相交或有洞的多邊形。

5 凸多邊形 凹多邊形 非簡單的多邊形

6 多邊形的正面與反面 在三度空間中,多邊形有正反兩面。通常我們把端點順序符合 逆時針方向的那一面稱為正面,另一面稱為反面。 v1v1 v2v2 v3v3 v4v4

7 OpenGL 多邊形相關函式  glRect*()  glPolygonMode()  glFrontFace()  glCullFace()

8 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: 用來存第二個端點的陣列

9 glBegin( type ) /* 一連串的 glVertex*() 呼叫 */ glEnd() 參數 type 可以是下面的常數值: GL_TRIANGLES GL_TRIANGLE_STRIP GL_TRIANGLE_FAN GL_QUADS GL_QUAD_STRIP GL_POLYGON

10 glPolygonMode (GLenum face, GLenum mode ) 控制多邊形的繪製的方式。 參數 face 設定繪製多邊形的正面或反面,其值為: GL_FRONT_AND_BACK 正反面都畫 參數 mode 設定繪製的模式,其值可為: GL_FILL 填滿多邊形內部(此為預設的模式) GL_LINE 只畫多邊形的框線 GL_POINT 只畫多邊形的端點

11 glFrontFace (GLenum mode ) 設定多邊形正面的決定方式。 參數 mode 設定正面的方向,其值可為: GL_CCW 逆時針方向為正面(此為預設值) GL_CW 順時針方向為正面 v3v3 v4v4 v1v1 v2v2 GL_CCW v3v3 v4v4 v1v1 v2v2 GL_CW

12 glCullFace (GLenum mode ) 設定多邊形那一個面被剔除( cull )。 參數 mode 選擇那一面被剔除,其值可為: GL_FRONT 正面 GL_BACK 反面 GL_FRONT_AND_BACK 正面和反面 呼叫此函式之前,你必須已經呼叫 glEnable(GL_CULL_FACE) 來啟動此 OpenGL 的剔除功能。 若要關閉此功能,則可呼叫: glDisable(GL_CULL_FACE)

13 範例: cube 繪製方法(使用 triangles ) vertex list 01234567 0 1 2 3 4 5 6 7 front back void make_cube_vertices ( GLfloat size ) { GLfloat half_size = size / 2.0f; vertexList[0] = vec3(-half_size, -half_size, half_size); vertexList[1] = vec3(-half_size, -half_size, -half_size); vertexList[2] = vec3(-half_size, half_size, -half_size); vertexList[3] = vec3(-half_size, half_size, half_size); vertexList[4] = vec3( half_size, -half_size, half_size); vertexList[5] = vec3( half_size, -half_size, -half_size); vertexList[6] = vec3( half_size, half_size, -half_size); vertexList[7] = vec3( half_size, half_size, half_size); } x z y

14 0 1 2 3 4 5 6 7 front back void draw_cube01 (void) { vec3 tv[36]; // vertices of triangles tv[0] = vertexList[2]; tv[1] = vertexList[3]; tv[2] = vertexList[7]; tv[3] = vertexList[7]; tv[4] = vertexList[6]; tv[5] = vertexList[2];...... tv[30] = vertexList[4]; tv[31] = vertexList[0]; tv[32] = vertexList[5]; tv[33] = vertexList[0]; tv[34] = vertexList[1]; tv[35] = vertexList[5]; glBufferData( GL_ARRAY_BUFFER, 36*sizeof(vec3), tv, GL_STATIC_DRAW ); glVertexAttribPointer( loc, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) ); glDrawArrays( GL_TRIANGLES, 0, 36 ); }

15 Triangle Strips with Winding Order Triangle strips do face culling differently. For every second triangle, the one who's winding order is opposite from the first triangle's order, the winding order is considered backwards for culling purposes. So if you have set the front face to be clockwise, and have face culling cull back-facing triangles, everything will work exactly as you expect so long as the order of the first triangle is correct. Every even numbered triangle will be culled if it has a clockwise winding, and every odd numbered triangle will be culled if it has a counter-clockwise winding.

16 範例: cube 繪製方法(使用 triangle strips ) void draw_cube02 (void) { vec3 tv[18]; // vertices of triangles tv[0] = vertexList[3]; tv[1] = vertexList[0]; tv[2] = vertexList[7]; tv[3] = vertexList[4]; tv[4] = vertexList[6]; tv[5] = vertexList[5]; tv[6] = vertexList[2]; tv[7] = vertexList[1]; tv[8] = vertexList[3]; tv[9] = vertexList[0]; tv[10] = vertexList[2]; tv[11] = vertexList[3]; tv[12] = vertexList[6]; tv[13] = vertexList[7]; tv[14] = vertexList[0];tv[15] = vertexList[1]; tv[16] = vertexList[4]; tv[17] = vertexList[5]; glBufferData( GL_ARRAY_BUFFER, 18*sizeof(vec3), tv, GL_STATIC_DRAW ); glVertexAttribPointer( loc, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) ); glDrawArrays( GL_TRIANGLE_STRIP, 0, 10 ); glDrawArrays( GL_TRIANGLE_STRIP, 10, 4 ); glDrawArrays( GL_TRIANGLE_STRIP, 14, 4 ); } 0 1 2 3 4 5 6 7

17 Draw Elements  glDrawElements()  glMultiDrawElements()  glDrawRangeElements()

18 vertex arrays index array

19 範例: cube 繪製方法(使用 elements ) GLuint buffer[2];// Buffer object ID’s enum {VERTEX_ARRAY, ELEMENT_ARRAY}; glGenBuffers( 2, buffer ); glBindBuffer( GL_ARRAY_BUFFER, buffer[VERTEX_ARRAY] ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, buffer[ELEMENT_ARRAY] ); 建立 Buffer Objects

20 void draw_cube (void) { GLushort idx[18] = { 3, 0, 7, 4, 6, 5, 2, 1, 3, 0, 2, 3, 6, 7, 0, 1, 4, 5 }; glBufferData( GL_ARRAY_BUFFER, 8*sizeof(vec3), vertexList, GL_STATIC_DRAW ); glVertexAttribPointer( loc, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) ); glBufferData( GL_ELEMENT_ARRAY_BUFFER, 18*sizeof(GLushort), idx, GL_STATIC_DRAW ); glDrawElements( GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0)); glDrawElements( GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, BUFFER_OFFSET(10*sizeof(GLushort))); glDrawElements( GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, BUFFER_OFFSET(14*sizeof(GLushort))); } 0 1 2 3 4 5 6 7

21 void make_sphere_vertices ( GLdouble radius, GLint slices, GLint stacks) { nVertices = slices * (stacks - 1) + 2; // two poles vertexList = new vec3[nVertices]; vertexList[0] = vec3(0.0f, radius, 0.0f); GLdouble ds = 2 * radius / stacks; GLdouble yval = radius, dtheta = 2.0 * M_PI / slices; int k = 1; for (int i = 1; i < stacks; i++) { yval -= ds; GLdouble r = std::sqrt(radius*radius - yval*yval); GLdouble ang = 0.0; for (int j = 0; j < slices; j++) { vertexList[k] = vec3(r*std::cos(ang), yval, r*std::sin(ang)); k++; ang += dtheta; } vertexList[k] = vec3(0.0f, -radius, 0.0f); } 範例: Sphere 繪製方法

22 glBufferData( GL_ARRAY_BUFFER, nVertices*sizeof(vec3), vertexList, GL_STATIC_DRAW ); glVertexAttribPointer( loc, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );

23 // North pole nv = nSlices+2; // number of vertices idx[0] = 0; for (i = 1; i <= nSlices; i++) idx[i] = i; idx[i] = 1; glBufferData( GL_ELEMENT_ARRAY_BUFFER, nv*sizeof(GLushort), idx, GL_STATIC_DRAW ); glDrawElements( GL_TRIANGLE_FAN, nv, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));

24 // inside stacks nv = 2*nSlices+2; // number of vertices for (int k = 1; k < nStacks - 1; k++) { int k1 = nSlices * (k -1) + 1; int k2 = nSlices * k + 1; for (int j = 0; j < 2*nSlices; j+=2) { idx[j] = k1++; idx[j+1] = k2++; } idx[nv-2] = idx[0]; idx[nv-1] = idx[1]; glBufferData( GL_ELEMENT_ARRAY_BUFFER, nv*sizeof(GLushort), idx, GL_STATIC_DRAW ); glDrawElements( GL_TRIANGLE_STRIP, nv, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0)); }

25 // South pole nv = nSlices+2; // number of vertices idx[0] = nVertices - 1; for (i = 1; i <= nSlices; i++) idx[i] = nVertices - nSlices - 2 + i; idx[i] = nVertices - nSlices - 1; glBufferData( GL_ELEMENT_ARRAY_BUFFER, nv*sizeof(GLushort), idx, GL_STATIC_DRAW ); glDrawElements( GL_TRIANGLE_FAN, nv, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0)); vertex list nVertices – 1 – nSlicesnVertices – 1

26 Hidden-Line Removal with Polygon Offset glEnable(GL_DEPTH_TEST); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); set_color(foreground); draw_object_with_filled_polygons(); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.0, 1.0); set_color(background); draw_object_with_filled_polygons(); glDisable(GL_POLYGON_OFFSET_FILL);

27 範例: Icosahedron 繪製方法 #define X.525731112119133606 #define Z.850650808352039932 void make_icosahedron_vertices ( GLdouble radius) { vdata[0] = radius * vec3(-X, 0.0, Z); vdata[1] = radius * vec3(X, 0.0, Z); vdata[2] = radius * vec3(-X, 0.0, -Z); vdata[3] = radius * vec3(X, 0.0, -Z); vdata[4] = radius * vec3(0.0, Z, X); vdata[5] = radius * vec3(0.0, Z, -X); vdata[6] = radius * vec3(0.0, -Z, X); vdata[7] = radius * vec3(0.0, -Z, -X); vdata[8] = radius * vec3(Z, X, 0.0); vdata[9] = radius * vec3(-Z, X, 0.0); vdata[10] = radius * vec3(Z, -X, 0.0); vdata[11] = radius * vec3(-Z, -X, 0.0); } GLushort tindices[20][3] = { {1,4,0}, {4,9,0}, {4,5,9}, {8,5,4}, {1,8,4}, {1,10,8}, {10,3,8}, {8,3,5}, {3,2,5}, {3,7,2}, {3,10,7}, {10,6,7}, {6,11,7}, {6,0,11}, {6,1,0}, {10,1,6}, {11,0,9}, {2,11,9}, {5,2,9}, {11,2,7} };

28 範例: Sphere 繪製方法( subdivision ) Icosahedron

29 void subdivide(vec3 v1, vec3 v2, vec3 v3) { vec3 v12, v23, v31; GLint i; v12 = (v1+v2)/2.0; v23 = (v2+v3)/2.0; v31 = (v3+v1)/2.0; // 映射至球面上 v12 = radius * normalize(v12); v23 = radius * normalize(v23); v31 = radius * normalize(v31); drawtriangle(v1, v12, v31); drawtriangle(v2, v23, v12); drawtriangle(v3, v31, v23); drawtriangle(v12, v23, v31); } v1 v2 v3 v12 v23 v31

30 void subdivide(vec3 v1, vec3 v2, vec3 v3, int depth) { GLfloat v12, v23, v31; GLint i; if (depth == 0) { drawtriangle(v1, v2, v3); return; } v12 = (v1+v2)/2.0; v23 = (v2+v3)/2.0; v31 = (v3+v1)/2.0; // 映射至球面上 v12 = radius * normalize(v12); v23 = radius * normalize(v23); v31 = radius * normalize(v31); subdivide(v1, v12, v31, depth-1); subdivide(v2, v23, v12, depth-1); subdivide(v3, v31, v23, depth-1); subdivide(v12, v23, v31, depth-1); } v1 v2 v3 v12 v23 v31 Recursive Subdivision

31 參考資料 1. OpenGL Programming Guide, 7E Version 3.0 and 3.1 (2010) 2. OpenGL Shading Language 3rd Edition (2010)


Download ppt "Modeling 靜宜大學資工系 蔡奇偉副教授. 大綱  何謂多邊形?  多邊形的種類  多邊形的正面與反面  填滿多邊形  OpenGL 多邊形相關函式  範例."

Similar presentations


Ads by Google