一、二维
1.1 缩放矩阵
x,y分别表示在x轴,y轴缩放的倍数
示例: 点(2,1)在x,y轴上分别缩放x倍,y倍
1.2 平移矩阵
x,y分表表示在x轴,y轴上移动的距离
示例:点(2,1)分别在x轴,y轴上平移x距离,y距离
1.3 旋转矩阵
示例:点(x,y) 绕原点逆时针旋转θ°
示例:
点 (2,0) 绕原点旋转90°
绕任一点旋转?
转为先平移到这个点, 再旋转即可。
1.4 变换顺序
先平移再旋转,得到的变换矩阵是:
示例:
(2,0) 先平移 (0,2) 再旋转90°应该为: (-2,2)
如果换成是先旋转再平移则是(0,4):
二、三维
2.1 缩放矩阵
x,y,z分别表示点在x,y,z轴缩放的倍数
示例:
点 (2,1,2) 在x,y,z轴上分别缩放x,y,z倍
2.2 平移矩阵
示例:
点(2,1,2) 在x,y,z轴上分别移动 x,y,z距离
2.3 旋转矩阵
θ 表示点绕过原点的 x, y, z 轴旋转θ°
注意:绕某轴旋转则眼睛看向某轴的负方向,逆时针为正,顺时针为负(和左右手坐标系没关系)。参考: https://zhuanlan.zhihu.com/p/147282442
示例:
- 点(2,1,2) 绕过原点的y轴旋转90°,应为:(2, 1, -2)
- 点(1,2,2) 绕过原点的x轴旋转90°,应为:(1,-2,2)
- 点(2,2,1) 绕过原点的z轴旋转90°,应为(-2,2,1)
绕任一点旋转?
转为先平移到这个点, 再旋转即可。
2.4 变换顺序(同二维,不再赘述)
三、threejs中的矩阵变换 (Matrix3)
3.1 矩阵存储格式
如果将矩阵的元素存储为数组的话,我们人类易读的是行优先
,但three.js
采用的是列优先
,它们区别如下:
不过,虽然three.js
内部存储是列优先
,但在传参时遵循的是行优先
,看下面源码:
3.2 旋转方向的奇怪问题
three.js
中使用矩阵旋转的时候有个奇怪的地方,如下:
new THREE.Matrix3().makeRotation(Math.PI/2)
:从0创建一个旋转矩阵,逆时针旋转90°;new THREE.Matrix3().rotate(Math.PI/2)
:累加旋转, 顺时针旋转90°;
下面是例子:
<script type="module">
import * as THREE from 'three';
//makeRotation: 逆时针为正
var m2 = new THREE.Matrix3().makeRotation(Math.PI/2);
var ret2 = new THREE.Vector2(2,0).applyMatrix3(m2);
//输出: (2,0) makeRotation(90°): {"x":1.2246467991473532e-16,"y":2}
console.log(`(2,0) makeRotation(90°): ${JSON.stringify(ret2)}`)
//rotate是累加: 顺时针为正
var m = new THREE.Matrix3().rotate(Math.PI/2);
var ret = new THREE.Vector2(2,0).applyMatrix3(m);
//输出: (2,0) rotate(90°): {"x":1.2246467991473532e-16,"y":-2}
console.log(`(2,0) rotate(90°): ${JSON.stringify(ret)}`)
</script>
3.3 其他示例
<script type="module">
import * as THREE from 'three';
//先平移后逆时针旋转
var m = new THREE.Matrix3().translate(0,2).rotate(-Math.PI/2);
var ret = new THREE.Vector2(2,0).applyMatrix3(m);
//(2,0) 先平移(0,2)后逆时针旋转90°: {"x":-1.9999999999999998,"y":2}
console.log(`(2,0) 先平移(0,2)后逆时针旋转90°: ${JSON.stringify(ret)}`)
//先逆时针旋转后平移
var m2 = new THREE.Matrix3().rotate(-Math.PI/2).translate(0,2);
var ret2 = new THREE.Vector2(2,0).applyMatrix3(m2);
//(2,0) 先逆时针旋转90°后平移(0,2): {"x":1.2246467991473532e-16,"y":4}
console.log(`(2,0) 先逆时针旋转90°后平移(0,2): ${JSON.stringify(ret2)}`)
</script>
四、c#中的矩阵 (Matrix3x2)
查看的c#矩阵源码地址:《Matrix3x2.Impl.cs》
4.1 矩阵存储格式
没有存储9个矩阵元素,而是6个,如:
内部存储是用了三个 Vector2 向量存储,参考源码:
4.2 奇怪的相乘顺序
一般认为的:
但实际上,c#是右乘,如:
//(2,0) 先逆时针旋转90°, 再平移 (0,2)
var m = Matrix3x2.CreateRotation(MathF.PI / 2) * Matrix3x2.CreateTranslation(0, 2);
//输出 (0,4)
Console.WriteLine(Vector2.Transform(new Vector2(2, 0), m));
但,,,好像结果是对的。。。这就牵扯到另外一个问题:
4.3 奇怪的矩阵转置
一般认为,平移矩阵是:
但c#构造后是:
参考源码:
一般认为,构造旋转矩阵是:
但c#构造后是:
参考源码:
但,恰好是 转置的矩阵
和 右乘
刚好和我们认为的(非转置矩阵
和 左乘
)效果一致。