跳转到内容

向量

向量(Vector)是游戏开发中最基础的数学工具,用于表示位置、方向、速度等。LayaAir引擎提供了 Vector2Vector3Vector4 三种向量类,分别位于 laya/maths/ 下。

Vector2 表示2D空间中的点或方向,包含 xy 两个分量。

let v = new Laya.Vector2(3, 4);
// 预定义常量(只读,禁止修改)
Laya.Vector2.ZERO; // (0, 0)
Laya.Vector2.ONE; // (1, 1)

图1-1

(图1-1)

let a = new Laya.Vector2(1, 2);
let b = new Laya.Vector2(3, 4);
let out = new Laya.Vector2();
// 设置值
a.setValue(5, 6);
// 缩放
Laya.Vector2.scale(a, 2, out); // out = a * 2
// 点积
let dot = Laya.Vector2.dot(a, b); // 标量结果
// 归一化(单位向量)
Laya.Vector2.normalize(a, out);
// 两点距离
let dist = Laya.Vector2.distance(a, b);
// 标量长度
let len = Laya.Vector2.scalarLength(a);
// 判断相等
let eq = Laya.Vector2.equals(a, b);
// 克隆
let c = a.clone();
a.cloneTo(out);
// 与数组互转
let arr = a.toArray(); // [x, y]
a.fromArray([10, 20]);

Vector3 是3D开发中最核心的向量类型,包含 xyz 三个分量。

let v = new Laya.Vector3(1, 2, 3);
// 预定义常量(只读)
Laya.Vector3.ZERO; // (0, 0, 0)
Laya.Vector3.ONE; // (1, 1, 1)
Laya.Vector3.Up; // (0, 1, 0)
Laya.Vector3.UnitX; // (1, 0, 0)
Laya.Vector3.UnitY; // (0, 1, 0)
Laya.Vector3.UnitZ; // (0, 0, 1)
Laya.Vector3.ForwardRH; // (0, 0, -1) 右手坐标系前方
Laya.Vector3.ForwardLH; // (0, 0, 1) 左手坐标系前方
let a = new Laya.Vector3(1, 2, 3);
let b = new Laya.Vector3(4, 5, 6);
let out = new Laya.Vector3();
Laya.Vector3.add(a, b, out); // 加法
Laya.Vector3.subtract(a, b, out); // 减法
Laya.Vector3.multiply(a, b, out); // 分量相乘
Laya.Vector3.scale(a, 2, out); // 缩放
Laya.Vector3.normalize(a, out); // 归一化
let dot = Laya.Vector3.dot(a, b); // 点积
Laya.Vector3.cross(a, b, out); // 叉积
let dist = Laya.Vector3.distance(a, b); // 距离
let distSq = Laya.Vector3.distanceSquared(a, b); // 距离平方(避免开方,用于比较)
let len = Laya.Vector3.scalarLength(a); // 标量长度
// 实例方法
a.set(10, 20, 30);
let l = a.length();
let lsq = a.lengthSquared();
a.normalize();
let d = a.dot(b);
a.cross(b, out);
a.vadd(b, out); // 实例加法
a.vsub(b, out); // 实例减法
a.scale(2, out); // 实例缩放
let start = new Laya.Vector3(0, 0, 0);
let end = new Laya.Vector3(10, 10, 10);
let out = new Laya.Vector3();
// t 从 0 到 1,实现平滑过渡
Laya.Vector3.lerp(start, end, 0.5, out); // out = (5, 5, 5)
let min = new Laya.Vector3(0, 0, 0);
let max = new Laya.Vector3(10, 10, 10);
let v = new Laya.Vector3(15, -3, 5);
let out = new Laya.Vector3();
Laya.Vector3.Clamp(v, min, max, out); // out = (10, 0, 5)
// 取两向量各分量最小/最大值
Laya.Vector3.min(a, b, out);
Laya.Vector3.max(a, b, out);
let v = new Laya.Vector3(1, 0, 0);
let out = new Laya.Vector3();
let out4 = new Laya.Vector4();
// 通过矩阵变换坐标(会做透视除法归一化)
Laya.Vector3.transformCoordinate(v, matrix, out);
// 通过矩阵变换为四维向量
Laya.Vector3.transformV3ToV4(v, matrix, out4);
// 通过矩阵变换为三维向量
Laya.Vector3.transformV3ToV3(v, matrix, out);
// 通过法线矩阵变换法线方向
Laya.Vector3.TransformNormal(normal, matrix, out);
// 通过四元数旋转向量
Laya.Vector3.transformQuat(v, quaternion, out);

Vector4 包含 xyzw 四个分量,常用于齐次坐标、Shader数据传递。

let v = new Laya.Vector4(1, 2, 3, 1);
Laya.Vector4.ZERO; // (0, 0, 0, 0)
Laya.Vector4.ONE; // (1, 1, 1, 1)
Laya.Vector4.UnitX; // (1, 0, 0, 0)
Laya.Vector4.UnitY; // (0, 1, 0, 0)
Laya.Vector4.UnitZ; // (0, 0, 1, 0)
Laya.Vector4.UnitW; // (0, 0, 0, 1)
let a = new Laya.Vector4(1, 2, 3, 4);
let b = new Laya.Vector4(5, 6, 7, 8);
let out = new Laya.Vector4();
Laya.Vector4.add(a, b, out);
Laya.Vector4.subtract(a, b, out);
Laya.Vector4.multiply(a, b, out);
Laya.Vector4.scale(a, 2, out);
Laya.Vector4.normalize(a, out);
Laya.Vector4.lerp(a, b, 0.5, out);
let dot = Laya.Vector4.dot(a, b);
let dist = Laya.Vector4.distance(a, b);
// 通过4x4矩阵变换
Laya.Vector4.transformByM4x4(v, matrix, out);
// 范围限制
Laya.Vector4.Clamp(v, min, max, out);
let direction = new Laya.Vector3();
Laya.Vector3.subtract(targetPos, currentPos, direction);
Laya.Vector3.normalize(direction, direction);

图4-1

(图4-1)

let aNorm = new Laya.Vector3();
let bNorm = new Laya.Vector3();
Laya.Vector3.normalize(a, aNorm);
Laya.Vector3.normalize(b, bNorm);
let cosAngle = Laya.Vector3.dot(aNorm, bNorm);
let angle = Math.acos(cosAngle); // 弧度
let degrees = angle * 180 / Math.PI; // 角度
let toTarget = new Laya.Vector3();
Laya.Vector3.subtract(targetPos, myPos, toTarget);
let dot = Laya.Vector3.dot(forward, toTarget);
// dot > 0:前方 | dot < 0:后方 | dot ≈ 0:侧面

图4-2

(图4-2)

// 由三角形三个顶点计算面法线
let edge1 = new Laya.Vector3();
let edge2 = new Laya.Vector3();
let normal = new Laya.Vector3();
Laya.Vector3.subtract(p1, p0, edge1);
Laya.Vector3.subtract(p2, p0, edge2);
Laya.Vector3.cross(edge1, edge2, normal);
Laya.Vector3.normalize(normal, normal);