如何做html網(wǎng)站網(wǎng)絡(luò)營銷服務(wù)外包
1、本節(jié)實(shí)現(xiàn)的內(nèi)容
上一節(jié)我們創(chuàng)建一個(gè)簡單的窗口,本節(jié)我們需要了解一下細(xì)節(jié)內(nèi)容,同時(shí)為了方便觀看,我們需要顯示一個(gè)世界坐標(biāo)軸,建立一個(gè)直觀的三維空間。
2、我們的眼睛設(shè)定(gluPerspective函數(shù))
上一節(jié)課,我們創(chuàng)建了一個(gè)簡單的opengl窗口,并顯示了一個(gè)簡單的3d模型正方體,這節(jié)我們就要開始了解更多的細(xì)節(jié)內(nèi)容。嗯,上一節(jié)課中,使用了視角的設(shè)置函數(shù)perspective,第一個(gè)參數(shù)表示視場角的大小,符合人眼的條件一般設(shè)置為40°~70°之間這個(gè)函數(shù)。在我理解,有點(diǎn)像是你眼睛展開的角度,比如說10度就有點(diǎn)像你能觀測的范圍只有10度,就像瞇著眼睛看世界,那么他看到的物體就范圍比較窄,如果你設(shè)置的是60度,那么它光視角就會(huì)更大一些,看到的范圍更多。這一點(diǎn)可以在我們后期,從三維坐標(biāo)轉(zhuǎn)換到屏幕的二維坐標(biāo)中體會(huì)到,說當(dāng)前的這個(gè)角度是60度,在坐標(biāo)轉(zhuǎn)換中一個(gè)三維坐標(biāo)點(diǎn)A如果在當(dāng)前視角的屏幕以外,那么,它A點(diǎn)與當(dāng)前屏幕正中間點(diǎn)的視線夾角肯定就超過了60度,我們在后期講解三維坐標(biāo)轉(zhuǎn)換時(shí)會(huì)講到。
void gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)
fovy:視角的大小,相當(dāng)于眼睛張開的角度。當(dāng)視角為0度時(shí),這就相當(dāng)于我們的眼睛閉起來了,那就神馬也看不到了。所以選擇一個(gè)合適的視角尤為重要,一般40度至70度最適合,當(dāng)然具體情況具體分析。
aspect:寬和高的比例,這里我們直接可以取程序窗口的寬度和高度比。
zNear:觀察點(diǎn)與近側(cè)裁剪平面的距離,眼睛距離近處的距離,一般選擇0.01。
zFar:觀察點(diǎn)與遠(yuǎn)側(cè)裁剪平面的距離,眼睛遠(yuǎn)處的裁面,一般為1000,超過這個(gè)距離將被裁剪看不到。
zNear和zFar說明了對于繪制的圖形,它與視線原點(diǎn)的距離0.01到1000之間必須是在兩者之間。
3、我們看向遠(yuǎn)方的視線(gluLookAt函數(shù))
我們還用到了一個(gè)函數(shù)gluLookAt,這個(gè)函數(shù)形象的表述了我們在三維世界里頭眼睛所在的位置和朝向的位置,還有一個(gè)視角的方向。
void gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz, GLdouble upx,GLdouble upy,GLdouble upz);
前兩個(gè)非常的好理解,第一個(gè)參數(shù)就表示的是你眼睛的位置,第二個(gè)參數(shù)就表示你要看物體的位置坐標(biāo),當(dāng)然,我們第二個(gè)參數(shù)可以不確定到具體的物體位置坐標(biāo),只要你向前看,視線上的任何一點(diǎn)都可以。第三個(gè)參數(shù),要是你視線的正上方向量,根據(jù)設(shè)定角度不同,可以實(shí)現(xiàn)側(cè)著頭觀察世界的效果。
4、通過我們的眼睛和視線探索世界
通過我們前面講到的我們的眼睛設(shè)定(gluPerspective函數(shù))和我們看向遠(yuǎn)方的視線(gluLookAt函數(shù)),我們就可以描述出我們觀察時(shí)間的方式。還拿上節(jié)課的例子,我們通過gluPerspective將眼睛以45度的角度睜開,我的眼睛位于一個(gè)(10.0f,10.0f,10.0f)點(diǎn)的位置,視線朝著原點(diǎn)(0.0f,0.0f,0.0f)點(diǎn)的位置望去,這就是我們以下代碼大致實(shí)現(xiàn)的內(nèi)容。
//獲取窗口大小RECT tempClientRect;GetClientRect(hWnd,&tempClientRect);//初始化3D視角glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(45,(float)tempClientRect.right/(float)tempClientRect.bottom,0.01f,1000.0f);glMatrixMode(GL_MODELVIEW);glLoadIdentity();//設(shè)置用戶眼睛視角,展示壯觀的三維世界從這里開始gluLookAt(10.0f,10.0f,10.0f,0.0f,0.0f,0.0f,0.0f,1.0f,0.0f);
說到這里,后期當(dāng)我們不停地改變眼睛的位置和視線的方向,就產(chǎn)生了視角移動(dòng)的效果,可以產(chǎn)生人物移動(dòng)觀察世界的效果,類似第一人稱射擊游戲或RPG游戲人物視角的效果,是不是很有感覺,我們將在后期完善相關(guān)代碼,隨后再詳細(xì)說。
5、窗口顯示比例的鎖定
當(dāng)我們創(chuàng)建了視角以后,我們發(fā)現(xiàn)一個(gè)問題:當(dāng)我們鼠標(biāo)拖動(dòng)窗口改變大小時(shí),我們剛剛顯示的物體竟然變形狀了,而且立方體的位置不再顯示在窗口的中心。試想以下,我們?nèi)绻谕嬗螒?#xff0c;出現(xiàn)人物如果會(huì)隨著程序窗口大小的改變而不斷地被拉長或壓扁,那將是個(gè)多么糟糕的事情。因此我們需要另一個(gè)函數(shù),來保證所有的物體保持橫寬比例。
OpenGL中的glViewport 函數(shù)用于定義視口(Viewport),也就是確定窗口中顯示的區(qū)域。它的定義如下:
void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);
x:視口的左下角X坐標(biāo)。
y:視口的左下角Y坐標(biāo)。
width:視口的寬度。
height:視口的高度。
glViewport函數(shù)的作用是將正投影坐標(biāo)(OpenGL的默認(rèn)坐標(biāo)系)映射到屏幕上實(shí)際顯示的區(qū)域。它將正投影坐標(biāo)系中的點(diǎn)映射到屏幕上指定大小的矩形區(qū)域內(nèi)。這里我們將的glViewport(0,0,tempClientRect.right,tempClientRect.bottom)就時(shí)將整個(gè)程序窗口平面設(shè)定為顯示區(qū)域,那么配合著gluPerspective中設(shè)定的平面橫縱比為(float)tempClientRect.right/(float)tempClientRect.bottom,我們就可以保持整個(gè)世界的橫縱比例保持一致,不至于出現(xiàn)拉長、壓扁的情況了。
//獲取窗口大小RECT tempClientRect;GetClientRect(hWnd,&tempClientRect);//重置視窗設(shè)置glViewport(0,0,tempClientRect.right,tempClientRect.bottom);glMatrixMode(GL_PROJECTION);glLoadIdentity();
在使用OpenGL進(jìn)行繪圖時(shí),我們通常需要先通過glViewport來設(shè)置視口,將整個(gè)窗口或窗口的一部分作為渲染區(qū)域。這樣,我們可以指定繪制的內(nèi)容在窗口的哪個(gè)位置顯示出來。通常情況下,我們將glViewport放置到窗口改變的消息處理函數(shù)中即可,但如果后期需要顯示多個(gè)glViewport視口,就需要改變glViewport的設(shè)置位置。
大家還記不記得魔獸爭霸3游戲界面里的人物選中頭像界面,在二維平面相框中顯示出來三維的頭像,就可以個(gè)用glViewport實(shí)現(xiàn)出來,我們將在后面的程序中實(shí)現(xiàn)這一個(gè)功能,敬請期待。
6、我們需要一個(gè)三維坐標(biāo)軸
接下來,我們看到的立方體是在一個(gè)黑色窗口里面,仿佛懸浮在空中一樣,沒有參照物,我們要?jiǎng)?chuàng)建一個(gè)可以看見的三維坐標(biāo)軸方便觀察。大家需要明確的一點(diǎn)是openGL中世界坐標(biāo)系(World Coordinates)是右手坐標(biāo)系,在二維屏幕上,屏幕水平方向是x 軸方向,向右為正,屏幕豎起方向是Y軸方向,向上為正,垂直于屏幕的方向是Z軸方向,從屏幕里往外為正。
我們首先去生成一個(gè)坐標(biāo)軸,我們需要使用的畫線操作。OpenGL的繪圖的函數(shù)很多,OpenGL的繪圖必須在在glBegin()和glEnd()函數(shù)之間完成,這里簡單介紹基本幾何繪圖函數(shù)。
GL_POINTS:單個(gè)頂點(diǎn)集
GL_LINES :多組雙頂點(diǎn)線段
GL_POLYGON: 單個(gè)簡單填充凸多邊形
GL_TRAINGLES:多組獨(dú)立填充三角形
GL_QUADS:多組獨(dú)立填充四邊形
GL_LINE_STRIP: 不閉合折線
GL_LINE_LOOP: 閉合折線
GL_TRAINGLE_STRIP: 線型連續(xù)填充三角形串
GL_TRAINGLE_FAN: 扇形連續(xù)填充三角形串
GL_QUAD_STRIP: 連續(xù)填充四邊形串
具體的使用方法上圖一目了然。這個(gè)圖我已經(jīng)收藏了,用的時(shí)候超方便。
有了這些方法,我們就可以采用其中的GL_LINES (多組雙頂點(diǎn)線段)來畫我們的三維坐標(biāo)軸了。這里我們用紅色的線表示x軸,綠色的線表示y軸,藍(lán)色線表示z軸。箭頭方向的表示對應(yīng)軸線的正值方向,另外一邊就是負(fù)值方向。
//顯示坐標(biāo)軸if(true){//設(shè)置線的寬度glLineWidth(3.0f);//顯示紅色的X坐標(biāo)軸glColor3f(1.0f,0.0f,0.0f);glBegin(GL_LINES);glVertex3f(-10.0f,0.0f,0.0f);glVertex3f(+10.0f,0.0f,0.0f);glEnd();//顯示綠色的Y坐標(biāo)軸glColor3f(0.0f,1.0f,0.0f);glBegin(GL_LINES);glVertex3f(0.0f,-10.0f,0.0f);glVertex3f(0.0f,+10.0f,0.0f);glEnd();//顯示藍(lán)色的Z坐標(biāo)軸glColor3f(0.0f,0.0f,1.0f); glBegin(GL_LINES);glVertex3f(0.0f,0.0f,-10.0f);glVertex3f(0.0f,0.0f,+10.0f);glEnd();}
添加以上代碼后,我們就可以看到一個(gè)簡陋的坐標(biāo)軸了。
7、添加坐標(biāo)軸的方向箭頭
我們畫出了坐標(biāo)軸,但是沒有方向箭頭,總感覺少點(diǎn)什么。我么還是把方向箭頭顯示出來,這樣我們就可以明確的感知到各個(gè)方向的正方向和負(fù)方向的區(qū)別了。
這里我們箭頭使用了前面正方體類似的系統(tǒng)函數(shù),系統(tǒng)還提供了類似四面體、正八面體、正十二面體、正二十面體、球體、圓環(huán)體、茶壺等多個(gè)基礎(chǔ)函數(shù),方便用戶使用。
//顯示一個(gè)椎體glutSolidCone(0.5,1.0,30,30);
當(dāng)然,系統(tǒng)提供的這些函數(shù)畫出的立體圖形只有默認(rèn)的方向,如果用戶想調(diào)整立體圖形的方向和位置,就要用到轉(zhuǎn)換矩陣相關(guān)函數(shù)。我們這里簡單介紹一下:
void glTranslatef(GLfloat x,GLfloat y,GLfloat z);
函數(shù)功能:簡單的理解,就是物體的位置移動(dòng)。參數(shù)x,y,z分別指定沿x,y,z軸方向的平移分量。其作用就是將你繪點(diǎn)坐標(biāo)的原點(diǎn)在當(dāng)前原點(diǎn)的基礎(chǔ)上平移一個(gè)(x,y,z)向量。
void glRotatef(GLfloat angle,GLfloat x,GLfloat y,GLfloat z);
函數(shù)功能:簡單的理解,就物體的旋轉(zhuǎn)。先解釋一下旋轉(zhuǎn)方向,做(0,0,0)到(x,y,z)的向量,方向滿足右手定則,用右手握住這條向量,大拇指指向向量的正方向,四指環(huán)繞的方向就是旋轉(zhuǎn)的方向。以點(diǎn)(0,0,0)到點(diǎn)(x,y,z)為軸,旋轉(zhuǎn)angle角度。
接下來,我們就可以使用glTranslatef和glRotatef函數(shù)對圓錐箭頭進(jìn)行位置和角度的調(diào)整。在Opengl中存在大量的位置和角度的調(diào)整,后期還會(huì)詳細(xì)了解以上操作函數(shù)。
//顯示坐標(biāo)軸箭頭glPushMatrix();glColor3f(1,0,0);glTranslatef(10,0,0);glRotatef(90,0.0f,1.0f,0.0f);glutSolidCone(0.5,1.0,30,30);glPopMatrix();//顯示坐標(biāo)軸箭頭glPushMatrix();glColor3f(0,1,0);glTranslatef(0,10,0);glRotatef(-90,1.0f,0.0f,0.0f);glutSolidCone(0.5,1.0,30,30);glPopMatrix();//顯示坐標(biāo)軸箭頭glPushMatrix();glColor3f(0,0,1);glTranslatef(0,0,10);glRotatef(0,1.0f,0.0f,0.0f);glutSolidCone(0.5,1.0,30,30);glPopMatrix();