Cesium 矩阵系统详解

🧮 Cesium 矩阵系统详解:Matrix3 与 Matrix4 核心 API 全指南

矩阵是 Cesium 中三维变换的数学基础,Matrix3 (3×3 矩阵)和 Matrix4(4×4 矩阵)分别针对不同的变换场景设计。本文从定义、核心 API、参数、示例、场景、注意事项六个维度,全面解析 Cesium 矩阵系统的使用。


一、Matrix3 深度解析

1. 定义与核心特性

  • 数学定义 :3×3 列主序矩阵,存储顺序为 [m00, m10, m20, m01, m11, m21, m02, m12, m22](列优先,与 WebGL 存储规范一致)。
  • 核心用途
    • 2D 仿射变换(平移、旋转、缩放);
    • 3D 空间旋转(无平移分量,避免冗余计算);
    • 法线变换(逆转置矩阵是法线变换的标准方式,Matrix3 更紧凑)。
  • 优势:比 Matrix4 更轻量化,旋转/法线变换计算效率更高。

2. 常见 API 详解

(1)Matrix3.IDENTITY - 单位矩阵
  • 参数:无(只读常量)

  • 用途:作为变换的初始状态(无旋转、无缩放)。

  • 示例

    javascript 复制代码
    const identityMatrix = Cesium.Matrix3.IDENTITY;
    console.log(identityMatrix); // 输出单位矩阵
  • 使用场景:重置变换、初始化矩阵变量。

  • 注意事项

    • 该矩阵是只读的,不能直接修改,需修改时使用 Matrix3.clone() 克隆后再操作。
(2)Matrix3.fromRotationX/Y/Z(angle) - 轴旋转矩阵
  • 参数angle(旋转角度,单位:弧度

  • 用途:创建绕 X/Y/Z 轴旋转的纯旋转矩阵。

  • 示例

    javascript 复制代码
    // 绕 Y 轴旋转 90 度(转弧度)
    const rotationMatrix = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(90));
  • 使用场景:3D 模型的单轴旋转、相机姿态调整。

  • 注意事项

    • 角度必须转成弧度,使用 Cesium.Math.toRadians(degrees) 转换;
    • 旋转是相对于笛卡尔坐标系原点的,若需绕模型自身中心旋转,需先平移到原点再旋转。
(3)Matrix3.fromQuaternion(quaternion, result) - 四元数转旋转矩阵
  • 参数

    • quaternionCesium.Quaternion 对象(归一化的四元数);
    • result(可选):存储结果的 Matrix3,避免创建新对象。
  • 用途:将四元数转换为旋转矩阵(四元数避免万向锁,适合平滑旋转)。

  • 示例

    javascript 复制代码
    // 创建绕 (1,1,0) 轴旋转 45 度的四元数
    const quaternion = Cesium.Quaternion.fromAxisAngle(
      Cesium.Cartesian3.normalize(Cesium.Cartesian3.fromElements(1,1,0), new Cesium.Cartesian3()),
      Cesium.Math.toRadians(45)
    );
    // 转成 Matrix3
    const rotationMatrix = Cesium.Matrix3.fromQuaternion(quaternion);
  • 使用场景:3D 模型的平滑旋转、相机姿态插值。

  • 注意事项

    • 输入的四元数必须归一化,否则旋转会产生缩放畸变。
(4)Matrix3.fromScale(scale, result) - 缩放矩阵
  • 参数

    • scaleCesium.Cartesian2(2D 缩放)或 Cesium.Cartesian3(3D 缩放);
    • result(可选):存储结果的 Matrix3。
  • 用途:创建 2D/3D 缩放矩阵。

  • 示例

    javascript 复制代码
    // 2D 缩放:X/Y 轴各放大 2 倍
    const scaleMatrix = Cesium.Matrix3.fromScale(Cesium.Cartesian2.fromElements(2, 2));
  • 使用场景:2D 图形缩放、3D 模型的非等比缩放。

  • 注意事项

    • 缩放因子为 0 会导致矩阵奇异(无法求逆),避免使用 0 值;
    • 3D 缩放时 Z 分量不影响 2D 变换,可设为 1。
