OpenGL中的向量蔽氨、矩陣

向量

首先我們了解一下標量和向量的區(qū)別:

標量:只有大小的量,如帆疟,1鹉究、3、5鸯匹;
向量:有方向的標量坊饶;

在 3D 笛卡爾坐標系, 基本上. 一個頂點 就是XYZ 坐標空間上的?個位置. ?在空間中給定的
?個位置 恰恰是由一個單獨的 XYZ 定義的. 而這這樣的 XYZ 就是向量;


向量

單位向量

向量?度為1. 我們稱為長度為1的向量為單位向量.如、在X軸上的向量量 (1,0,0)殴蓬。

向量長度(向量的模)計算公式:


向量的長度公式

如果?個向量不是單位向量, 而我們把它縮放到 1. 這個過程叫做標準化. 將?個向量進行標準化就是將它的縮為1; 也叫做單位化向量匿级,即非零向量除以向量的模,如下圖所示;


單位和向量

OPenGl定義向量[ math3d 庫]

在OpenGL中提供了一個數(shù)學庫類 #include<math3d.h>
我們會兩個比較常見的類:

  • M3DVector3f:表示三維向量(x,y,z)-(f)表示float類型的意思染厅。
    同時也可以用來設(shè)置三維數(shù)組也是沒有問題的
 typedef float   M3DVector3f[3];     // Vector of three floats (x, y, z) 默認是一個一維數(shù)組
  • M3DVector4f:表示四維向量(x,y,z,w)w表示縮放因子w默認為1.0-(f)同上
    我們也可以用M3DVector4f來表示顏色值的設(shè)置
M3DVector4f color[] = {1.0f, 1.0f, 0.0f, 1.0f};

向量點乘

向量可以進?加法,減法計算. 但是向量里有?個在開發(fā)中使?價值非常高的操作,叫做
“點乘(dot product)” .點乘只能發(fā)生在2個向量之間進行;
2個(三維向量)單元向量之間進?點乘運算將得到?個標量(不是三維向量,是?個標量).
它表示兩個向量之間的夾?;
前提條件: 2個向量必須為單位向量;
動作: 2個三維向量之間進?點乘;
結(jié)果: 返回?個[-1,1]范圍的值. 這個值其實就是夾角的cos值(余弦值);

向量點乘

那么在代碼中如何實現(xiàn)點乘呢痘绎?2個向量相乘

//1.m3dDotProduct3 函數(shù)獲得2個向量量之間的點乘結(jié)果;
m3dDotProduct3(const M3DVector3f u, const M3DVector3f v)

根據(jù)兩個向量獲取角度值

float m3dGetAngleBetweenVectors3(const M3DVector3f u, const M3DVector3f v)

向量叉乘

向量之間的叉乘(cross product) 也是在業(yè)務(wù)開發(fā)里?常有?的?個計算方式; 2個向量之間叉乘就可以得到另外?個向量,新的向量會與原來2個向量定義的平面垂直. 同時進行叉乘,不必為單位向量;
前提: 2個普通向量
動作: 向量與向量叉乘
結(jié)果: 向量(垂直于原來2個向量定義的平面的向量)


向量叉乘

math3d 庫中提供了了關(guān)于叉乘的API

//1.m3dCrossProduct3 函數(shù)獲得2個向量量之間的叉乘結(jié)果得到?個新的向量
    void m3dCrossProduct3(M3DVector3f result,const M3DVector3f  u ,const
    M3DVector3f v);

注意:result是存放新返回的向量,與點乘不同的是肖粮,叉乘要按照順序來設(shè)置孤页,不然得出的值會是相反值,例如:v1乘v2是向上的向量涩馆,v2乘v1是向下的向量行施,所以需要注意順序,不能亂乘魂那。

矩陣

假設(shè), 在空間有一個點.使用 xyz 描述它的位置. 此時讓其圍繞任意位置旋轉(zhuǎn)一定?度
后. 我們需要知道這個點的新的位置. 此時需要通過矩陣進行計算;
為什么?
因為新的位置的x不單純與原來的x還和旋轉(zhuǎn)的參數(shù)有關(guān). 甚?至于y和z坐標有關(guān);


