gl-matrix矩阵库


🧮 gl-matrix矩阵库全API详解(WebGIS专属优化版)

gl-matrix是专为WebGL设计的轻量级、高性能线性代数库 ,核心优势是基于Float32Array存储数据(与WebGL原生兼容)、纯函数式设计、无依赖,是Cesium/Mapbox等WebGIS框架的底层矩阵运算核心。以下从向量、矩阵、四元数三大模块,结合WebGIS场景详解所有核心API。


📌 基础概念与通用规则

1. 核心特性
  • 列主序存储 :矩阵采用WebGL原生的列主序格式,直接传递给gl.uniformMatrix4fv()无需转置
  • 纯函数设计:所有函数均为纯函数,避免副作用,结果存储到目标数组(第一个参数),减少内存分配
  • 性能优先 :复用目标数组(out参数)避免频繁创建新对象,运算速度比普通数组快3-5倍
  • GIS适配:完美支持地理坐标变换、投影矩阵、三维姿态控制等WebGIS核心需求
2. 通用API模式

绝大多数函数遵循:

javascript 复制代码
fn(out: Float32Array, a: Float32Array, b: Float32Array, ...args) → Float32Array
  • out:目标数组,用于存储运算结果,避免创建新对象
  • a/b:输入数组(向量/矩阵)
  • 返回值:与out同一引用,支持链式调用

一、向量模块(vec2/vec3/vec4)

用于存储坐标、方向、颜色等n维数据,vec3是WebGIS中最常用的(三维地理坐标、法向量),vec2用于二维投影坐标,vec4用于齐次坐标。

1. 创建与复制API

API名称 作用 示例
vecN.create() 创建空的N维向量,初始值为[0,0,...] const pos = vec3.create(); // [0,0,0]
vecN.fromValues(x,y,...) 从数值直接创建N维向量 const beijing = vec3.fromValues(116.4, 39.9, 0); // 北京经纬度
vecN.copy(out, a) 复制向量aout vec3.copy(outPos, beijing); // outPos = [116.4,39.9,0]
vecN.set(out, x,y,...) 直接设置向量out的数值 vec3.set(outPos, 121.5, 31.2, 0); // 上海坐标

2. 基础运算API

API名称 作用 GIS场景
vecN.add(out, a, b) 向量加法:out = a + b 计算坐标偏移:vec3.add(out, currentPos, offset)
vecN.sub(out, a, b) 向量减法:out = a - b 计算两点方向向量:vec3.sub(out, targetPos, currentPos)
vecN.mul(out, a, b) 分量乘法:out[i] = a[i] * b[i] 坐标缩放:vec3.mul(out, pos, vec3.fromValues(2,2,2))(放大2倍)
vecN.scale(out, a, s) 标量乘法:out = a * s 地理坐标转换为投影坐标:vec3.scale(out, lngLat, scale)
vecN.scaleAndAdd(out, a, b, s) 缩放并相加:out = a + b*s 相机平滑移动:vec3.scaleAndAdd(out, cameraPos, moveDir, deltaTime)

3. 向量属性与几何API