(5)Matrix3.multiply(left, right, result) - 矩阵乘法
  • 参数

    • left:左矩阵;
    • right:右矩阵;
    • result(可选):存储乘积的 Matrix3。
  • 用途:组合多个变换(如缩放 + 旋转)。

  • 示例

    javascript 复制代码
    // 先缩放 2 倍,再绕 Y 轴旋转 90 度
    const scaleMatrix = Cesium.Matrix3.fromScale(Cesium.Cartesian3.fromElements(2,2,2));
    const rotationMatrix = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(90));
    // 乘法顺序:left * right → 先应用 right 的变换,再应用 left 的变换
    const combinedMatrix = Cesium.Matrix3.multiply(rotationMatrix, scaleMatrix, new Cesium.Matrix3());
  • 使用场景:组合多个基础变换(缩放→旋转→平移,Matrix3 仅支持缩放+旋转)。

  • 注意事项

    • 列主序矩阵的乘法顺序是右乘先执行 ,即 A*B 表示先应用 B 的变换,再应用 A 的变换;
    • 矩阵乘法不满足交换律,顺序错误会导致变换结果不符合预期。
(6)Matrix3.inverse(matrix, result) - 逆矩阵
  • 参数

    • matrix:输入矩阵;
    • result(可选):存储逆矩阵的 Matrix3。
  • 用途:还原变换(如将模型坐标转换为世界坐标的逆操作)。

  • 示例

    javascript 复制代码
    const rotationMatrix = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(90));
    // 旋转矩阵是正交矩阵,逆矩阵等于转置矩阵
    const inverseMatrix = Cesium.Matrix3.inverse(rotationMatrix, new Cesium.Matrix3());
  • 使用场景:逆变换计算、法线变换(需逆转置矩阵)。

  • 注意事项

    • 奇异矩阵(行列式为 0,如缩放因子为 0 的矩阵)无法求逆,会返回 undefined
    • 旋转矩阵是正交矩阵,其逆矩阵等于转置矩阵,可使用 Matrix3.transpose() 替代 inverse() 提升性能。
(7)Matrix3.transpose(matrix, result) - 转置矩阵
  • 参数

    • matrix:输入矩阵;
    • result(可选):存储转置矩阵的 Matrix3。
  • 用途:法线变换(模型矩阵的逆转置矩阵用于法线向量的正确变换)、矩阵数据格式转换。

  • 示例

    javascript 复制代码
    const modelMatrix3 = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(90));
    // 转置旋转矩阵(正交矩阵的逆等于转置)
    const transposedMatrix = Cesium.Matrix3.transpose(modelMatrix3, new Cesium.Matrix3());
  • 使用场景:3D 模型的法线变换、WebGL 着色器矩阵传递。

  • 注意事项

    • 转置仅交换矩阵的行和列,不改变矩阵的行列式值。

二、Matrix4 深度解析

1. 定义与核心特性

  • 数学定义 :4×4 列主序矩阵,存储顺序为 [m00, m10, m20, m30, m01, m11, m21, m31, m02, m12, m22, m32, m03, m13, m23, m33],通过齐次坐标(w 分量)支持平移变换。
  • 核心用途
    • 3D 全量仿射变换(平移、旋转、缩放的组合);
    • 模型矩阵、视图矩阵、投影矩阵的核心表示;
    • 坐标空间转换(如世界坐标→相机坐标→裁剪坐标)。
  • 优势:用单个矩阵表示所有 3D 变换,便于组合、传递给 WebGL 着色器。

2. 常见 API 详解

(1)Matrix4.IDENTITY - 单位矩阵
  • 参数:无(只读常量)

  • 用途:初始化 3D 变换的初始状态(无平移、无旋转、无缩放)。

  • 示例

    javascript 复制代码
    const modelMatrix = Cesium.Matrix4.clone(Cesium.Matrix4.IDENTITY); // 克隆后可修改
  • 使用场景:3D 模型的初始变换、矩阵重置。

  • 注意事项

    • 内置 IDENTITY 是只读的,需修改时必须先克隆。
(2)Matrix4.fromTranslation(translation, result) - 平移矩阵
  • 参数

    • translationCesium.Cartesian3(X/Y/Z 轴的平移量,单位:米);
    • result(可选):存储结果的 Matrix4。
  • 用途:创建仅包含平移的矩阵。

  • 示例

    javascript 复制代码
    // 沿 X 轴平移 100 米,Y 轴平移 50 米
    const translation = Cesium.Cartesian3.fromElements(100, 50, 0);
    const translateMatrix = Cesium.Matrix4.fromTranslation(translation);
  • 使用场景:3D 模型的位置调整、相机平移。

  • 注意事项

    • 平移量的单位是米(Cesium 笛卡尔坐标系的默认单位)。
