OpenGL下的情境層次化渲染

來源:互聯網
上載者:User

 目前使用VC6.0+OpenGL圖形庫已經逐漸成為開發3D應用程式的主流,但是在使用OpenGL圖形庫中會涉及到很多2D或者3D座標,正確理解這 些座標的含義是使用OpenGL開發應用程式的前提,另外對於一個複雜的3D情境如果使用程式的手段來進行有效渲染也是至關重要的。本文主要探討這兩個 方面的問題。
  1. 相關基礎知識

   要渲染真實世界的3D物體,首先必須瞭解OpenGL裡面的座標系統。OpenGL是使用頂點(Vertex)來描述幾何物體的,最開始幾何物體處於世 界座標之下,然後所有的頂點都通過模型視圖變換、投影變換以及視口變換來轉換為螢幕座標。通過這種流水線似的作業,3D情境就可以在螢幕上展現出來了。
全局座標系統遵循右手定則,即X軸是從左至右,Y軸由下至上,Z軸是垂直於螢幕由裡到外。這樣在OpenGL裡面使用的座標值都是在這樣的一個座標系統之下定位的,然後通過一系列的變換轉換為人眼座標,進而最後轉換為螢幕座標(2D座標)。

  2. 情境的層次化渲染

  對於一個複雜的情境,如果才能有效進行渲染呢?這裡就藉助一個樣本來進行說明。
例子是這樣的,需要在一個SDI視窗下繪製如下的一個2D的貨車(實際上在進行情境層次化渲染這方面,2D渲染的思路與3D渲染思路是一樣的)

   實現的思路首先應該是對這個貨車分解幾個獨立的子實體:貨車主體(前面那個大矩形)、貨車主體車輪、拖車主體(後面的矩形)、拖車主體車輪。那麼整個貨 車在運動的時候應該是以主貨車為運動的主體,其他的子實體都對主貨車做相對運動,這就好比是爸爸牽著兒子走路一樣,整體上爸爸和兒子是一起往前走的,但是 就局部來說,兒子可以繞爸爸做四周環繞運動。所以在利用OpenGL渲染比較複雜的3D物體時,首先要分清楚此3D物體的自由度的個數,然後分離出一個主 體部分,其他部分只是對這個主體部分做相對運動即可。這樣的思路在渲染複雜的機器人的時候也應用到了。

那麼在OpenGL裡面如果實現各個實體之間的相對運動呢?事實上OpenGL裡面提供了這樣的一對函數:glPushMatrix()和glPopMatrix()。其功能是前者把當前所有的矩陣棧都壓入堆棧,後者剛好相反。先看下面的例子:

//對整個貨車做運動變換A
變換A
glPushMatrix();
//繪製貨車主體
glPopMatrix();
glPushMatrix();
//繪製拖車主體
glPopMatrix();

   上面代碼看出來,在第一對glPushMatrix()和glPopMatrix()之間繪製的貨車主體不會影響到第二對glPushMatrix() 和glPopMatrix()裡面繪製的拖車主體,也就是說,平行的兩對glPushMatrix()和glPopMatrix()互相不影響。但是變換 A卻可以影響貨車主體和拖車主體,因為它們是上下級的關係,而不是平行的關係。

  所以從上面的分析中可以看出,可以利用glPushMatrix()和glPopMatrix()來實現主體和子體之間的相對運動,而且子體之間的繪製也不會相互影響,基於這樣的思想,可以編製如下代碼:(這裡只列出主體代碼DrawLorry和DrawWheel)

//m_rot 和m_trans分別表示輪胎的旋轉量和整個貨車在X軸上的平移量,已經在有關//函數裡面進行了初始化
void CTerraintestView::DrawLorry()
{//控制貨車的運動
//這裡施加的幾何變換將影響到所有的下面繪製的物體
glTranslatef(m_trans,0,0);
glColor3f(1.0,0.5,0);
//繪製貨車
glBegin(GL_POLYGON ); glVertex2f(-0.3f,0.2f); glVertex2f(-0.3f,-0.2f); glVertex2f(0.3f,-0.2f); glVertex2f(0.3f,0.2f);
glEnd();
//繪製拉繩
glBegin(GL_LINES );
glVertex2f(-0.3,0); glVertex2f(-0.6,0);
glEnd();
//繪製貨車輪胎
glPushMatrix(); glTranslatef(0,-0.3f,0); glTranslatef(-0.2,0,0); glPushMatrix(); glRotatef(m_rot,0,0,1); DrawWheel(0.1); glPopMatrix(); glTranslatef(0.4,0,0); glRotatef(m_rot,0,0,1); DrawWheel(0.1);
glPopMatrix();
glPushMatrix();
//總比貨車滯後0.3 glTranslatef(-0.6,0,0);
//繪製後面的拖車
glBegin(GL_POLYGON); glVertex2f(-0.2f,0.2f); glVertex2f(-0.2f,-0.2f); glVertex2f(0.2f,-0.2f); glVertex2f(0.2f,0.2f);
glEnd();
// 繪製拖車的輪胎 glPushMatrix(); glTranslatef(0,-0.3f,0); glTranslatef(-0.1,0,0); DrawWheel(0.1); glTranslatef(0.2,0,0); DrawWheel(0.1); glPopMatrix();
glPopMatrix();
}
void CTerraintestView::DrawWheel(float radius)
{//繪製輪胎
float step=0.05;
float i;
float x,y;
glBegin(GL_LINE_STRIP );
glVertex2f(radius,0);
for (i=step;i<360.0;i+=step)
{ //計算兩個座標
x=radius*cos(i*3.1415926/180.0);
y=radius*sin(i*3.1415926/180.0);
glVertex2f(x,y);
}
glEnd();
}

  3.小結:

   前面的分析看出,無論是對複雜的情境還是對多DOFs(自由度的簡稱)的物體來說,使用分解的方式將複雜物體分解為相對獨立的子實體(對於更加複雜的場 景需要建立情境的層次樹),並結合glPushMatrix()和glPopMatrix()來實現對各個子實體的繪製,進而實現整個3D物體的繪製工 作。這種思路對於大型的複雜情境的繪製尤為有用。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.