quat
v2.1.4
Published
A high-performance quaternion library for 3D math, inspired by gl-matrix.
Maintainers
Readme
quat:高性能四元数运算库
一款轻量且高性能的 TypeScript 四元数库,专为 3D 旋转计算设计。支持四元数的创建、运算、插值、转换等全功能操作,以及批量点旋转,同时提供通用模块支持(ESM/CJS/IIFE),可无缝集成到 Node.js、打包工具及浏览器环境中。
核心特性
- 多环境兼容:支持 ESM(Node.js/打包工具)、CommonJS(Node.js)和 IIFE(浏览器全局变量),可通过 CDN 直接引入。
- 极致性能:基于
Float32Array实现,内存布局优化,CPU 缓存利用率高,垃圾回收开销最小化。 - 完整 3D 旋转工具链:覆盖四元数与欧拉角/矩阵的转换、插值计算及批量顶点旋转。
- 类型安全:严格的 TypeScript 类型定义 + 运行时类型检查,避免无效旋转数据导致的错误。
- 浏览器友好:提供 IIFE 构建版本(v1.1.0+),可通过 unpkg 加载,自动暴露全局变量
quat直接使用。
安装方式
1. 包管理器(ESM/CJS)
适用于 Node.js 或打包工具(Webpack/Vite/Rollup):
# npm 安装
npm install quat
# yarn 安装
yarn add quat2. 浏览器 CDN(IIFE)
直接在浏览器中加载预构建的 IIFE 包(自动暴露全局变量 quat):
<!-- 加载 v1.1.0 版本(可替换为 npm 最新版本) -->
<script src="https://unpkg.com/quat@latest/dist/index.global.js"></script>
<!-- 通过全局变量 quat 使用 -->
<script>
const q = quat.create(); // 创建单位四元数:[0,0,0,1]
</script>使用示例
ESM 环境(TypeScript/JavaScript)
import * as quat from 'quat';
// 1. 创建四元数
const q1 = quat.create(); // 单位四元数:[0,0,0,1]
const q2 = quat.from([0, 1, 0], Math.PI / 2); // 绕 Y 轴旋转 90°
const q3 = quat.of(Math.PI/2, 0, 0); // 从 XYZ 欧拉角创建(绕 X 轴旋转 90°)
const q4 = quat.set(0.5, 0.5, 0, Math.SQRT1_2); // 从显式分量创建
// 2. 四元数运算
const combined = quat.multiply(q2, q3); // 组合旋转(先应用 q2,再应用 q3)
const conjugate = quat.conjugate(combined); // 计算共轭(翻转虚部)
const inverse = quat.invert(combined); // 计算逆(反转旋转方向)
const normalized = quat.normalize(q4); // 归一化(确保单位长度,保证旋转有效性)
// 3. 插值计算
const slerped = quat.slerp(q2, q3, 0.5); // 球面线性插值(平滑旋转,角速度恒定)
const lerped = quat.lerp(q2, q3, 0.5); // 线性插值(速度快,需后续归一化)
const sqlerped = quat.sqlerp(q1, q2, q3, q4, 0.5); // 球面二次插值(带控制点,曲线更平滑)
// 4. 单个点旋转
const point = [1, 0, 0];
const rotatedPoint = quat.rotatePoint(q2, point); // 旋转结果:[0,0,1]
// 5. 批量顶点旋转(WebGL 友好)
const vertices = new Float32Array([1,0,0, 0,1,0, 0,0,1]); // 3 个点(扁平化存储)
const rotatedVertices = new Float32Array(vertices.length);
quat.rotatePoints(q2, vertices, rotatedVertices); // 批量旋转,比循环调用快约 40%
// 6. 矩阵转换
const mat = quat.toMat3(q2); // 四元数 → 3x3 列优先矩阵
const qFromMat = quat.fromMat3(mat); // 3x3 列优先矩阵 → 四元数
// 7. 工具函数
const isQuat = quat.isQuat(q2); // 类型检查:返回 true
const quatStr = quat.str(q2); // 转为字符串:"quat(0.707107, 0.000000, 0.000000, 0.707107)"CommonJS 环境(Node.js)
const quat = require('quat');
// 创建随机旋转四元数
const randomQuat = quat.random();
// 提取旋转轴和角度
const axis = new Float32Array(3);
const angle = quat.getAxisAngle(axis, randomQuat);
console.log(`绕轴 [${axis.join(', ')}] 旋转 ${angle.toFixed(2)} 弧度`);浏览器 IIFE 环境(全局变量)
<script src="https://unpkg.com/quat@latest/dist/index.global.js"></script>
<script>
// 绕 Z 轴旋转正方形顶点
const rotateZ90 = quat.from([0,0,1], Math.PI/2); // 绕 Z 轴旋转 90°
const squareVertices = new Float32Array([
1,1,0, -1,1,0, -1,-1,0, 1,-1,0 // 4 个顶点的坐标
]);
const rotatedSquare = new Float32Array(squareVertices.length);
quat.rotatePoints(rotateZ90, squareVertices, rotatedSquare);
console.log('旋转后的顶点:', rotatedSquare);
</script>完整 API 参考
所有方法均支持可选的 out 参数以复用内存(减少垃圾回收),若未传入 out,则默认创建新的 Float32Array 实例返回。
1. 四元数创建
| 方法 | 函数签名 | 描述 |
|--------|--------------------------------------------------------------------------|----------------------------------------------------------------------|
| create | (): Quat | 创建单位四元数 [0, 0, 0, 1]。 |
| from | (axis: [number,number,number] \| ReadonlyVec3, angle: number, out?: Quat): Quat | 从旋转轴(建议单位向量)和角度(弧度)创建四元数。 |
| of | (x: number, y: number, z: number, out?: Quat): Quat | 从 XYZ 欧拉角(弧度,旋转顺序 X→Y→Z,与 Three.js 兼容)创建四元数。 |
| set | (x: number, y: number, z: number, w: number, out?: Quat): Quat | 从显式分量创建四元数(x/y/z 为虚部,w 为实部)。 |
| fromMat3 | (mat: ReadonlyMat3, out?: Quat): Quat | 将 3x3 列优先旋转矩阵转换为四元数。 |
| fromArray | (arr: number[]): Quat | 将 4 元素普通数组 [x,y,z,w] 转换为四元数,数组长度非 4 时抛出错误。 |
| random | (out?: Quat): Quat | 生成随机单位四元数(旋转分布均匀)。 |
2. 四元数运算
| 方法 | 函数签名 | 描述 |
|--------------|--------------------------------------------------------------------------|----------------------------------------------------------------------|
| multiply | (a: ReadonlyQuat, b: ReadonlyQuat, out?: Quat): Quat | 四元数乘法(out = a * b),几何意义:先应用 b 的旋转,再应用 a 的旋转。 |
| add | (a: ReadonlyQuat, b: ReadonlyQuat, out?: Quat): Quat | 四元数分量相加(out[i] = a[i] + b[i])。 |
| scale | (a: ReadonlyQuat, s: number, out?: Quat): Quat | 四元数标量缩放(out[i] = a[i] * s)。 |
| conjugate | (a: ReadonlyQuat, out?: Quat): Quat | 计算共轭四元数(翻转虚部:out = [-x, -y, -z, w])。 |
| invert | (a: ReadonlyQuat, out?: Quat): Quat | 计算逆四元数(单位四元数的逆等于其共轭)。 |
| normalize | (a: ReadonlyQuat, out?: Quat): Quat | 归一化四元数(确保单位长度,是有效旋转的前提,避免缩放效果)。 |
| exp | (a: ReadonlyQuat, out?: Quat): Quat | 计算四元数的指数(高阶旋转数学运算)。 |
| ln | (a: ReadonlyQuat, out?: Quat): Quat | 计算四元数的自然对数(高阶旋转数学运算)。 |
| pow | (a: ReadonlyQuat, b: number, out?: Quat): Quat | 计算四元数的标量幂(a^b),基于 ln 和 exp 实现(如 pow(q, 0.5) 可将旋转角度减半)。 |
3. 插值计算
| 方法 | 函数签名 | 描述 |
|------------|--------------------------------------------------------------------------|----------------------------------------------------------------------|
| slerp | (a: ReadonlyQuat, b: ReadonlyQuat, t: number, out?: Quat): Quat | 球面线性插值,保持角速度恒定(最适合平滑旋转动画),t ∈ [0,1](0 对应 a,1 对应 b)。 |
| lerp | (a: ReadonlyQuat, b: ReadonlyQuat, t: number, out?: Quat): Quat | 线性插值,速度快但角速度非恒定,需后续归一化才能作为有效旋转四元数。 |
| sqlerp | (a: ReadonlyQuat, b: ReadonlyQuat, c: ReadonlyQuat, d: ReadonlyQuat, t: number, out?: Quat): Quat | 球面二次插值,通过两个控制点(b、c)实现 a 到 d 的平滑曲线过渡。 |
4. 点与顶点旋转
| 方法 | 函数签名 | 描述 |
|----------------|--------------------------------------------------------------------------|----------------------------------------------------------------------|
| rotatePoint | (q: ReadonlyQuat, point: [number,number,number] \| ReadonlyVec3, out?: Vec3): Vec3 | 旋转单个 3D 点,基于公式 p' = q * p * q⁻¹(p 为纯四元数 [x,y,z,0])。 |
| rotatePoints | (q: ReadonlyQuat, points: Float32Array, out: Float32Array): Float32Array | 批量旋转扁平化 3D 点数组(格式:[x1,y1,z1,x2,y2,z2,...]),专为 WebGL 顶点数据优化,比循环调用 rotatePoint 快 40%+。若 points 与 out 长度不相等或长度非 3 的倍数,将抛出错误。 |
5. 矩阵转换
| 方法 | 函数签名 | 描述 |
|--------------|--------------------------------------------------------------------------|----------------------------------------------------------------------|
| toMat3 | (q: ReadonlyQuat, out?: Mat3): Mat3 | 将四元数转换为 3x3 列优先旋转矩阵(兼容 WebGL/OpenGL)。 |
| fromMat3 | (mat: ReadonlyMat3, out?: Quat): Quat | 将 3x3 列优先旋转矩阵转换为四元数(toMat3 的逆操作)。 |
6. 旋转轴与角度提取
| 方法 | 函数签名 | 描述 |
|----------------|--------------------------------------------------------------------------|----------------------------------------------------------------------|
| getAxisAngle | (outAxis: Vec3, q: ReadonlyQuat): number | 从四元数中提取旋转轴(存储到 outAxis)和角度(返回值,单位:弧度),复用 outAxis 避免内存分配。 |
7. 工具函数
| 方法 | 函数签名 | 描述 |
|------------------|--------------------------------------------------------------------------|----------------------------------------------------------------------|
| clone | (a: ReadonlyQuat): Quat | 深拷贝四元数。 |
| copy | (a: ReadonlyQuat, out: Quat): Quat | 将 a 的值复制到 out(复用 out 的内存)。 |
| toArray | (q: ReadonlyQuat): number[] | 将四元数转换为 4 元素普通数组 [x,y,z,w]。 |
| str | (a: ReadonlyQuat): string | 将四元数转换为人类可读字符串(如:"quat(0.707107, 0.000000, 0.000000, 0.707107)")。 |
| length | (a: ReadonlyQuat): number | 计算四元数的模长(长度),公式:√(x²+y²+z²+w²)。 |
| squaredLength | (a: ReadonlyQuat): number | 计算四元数的平方模长(x²+y²+z²+w²),比 length 快(避免开方),适合用于比较。 |
| dot | (a: ReadonlyQuat, b: ReadonlyQuat): number | 计算两个四元数的点积(a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w),用于相似度判断和 slerp 计算。 |
| equals | (a: ReadonlyQuat, b: ReadonlyQuat): boolean | 检查两个四元数是否近似相等(考虑浮点误差,判断条件:dot(a,b) ≥ 1 - 1e-6)。 |
| exactEquals | (a: ReadonlyQuat, b: ReadonlyQuat): boolean | 检查两个四元数是否完全相等(严格分量对比,仅用于精确值判断)。 |
| isQuat | (value: unknown): value is Quat | 运行时类型守卫:判断值是否为有效四元数(Float32Array 且长度为 4)。 |
| isVec3 | (value: unknown): value is Vec3 | 运行时类型守卫:判断值是否为有效三维向量(Float32Array 且长度为 3)。 |
类型定义
TypeScript 类型定义已内置(无需额外安装 @types/quat):
// 四元数:[x(虚部), y(虚部), z(虚部), w(实部)]
export type Quat = Float32Array & { length: 4 };
export type ReadonlyQuat = Readonly<Float32Array> & { length: 4 };
// 三维向量:[x, y, z](用于点坐标或旋转轴)
export type Vec3 = Float32Array & { length: 3 };
export type ReadonlyVec3 = Readonly<Float32Array> & { length: 3 };
// 3x3 矩阵(列优先存储,兼容 WebGL/OpenGL)
// 存储格式:[m00, m10, m20, m01, m11, m21, m02, m12, m22]
export type Mat3 = Float32Array & { length: 9 };
export type ReadonlyMat3 = Readonly<Float32Array> & { length: 9 };许可证
MIT