(3)Matrix4.fromRotationX/Y/Z(angle, result) - 轴旋转矩阵
  • 参数

    • angle:旋转角度(弧度);
    • result(可选):存储结果的 Matrix4。
  • 用途:创建绕 X/Y/Z 轴旋转的 4×4 矩阵(包含单位平移分量)。

  • 示例

    javascript 复制代码
    // 绕 Z 轴旋转 45 度
    const rotateMatrix = Cesium.Matrix4.fromRotationZ(Cesium.Math.toRadians(45));
  • 使用场景:3D 模型的单轴旋转、相机姿态调整。

  • 注意事项

    • 旋转是相对于笛卡尔坐标系原点的,若需绕模型自身中心旋转,需先平移到原点再旋转。
(4)Matrix4.fromScale(scale, result) - 缩放矩阵
  • 参数

    • scaleCesium.Cartesian3(X/Y/Z 轴的缩放因子);
    • result(可选):存储结果的 Matrix4。
  • 用途:创建 3D 缩放矩阵。

  • 示例

    javascript 复制代码
    // X/Y/Z 轴各放大 2 倍
    const scaleMatrix = Cesium.Matrix4.fromScale(Cesium.Cartesian3.fromElements(2, 2, 2));
  • 使用场景:3D 模型的等比/非等比缩放。

  • 注意事项

    • 非等比缩放会导致模型材质拉伸,需确保 3D 模型的 UV 坐标适配。
(5)Matrix4.fromRotationTranslation(rotation, translation, result) - 旋转+平移组合矩阵
  • 参数

    • rotationCesium.Matrix3(旋转矩阵);
    • translationCesium.Cartesian3(平移向量);
    • result(可选):存储结果的 Matrix4。
  • 用途:组合旋转和平移变换,是 3D 模型定位的核心 API。

  • 示例

    javascript 复制代码
    // 绕 Y 轴旋转 90 度,再平移到 (100,50,0)
    const rotationMatrix = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(90));
    const translation = Cesium.Cartesian3.fromElements(100, 50, 0);
    const modelMatrix = Cesium.Matrix4.fromRotationTranslation(rotationMatrix, translation);
  • 使用场景:3D 模型的初始定位、3DTiles 模型的变换。

  • 注意事项

    • 变换顺序:先旋转,再平移(符合列主序乘法规则)。
(6)Matrix4.multiply(left, right, result) - 矩阵乘法
  • 参数

    • left:左矩阵;
    • right:右矩阵;
    • result(可选):存储乘积的 Matrix4。
  • 用途:组合多个 3D 变换(如缩放+旋转+平移)。

  • 示例

    javascript 复制代码
    // 组合变换:缩放 2 倍 → 绕 Y 轴旋转 90 度 → 平移 (100,50,0)
    const scaleMatrix = Cesium.Matrix4.fromScale(Cesium.Cartesian3.fromElements(2,2,2));
    const rotateMatrix = Cesium.Matrix4.fromRotationY(Cesium.Math.toRadians(90));
    const translateMatrix = Cesium.Matrix4.fromTranslation(Cesium.Cartesian3.fromElements(100,50,0));
    
    // 乘法顺序:translate * rotate * scale → 先缩放,再旋转,最后平移
    const combinedMatrix = Cesium.Matrix4.multiply(
      translateMatrix,
      Cesium.Matrix4.multiply(rotateMatrix, scaleMatrix, new Cesium.Matrix4()),
      new Cesium.Matrix4()
    );
  • 使用场景:复杂 3D 变换的组合、坐标空间转换链。

  • 注意事项

    • 列主序矩阵的乘法顺序是右乘先执行 ,即 A*B*C 表示先应用 C,再应用 B,最后应用 A;
    • 避免频繁创建新矩阵,复用 result 参数可提升性能。
(7)Matrix4.getTranslation(matrix, result) - 提取平移分量
  • 参数

    • matrix:输入 Matrix4;
    • result(可选):存储平移向量的 Cesium.Cartesian3
  • 用途:从模型矩阵中提取当前的平移位置。

  • 示例

    javascript 复制代码
    const modelMatrix = Cesium.Matrix4.fromTranslation(Cesium.Cartesian3.fromElements(100,50,0));
    const translation = Cesium.Matrix4.getTranslation(modelMatrix, new Cesium.Cartesian3());
    console.log(translation); // 输出 Cartesian3(100,50,0)
  • 使用场景:动态调整模型位置、获取模型的世界坐标。

  • 注意事项

    • 提取的平移向量是笛卡尔坐标系下的米单位。
(8)Matrix4.setTranslation(matrix, translation, result) - 设置平移分量
  • 参数

    • matrix:输入 Matrix4;
    • translation:新的平移向量;
    • result(可选):存储修改后的 Matrix4。
  • 用途:在不修改旋转/缩放的前提下,调整模型的位置。

  • 示例

    javascript 复制代码
    const modelMatrix = Cesium.Matrix4.fromRotationY(Cesium.Math.toRadians(90));
    // 设置平移到 (100,50,0),保留旋转分量
    const updatedMatrix = Cesium.Matrix4.setTranslation(modelMatrix, Cesium.Cartesian3.fromElements(100,50,0), new Cesium.Matrix4());
  • 使用场景:动态移动 3D 模型、相机位置调整。

  • 注意事项

    • 若不指定 result,会直接修改输入矩阵(引用类型),需注意副作用。