API名称 作用 GIS场景
vecN.length(a) 计算向量长度(模):` a
vecN.distance(a, b) 计算两点间欧氏距离:` a-b
vecN.dot(a, b) 点积:`a·b = a
vecN.cross(out, a, b) 叉积:仅vec3支持,out = a×b(垂直于a和b的向量) 生成地形法向量、计算多边形朝向、判断点在直线哪一侧
vecN.normalize(out, a) 归一化向量:`out = a/ a
vecN.angle(a, b) 计算两向量夹角(弧度):`θ = arccos(a·b/( a

4. 插值与变换API

API名称 作用 GIS场景
vecN.lerp(out, a, b, t) 线性插值:out = a + (b-a)*tt∈[0,1] 坐标平滑过渡、动画插值、轨迹生成
vecN.slerp(out, a, b, t) 球面线性插值:仅vec3支持,平滑插值三维方向 无人机姿态过渡、相机朝向平滑旋转
vecN.transformMat4(out, a, m) 向量与4x4矩阵相乘:out = m × a 地理坐标→世界坐标/裁剪坐标转换、模型变换
vecN.transformMat3(out, a, m) 向量与3x3矩阵相乘:out = m × a 法向量变换、二维坐标旋转缩放

二、矩阵模块(mat2/mat3/mat4)

用于存储线性变换(平移、旋转、缩放、投影),mat4是WebGL/ WebGIS的核心(4x4矩阵支持齐次坐标变换)。

1. 创建与基础矩阵API

API名称 作用 示例
matN.create() 创建空的N×N矩阵,初始值为单位矩阵 const modelMat = mat4.create();
matN.identity(out) 将矩阵设置为单位矩阵(对角线为1,其余为0) mat4.identity(modelMat); // 重置变换矩阵
matN.copy(out, a) 复制矩阵aout mat4.copy(outMat, modelMat);
matN.fromTranslation(out, v) 从平移向量创建4x4矩阵 mat4.fromTranslation(out, vec3.fromValues(10,20,0)); // 平移(10,20,0)
matN.fromRotation(out, rad, axis) 从轴角创建4x4旋转矩阵 mat4.fromRotation(out, Math.PI/2, vec3.fromValues(0,1,0)); // 绕Y轴转90°
matN.fromScaling(out, v) 从缩放向量创建4x4矩阵 mat4.fromScaling(out, vec3.fromValues(2,2,2)); // 放大2倍

2. 矩阵变换API

API名称 作用 注意事项
mat4.translate(out, a, v) 平移变换:out = a × translate(v)(右乘,先应用平移) 变换顺序:缩放→旋转→平移(矩阵乘法从右到左应用)
mat4.rotate(out, a, rad, axis) 旋转变换:out = a × rotate(rad, axis) 旋转轴需归一化,否则会导致缩放错误
mat4.scale(out, a, v) 缩放变换:out = a × scale(v) 非均匀缩放会导致法向量方向错误,需用mat4.normalFromMat4修正
mat4.mul(out, a, b) 矩阵乘法:out = a × b 顺序至关重要:modelView = viewMat × modelMat(先模型变换,再视图变换)

3. 投影与视图矩阵(WebGIS核心)

API名称 作用 GIS场景示例
mat4.ortho(out, left, right, bottom, top, near, far) 正交投影矩阵 无透视效果,适合二维GIS(Mapbox) const zoom = 10; const scale = Math.pow(2, zoom); mat4.ortho(out, -width/2scale, width/2 scale, -height/2scale, height/2scale, -1, 1);
mat4.perspective(out, fovy, aspect, near, far) 透视投影矩阵 有近大远小效果,适合三维GIS(Cesium) mat4.perspective(out, Math.PI/3, window.innerWidth/window.innerHeight, 1, 1e7); // 60°视场角,10公里远裁剪面
mat4.lookAt(out, eye, center, up) 视图矩阵 相机看向目标点,模拟人眼视角 const eye = vec3.fromValues(116.4, 39.9, 1000); // 北京上空1000米const center = vec3.fromValues(116.4, 39.9, 0); // 北京地面mat4.lookAt(out, eye, center, vec3.fromValues(0,1,0)); // Y轴为上方向

4. 高级矩阵运算API

API名称 作用 GIS场景
mat4.invert(out, a) 求逆矩阵:out = a⁻¹ 世界坐标→相机坐标转换、反向变换
mat4.transpose(out, a) 转置矩阵:out[i][j] = a[j][i] 法向量矩阵计算、矩阵格式转换
mat4.normalFromMat4(out, a) 法向量矩阵:out = (a⁻¹)ᵀ(逆矩阵的转置) 模型缩放时修正法向量方向,避免光照错误
mat4.determinant(a) 计算矩阵行列式:判断矩阵是否可逆 检测变换矩阵是否合法(行列式为0则不可逆)

三、四元数模块(quat)

用于高效表示三维旋转,避免欧拉角的万向锁问题,旋转组合运算比矩阵快2-3倍,适合无人机姿态、三维模型旋转等WebGIS场景。

1. 创建与初始化API

API名称 作用 示例
quat.create() 创建空的四元数,初始值为[0,0,0,1](无旋转) const rotQuat = quat.create();
quat.fromEuler(out, x, y, z) 从欧拉角(弧度)创建四元数 x/y/z分别为绕X/Y/Z轴的旋转角度 quat.fromEuler(out, 0, Math.PI/2, 0); // 绕Y轴转90°
quat.fromAxisAngle(out, axis, rad) 从轴角创建四元数 绕axis轴旋转rad弧度 quat.fromAxisAngle(out, vec3.fromValues(0,1,0), Math.PI/2); // 同上方示例
quat.copy(out, a) 复制四元数aout quat.copy(outQuat, rotQuat);

2. 旋转运算API

API名称 作用 GIS场景
quat.mul(out, a, b) 四元数乘法:out = a × b(组合两个旋转,先应用b,再应用a) 无人机姿态组合(先俯仰,再偏航)
quat.invert(out, a) 逆四元数:out = a⁻¹(反向旋转) 无人机姿态回滚、反向旋转模型
quat.normalize(out, a) 归一化四元数:避免数值误差导致旋转错误 长时间旋转后修正四元数精度

3. 转换与插值API

API名称 作用 GIS场景
quat.toMat4(out, q) 将四元数转换为4x4旋转矩阵 用于WebGL模型变换 quat.toMat4(modelMat, rotQuat); // 旋转矩阵应用到模型
quat.lerp(out, a, b, t) 线性插值:短距离旋转平滑过渡 无人机小角度姿态调整
quat.slerp(out, a, b, t) 球面线性插值:长距离旋转平滑过渡 无方向突变 无人机大角度转向、相机朝向平滑切换
quat.getAxisAngle(outAxis, outRad, q) 从四元数提取轴角 得到旋转轴和旋转角度 调试旋转参数、显示无人机姿态信息

🚀 WebGIS专属优化实践

1. 性能优化

  • 复用目标数组 :始终复用out参数,避免频繁创建新Float32Array

    javascript 复制代码
    // 推荐写法
    const out = vec3.create();
    vec3.add(out, pos1, pos2);
    vec3.normalize(out, out);
    
    // 不推荐写法(创建2个临时数组)
    const temp = vec3.add(vec3.create(), pos1, pos2);
    const result = vec3.normalize(vec3.create(), temp);
  • 预计算静态矩阵:投影矩阵、视图矩阵等静态数据预计算并缓存,避免每一帧重复计算

  • 避免不必要的归一化:仅在向量方向变化时归一化,静态方向向量一次归一化即可

2. GIS场景最佳实践

  • 坐标转换流水线 :地理坐标→世界坐标→裁剪坐标

    javascript 复制代码
    const lngLat = vec3.fromValues(116.4, 39.9, 0);
    const worldPos = vec3.create();
    vec3.transformMat4(worldPos, lngLat, modelMat); // 地理→世界
    vec3.transformMat4(clipPos, worldPos, viewProjMat); // 世界→裁剪
  • 地形法向量计算

    javascript 复制代码
    const v1 = vec3.create();
    const v2 = vec3.create();
    vec3.sub(v1, pos2, pos1);
    vec3.sub(v2, pos3, pos1);
    vec3.cross(normal, v1, v2); // 生成法向量
    vec3.normalize(normal, normal);
  • 无人机姿态控制

    javascript 复制代码
    const pitch = quat.create();
    const yaw = quat.create();
    quat.fromEuler(pitch, Math.PI/6, 0, 0); // 俯仰30°
    quat.fromEuler(yaw, 0, Math.PI/2, 0); // 偏航90°
    const finalRot = quat.create();
    quat.mul(finalRot, yaw, pitch); // 先俯仰,再偏航
    quat.toMat4(modelMat, finalRot);

📚 快速参考表

模块 核心用途 关键API
vec3 地理坐标、法向量、方向向量 fromValuesdotcrossnormalizetransformMat4
mat4 投影、视图、模型变换矩阵 orthoperspectivelookAtmulinvertnormalFromMat4
quat 三维旋转、姿态控制 fromEulertoMat4mulslerp
相关推荐
(; ̄ェ ̄)。4 小时前
机器学习入门(九)为什么sklearn正规方程法矩阵不可逆却可以计算出结果
机器学习·矩阵·sklearn
小尧嵌入式4 小时前
【Linux开发二】数字反转|除数累加|差分数组|vector插入和访问|小数四舍五入及向上取整|矩阵逆置|基础文件IO|深入文件IO
linux·服务器·开发语言·c++·线性代数·算法·矩阵
Σίσυφος19004 小时前
视觉矩阵之 正交矩阵
人工智能·算法·矩阵
独自破碎E5 小时前
【从下至上+动态规划】矩阵的最小路径和
算法·矩阵·动态规划
52Hz11815 小时前
力扣73.矩阵置零、54.螺旋矩阵、48.旋转图像
python·算法·leetcode·矩阵
DuHz15 小时前
矩阵束法(Matrix Pencil)用于 FMCW 雷达干扰抑制:论文精读
人工智能·机器学习·矩阵
砚边数影19 小时前
AI数学基础(一):线性代数核心,向量/矩阵运算的Java实现
java·数据库·人工智能·线性代数·矩阵·ai编程·金仓数据库
ct97821 小时前
WebGL开发
前端·gis·webgl
Physicist in Geophy.1 天前
矩阵 与 算子
矩阵·算子