[OGRE]1.從0開始,從2D到3D

初識OGRE:很早之前聽說OGRE,是在學習Qt的時候,當時只知道Qt可以和一個叫OGRE的"遊戲引擎"一起搭配使用,後來才發現原來OGRE不能算是一個遊戲引擎,只能說是一個遊戲引擎的一部分(一個遊戲引擎包括了物理引擎,網絡引擎,聲音和渲染引擎等),OGRE只是其中的渲染引擎,負責圖形方面的渲染而已,而其它那些遊戲引擎的其它部分則是以插件的形式存在的.

四元數:之前接觸到的遊戲引擎都是2D的,所以對3D的世界還是有點好奇和迷茫的,多了一個維的世界也多了好多東西,方向啊位置啊,還有一個四元數...(這個還沒完全搞清楚).OGRE中比較基本的用來設置位置的就是矢量Vector3了,裏面的變量是x,y,z這個普通人都可以理解.還有一個是四元數,一般是用四元數來進行旋轉的操作.下面是一篇轉載的關於OGRE四元數的文章.原文:http://blog.sina.com.cn/s/blog_7fff68b90100w1dj.html

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

在學習四元數之前,讓我們回顧一下歐拉角、矩陣和向量數學這些基礎知識。在這篇文章和 Ogre中,我們使用的都是右手座標系。這意味着兩件事:其一,我們認爲+X軸指向屏幕的正右方,+Y軸指向屏幕的正上方,+Z軸透過屏幕垂直指向你。其 二,要查+45度角是如何旋轉的,將你的右手拇指沿旋轉軸方向伸出,其餘手指的自然彎曲方向就是實際的角度旋轉方向。
向量:
在數學裏,一個向量描述了在3D空間中從一點指向另一點的一條有方向的線段。它具有方 向和距離。這說明它並不是一般意義上的沒有方向的線段(譯者注:線段沒有方向)也不是一條無限的射線(譯者注:射線沒有大小)。向量具有射線與線段的共同 特徵。(譯者注:向量是一個有大小由方向的量。)
在3D空間中描述兩個點需要六個參數。在Ogre中,向量的存儲是假設第一個點爲 (0,0,0)第二個點爲一個相關偏移量。這是向量的一個通常用法。可以用(0,0,0)作爲世界的根,或者將根設定於一個對象的物體座標系中。當進行變 換(transformations)時只要知道你工作在那個座標體系下就可以了。由於向量只有三個參數,所以經常被用來定義三位點。
長度爲1的向量稱爲規格化向量。當我們僅僅要描述一個方向時可以使用單位向量或規格化向量。如果你期望的結果是一個需要通過許多精確的運算時,使用規格化限量是必須的。不要忘記規格化你的向量!
在Ogre中,向量的普遍用法是描述一個單一的點、使用單位向量定義一個方向或者計算兩點之間的距離。
下面是一些有用的向量操作
·向量B減去向量A
得到一個包含從A到B的距離和方向的向量(在這個例子中,A可以是(0,0,0),表示B的向量可以按A的自身的物體座標系定義,而不是世界座標系)。
即:Bv – Av = Av ->Bv 。
·向量A加上向量B
向量A加上向量B得到向量C。如果向量A與向量B首尾相接,就好像兩個箭頭依次指出了一個路徑,向量C由向量A的尾部指向B的首部,構成一個三角形。
·乘上或除以一個標量
乘上或除以一個標量並不改變向量的方向,只是改變此向量的大小。 例如,Vector(1,1,1)描述了一條(或者一個默認原點的3D點)與XZ軸平面正向夾角45度的線(向上,位與+X,+Y,+Z三個軸所圍空間 中),與XY平面45度(面向你),與YZ平面45度(向右)。其長度爲sqrt(X^2+Y^2+Z^2)或者sqrt(3)。如果我們將向量乘以2, 得到(2,2,2),構成了一個相同方向的向量。詳情參閱Ogre API的Vector3::length()。
·向量的叉乘
兩個向量叉乘得到一個與兩個向量都垂直的向量。這是一個非常有用 的操作。如果你要指出垂直於一個多邊形的向量,你可以叉乘多邊形的兩個邊,那麼你就能夠得到一個垂直於這個多邊形平面的向量。詳情參閱Ogre API的Vector3 Vector3::crossProduct(Vector3)。
·向量的點乘
兩個向量點乘能得到它們的夾角。計算如下:DP(V1, V2) = (Cos Th) * Len1 * Len2,Len1和Len2是向量的大小。儘管如此,你也最好將向量都規格化,這可以使它們的大小都爲1。規格化後的點乘計算:Th = ArcCos(V1, V2); Len1=Len2=1。詳情參閱Ogre API的Real Vector3::dotProduct(Vector3)。
歐拉旋轉:
我們最常用的旋轉方法應該是使用yaw, roll和pitch。yaw是在XZ軸平面上圍繞Y軸左右旋轉,當開車時使用的是yaw。pitch在YZ軸平面上圍繞X軸上下旋轉,噴氣機飛行或爬坡 時用pitch向上或向下。roll是在XY軸平面上繞Z軸傾斜旋轉,從字面意思上說,當你駕駛汽車高速急轉彎時,你的汽車會出現roll運動:P
歐拉旋轉十分的有用,Ogre API也提供了歐拉旋轉。但是,旋轉時也會出問題。一個是操作的順序不能亂。如果你將對象先pitch 90度,然後再yaw 45度得到的結果肯定與先yaw 90度再pitch 45度不同。另外一個叫做萬向節鎖。萬向節是一個旋轉軸。這個問題發生在兩個旋轉軸重合時,此時需要刪掉一個。
(譯者注:歐拉角最著名的問題是這樣的:當你先yaw 45度再pitch 90度,和先pitch90度再roll 90度是等價的。事實上,一旦先擇±90度爲pitch角,就被限定在只能繞豎軸旋轉。這種現象,角度爲±90度的第二次旋轉使得第一次和第三次旋轉軸相 同,成爲萬向鎖。爲了消除限制歐拉角的這種別名現象,規定萬向鎖情況下只能由yaw完成繞豎軸的旋轉。即若pitch = ±90度,則roll = 0)
總的來說,歐拉角在實際的應用是受限的。這裏我所指的是使用yaw, roll, pitch操作讓對象任意旋轉並不是很實用。如果你要一個可以任意pitch / yaw的相機(就像許多第一人稱視角射擊遊戲)的話,它們是很有用的。使用雙場景節點的技巧,你可以得到一個僅用yaw和pitch操作卻能實現你所需要 的全部旋轉功能的相機。儘管如此,當你的一個對象面對一個方向,而且你想讓它面對處於任意位置的對象時,取當前的yaw, roll和pitch值後再計算與新方向之間的角度差並不是十分有效的。同樣的,如何使旋轉更加平滑?進入矩陣的學習。
矩陣旋轉:
由於使用任意三圍歐拉旋轉會產生大量的操作,通常使用矩陣來存儲和轉換它們。
我們使用三個矩陣來分別表示來自X, Y, Z軸的角偏移,即我們上述的pitch (圍繞X軸), yaw(圍繞Y軸)和roll(圍繞Z軸)。我們將其存入獨立的矩陣: matRotationX, matRotationY, matRotationZ。當我們確定我們要旋轉的角度,並且將其存儲到矩陣中。我們可以通過矩陣乘法將大量的旋轉操作合併爲一個簡單的矩陣轉換操作:
matTransform = matRotationX * matRotationY * matRotationZ;
幸運的是,Ogre提供Matrix3類來操作3X3的矩陣。這個類中也包含有*操作,因此上面的那個語句將在你的代碼中良好的工作。不過,在Ogre中要真正旋轉一個對象,你可以將其轉換爲軸/角旋轉存儲數據到矩陣自己做變換或者轉換爲四元數。
注意,矩陣的乘法是不可交換的。A*B != B*A。矩陣旋轉的順序都是很重要的,就像歐拉角一樣,不能隨意變化。另外,以矩陣形式表現的歐拉角依然受到萬向鎖的影響。
矩陣也可以用來操作軸/角旋轉。上述矩陣使用了yaw, roll, pitch的概念。試想一下要是這些換爲分別繞X, Y和Z軸的旋轉,這將實現所有的軸/角旋轉。通過這個我們避免了萬向鎖問題(尚未弄明白)。Ogre尚未提供旋轉矩陣與四元數之間的轉換。因此如果你要使 用旋轉矩陣,你將需要自己手動將其轉爲四元數。
歐拉角和矩陣以及旋轉矩陣有個共同的問題,叫做矩陣偏移,這將在下一部分敘述。
四元數旋轉:
對於初學者來說,四元數是一個相當有趣的概念。正如上面描述的那樣,當使用四元數時, 我發現停止用yaw, pitch和roll思考而改爲用繞軸的旋轉來思考變得很容易。例如,我們要模仿一架噴氣機上的推進器,噴氣機面向Z軸。在歐拉角中,這個旋轉應該被稱作 roll。在四元數中,其爲繞一指向Z軸的向量旋轉或繞Vector3::UNIT_Z旋轉。
四元數由四部分組成: 一個具有x,y,z座標和w旋轉分量的向量。這是我在矩陣那一節提到的軸/角的表示方法。即使使用假設的參數,四元數數學也是相當棘手的。幸運的是,我們 不需要從數學的角度使用它,也不需要了解它爲什麼要解釋成旋轉。來做個試驗,首先豎起你左手的食指,然後用你的右手握住筆的一頭。現在用你手腕和手做圓周 運動,儘可能水平的旋轉筆,始終保持其垂直於你左手的手指、平行於地面,就好像你把筆放在桌子上旋轉一樣。將這個想象成爲繞 Vector3::UNIT_Y旋轉的四元數。
這時我們有一個從(0,0,0)到(1,1,-1)的向量。用剛纔的手指向右指、保持與地面45度夾角。現在,圍繞你的手指旋轉筆,始終保持筆與手指垂直。注意我們如何通過角與軸的選擇創建了一個不同的旋轉。
像矩陣一樣,我們也可以使用四元數相乘來計算之間的角度。不過四元數相乘仍然是不可交換的。Q1*Q2 != Q2*Q1。適用的順序依然很重要。四元數也避免了萬向鎖問題。
四元數的優點
四元數有許多矩陣沒有的優點。不過它依然遵循像數一樣的正、負、乘法或加法等操作。按照實踐得到的結論,優點如下:
·在軸/角表示中避免了萬向鎖。
·修改旋轉更加容易。
假設我們描述一個-45度軸向左yaw旋轉,創建一個新的四元數描述10度軸yaw向右旋轉。將兩個四元數相乘,我們擁有了一個-35度軸的旋轉。這可以使用在其它對象或多個相同的對象需要實現相同旋轉的情況。旋轉因子的變化取決於環境。
·避免了耗費操作的矩陣偏移
當在矩陣上使用計算機中有限的點精確度執行大量的操作時,會發生矩 陣偏移。四捨五入掉的實數逐漸增大,將會不可避免的弄壞矩陣。矩陣偏移將會導致異常的旋轉的出現。必須把矩陣規格化才能重置旋轉,這將非常耗費操作。從另 一方面來說,四元數也有類似的痛苦的偏移,不過,由9個或更多的參數操作降至4個,這比規格化省力多了。
·增值旋轉
當旋轉對象時,我們希望對象旋轉進行的平緩。我們常說“從你當前位 置轉到這個點。但是要使用300幀來實現它,每次移動整個角度的1/300。”矩陣的增值是可能的,但是別的方式可以麼?四元數提供了兩種增值方法: 線的(linear)和三次的(cubic)。Ogre提供了三個執行方法: slerp, nlerp和squad。一次增值允許兩個四元數間增加的百分比是指定的。線性指的是運動的速率是固定的,如果使用相機或節點會感覺到是急動的。 slerp和nlerp都是線性的,slerp更精確但更慢些。squad或cubic增值允許一次性指定四個四元數a, p, q, b。p, q用來定義點a,b間的增值曲線。它允許我們在增值時緩慢的增大速度,停止,減少速度。
·Ogre使用四元數
這是應該你願讀這篇文章的原因吧

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

