threejs系列之:矩阵推导🎰

写在最前

往期回顾:

  1. # threejs系列: 相机与投影 📷
  2. # threejs系列: 光源与光照🪀
  3. # threejs系列: 自定义几何体🎃
  4. # threejs系列: 几何变换(上)🍺
  5. # threejs系列: 几何变换(下)🏄‍♂️
  6. threejs系列: 矩阵推导🎰
  7. threejs系列: 物体详解🐧
  8. threejs系列: 材质与贴图详解🦥
  9. threejs系列: 曲线详解🥓
  10. threejs系列: 动画详解🧠
  11. .......

高强度持续更新,从0到1深入了解 threejs 的奥秘,喜欢的点个关注呀

矩阵

数学上,矩阵定义为是一个有m行(row)n列(column)元素的矩形阵列。在线性代数中矩阵和向量是随处可见的,向量与矩阵的计算也是该熟记的。

下面是一个3 * 3的矩阵。
{ 1 2 3 4 5 6 7 8 9 } \left\{ \begin{matrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ \end{matrix} \right\} ⎩ ⎨ ⎧147258369⎭ ⎬ ⎫

矩阵加法

矩阵的加减法很简单,只需要把相对位置算数就可以,前提是矩阵的行列数相同
{ 1 4 } + { 2 5 } = { 1 + 2 4 + 5 } = { 3 9 } \left\{ \begin{matrix} 1\\ 4\\ \end{matrix} \right\} + \left\{ \begin{matrix} 2\\ 5\\ \end{matrix} \right\} = \left\{ \begin{matrix} 1 + 2\\ 4 + 5\\ \end{matrix} \right\} = \left\{ \begin{matrix} 3\\ 9\\ \end{matrix} \right\} {14}+{25}={1+24+5}={39}

矩阵乘法

矩阵乘以一个数字:
{ 1 4 } ∗ 4 = { 1 ∗ 4 4 ∗ 4 } = { 4 16 } \left\{ \begin{matrix} 1\\ 4\\ \end{matrix} \right\} * 4 = \left\{ \begin{matrix} 1 * 4\\ 4 * 4\\ \end{matrix} \right\} = \left\{ \begin{matrix} 4\\ 16\\ \end{matrix} \right\} {14}∗4={1∗44∗4}={416}

矩阵与矩阵相乘:

前提:只有第一个矩阵的列的个数等于第二个矩阵的行的个数,这样的两个矩阵才能相乘。

A矩阵与B矩阵两个矩阵相乘得到的矩阵,会有矩阵A有相同的行数,会有矩阵B相同的列数。

例如:

2 * 3 矩阵 与 3 * 2 矩阵得到的就是一个 2 行 2 列的矩阵。

然后以分别进行 红蓝 、 红绿 、 橙蓝 、 橙绿组合进行点乘。
{ a b c d f e } ∗ { h i j k l m } = { a ∗ h + b ∗ j + c ∗ l a ∗ i + b ∗ k + c ∗ m d ∗ h + f ∗ j + e ∗ l d ∗ i + f ∗ k + e ∗ m } \left\{ \begin{matrix} a & b & c\\ d & f & e\\ \end{matrix} \right\} * \left\{ \begin{matrix} h & i\\ j & k\\ l & m\\ \end{matrix} \right\} = \left\{ \begin{matrix} a * h + b * j + c* l & a * i + b * k + c * m\\ d * h + f * j + e * l & d * i + f * k + e * m\\ \end{matrix} \right\} {adbfce}∗⎩ ⎨ ⎧hjlikm⎭ ⎬ ⎫={a∗h+b∗j+c∗ld∗h+f∗j+e∗la∗i+b∗k+c∗md∗i+f∗k+e∗m}

以上就是矩阵的简单计算。

向量

在上篇文章我们讲到的向量其实也能看作是一个m * 1的矩阵,比如:
向量 x , y , z = { x y z } 向量 x, y, z = \left\{ \begin{matrix} x\\ y\\ z\\ \end{matrix} \right\} 向量x,y,z=⎩ ⎨ ⎧xyz⎭ ⎬ ⎫

在几何平面上:

o j ⃗ 为 y 坐标的单位向量, o i ⃗ 为 x 坐标的单位向量, o A ⃗ 可以表示为 3 o i ⃗ + 2 o j ⃗ \vec{oj} 为y坐标的单位向量,\vec{oi}为x坐标的单位向量,\vec{oA}可以表示为 3\vec{oi} + 2\vec{oj} oj 为y坐标的单位向量,oi 为x坐标的单位向量,oA 可以表示为3oi +2oj
则矩阵表示的话是为: 3 { 1 0 } + 2 { 0 1 } = { 3 ∗ 1 + 2 ∗ 0 3 ∗ 0 + 2 ∗ 1 } = { 3 2 } 则矩阵表示的话是为: 3 \left\{ \begin{matrix} 1\\ 0\\ \end{matrix} \right\} + 2 \left\{ \begin{matrix} 0\\ 1\\ \end{matrix} \right\} = \left\{ \begin{matrix} 3 * 1 + 2* 0\\ 3 * 0 + 2 * 1\\ \end{matrix} \right\} = \left\{ \begin{matrix} 3\\ 2\\ \end{matrix} \right\} 则矩阵表示的话是为:3{10}+2{01}={3∗1+2∗03∗0+2∗1}={32}

=
计算方式和矩阵如出一辙 { 1 0 0 1 } { 3 2 } = { 3 ∗ 1 + 2 ∗ 0 3 ∗ 0 + 2 ∗ 1 } = { 3 2 } 计算方式和矩阵如出一辙 \left\{ \begin{matrix} 1 & 0\\ 0 & 1\\ \end{matrix} \right\} \left\{ \begin{matrix} 3\\ 2\\ \end{matrix} \right\} = \left\{ \begin{matrix} 3 * 1 + 2* 0\\ 3 * 0 + 2 * 1\\ \end{matrix} \right\} = \left\{ \begin{matrix} 3\\ 2\\ \end{matrix} \right\} 计算方式和矩阵如出一辙{1001}{32}={3∗1+2∗03∗0+2∗1}={32}

这里由两个坐标系单位向量组成的矩阵也被称之为单位矩阵
{ 1 0 0 1 } \left\{ \begin{matrix} 1 & 0\\ 0 & 1\\ \end{matrix} \right\} {1001}

图中的 o j ⃗ 和 o i ⃗ \vec{oj} 和 \vec{oi} oj 和oi 也被称为坐标系的基向量

旋转矩阵推导

将坐标轴逆时针旋转45°


o i ⃗ 由旋转公式可得: { c o s 45 ° s i n 45 ° } , o j ⃗ = { − s i n 45 ° c o s 45 ° } \vec{oi}由旋转公式可得: \left\{ \begin{matrix} cos45°\\ sin45°\\ \end{matrix} \right\} , \vec{oj} = \left\{ \begin{matrix} -sin45°\\ cos45°\\ \end{matrix} \right\} oi 由旋转公式可得:{cos45°sin45°},oj ={−sin45°cos45°}

矩阵表示为:
{ c o s 45 ° − s i n 45 ° s i n 45 ° c o s 45 ° } { 3 2 } \left\{ \begin{matrix} cos45° & -sin45°\\ sin45° & cos45°\\ \end{matrix} \right\} \left\{ \begin{matrix} 3\\ 2\\ \end{matrix} \right\} {cos45°sin45°−sin45°cos45°}{32}

所以平面旋转矩阵为:
{ c o s 45 ° − s i n 45 ° s i n 45 ° c o s 45 ° } \left\{ \begin{matrix} cos45° & -sin45°\\ sin45° & cos45°\\ \end{matrix} \right\} {cos45°sin45°−sin45°cos45°}

缩放矩阵推导

我们将坐标系缩小2倍


o i ⃗ 此时坐标: { 1 / z 0 } , o j ⃗ = { 0 1 / z } ,又因为 O A ⃗ = 3 O i ⃗ + 2 O j ⃗ ,所以矩阵表示为: { 1 / z 0 0 1 / z } { 3 2 } \vec{oi}此时坐标: \left\{ \begin{matrix} 1 / z\\ 0\\ \end{matrix} \right\} , \vec{oj} = \left\{ \begin{matrix} 0\\ 1 / z\\ \end{matrix} \right\} , 又因为\vec{OA} = 3\vec{Oi} + 2\vec{Oj}, 所以矩阵表示为: \left\{ \begin{matrix} 1 / z & 0\\ 0 & 1 / z\\ \end{matrix} \right\} \left\{ \begin{matrix} 3\\ 2\\ \end{matrix} \right\} oi 此时坐标:{1/z0},oj ={01/z},又因为OA =3Oi +2Oj ,所以矩阵表示为:{1/z001/z}{32}

缩放矩阵为:
{ z 0 0 z } \left\{ \begin{matrix} z & 0\\ 0 & z\\ \end{matrix} \right\} {z00z}

线性变换

你会发现这种变换坐标系然后通过基向量获取点向量的方式很有趣,这种方式在数学中叫做线性变换

线性变换在几何直观上有如下特点:

  • 变换前后,直线仍然保持是直线的状态
  • 变换前后,原点保持固定,不会变化

平移矩阵推导

仿射变换

由于线性变换拥有原点固定的特点,所以无法进行平移,只能旋转和缩放。

一刻也无需为无法平移感伤,接下来出场的是 仿射变换

仿射变换与线性变换的最大不同就是原点可以移动

通过添加一个维度进行线性变换然后在低纬度上投影,这样看上去就是在低纬度上移动了。

这张图形象的说明了仿射变换。

齐次坐标

齐次坐标就是将原先 n 维坐标改成 n + 1 维坐标表示。在3d图形学中,我们需要在向量中添加一个分量叫做 w ,表示在4维空间中的位置。物体的坐标其实是 (x/w, y/w ,z/w),因此当 w = 1 时,物体的xyz不会变化,所以通常我们都将 w 设置为1。

推导

我们回到平移推导,我们假设将坐标(x,y)平移到坐标(x',y'),因为线性变换无法平移,所以我们需乘以一个未知的齐次平移矩阵
{ x y z } ∗ { a b c d e f g h 1 } = { a x + b y + c z d x + e y + f z g x + h y + i z } \left\{ \begin{matrix} x\\ y\\ z\\ \end{matrix} \right\} * \left\{ \begin{matrix} a & b & c\\ d & e & f\\ g & h & 1\\ \end{matrix} \right\} = \left\{ \begin{matrix} ax + by + cz\\ dx + ey + fz\\ gx + hy + iz\\ \end{matrix} \right\} ⎩ ⎨ ⎧xyz⎭ ⎬ ⎫∗⎩ ⎨ ⎧adgbehcf1⎭ ⎬ ⎫=⎩ ⎨ ⎧ax+by+czdx+ey+fzgx+hy+iz⎭ ⎬ ⎫

得到以下等式

ini 复制代码
x' = ax + by + cz;
y' = dx + ey + fz;
1  = gx + hy + z;

从式子我们可以首先得出 g = 0, h = 0, z = 1;

因为是平移,所以我们知道x'是 x移动了Tx, y'是y移动了Ty

ini 复制代码
x' = x + Tx;
y' = y + Tx;

所以上面两个等式结合,我们可以知道,a = 1,b = 0, cz = Tx;d = 0, e = 1,f = Ty。

将其带入后得到平移矩阵
{ 1 0 T x 0 1 T y 0 0 1 } \left\{ \begin{matrix} 1 & 0 & Tx\\ 0 & 1 & Ty\\ 0 & 0 & 1\\ \end{matrix} \right\} ⎩ ⎨ ⎧100010TxTy1⎭ ⎬ ⎫

至此,三个基础得几何转换矩阵都得出来了,这里不禁感叹道还真是不容易呢😅

threejs 矩阵

矩阵的计算是相对复杂得,幸运的是threejs为我们封装了数学方法,接下来我们看看threejs如何使用矩阵。

threejs提供了Matrix4 类让我们快速的创建一个 4*4 矩阵。

m4 = new THREE.Matrix4();

然后通过.set方法进行填充元素。

m4.set(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);

通过.element方法查看元素

m4.element

我们来进行矩阵进行几何变换:

js 复制代码
// 缩放
mesh.matrix.makeScale(0.5, 0.5, 0.5);
mesh.matrixAutoUpdate = false;

API就不一一讲了,都是易懂的。

相关推荐
JS菌7 小时前
手写一个 AI Agent 全栈项目:从沙箱执行到子智能体的完整实现
前端·人工智能·后端
excel8 小时前
HLS TS 文件损坏的元凶:Git 提交与拉取
前端
Aphasia3118 小时前
https连接传输流程
前端·面试
徐小夕8 小时前
万字长文!千万级文档 RAG 知识库系统落地实践
前端·算法·github
threelab9 小时前
Three.js 物理模拟着色器 | 三维可视化 / AI 提示词
开发语言·前端·javascript·人工智能·3d·着色器
kyriewen9 小时前
CSS Container Queries:彻底告别 @media 写到手软,附 5 个真实布局案例
前端·css·面试
小小小小宇10 小时前
OpenMemory MCP
前端
和平宇宙11 小时前
AI笔记005. hermes-DeepSeek V4 Pro, 128K上下文引发的探索
前端·人工智能·笔记
IT_陈寒11 小时前
Redis持久化这个坑,我爬了一整天才出来
前端·人工智能·后端