Modeling
Sponsored Links
This presentation is the property of its rightful owner.
1 / 31

Modeling PowerPoint PPT Presentation


  • 85 Views
  • Uploaded on
  • Presentation posted in: General

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

Download Presentation

Modeling

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Modeling

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


大綱

  • 何謂多邊形?

  • 多邊形的種類

  • 多邊形的正面與反面

  • 填滿多邊形

  • OpenGL 多邊形相關函式

  • 範例


v7

v1

v1

v5

v6

v2

v2

v3

v4

v3

v3

v1

v1

v4

v5

v4

v2

v3

v2

何謂多邊形?

n邊的多邊形(polygon)是由 n個共平面的端點 v1, v2, …, vn和 n條邊線 (v1, v2),(v2, v3), …, (vn-1, vn), (vn, v1) 所組成。


多邊形的種類

  • 簡單多邊形(simple polygon)

    • 邊線都不相交而且沒有洞的多邊形。又可分成:

    • 凸多邊形(convex polygon)

      • 假定 a和 b是多邊形中任意的兩點。線段 ab上所有的點也都在多邊形中。

    • 凹多邊形(concave polygon)

      • 不是凸的簡單多邊形即為凹多邊形。

  • 非簡單多邊形(non-simple polygon)

    • 邊線相交或有洞的多邊形。


凸多邊形

凹多邊形

非簡單的多邊形


v3

v2

反面

正面

v4

v1

多邊形的正面與反面

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


OpenGL 多邊形相關函式

  • glRect*()

  • glPolygonMode()

  • glFrontFace()

  • glCullFace()


(x2, y2)

(x1, y1)

(x1, y1)

(x2, y2)

  • glRect{sifd} (TYPE x1, TYPE y1, TYPE x2, TYPE y2)

    • 在 z = 0 的平面上,畫一個以 (x1, y1) 和 (x2, y2) 為對角端點的矩形。

  • glRect{sifd}v (TYPE *v1, TYPE *v2)

    • v1: 用來存第一個端點的陣列

    • v2: 用來存第二個端點的陣列


  • glBegin(type)

  • /* 一連串的 glVertex*() 呼叫 */

  • glEnd()

  • 參數 type可以是下面的常數值:

    • GL_TRIANGLES

    • GL_TRIANGLE_STRIP

    • GL_TRIANGLE_FAN

    • GL_QUADS

    • GL_QUAD_STRIP

    • GL_POLYGON


  • glPolygonMode (GLenumface, GLenummode)

    • 控制多邊形的繪製的方式。

  • 參數 face設定繪製多邊形的正面或反面,其值為:

    • GL_FRONT_AND_BACK正反面都畫

  • 參數 mode設定繪製的模式,其值可為:

    • GL_FILL填滿多邊形內部(此為預設的模式)

    • GL_LINE只畫多邊形的框線

    • GL_POINT只畫多邊形的端點


  • glFrontFace (GLenummode)

    • 設定多邊形正面的決定方式。

  • 參數 mode設定正面的方向,其值可為:

    • GL_CCW逆時針方向為正面(此為預設值)

    • GL_CW順時針方向為正面

v3

v3

v2

v2

正面

GL_CCW

GL_CW

正面

v4

v4

v1

v1


  • glCullFace (GLenummode)

    • 設定多邊形那一個面被剔除(cull)。

  • 參數 mode選擇那一面被剔除,其值可為:

    • GL_FRONT正面

    • GL_BACK反面

    • GL_FRONT_AND_BACK正面和反面

  • 呼叫此函式之前,你必須已經呼叫

    • glEnable(GL_CULL_FACE)

  • 來啟動此 OpenGL 的剔除功能。

  • 若要關閉此功能,則可呼叫:

    • glDisable(GL_CULL_FACE)


2

vertex list

6

3

7

0

1

2

3

4

5

6

7

back

1

5

front

0

4

範例:cube 繪製方法(使用 triangles)

y

x

z

void make_cube_vertices ( GLfloat size )

{

GLfloathalf_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);

}


2

6

3

7

back

1

5

front

0

4

  • 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 );

  • }


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.


範例: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 );

  • }

2

6

3

7

1

5

0

4


Draw Elements

  • glDrawElements()

  • glMultiDrawElements()

  • glDrawRangeElements()


vertex arrays

index array


範例:cube 繪製方法(使用 elements)

建立 Buffer Objects

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] );


  • void draw_cube (void)

  • {

    • GLushortidx[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)));

  • }

2

6

3

7

1

5

0

4


範例:Sphere 繪製方法

  • 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;

    • GLdoubleyval = radius, dtheta = 2.0 * M_PI / slices;

    • intk = 1;

    • for (inti = 1; i < stacks; i++)

    • {

      • yval -= ds;

      • GLdouble r = std::sqrt(radius*radius - yval*yval);

      • GLdoubleang = 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);

  • }


glBufferData( GL_ARRAY_BUFFER, nVertices*sizeof(vec3),vertexList, GL_STATIC_DRAW );

glVertexAttribPointer( loc, 3, GL_FLOAT, GL_FALSE, 0,BUFFER_OFFSET(0) );


  • // 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));


  • // 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));

  • }


  • // 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 –nSlices

nVertices –1


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);


範例: 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);

  • }

  • GLushorttindices[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}

  • };


範例:Sphere 繪製方法(subdivision)

Icosahedron


  • void subdivide(vec3 v1, vec3 v2, vec3 v3)

  • {

    • vec3 v12, v23, v31;

    • GLinti;

    • 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);

  • }

v2

v23

v12

v1

v3

v31


Recursive Subdivision

  • void subdivide(vec3 v1, vec3 v2, vec3 v3, intdepth)

  • {

    • GLfloatv12, v23, v31;

    • GLinti;

    • 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);

  • }

v2

v23

v12

v1

v3

v31


參考資料

  • OpenGL Programming Guide, 7E Version 3.0 and 3.1 (2010)

  • OpenGL Shading Language 3rd Edition (2010)


  • Login