目前對於四元數,現在先將其定義爲一個可以用來旋轉的解決了萬向鎖的東西就行了,而且他提供了非線性的旋轉,這會讓視覺更舒服.


面向場景:在這幾天對OGRE的學習中深刻感受到什麼是面向場景的架構,OGRE有一個SceneManager,用來管理場景中的節點,節點你可以當作樹枝,在節點下可以掛載其它的節點,也可以掛載實體(實體指的是可以在場景中渲染的物體,燈光 攝像機 粒子這些就不能當作實體).所以整個OGRE的場景就會像一棵樹一樣,如果將節點從父節點銷燬,OGRE就不會對其進行渲染.

下面是一段節點生成和添加實體的代碼:

Ogre::Entity* ogreScene = mSceneManager->createEntity("Head", "mada.mesh");//使用場景管理器生成實體
ogreScene->setMaterialName("Examples/EnvMappedRustySteel");
ogreScene->setCastShadows(true);



  Ogre::SceneNode* headNode = mSceneManager->getRootSceneNode()->createChildSceneNode("headNode");
  headNode->attachObject(ogreScene);//將實體添加到場景下


和之前接觸的2D引擎不同,OGRE對物體位置的操作是通過對節點的操作進行的.節點下有setPosition(Ogre::Vector3)函數.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章