02 · Vector2 与 Vector4 快速入门

返回目录 · 上一章 · 下一章

本章只建立使用边界,核心接口的详细规律可参照后面的 Vector3 章节。所有示例均先 import * as THREE from 'three'。

1. Vector2:二维数据不必伪装成三维

鼠标位置、UV 和二维速度都只需要两个分量:

const uv = new THREE.Vector2(0.25, 0.75);
const offset = new THREE.Vector2(0.1, -0.2);
const sampleUv = uv.clone().add(offset); // [0.35, 0.55]
const speed = new THREE.Vector2(3, 4).length(); // 5

set、copy、clone、add、sub、multiplyScalar、normalize 和 lerp 与 Vector3 的基本习惯相同:大多数运算修改接收对象并返回它;length、dot、cross 等查询返回数字。equals 是逐分量精确比较,不是浮点容差比较。

Vector2 的 width/height 是 x/y 的别名,便于表示尺寸;对象并不会因此自动拒绝负数。angle() 返回相对二维正 X 轴的方向角,angleTo(v) 返回两向量的非负夹角;需要有符号转角时可用 Math.atan2(a.cross(b), a.dot(b)),并单独处理零向量。

cross(v) 返回 x * v.y - y * v.x,是有向面积标量,详见二维叉积。

2. Vector2 与 Matrix3

二维平移可以通过补一个固定的齐次分量 1 合并进矩阵:

const moveUv = new THREE.Matrix3().makeTranslation(0.2, -0.1);
const transformed = new THREE.Vector2(0.3, 0.4).applyMatrix3(moveUv);
console.log(transformed.toArray()); // [0.5, 0.3],存在浮点舍入

Vector2.applyMatrix3() 按点 (x,y,1) 计算前两行,不做一般投影矩阵所需的齐次除法。因此它适合二维仿射变换;不能把任意 3×3 单应矩阵传进去就期待正确透视结果。二维方向应排除平移项,可改用 (dx,dy,0) 的 Vector3。

3. Vector4:四个分量与齐次坐标

构造函数默认值为 (0,0,0,1)。它既可以容纳任意四维数据,也可以表示齐次坐标,但操作仍只是数学运算。

const transform = new THREE.Matrix4().makeTranslation(10, 0, 0);
const point = new THREE.Vector4(1, 2, 3, 1).applyMatrix4(transform);
const direction = new THREE.Vector4(1, 2, 3, 0).applyMatrix4(transform);
console.log(point.toArray()); // [11, 2, 3, 1]
console.log(direction.toArray()); // [1, 2, 3, 0]

矩阵平移列乘以 w,所以点受到平移,方向不受平移。透视投影后的 clip 坐标则需要另外除以 w:

const clip = new THREE.Vector4(2, 4, 1, 2);
const ndc = new THREE.Vector3(clip.x, clip.y, clip.z).divideScalar(clip.w);

这里不能使用 clip.normalize() 代替透视除法:normalize 除以四维欧氏长度,而透视除法除以 w,两者目的和结果不同。w 接近 0 时,投影位置可能发散,必须先判定是否适合显示。

4. 不要混淆 Vector4、颜色和四元数

Vector4 的 set/copy/clone、分量运算和数组交换适合四分量数据;applyMatrix4 保留计算得到的 w。材质颜色通常用 Color 管理颜色空间;RGBA 数据可用 Vector4 存储,但它不会自动执行颜色转换。

Quaternion 虽也有 x、y、z、w,却有专门的旋转乘法和插值规则。对四元数逐分量做普通 Vector4 运算不能代替旋转组合。详见Quaternion。

练习(不附答案)

  1. 用 Vector2 求两个 UV 点的中点,保留两个输入不变。
  2. 将二维方向 (1,0) 用 Matrix3 旋转并平移,分别按点和方向处理,比较结果。
  3. 用数值说明 Vector4 的 normalize 与除以 w 为什么不能互换。
  4. 为鼠标位置、纹理尺寸、RGBA、模型朝向分别选择合适的数据类型并解释原因。