- 1. Unity坐标系:
- 1. **世界坐标、屏幕坐标与视口坐标**
- 2. 坐标空间
- 3. 屏幕空间
- 2. 向量
- 1. 单位向量:
- 2. 向量的模:
- 3. 线性无关
- 4. 向量的点积(内积):
- 5. 向量的叉积(外积):
- 3. 矩阵
- 1. 方块矩阵:
- 2. 对角矩阵:
- 3. 单位矩阵:
- 4. 矩阵的加减法
- 5. 矩阵乘法:
- 6. 转置矩阵
- 7. 伴随矩阵
- 8. 逆矩阵
- 9. 正交矩阵
- 10. 正交投影矩阵
- 11. 镜像矩阵
- 12. 切变矩阵
- 13. 投影矩阵
- 4. 行列式
- 1. 二阶行列式的计算方法为对角线相加减
- 2. 行列式的计算
- 3. 代数余子式
- 4. 行列式的性质
- 4. 变换
- 1. 齐次坐标:用N+1个数来表示N维坐标的一种方式
- 2. 线性变换
- 3. 仿射变换
- 4. 2D平移变换
- 5. 2D缩放变换
- 6. 2D旋转变换
- 7. 逆矩阵(变换回原本的状态)
- 7. 复合变换
- 8. 3D变换
- 9. 法线变换
- 5. Matrix4x4
- 6. 案例
- 1. 一条直线与平面的交点
- 2. 求角度
- 世界坐标为世界空间下物体的坐标,相对于世界坐标原点。
- 屏幕坐标为 Game 窗口下的坐标。左下角为 (0,0) 点
- 视口坐标将 Game 窗口坐标单位化,左下角 (0,0),右上角 (1,1)。
- 在正交相机下,世界坐标可与屏幕坐标直接转换,在摄像机参考系下,最接近摄像机平面的位置。
- 在透视坐标系下,世界坐标与屏幕坐标直接转换只能得到摄像机原点,因此需要视口坐标辅助转换。 将屏幕坐标转换视口坐标时,默认其z轴为0,世界坐标转换视口坐标时,z轴为世界坐标到摄像机屏平面的距离。 延长其z轴到目的平面,再将视口坐标转换为世界坐标,即可精确获得世界坐标的某一点。
- 模型空间:每个模型都有自己独有的坐标系空间。
- 世界空间:(例如unity中的坐标系)
- 观察者空间:摄像机所在的坐标系。
- 裁剪空间:摄像机所包含的范围,由视锥体决定。
- 屏幕空间:屏幕所在的二维空间。
- 用向量除以长度。得到方向相同,但长度为1的向量。 a’ = a · |a|
- 一个单位向量的平面直角坐标系上的坐标表示可以是:(n,k) ,则有n²+k²=1。其中k/n就是原向量在这个坐标系内的所在直线的斜率。
即向量的长度。 |a|
3. 线性无关一组向量中,任意一个向量都不能由其它几个向量线性表示,则称这组向量线性无关。
4. 向量的点积(内积):- 计算方式1: a · b = axbx + ayby 例:(0, 2) · (3, 3) = 0 * 3 + 2 * 3 = 6
- 计算方式2: a · b = |a| |b| cos 例:(0, 2) · (3, 3) = 2 * 3√2 * (√2)/2 = 6
推导过程:c²=a²+b²-2|a||b|cos
- 应用:
- 点乘结果越大,夹角越小。
- 可用来判断夹角:>0时,a| = |b|cos = a · b / |a| 投影: b->a = (a · b / |a|) * (a · |a|)
- 计算方式: a x b = (ax, ay, az) x (bx, by, bz) = (aybz - azby, azbx - axbz, axby - aybx) 例:(1,2,3)x(-2,-2,3) = (6-(-6),(-6)-3,(-2)+4)=(12,-9,2)
- 模长:|c| = | a x b | = |a| |b| sin 在二维向量中可设z为0,那么: a x b = ( 0, 0, x1y2-x2y1) 很明显这也是一个向量,并且是垂直于向量a和b构成的平面的法向量,而其方向的正负就取决于它们的输入(x1,y1)和(x2,y2)的值。
- 应用: 叉积结果垂直与两条向量构成面的法向量(坐标系与当前坐标系相同) 垂直方向->左/右手坐标系->左/右手定则:四指从a向量向b向量弯曲,大拇指方向即为c向量方向。
行数列数相等的矩阵
2. 对角矩阵:除了一条对角线上的元素都为0的方块矩阵
3. 单位矩阵:对角线元素都为1的对角矩阵。矩阵x单位矩阵得到原矩阵。
4. 矩阵的加减法只有维度相同的矩阵才能相加减,计算结果为各个位置数值的各自和矩阵
5. 矩阵乘法:- 矩阵 x 单位矩阵 = 矩阵本身
- 满足结合律:(AB)C = A(BC)
- (AB)T = BTAT
- 行向量左乘矩阵:M将 a 向量转换为 b 向量 (新坐标系下 的 a 向量)
A* = [a11,a21,a31] [a12,a22,a32] [a13,a23,a33]
AB = BA = E,A-1=B
- 方阵才有逆矩阵,未必所有方阵可逆
- 若可逆,逆矩阵唯一
- 可逆矩阵的行列式不为0
- 求逆矩阵 A-1 = 1/|A| * [a11,a21,a31] [a12,a22,a32] [a13,a23,a33]
- 逆矩阵的作用:一个向量乘逆矩阵后,可乘它的逆矩阵回复原本的位置。
- 逆矩阵的性质:
奇异矩阵:行列式|A|等于0的方阵。
- 正交矩阵满足:M MT = I (单位矩阵) ∵ 矩阵有:M M-1 = I ∴正交矩阵满足:M-1 = MT
- 正交矩阵满足条件:
矩阵的每一行都是单位向量。 矩阵的所有行互相垂直。
显然,三维坐标系满足正交矩阵 3. 正交基:如果一组向量互相垂直,这组向量就被称作正交基。 4. 标准正交基:如果一组向量互相垂直并且所有向量都是单位向量,则称标准正交基。
-
正交投影 某个向量向某条轴的投影。 例->向x轴投影:x向量(1, 0),y向量(0, 1)
-
正交投影矩阵
- 2D镜像矩阵
- 3D镜像矩阵
- 透视投影
- 透视投影矩阵 |1 0 0 0| |0 1 0 0| |0 0 1 1/d| |0 0 0 0|
A -> |A|
- 2D中,行列式等于以基向量为两边的平行四边形的有符号面积。
- 3D中,行列式等于以变换后的基向量为三边的平行六边形的有符号体积。
三阶行列式计算 行列式计算
- 行列式可以按某一行或某一列展开成元素与其对应的代数余子式的乘积之和。
- 行列式某元素的余子式:行列式划去该元素所在的行与列的各元素,剩下的元素按原样排列,得到的新行列式。
- 行列式某元素的代数余子式:行列式某元素的余子式与该元素对应的正负符号的乘积(左上角为正,相邻即相反)。
- 定理:行列式等于它的任一行(列)的各元素与其对应的代数余子式乘积之和。 代数余子式性质:D = (-1)i+j D1 = (-1)i+j ai j mi j
叉乘也源于此:
- 行列式与它的转置行列式相等
- 互换行列式两行(列),行列式变号
- 行列式的某一行(列)中所有元素都乘以同一数k,等于用数k乘此行列式
- 行列式中如果有两行(列)成比例,则此行列式等于零。
- 若行列式的某一行(列)的元素都是两数之和,那么可以拆分成两个行列式 |1 3|=|1 1|+|1 2| = 1 |1 4| |1 1| |1 3|
- 把行列式的某一行(列)的个元素乘以同一数然后加到另一行(列)对应的元素上,行列式不变。 |1 3|=|1 3| |1 4| |0 1| (操作:- |1 3|)
- 三角形行列式的值是主对角线上的n个元素之积。
变换有两种基本形式:变换物体和变换坐标系。 A · B 的行向量是对A的基向量进行B变换的结果。
1. 齐次坐标:用N+1个数来表示N维坐标的一种方式- 点的齐次坐标:(x,y,z,1)
- 向量的齐次坐标:(x,y,z,0)
- 点与点的减法可得到一个向量。 向量和向量之间的加法得到一个向量。 点和向量之间的加法,可以得到一个移动了向量距离之后的点
缩放,旋转,推移(切变)
- 变换前是直线的,变换后依然是直线
- 直线比例保持不变
- 变换前是原点的,变换后依然是原点
线性变换 + 平移
- 先通过平移矩阵回到原点
- 通过(旋转)矩阵进行线性变换
- 先通过平移矩阵的逆矩阵回到原来的位置
同属的其他变换: 4. 等角变换:变换前后夹角大小和方向不变。 5. 正交变换,刚体变换…
4. 2D平移变换- 结论: x’ = x + a y’ = y + b
- 2D平移矩阵: 列向量: |10 tx| |0 1 ty| |0 0 1 |
- 将一个点P平移(tx,ty)单位到P’ P’=MP=P+d=P+ |tx| |ty| |0|
- 3D平移矩阵:
**注:**当w为0时,平移矩阵将无法令向量平移。(w=0,即点位于无穷远处)
- 2D缩放矩阵: |sx 0 0| |0 sy 0| |0 0 1 |
- 沿任意方向缩放:
-
设沿n轴推进缩放: V’ = V’⊥ + V’∥ = V⊥ + kV∥(沿轴缩放时垂直分量不变,平行分量伸缩) = V⊥ + k(V·n)n = V - (V·n)n + k(V·n)n (因为:V - V∥= V⊥) = V - (V+k)(V·n)n
-
二维沿任意方向缩放二维矩阵:
-
三维沿任意方向缩放二维矩阵:
-
-
结论: x’ = xcosθ - ysinθ y’ = xsinθ + ycosθ (θ为正时为逆时针,为负时为顺时针)
-
2D旋转矩阵: 列向量: |cos -sin 0| |sin cos 0| |0 0 1 | 行向量: |cos sin 0| |-sin cos 0| |0 0 1 |
P’=MP= |txcos-tysin| |txsin+tycos| |1|
-
证明: x = rcosa, y = rsina x’ = rcos(a+b), y’ = rsin(a+b) x’ = rcosbcosa - rsinbsina y’ = rsinbcosa + rcosbsina x’ = xcosb - ysinb y’ = xsinb + ycosb
-
另一种证明方式(旋转坐标轴):
**注:**即便w为0,旋转矩阵仍能让向量正常旋转。(w=0,即点位于无穷远处)
-
三维绕轴旋转(行向量) Z轴 |cos sin 0| |-sin cos 0| |0 0 1| X轴 |1 0 0| |0 cos sin| |0 -sin cos| Y轴 |cos 0 -sin| |0 1 0 | |sin 0 cos|
三维绕轴旋转,可视为将三行各个轴的单位向量 |1 0 0| |0 1 0| |0 0 1| 绕各个轴旋转。 例: 绕y轴旋转: x轴向量(1, 0, 0)绕y轴旋转θ角,得到的位置变为(cos, 0, -sin) 绕任意轴旋转:
- 平移矩阵的逆矩阵 |1 0 -tx| |0 1 -ty| |0 0 1 |
- 缩放矩阵的逆矩阵 |1/sx 0 0| |0 1/sy 0| |0 0 1 |
- 旋转矩阵的逆矩阵 |cos sin 0| |-sin cos 0| |0 0 1 |
- 物体变换与坐标系变换:顺序相反(从左到右变成从右到左),方式相反。(放大变缩小)
- 物体的变换(移动物体):多个变换连乘时,注意顺序且变换方阵在左,点的矩阵在右。从右到左连乘,计算时左乘右。
- 坐标系复合变换(移动坐标系):从左到右连乘。
两种变换的最终结果是相同的。
- 3D平移矩阵: |1 0 0 tx | |0 1 0 ty | |0 0 1 tz | |0 0 0 1 | 2. 3D缩放矩阵 |sx 0 0 0| |0 sy 0 0| |0 0 sz 0| |0 0 0 1|
- 3D旋转矩阵: x轴: |1 0 0| |0 cos -sin 0| |0 sin cos 0| |0 0 0 1| y轴: |cos 0 sin 0| |0 1 0 0| |-sin 0 cos 0| |0 0 0 1| z轴: |cos -sin 0 0| |sin cos 0 0| |0 0 1 0| |0 0 0 1|
- 法线向量是需要进行归一化的,它的长度必须为1.0。
- 法线向量是表示方向的,跟顶点不一样不是表示位置,所以法线向量只有三个分量,不存在齐次坐标。
- 法线向量的变换中,一般只有旋转变换和部分缩放变换。因为法线向量表示方向,平移后不变化,而且法线如果等轴缩放,归一化后也不变化,另外,法线主要是计算光照,透视变换也用不到。
Unity 可创建一个4x4的矩阵,使用 Matrix4x4 结构体创建,入参为四列。
- SetColumn 设置指定列
- SetRow 设置指定行
- x4.m12 第二行第三列
- Matrix4x4.identity 单位矩阵
- Matrix4x4.zero 零矩阵
- Matrix4x4.Transpose(x4) 转置一个矩阵
- Matrix4x4.Inverse(x4) 求逆矩阵
- Matrix4x4.Translate(Vector3) 得到一个平移矩阵
- Matrix4x4.Rotate(Quaternion q) 得到一个旋转矩阵
- Matrix4x4.Scale(Vector3 vector) 得到一个缩放矩阵
///
/// 计算直线与平面的交点
///
/// 直线上某一点
/// 直线的方向
/// 垂直于平面的的向量
/// 平面上的任意一点
///
private Vector3 GetIntersectWithLineAndPlane(Vector3 point, Vector3 direct, Vector3 planeNormal, Vector3 planePoint)
{
float d = Vector3.Dot(planePoint - point, planeNormal) / Vector3.Dot(direct.normalized, planeNormal);
//print(d);
return d * direct.normalized + point;
}
2. 求角度
///
/// 两个向量判断夹角
///
public static float GetAngle(Vector3 fromVector, Vector3 toVector)
{
float angle = Vector3.Angle(fromVector, toVector); //求出两向量之间的夹角
Vector3 normal = Vector3.Cross(fromVector, toVector);//叉乘求出法线向量
return angle *= Mathf.Sign(Vector3.Dot(normal, Vector3.back)); //求法线向量与物体上方向向量点乘,得知是否小于90°,结果为1或-1,修正旋转方向
}