(9)Matrix4.toArray(matrix, result) - 矩阵转列主序数组
  • 参数

    • matrix:输入 Matrix4;
    • result(可选):存储数组的 Float64Array
  • 用途:将矩阵转换为 WebGL 着色器支持的列主序数组,传递给 uniform 变量。

  • 示例

    javascript 复制代码
    const modelMatrix = Cesium.Matrix4.IDENTITY;
    const matrixArray = Cesium.Matrix4.toArray(modelMatrix);
    // 传递给 WebGL 着色器
    gl.uniformMatrix4fv(modelMatrixLocation, false, matrixArray);
  • 使用场景:自定义 WebGL 着色器的矩阵传递、与外部渲染引擎交互。

  • 注意事项

    • WebGL 要求矩阵是列主序的,Cesium 的 toArray() 直接输出符合要求的数组,无需转置。

三、Matrix3 vs Matrix4 对比与适用场景

特性 Matrix3 Matrix4
维度 3×3 4×4
支持的变换 旋转、缩放、2D 平移 平移、旋转、缩放(全 3D 变换)
存储效率 9 个浮点数(更轻量化) 16 个浮点数(更灵活)
核心场景 2D 变换、3D 旋转、法线变换 3D 全量变换、模型/视图/投影矩阵
性能 计算更快(适合高频变换) 计算稍慢(但功能更全)

四、通用注意事项

1. 列主序存储

Cesium 的矩阵均为列主序,与 WebGL 规范一致,避免了矩阵转置的性能开销。在手动创建矩阵时,需注意数组顺序为列优先:

javascript 复制代码
// 手动创建平移矩阵:X 轴平移 100 米
const translateMatrixArray = [
  1, 0, 0, 0,  // 第一列
  0, 1, 0, 0,  // 第二列
  0, 0, 1, 0,  // 第三列
  100, 0, 0, 1 // 第四列(平移分量)
];
const translateMatrix = Cesium.Matrix4.fromArray(translateMatrixArray);

2. 矩阵乘法顺序

列主序矩阵的乘法顺序是右乘先执行 ,即 A*B*C 表示变换顺序为 C → B → A,这与直觉上的"先做 C,再做 B,最后做 A"一致。

3. 性能优化

  • 复用矩阵对象 :在循环或高频变换中,提前创建 result 参数并复用,避免频繁创建新矩阵导致垃圾回收;
  • 优先使用内置 API:Cesium 的矩阵 API 经过 GPU 优化,比手动实现矩阵运算快 5-10 倍;
  • 避免奇异矩阵:不要使用缩放因子为 0 的矩阵,否则无法求逆,会导致变换异常。

4. 坐标空间一致性

Cesium 中所有矩阵变换默认基于笛卡尔坐标系(米单位) ,与地理坐标系(经纬度)的转换需通过 Cesium.Transforms.eastNorthUpToFixedFrame() 等 API 实现。


通过掌握 Matrix3 和 Matrix4 的核心 API,你可以灵活实现 Cesium 中所有的三维变换需求,从简单的模型平移到复杂的坐标空间转换,为 WebGIS 三维可视化提供坚实的数学基础。

相关推荐
两点王爷2 小时前
KML文件格式和支持添加的内容
gis
小陈phd2 小时前
langGraph从入门到精通(十一)——基于langgraph构建复杂工具应用的ReAct自治代理
前端·人工智能·react.js·自然语言处理
我要敲一万行2 小时前
前端面试erp项目常问问题
前端·面试
2 小时前
ubuntu 通过ros-noetic获取RTK模块的nmea格式数据
java·前端·javascript
&活在当下&2 小时前
uniapp 选择城市区号索引列表实现
前端·uni-app
阿珊和她的猫2 小时前
简述 React 的虚拟 DOM 机制
前端·react.js·前端框架
梵得儿SHI2 小时前
Vue 高级特性:混入(Mixin)使用场景与问题、Vue3 组合式 API 替代方案精讲
前端·javascript·vue.js·组合式api·参数传递·mixin机制·显式调用
qq_336313932 小时前
javaweb-HTML和CSS(2)
前端·css·html
Sapphire~2 小时前
【模板】Jinja风格 Ruby风格
前端·后端