Quadrics in OpenGL (L9)

2015-12-17_195331

以往我們只會畫平面、立方體或三角錐...等,由平面組成的立體圖形,今天要介紹複雜一點的圖形,那就是二次曲面( Quadric ),包含了圓形、扇形、球體、圓柱體以及圓錐體。實作方面不難,只要套用 GLUquadricObj 這個物件即可。

 GLuint quadratic_object;
 GLUquadric * quadratic;

首先在自己的 Class 裡面加入兩個 data members 分別是 quadratic_objectquadratic。quadratic_object 是待會用來切換不同二次曲面的參數,quadratic 則是儲存 GLUquadric 物件的指標。

quadratic = gluNewQuadric();
gluQuadricNormals(quadratic, GLU_SMOOTH);//GLU_NONE, GLU_FLAT
gluQuadricTexture(quadratic, GL_TRUE);

接著,在 initializeGL() 裡面定義 quadratic,

quadratic = gluNewQuadric() 表示建立一個二次曲面空間給 quadratic。

gluQuadricNormals(quadratic, GLU_SMOOTH) 設定外觀效果給 lighting 使用,除了 GLU_SMOOTH 外,還有 GLU_NONEGLU_FLAT 可以使用。

gluQuadricTexture(quadratic, GL_TRUE) 讓 texture 可以 mapping 到我們的二次曲面上。

switch(quadratic_object)
{
case 0:
	drawCube();	//cube
	break;
case 1:
	glTranslatef(0.0f, 0.0f, -1.5f);
	gluCylinder(quadratic, 1.0f, 1.0f, 3.0f, 32, 32);	//cylinder
	break;
case 2:
	gluDisk(quadratic, 0.5f, 1.5f, 32, 32);	//CD disk
	break;
case 3:
	gluSphere(quadratic, 1.3f, 32, 32);	//sphere
	break;
case 4:
	glTranslatef(0.0f, 0.0f, -1.5f);
	gluCylinder(quadratic, 1.0f, 0.0f, 3.0f, 32, 32);	//cone
	break;
case 5:
	int angle_start = 0;
	int sweep_angle = 180;
	gluPartialDisk(quadratic, 0.5f, 1.5f, 32, 32, angle_start, sweep_angle);	//fan
	break;
}

最後就是在 paintGL() 上繪出不同形狀的圖形了,透過不一樣的 function 來繪製不同的形狀。

drawCube() 是前面一直會用到的很簡單的立方體。


glBegin(GL_QUADS);
//front
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
//back
glNormal3f(0.0f, 0.0f,-1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f,-1.0f,-1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f,-1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f,-1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f,-1.0f,-1.0f);
//top
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f,-1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f,-1.0f);
// bottom
glNormal3f(0.0f,-1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,-1.0f,-1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,-1.0f,-1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 1.0f);
//right
glNormal3f(1.0f, 0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f,-1.0f,-1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f,-1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f,-1.0f, 1.0f);
//left
glNormal3f(-1.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f,-1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f,-1.0f);
glEnd();

gluCylinder(quadratic, 1.0f, 1.0f, 3.0f, 32, 32) 為繪製圓柱體,第一個參數是表示底部的半徑,第二個參數表示頂部的半徑,第三個參數表示圓柱體的高,第四個參數 32 表示 slices,代表多少切片圍繞在圓柱體,第五個參數 32 表示 stacks,表示圓柱體是用多少堆疊起來,數值越高表示精度越高

gluDisk(quadratic, 0.5f, 1.5f, 32, 32) 表示圓盤,0.5f 表示內圈半徑,1.5f 表示外圈半徑。內圈半徑一定要小於外圈半徑。

gluSphere(quadratic, 1.3f, 32, 32) 繪製球體,1.3f 為球體半徑。

gluCylinder(quadratic, 1.0f, 0.0f, 3.0f, 32, 32) 繪製圓錐,特別注意到這裡的 function 與繪製圓柱體一樣,只是今天第二個參數(頂部的半徑設為零),就會呈現圓錐體。

gluPartialDisk(quadratic, 0.5f, 1.5f, 32, 32, angle_start, sweep_angle) 繪製扇形。0.5f 表示內半徑,1.5f 表示外半徑,angle_start 表示扇形起始點,sweep_angle 表示掃過的角度有多少。

 

 


透過變更 quadratic_object 來選擇不同的圖形輸出,執行結果:

picasion.com_bbf0c4deb01ab0c797f51566ae4a9a0e

至於文章前面像釘子網的圖形,我是用陣列方式匯出多個圓錐形來實現的。

 

 


reference : http://nehe.gamedev.net/tutorial/quadrics/20001/

 

Leave a Reply

Your email address will not be published. Required fields are marked *