相機(jī)
觀察坐標(biāo)就是以相機(jī)的視角作為場(chǎng)景原點(diǎn)時(shí)場(chǎng)景中所有的頂點(diǎn)坐標(biāo)。創(chuàng)建一個(gè)相機(jī)其實(shí)就是創(chuàng)建一個(gè)觀察矩陣。
要?jiǎng)?chuàng)建一個(gè)相機(jī),我們需要它在世界空間中的位置、觀察的方向、一個(gè)指向它右側(cè)的向量以及一個(gè)指向它上方的向量。
位置
位置就是一個(gè)指向攝像機(jī)位置的向量。我們依然把相機(jī)放在場(chǎng)景中稍向后退的地方:

觀察方向
我們把觀察方向定義為由物體指向相機(jī)的方向,這里我們選擇原點(diǎn)為觀察物體:

函數(shù)glm::normalize()用于將一個(gè)向量歸一化,即將其長度縮放為1,但保持其方向不變。歸一化一個(gè)向量可以使它在計(jì)算中更易處理,同時(shí)還可以用于表示方向。
右方向量
為了獲得相機(jī)的右方,即空間的x軸正方向,我們使用一個(gè)豎直向上的向量與觀察方向進(jìn)行叉乘:

上方向量
為了獲得相機(jī)的上方,即空間的y軸正方向,我們使用觀察方向與右方向量進(jìn)行叉乘:

觀察矩陣
當(dāng)我們擁有了相機(jī)的幾個(gè)要素后,就可以通過函數(shù)glm::lookAt()來創(chuàng)建一個(gè)觀察矩陣。

glm::lookAt()的三個(gè)參數(shù)分別是相機(jī)位置,目標(biāo)物體位置和一個(gè)豎直向上的向量。
相機(jī)的移動(dòng)
為了實(shí)現(xiàn)相機(jī)的移動(dòng),我們?cè)傩枰x一個(gè)移動(dòng)向量:

現(xiàn)在觀察矩陣為:

第二個(gè)參數(shù)目標(biāo)物體的位置變?yōu)榱讼鄼C(jī)位置加上移動(dòng)向量。這樣能保證無論怎么移動(dòng),相機(jī)都會(huì)看著目標(biāo)方向。
我們創(chuàng)建一個(gè)函數(shù),實(shí)現(xiàn)使用WASD按鍵控制相機(jī)的移動(dòng)的功能:

向前或向后移動(dòng),就把相機(jī)位置加上或減去移動(dòng)向量。向左右移動(dòng),就使用叉乘來創(chuàng)建一個(gè)右向量,并沿著它相應(yīng)移動(dòng)。
相機(jī)的轉(zhuǎn)動(dòng)
為了實(shí)現(xiàn)相機(jī)的轉(zhuǎn)動(dòng),我們需要通過歐拉角來計(jì)算方向向量:
計(jì)算鼠標(biāo)距上一幀的偏移量。
把偏移量添加到攝像機(jī)的俯仰角和偏航角中。
對(duì)偏航角和俯仰角進(jìn)行最大和最小值的限制。
計(jì)算方向向量。
我們必須先儲(chǔ)存上一幀的鼠標(biāo)位置,我們把它的初始值設(shè)置為屏幕的中心:

接著初始化歐拉角:

創(chuàng)建一個(gè)回調(diào)函數(shù),在回調(diào)函數(shù)中實(shí)現(xiàn)上面的四個(gè)步驟:

接著使用函數(shù)glfwSetCursorPosCallback()接收這個(gè)回調(diào)函數(shù),它會(huì)在每次鼠標(biāo)光標(biāo)位置發(fā)生變化時(shí)被調(diào)用。
縮放
我們要使用鼠標(biāo)滾輪進(jìn)行縮放。縮放,實(shí)際上就是調(diào)整視野的大小,即改變fov。
同樣,需要?jiǎng)?chuàng)建一個(gè)回調(diào)函數(shù)。

offsetY表示鼠標(biāo)滾輪在垂直方向上的偏移量。這里fov是一個(gè)初始值為為45.0的全局變量。
我們一般把fov限制在1.0到45.0之間。
同時(shí)要更新透視投影矩陣