矩陣

矩陣只有?行或者?列都是合理的. 只有??或者?列數(shù)字可以稱為向量. 也可以稱為矩陣;

OPenGl中三維矩陣/四維矩陣的聲明

typedef float M3DMatrix33f[9];
 typedef float M3DMatrix44f[16];

在其他編程標準中, 許多矩陣庫定義?個矩陣時,使用二維數(shù)組;
OpenGL的約定里,更多傾向使??維數(shù)組; 這樣做的原因是: OpenGL 使用的是 Column-Major(以列列為主)矩陣排序的約定蛾号,如下圖:


行列優(yōu)先的矩陣
  • 行優(yōu)先矩陣:一行一行讀取
  • 列優(yōu)先矩陣:一列一列讀取
    兩者的關(guān)系為:行優(yōu)先矩陣經(jīng)過轉(zhuǎn)置 即可的到列優(yōu)先矩陣

由上我們知道OPenGl中的矩陣是列優(yōu)先矩陣琅翻,那么其中的值分別代表什么呢褂始?如下圖

4*4矩陣
  • 這16個值表示空間中一個特定的位置; 這4列中,每一列都是有4個元素組成的向量;

  • 如果將?個對象所有的頂點向量乘以這個矩陣,就能讓整個對象變換到空間中給定的位置和?方向;

那么?個4*4矩陣是如何在3D空間中表示?個位置和?向的呢?
列向量進?了特別的標注:矩陣的最后一?都為0您访,只有最后?個元素為1活逆,如上如所示精刷。

單元矩陣

主對角線上數(shù)據(jù)都是1,其余元素都是0蔗候,即為單元矩陣怒允;

 //單元矩陣初始化?方式1
GLFloat m[] = {
           1,0,0,0, //X Column
            0,1,0,0, //Y Column
            0,0,1,0, //Z Column
            0,0,0,1 // Translation
}

