二次曲面是一種畫復合對象的方法,這種方法通常并不需要很多的三角形。我們將要使用第七課的代碼。我們將要增加7個變量以及修改紋理以增加一些變化 :
bool sp; // 空格鍵是否按下
int part1; // 圓盤的起始角度
int part2; // 圓盤的結束角度
int p1=0; // 增量1
int p2=1; // 增量1
GLUquadricObj *quadratic; // 二次幾何體
GLuint object=0; // 二次幾何體標示符
好了我們現在開始搞InitGL()函數。我們打算增加3行代碼用來初始化我們的二次曲面。這3行代碼將在你使1號光源有效后增加,但是要在返回之前。第一行代碼將初始化二次曲面并且創建一個指向改二次曲面的指針,如果改二次曲面不能被創建的話,那么該指針就是NULL。第二行代碼將在二次曲面的表面創建平滑的法向量,這樣當燈光照上去的時候將會好看些。另外一些可能的取值是:GLU_NONE和GLU_FLAT。最后我們使在二次曲面表面的紋理映射有效。
quadratic=gluNewQuadric(); // 創建二次幾何體
gluQuadricNormals(quadratic, GLU_SMOOTH); // 使用平滑法線
gluQuadricTexture(quadratic, GL_TRUE); // 使用紋理
現在我決定在本課里保留立方體,這樣你可以看到紋理是如何映射到二次曲面對象上的。而且我打算將繪制立方體的代碼定義為一個單獨的函數,這樣我們在定義函數Draw()的時候它將會變的不那么凌亂。每個人都應該記住這些代碼:
GLvoid glDrawCube() // 繪制立方體
{
glBegin(GL_QUADS);
// 前面
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);
// 后面
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);
// 上面
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);
// 下面
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);
// 右面
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);
// 左面
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();
}
接下來就是場景繪制函數了,在這里我只寫一個簡單的例子。并且當我繪制一個部分的盤子的時候,我將使用一個靜態變量(一個局部的變量,該變量可以保留他的值不論你任何時候調用他)來表達一個非常酷的效果。為了清晰起見我將要重寫DrawGLScene函數。
你們將會注意到當我討論這些正在使用的參數時我忽略了當前函數的第一個參數(quadratic)。這個參數將被除立方體外的所有對象使用。所以當我討論這些參數的時候我忽略了它。
int DrawGLScene(GLvoid)
{
//...
// 這部分是新增加的
switch(object) // 繪制哪一種二次幾何體
{
case 0: // 繪制立方體
glDrawCube();
break;
我們創建的第2個對象是一個圓柱體。參數1(1.0F)是圓柱體的底面半徑,參數2(1.0F)是圓柱體的餓頂面半徑,參數3(3.0F)是圓柱體的高度。參數4(32)是緯線(環繞Z軸有多少細分),參數5(32)是經線(沿著Z軸有多少細分)。細分越多該對象就越細致。我們可以用增加細分的方法來增加對象的多邊形數。因此你可以犧牲速度換回質量(以時間換質量),大多數的時候我們都可以很容易的找到一個合適的“度”。
case 1: // 繪制圓柱體
glTranslatef(0.0f,0.0f,-1.5f);
gluCylinder(quadratic,1.0f,1.0f,3.0f,32,32);
break;
對象3將會創建一個CD樣子的盤子。參數1(0.5F)是盤子的內圓半徑,該參數可以為0,則表示在盤子中間沒孔,內圓半徑越大孔越大。參數2(1.5F)表示外圓半徑,這個參數必須比內圓半徑大。參數3(32)是組成該盤子的切片的數量,這個數量可以想象成披薩餅中的切片的數量。切片越多,外圓邊緣就越平滑。最后一個參數(32)是組成盤子的環的數量。環很像唱片上的軌跡,一環套一環。這些環從內圓半徑細分到外圓半徑。再說一次,細分越多,速度越慢。
case 2: // 繪制圓盤
gluDisk(quadratic,0.5f,1.5f,32,32);
break;
我們的第4個對象我知道你們為描述它耗盡精力。就是球。繪制球將會變的非常簡單。參數1是球的半徑。如果你無法理解半徑/直徑等等的話,可以理解成物體中心到物體外部的距離,在這里我們使用1.3F作為半徑。接下來兩個參數就是細分了,和圓柱體一樣,參數2是緯線,參數3是經線。細分越多球看起來就越平滑,通常球需要多一些的細分以使他們看起來平滑。
case 3: // 繪制球
gluSphere(quadratic,1.3f,32,32);
break;
我們創建的第4個對象使用與我們曾經創建的圓柱體一樣的命令來創建,如果你還記得的話,我們可以通過控制參數2和參數3來控制頂面半徑和地面半徑。因此我們可以使頂面半徑為0來繪制一個圓錐體,頂面半徑為0將會在頂面上創建一個點。因此在下面的代碼中,我們使頂面半徑等于0,這將會創建一個點,同時也就創建了我們的圓錐。
case 4: // 繪制圓錐
glTranslatef(0.0f,0.0f,-1.5f);
gluCylinder(quadratic,1.0f,0.0f,3.0f,32,32);
break;
我們的第6個對象將被gluPartialDisk函數創建。我們打算創建的這個對象使用了一些命令,這些命令在我們創建對象之前,你將會清楚的看到。但是命令gluPartialDisk擁有兩個新的參數。第5個參數是我們想要繪制的部分盤子的開始角度,參數6是旋轉角,也就是轉過的角度。我們將要增加旋轉角,這將引起盤子沿順時針方向緩慢的被繪制在屏幕上。一旦旋轉角達到360度我們將開始增加開始角度,這樣盤子看起來就想是被逐漸的抹去一樣。我們將重復這些過程。
case 5: // 繪制部分圓盤
part1+=p1;
part2+=p2;
if(part1>359)
{
p1=0;
part1=0;
p2=1;
part2=0;
}
if(part2>359)
{
p1=1;
p2=0;
}
gluPartialDisk(quadratic,0.5f,1.5f,32,32,part1,part2-part1);
break;
};
//...
}
In the KillGLWindow() section of code, we need to delete the quadratic to free up system resources. We do this with the command gluDeleteQuadratic.
GLvoid KillGLWindow(GLvoid)
{
gluDeleteQuadric(quadratic); // 刪除二次幾何體
在最后,我給出鍵盤輸入代碼。僅僅增加一些對剩余鍵的檢查。
if (keys[' '] && !sp) // 空格是否按下
{
sp=TRUE; // 是,則繪制下一種二次幾何體
object++;
if(object>5)
object=0;
}
if (!keys[' ']) // 空格是否釋放
{
sp=FALSE; // 記錄這個狀態
}
這就是全部了。現在你可以在OpenGL中繪制二次曲面了。