Appearance
向量的概念与表示
如果你学过 Canvas 2D 编程,一定写过这样的代码:
javascript
const x = 100;
const y = 200;
ctx.fillRect(x, y, 50, 50);这里的 (100, 200) 表示矩形的位置。如果要让矩形移动,你可能会写:
javascript
x += velocityX;
y += velocityY;velocityX 和 velocityY 表示速度,也就是每帧的位移。你有没有想过,位置、速度、位移这三个概念有什么共同点?
它们都可以用向量来表示。
什么是向量
首先要问一个问题:什么是向量?
向量是既有大小又有方向的量。
这个定义听起来有点抽象。让我们用更直观的方式理解:
- 标量(Scalar):只有大小,没有方向。例如温度 25°C,质量 5kg,时间 10 秒。
- 向量(Vector):既有大小又有方向。例如速度"向东 10 米/秒",力"向上 50 牛顿"。
在 3D 图形学中,向量可以理解为空间中的一个箭头:
- 箭头的长度表示向量的大小(也叫模或长度)
- 箭头的指向表示向量的方向
想象一个从原点 (0, 0, 0) 指向点 (1, 2, 3) 的箭头,这就是一个向量。
向量的三种用途
向量在 3D 图形学中有三种主要用途:
1. 表示位置(点)
向量可以表示空间中的一个点。例如 (3, 5, 2) 表示 x=3, y=5, z=2 的位置。
在这种情况下,向量是从原点 (0, 0, 0) 指向目标点的箭头。
2. 表示方向
向量可以表示一个方向。例如相机的朝向、光线的方向、物体的前进方向。
表示方向时,向量的长度通常是 1(称为单位向量),只保留方向信息。
3. 表示位移
向量可以表示从一个点到另一个点的移动。例如物体的速度、力的作用方向。
如果一个物体在位置 A(1, 2, 3),速度是 v(0.1, 0, 0.2),那么下一帧的位置就是 A + v = (1.1, 2, 3.2)。
向量的数学表示
向量有两种常见的数学表示方式:
行向量表示
使用圆括号和逗号:
$$ \mathbf{v} = (x, y, z) $$
例如:$\mathbf{v} = (1, 2, 3)$
列向量表示
使用矩阵形式:
$$ \mathbf{v} = \begin{bmatrix} x \ y \ z \end{bmatrix} $$
例如:
$$ \mathbf{v} = \begin{bmatrix} 1 \ 2 \ 3 \end{bmatrix} $$
在本书中,我们主要使用行向量表示,因为它更简洁。但你需要知道,在矩阵运算中,列向量表示更常用(这将在后续章节中看到)。
从 2D 到 3D
如果你熟悉 2D 图形编程,那么 2D 向量你已经很熟悉了:
javascript
const position2D = { x: 100, y: 200 };这是一个 2D 向量,只有 x 和 y 两个分量。
3D 向量只是在此基础上增加了 z 轴:
javascript
const position3D = { x: 100, y: 200, z: 50 };z 轴表示深度:
- z 值越大,物体越靠近观察者(屏幕外)
- z 值越小,物体越远离观察者(屏幕内)
在 3D 图形学中,我们使用右手坐标系作为约定:
- x 轴:向右为正
- y 轴:向上为正
- z 轴:向外(朝向你)为正
记忆方法:伸出右手,拇指指向 x 轴正方向,食指指向 y 轴正方向,中指指向 z 轴正方向。
向量的分量
向量的 x、y、z 称为向量的分量(Component)。
对于向量 $\mathbf{v} = (3, 5, 2)$:
- x 分量是 3(沿 x 轴移动 3 个单位)
- y 分量是 5(沿 y 轴移动 5 个单位)
- z 分量是 2(沿 z 轴移动 2 个单位)
分量是标量(普通数字),而向量是由这些分量组合而成的。
一个有趣的事实:向量可以看作是三个轴向分量的叠加。向量 (3, 5, 2) 可以分解为:
$$ \mathbf{v} = 3 \cdot (1, 0, 0) + 5 \cdot (0, 1, 0) + 2 \cdot (0, 0, 1) $$
其中 (1, 0, 0)、(0, 1, 0)、(0, 0, 1) 是三个基向量(Base Vector),分别代表 x、y、z 轴的单位方向。
代码实现:Vector3 类
现在让我们用 JavaScript 实现一个基础的 Vector3 类。
为什么要用 class 而不是简单的对象字面量?因为后续我们会为向量添加各种运算方法(加减乘除、点积叉积等),使用 class 可以更好地组织代码。
javascript
class Vector3 {
constructor(x = 0, y = 0, z = 0) {
this.x = x;
this.y = y;
this.z = z;
}
toString() {
return `Vector3(${this.x}, ${this.y}, ${this.z})`;
}
}这是一个非常简单的实现:
constructor接收三个参数 x、y、z,默认值都是 0- 将参数存储为实例属性
toString方法用于调试输出
使用示例:
javascript
// 创建一个表示位置的向量
const position = new Vector3(10, 20, 5);
console.log(position.toString()); // Vector3(10, 20, 5)
// 创建一个零向量
const zero = new Vector3();
console.log(zero.toString()); // Vector3(0, 0, 0)
// 创建一个表示方向的向量(向右上方)
const direction = new Vector3(1, 1, 0);
console.log(direction.toString()); // Vector3(1, 1, 0)为什么默认值设为 0?因为零向量 (0, 0, 0) 在图形学中有特殊意义:
- 作为位置:表示原点
- 作为方向:表示无方向
- 作为速度:表示静止
这个设计与 Three.js 的 Vector3 保持一致,Three.js 是业界最流行的 3D 库之一。
小结
在本章中,我们学习了:
- 向量的定义:既有大小又有方向的量
- 向量的几何意义:空间中的箭头
- 向量的三种用途:位置、方向、位移
- 向量的表示方式:行向量
(x, y, z)和列向量 - 从 2D 到 3D:增加 z 轴,使用右手坐标系
- 向量的分量:x、y、z 分别表示在三个轴上的投影
- 代码实现:创建了
Vector3类的基础结构
现在我们知道了向量是什么,下一章将学习如何对向量进行运算——加法、减法和数乘。这些运算是所有复杂变换的基础。
练习:
- 创建一个向量表示点 (5, 10, 15)
- 创建一个向量表示"向右"的方向(提示:只有 x 分量不为 0)
- 创建一个向量表示"沿 45° 角向右上方"的方向(提示:x 和 y 分量相等且为正)
试着在浏览器控制台中运行上面的 Vector3 类代码,完成这三个练习。