// 單元矩陣初始化?方式 2
M3DMatrix44f m = {
1,0,0,0, //X Column
0,1,0,0, //Y Column
0,0,1,0, //Z Column
0,0,0,1 // Translation }

//單元矩陣初始化?方式3
void m3dLoadIdentity44f(M3DMatrix44f m);

向量 X 單元矩陣 = 向量 X 1,不會發(fā)生任何變化锈遥;


向量X單元矩陣

向量與單元矩陣相乘的前提是:向量的列數(shù) == 單元矩陣的行數(shù)误算;如下就不能相乘


不能相乘的向量與矩陣

矩陣的點乘

矩陣可以進行點乘的前提:兩個矩陣的行列數(shù)相等
矩陣A · 矩陣B = 矩陣C
-規(guī)則: 矩陣A的第一個元素與矩陣B的第一個元素的乘積 = 矩陣C的第一個元素


矩陣點乘

矩陣的叉乘

矩陣可以進行叉乘的前提:第一個矩陣的列數(shù) = 第二個矩陣的行數(shù)
矩陣A X 矩陣B = 矩陣C
規(guī)則:矩陣A第一行與矩陣B第一列對應(yīng)元素乘積的綜合 = 矩陣C的第一個元素


矩陣的叉乘

OpenGL中的矩陣相乘

  • 線性代數(shù)?度
    OpenGL中的矩陣規(guī)定是以行為主仰美,所以頂點以列向量的方式表示
    在線性代數(shù)學的維度,為了便于書寫. 所以坐標計算. 都是從左往右順序,進?計算. 如下
    列公式:
    變換后頂點向量 = V_local * M_model * M_view * M_pro
    變換后頂點向量 = 頂點 ? 模型矩陣 ? 觀察矩陣 ? 投影矩陣
    這種方式叫做左乘,如下圖以線性代數(shù)的方式進行MVP矩陣的計算
線性代數(shù)MVP矩陣相乘順序
  • OpenGL?度
    OpenGL中的矩陣規(guī)定是以列為主,所以頂點以列向量的方式表示
    在OpenGL 的維度. 如下列列公式:
    變換頂點向量 = M_pro * M_view * M_model * V_local
    變換頂點向量 = 投影矩陣 ? 視圖變換矩陣 ? 模型矩陣 ? 頂點
    這種方式叫做右乘,如下圖以O(shè)PenGL的方式進行MVP矩陣的計算
    OPenGL中MVP矩陣相乘順序
OpenGL矩陣堆棧中矩陣相乘源碼分析
矩陣左乘

上圖矩陣相乘主要有三步:

  1. 從棧頂獲取棧頂矩陣 復制到 mTemp;
  2. 將棧頂矩陣 mTemp 左乘 mMatrix ;
  3. 將結(jié)果放回棧頂空間?;

在我們繪制金字塔儿礼、六邊形的案例中咖杂,我們用到了MVP(模型視圖投影矩陣),那么其中各矩陣的相乘規(guī)則是什么樣的呢蚊夫?


代碼中矩陣的順序

1诉字、ChangeSize函數(shù)中,得到投影矩陣知纷,將投影矩陣壓入投影矩陣堆棧棧頂壤圃,并與模型視圖矩陣棧頂相乘,將結(jié)果覆蓋棧頂琅轧,即 投影矩陣 * 單元矩陣 = 投影矩陣

2伍绳、RenderScene函數(shù)中,將棧頂矩陣copy一份乍桂,然后將觀察者矩陣與模型視圖矩陣堆棧棧頂相乘冲杀,其結(jié)果覆蓋棧頂矩陣,即投影矩陣 * 視圖矩陣 = 視圖投影矩陣

3睹酌、得到模型矩陣权谁,將模型矩陣與棧頂矩陣相乘,其結(jié)果覆蓋棧頂矩陣憋沿,即 模型矩陣 * 視圖投影矩陣 = 模型視圖投影矩陣

上述代碼旺芽,矩陣堆棧的變化過程如下:

MVP矩陣堆棧變化

由此可知,在實際的代碼中辐啄,mvp矩陣的計算順序是pvm采章,最后再將頂點矩陣與mvp矩陣相乘,得到物體變換后的頂點和位置壶辜。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末悯舟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子士复,更是在濱河造成了極大的恐慌,老刑警劉巖翩活,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件阱洪,死亡現(xiàn)場離奇詭異,居然都是意外死亡菠镇,警方通過查閱死者的電腦和手機冗荸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來利耍,“玉大人蚌本,你說我怎么就攤上這事盔粹。” “怎么了程癌?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵舷嗡,是天一觀的道長。 經(jīng)常有香客問我嵌莉,道長进萄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任锐峭,我火速辦了婚禮中鼠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘沿癞。我一直安慰自己援雇,他們只是感情好,可當我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布椎扬。 她就那樣靜靜地躺著惫搏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪盗舰。 梳的紋絲不亂的頭發(fā)上晶府,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天,我揣著相機與錄音钻趋,去河邊找鬼川陆。 笑死,一個胖子當著我的面吹牛蛮位,可吹牛的內(nèi)容都是我干的较沪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼失仁,長吁一口氣:“原來是場噩夢啊……” “哼尸曼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起萄焦,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤控轿,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后拂封,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體茬射,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年冒签,在試婚紗的時候發(fā)現(xiàn)自己被綠了在抛。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡萧恕,死狀恐怖刚梭,靈堂內(nèi)的尸體忽然破棺而出肠阱,到底是詐尸還是另有隱情,我是刑警寧澤朴读,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布屹徘,位于F島的核電站,受9級特大地震影響磨德,放射性物質(zhì)發(fā)生泄漏缘回。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一典挑、第九天 我趴在偏房一處隱蔽的房頂上張望酥宴。 院中可真熱鬧,春花似錦您觉、人聲如沸拙寡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽肆糕。三九已至,卻和暖如春在孝,著一層夾襖步出監(jiān)牢的瞬間诚啃,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工私沮, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留始赎,地道東北人。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓仔燕,卻偏偏與公主長得像造垛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子晰搀,可洞房花燭夜當晚...
    茶點故事閱讀 45,055評論 2 355