學(xué)習(xí)目標(biāo):
- 向量、矩陣和基礎(chǔ)變化(了解)
- 使用矩陣/向量移動幾何圖形(實(shí)踐)
- 矩陣堆棧(理解)
1. 向量與矩陣
- 向量:向量是研究2D、3D數(shù)學(xué)的標(biāo)準(zhǔn)工具。向量V是一個既有大小又有方向的量(聯(lián)系位移和速度的概念)。在數(shù)學(xué)上,常用一條有方向的線段來表示向量。
- 理解向量把握:
- 1.向量的大小就是向量的長度(模)。向量的長度非負(fù)。
- 2.向量的方向描述了向量的指向。
- 3.向量是沒有位置的,與點(diǎn)是不同的。
- 4.向量與標(biāo)量不同,標(biāo)量是只有大小而沒有方向的量,例如位移是向量,而距離是標(biāo)量。
- OpenGL中向量的使用:
math3d中,有兩個數(shù)據(jù)類型,能夠表示三維或四維。M3DVector3f可以表示一個三維向量(x,y,z),而M3DVector4f則可以表示一個四維向量(x,y,z,w),w稱為縮放因子。在典型情況下,w坐標(biāo)設(shè)為1.0。x,y,z值通過除以w,來進(jìn)?行縮放。?除以1.0則本質(zhì)上不改變x,y,z值。
//聲明一個三分量頂點(diǎn)數(shù)組,例如生成一個三角形
M3DVector3f vVerts[] = {
-0.5f,0.0f,0.0f,
0.5f,0.0f,0.0f,
0.0f,0.5f,0.0f
};
- 向量點(diǎn)乘和叉乘
- 點(diǎn)乘
//實(shí)現(xiàn)點(diǎn)乘方法: //?法1:返回的是-1,1之間的值。它代表這2個向量的余弦值。 float m3dDotProduct3(const M3DVector3f u,const M3DVector3f v); //?法2:返回2個向量之間的弧度值。 float m3dGetAngleBetweenVector3(const M3DVector3f u,const M3DVector3f v);- 叉乘
//result 為法向量 void m3dCrossProduct3(M3DVector3f result,const M3DVector3f u ,const M3DVector3f v); -
矩陣:從形式上就是一個數(shù)字表,以行和列的形式呈現(xiàn),簡單的矩陣如下圖所示:
矩陣.png- 定義矩陣
//定義4*4矩陣 M3DMatrix44f mCamera; -
OpenGL中的基礎(chǔ)變化:
OpenGL變換術(shù)語概況.png
2. 使用矩陣/向量移動幾何圖形
- 核心:
- 平移之后的坐標(biāo),該函數(shù)主動賦值到參數(shù)1中
//參數(shù)1:平移之后的坐標(biāo),該函數(shù)主動賦值到參數(shù)1中 //參數(shù)2:平移的x //參數(shù)3:平移的y //參數(shù)4:平移的z m3dTranslationMatrix44(translationMatrix, xPos, yPos, 0); - 旋轉(zhuǎn)換后的坐標(biāo),該函數(shù)主動賦值到參數(shù)1中
//參數(shù)1:旋轉(zhuǎn)換后的坐標(biāo),該函數(shù)主動賦值到參數(shù)1中 //參數(shù)2:旋轉(zhuǎn)的角度 需要把弧度轉(zhuǎn)化為角度 //參數(shù)3/4/5:圍繞哪個軸旋轉(zhuǎn) static float yRot = 0.0f; yRot += 5.0f; m3dRotationMatrix44(rotationMatrix, m3dDegToRad(yRot), 0, 0, 1); - 把平移和旋轉(zhuǎn)合并(乘)起來
//把平移和旋轉(zhuǎn)合并(乘)起來 //參數(shù)1:合并后的坐標(biāo) //參數(shù)2/3:需要合并的兩個坐標(biāo) m3dMatrixMultiply44(finalTransform, translationMatrix, rotationMatrix);
//召喚場景 void renderScene(void){ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); M3DMatrix44f rotationMatrix,translationMatrix,finalTransform; //參數(shù)1:平移之后的坐標(biāo),該函數(shù)主動賦值到參數(shù)1中 //參數(shù)2:平移的x //參數(shù)3:平移的y //參數(shù)4:平移的z m3dTranslationMatrix44(translationMatrix, xPos, yPos, 0); //參數(shù)1:旋轉(zhuǎn)換后的坐標(biāo),該函數(shù)主動賦值到參數(shù)1中 //參數(shù)2:旋轉(zhuǎn)的角度 需要把弧度轉(zhuǎn)化為角度 //參數(shù)3/4/5:圍繞哪個軸旋轉(zhuǎn) static float yRot = 0.0f; yRot += 5.0f; m3dRotationMatrix44(rotationMatrix, m3dDegToRad(yRot), 0, 0, 1); //把平移和旋轉(zhuǎn)合并(乘)起來 //參數(shù)1:合并后的坐標(biāo) //參數(shù)2/3:需要合并的兩個坐標(biāo) m3dMatrixMultiply44(finalTransform, translationMatrix, rotationMatrix); GLfloat vColor[] = { 1.0f, 0.8f, 0.9f, 1.0f }; shaderManaget.UseStockShader(GLT_SHADER_FLAT,finalTransform,vColor); squareBatch.Draw(); glutSwapBuffers(); } - 平移之后的坐標(biāo),該函數(shù)主動賦值到參數(shù)1中
3.矩陣堆棧
- 使用矩陣堆棧的原因:我們在使用矩陣對渲染的視圖做圖形變換(如平移、旋轉(zhuǎn)、縮放)時,需要對矩陣進(jìn)行點(diǎn)乘或者叉乘計(jì)算,將計(jì)算的結(jié)果使用GLMatrixStack存儲,保證了每一次的變換都是獨(dú)立進(jìn)行的。
- 模型矩陣:將頂點(diǎn)由局部坐標(biāo)系轉(zhuǎn)換到世界坐標(biāo)系;
- 視圖矩陣:將頂點(diǎn)由世界坐標(biāo)系轉(zhuǎn)換到視圖坐標(biāo)系;
- 投影矩陣:將頂點(diǎn)由視圖坐標(biāo)系轉(zhuǎn)換到屏幕中。
- 模型視圖投影矩陣 = 投影矩陣 * 模型視圖矩陣(注意這里不能寫成 模型視圖矩陣 * 投影矩陣,矩陣乘法不滿足交換)。
- 使用方法:
- 初始化矩陣堆棧:通過看他具體實(shí)現(xiàn)我們可以看到,它會創(chuàng)建一個棧結(jié)構(gòu)的存儲控件,iStackDepth表示該??臻g的深度為64,就是說我們可以對它進(jìn)行64次的push操作,同時會在棧頂添加一個單元矩陣.
GLMatrixStack::GLMatrixStack(int iStackDepth = 64)//創(chuàng)建一個矩陣堆棧,初始化時會在創(chuàng)建時在棧頂加入一個單元矩陣 (FILO:先進(jìn)后出) GLMatrixStack modelViewMatrix; //在棧頂載入一個單元矩陣 modelViewMatrix.LoadIdentity(); //在棧頂載入任何矩陣,參數(shù):4*4矩陣 modelViewMatrix.LoadMatrix(<#const float *mMatrix#>) //矩陣乘以矩陣堆棧頂部矩陣,相乘結(jié)果存儲到堆棧的頂部 modelViewMatrix.MultMatrix(const M3DMatrix44f); //將指定矩陣壓入矩陣堆棧 modelViewMatrix.PushMatrix(<#const float *mMatrix#>) //將當(dāng)前矩陣壓入矩陣堆棧,就是將當(dāng)前矩陣堆棧的頂部矩陣copy一份 加到矩陣堆棧的頂部 modelViewMatrix.PushMatrix(); //將M3DMatrix44f 矩陣對象壓入當(dāng)前矩陣堆棧 modelViewMatrix.PushMatrix(<#GLFrame &frame#>) //出棧 modelViewMatrix.PopMatrix(); //獲取矩陣棧頂?shù)闹?modelViewMatrix.GetMatrix();
- 初始化矩陣堆棧:通過看他具體實(shí)現(xiàn)我們可以看到,它會創(chuàng)建一個棧結(jié)構(gòu)的存儲控件,iStackDepth表示該??臻g的深度為64,就是說我們可以對它進(jìn)行64次的push操作,同時會在棧頂添加一個單元矩陣.

