1 向量
1.1 向量的定义
坐标系中的一个坐标(x,y,z),即从坐标原点(0,0,0)指向(x,y,z)的一个向量,包含方向和模(到坐标原点的距离)
向量的模|xyz|的计算公式:
image如下图:
image向量(x0,y0,0)的模是
image而(x0,y0,0)与(x0,y0,z0)连线垂直于z=0平面,所以(x0,y0,z0)的长度为
image1.2 单位向量
模为1的向量
1.3 向量的标准化
(x,y,z) ---> (x/|xyz|,y/|xyz|,z/|xyz|)
image注意: 零向量不能被标准化,数学上没意义:除数为0,几何上也没有意义:零向量没有方向
1.4 零向量
大小为0,没有方向
1.5 负向量
与原向量大小相等,方向相反
1.6 标量与向量的乘法
向量的每个元素*标量后组成的向量,几何意义是:缩放向量的长度,当标量为-1时,是翻转
image注意:
- 标量和向量相乘时,不需要写乘法。将2个量挨着写即表示相乘(常将标量写在左边)
- 标量与向量的乘法和除法优先级高于加法和减法
- 标量不能除以向量,并且向量不能除以另一个向量
- 负向量能被认为乘法的特殊情况,乘以标量-1
1.7 向量的加法和减法:加减法的两个向量维度必须相同
对应分量相加/相减
a+b几何意义:平移向量,使向量a的头连接向量b的尾,接着从a的尾向b的头画一个向量
a-b:是向量a和b的尾向连,从b的头画一个向量指向a的头。a-b的模是a,b两点之间的距离
注意:向量不能与标量或者维度不同的向量相加减;向量加法满足交换律a+b = b+a,当a=b时a-b = b-a
1.8 向量的点乘
点乘的含义是:两个向量的夹角的余弦值(前提是相乘的两个向量均为单位向量)
A · B = |A|·|B|·cos<A,B>
1.9 向量的叉乘
两个向量叉乘,得到一个新向量C,与原来的两个向量垂直的向量。
叉乘,也叫向量的外积、向量积。
|向量C|=|向量A✖向量B|=|A||B|sin<A,B>
向量C的方向与A,B所在的平面垂直,且方向要用“右手法则”判断(用右手的四指先表示向量A的方向,然后手指朝着手心的方向摆动到向量B的方向,大拇指所指的方向就是向量C的方向)
注:向量的叉乘不满足交换律,因为A✖B=-B✖A;乘法在加减法之前计算; 当点乘和叉乘在一起时, 叉乘优先计算;任意向量与自身叉乘等于零向量
给定 2 个向量量 v 和 n . 能将 v 分解成 2 个向量: V1 和 V2; 它们分别平行于和垂直于 n; 并且满⾜足 v = v1 + v2; 一般平行向量 V2 为 v 在 n 上的投影
imageV2 平⾏于 n ,可求解:
image
V1 = V -V2
2 矩阵 float m[]=[A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15]
2.1 行优先矩阵排序,即行矩阵
image2.2 列优先矩阵排序,即列矩阵
image注意: 列矩阵是矩阵的最后一行都为0,只有最后一个元素为1
2.3 单元矩阵
GLFloat m[] = { 1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1}
对角线为1,其他位置为0 的矩阵
一个向量 * 单元矩阵 不会发生变化
2.4 矩阵相乘
A ✖ B 计算的前提条件是: A的列数 = B的行数
3 OpenGL中的矩阵和向量
OpenGL中向量和矩阵都倾向于采用一维数组表示
3.1 向量的声明和定义,计算
- 三维向量/四维向量的声明
typedef float M3DVector3f[3];
typedef float M3DVector4f[4];
- 定义第一个三维向量
M3DVector3f vVector;
- 定义一个四维向量并初始化
M3DVector4f vVertex = {0,0,1,1};
- 向量的点乘
float m3dDotProduct3(const M3DVector3f u,const M3DVector3f v);
- 获取2个向量之间夹⻆的弧度值
float m3dGetAngleBetweenVector3(const M3DVector3f u,const
M3DVector3f v);
- 向量的叉乘 result = u ✖ v
void m3dCrossProduct3(M3DVector3f result,const M3DVector3f u ,const M3DVector3f v);
3.2 矩阵的声明,定义和计算
三维矩阵/四维矩阵的声明
typedef float M3DMatrix33f[9];
typedef float M3DMatrix44f[16]
单元矩阵的三种定义方式
- 方式1:
GLFloat m[] = { 1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1}
- 方式2 :
M3DMatrix44f m = { 1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1}
- 方式3 :
void m3dLoadIdentity44f(M3DMatrix44f m);
3.2 顶点变换
- 线性代数下的顶点变换为:
变换后顶点向量 = V_local * M_model * M_view * M_pro
变换后顶点向量 = 顶点 ✖ 模型矩阵 ✖ 观察矩阵 ✖ 投影矩阵;
image注:图引自逻辑教育CC老师课件
- OpenGL下的顶点变换为:
变换顶点向量 = M_pro * M_view * M_model * V_local
变换顶点向量 = 投影矩阵 ✖ 视图变换矩阵 ✖ 模型矩阵 ✖ 顶点
3.3 矩阵的计算
-
左乘
MultMatrix(const M3DMatrix44f mMatrix)
1). 从栈顶获取栈顶矩阵 复制到 mTemp
2). 将栈顶矩阵 mTemp 左乘 mMatrix (mTemp ✖ mMatrix )
3). 将结果放回栈顶空间⾥;
3.2 OpenGL中的矩阵变换
-
视图变换:将观察者放在你希望的任何位置,并允许在任何方向上观察场景, 确定视图变换就像在场景中放置观察者并让它指向某⼀个方向观察,默认观察者位于(0,0,0)向Z轴负方向进行观察。在应用任何其他模型变换之前, 必须先应⽤视图变换
-
模型变换:在场景中移动物体进行平移、旋转、缩放
image -
模型视图变换:描述视图/模型变换的二元性
-
投影:改变视景体⼤小和设置它的投影方式
-
视⼝:伪变化,对窗口上最终输出进行缩放
3.3 OpenGL中矩阵变换的使用
- 平移
将矩阵m 在x方向平移x0个单位,y方向平移y0个单位,z方向平移z0个单位后结果存放在m矩阵中。
void m3dTranslationMatrix44(M3DMatrix44f m, floata x0, float y0, float z0);
- 旋转
围绕某一轴旋转一定弧度
m3dRotationMatrix44(m3dDegToRad(45.0), floata x, float y, float z);
- 缩放 :
将矩阵m 在x方向缩放xScale倍,y方向缩放yScale倍,z方向缩放zScale倍后结果存放在m矩阵中。
void m3dScaleMatrix44(M3DMatrix44f m, floata xScale, float yScale, float zScale);
注意:xScale取值-1时,是围绕X轴翻转,
yScale取值-1时,是围绕Y轴翻转,
zScale取值-1时,是围绕Z轴翻转,
- 综合变化: product = a ✖ b
void m3dMatrixMultiply44(M3DMatrix44f product, const M3DMatrix44f a, const M3DMatrix44f b);
3.4 矩阵堆栈的使用 GLMatrixStack::GLMatrixStack(int iStackDepth = 64);
- 在堆栈顶部载⼊⼀个单元矩阵
void GLMatrixStack::LoadIdentity(void);
image
- 在堆栈顶部载⼊任何矩阵 参数:4*4矩阵
void GLMatrixStack::LoadMatrix(const M3DMatrix44f m);
image
- 矩阵乘以矩阵堆栈顶部矩阵,相乘结果存储到堆栈的顶部
void GLMatrixStack::MultMatrix(const M3DMatrix44f);
image
- 获取矩阵堆栈顶部的值 GetMatrix 函数 为了适应GLShaderMananger的使用,或者获取顶部矩阵的副本
const M3DMatrix44f & GLMatrixStack::GetMatrix(void);
void GLMatrixStack::GetMatrix(M3DMatrix44f mMatrix);
image
- 将当前矩阵压入堆栈(栈顶矩阵copy一份到栈顶)
void GLMatrixStack::PushMatrix(void);
image
将M3DMatrix44f 矩阵对象压入当前矩阵堆栈
void PushMatrix(const M3DMatrix44f mMatrix);
image
- 将GLFame 对象压入矩阵对象
void PushMatrix(GLFrame &frame);
image
- 出栈(出栈指的是移除顶部的矩阵对象) void
GLMatrixStack::PopMatrix(void);
image
3.5 仿射变换
//Rotate 函数angle参数是传递的度数,⽽不是弧度
void MatrixStack::Rotate(GLfloat angle,GLfloat x,GLfloat y,GLfloat z);
void MatrixStack::Translate(GLfloat x,GLfloat y,GLfloat z);
void MatrixStack::Scale(GLfloat x,GLfloat y,GLfloat z);
3.6 GLFrame
GLFrame和矩阵对应
GLFrame定义:
GLFrame
{
protected:
M3DVector3f vOrigin;//x
M3DVector3f vForward; //z
M3DVector3f vUp; //y
}
GLFrame操作也与矩阵相似:
在矩阵堆栈中存储的是GLFrame对应的矩阵
//将堆栈的顶部压⼊任何矩阵
void GLMatrixStack::LoadMatrix(GLFrame &frame);
//矩阵乘以矩阵堆栈顶部的矩阵。相乘结果存储在堆栈的顶部 void GLMatrixStack::MultMatrix(GLFrame &frame);
//将当前的矩阵压栈
void GLMatrixStack::PushMatrix(GLFrame &frame);
照相机管理
GetCameraMatrix这个函数⽤来检索条件适合的观察者矩阵,存入第一个参数中
void GetCameraMatrix(M3DMatrix44f m,bool bRotationOnly = flase);
image
注:图引自逻辑教育CC老师课件
网友评论