矩阵变换

Three.js 使用 `matrices`(矩阵)来表示 3D 变换:平移(position)、旋转和缩放。 每个 `Object3D` 实例都包含一个 `matrix`,用于存储该对象的位置、旋转与缩放。 本页介绍如何更新对象的变换。

便捷属性与 `matrixAutoUpdate`

更新对象变换有两种方式:

  1. 修改对象的 `position`、`quaternion`、`scale` 属性, 由 three.js 根据这些属性重新计算矩阵:
    object.position.copy( start_position );
    object.quaternion.copy( quaternion );
    
    默认情况下 `matrixAutoUpdate = true`,矩阵会自动重算。 如果对象是静态的,或你希望手动控制重算时机,可将其设为 `false` 以获得更好性能:
    object.matrixAutoUpdate = false;
    
    修改属性后,再手动更新矩阵:
    object.updateMatrix();
    
  2. 直接修改对象矩阵。`Matrix4` 提供了多种矩阵修改方法:
    object.matrix.setRotationFromQuaternion( quaternion );
    object.matrix.setPosition( start_position );
    object.matrixAutoUpdate = false;
    
    注意这种方式下 `matrixAutoUpdate` 必须设为 `false`, 并且要确保不要调用 `updateMatrix`。 调用 `updateMatrix` 会根据 `position`、`scale` 等重新计算矩阵, 从而覆盖你手动写入的矩阵内容。

对象矩阵与世界矩阵

对象的 `matrix` 存储的是相对于父对象的局部变换; 若要获取对象在世界坐标中的变换,需要访问对象的世界矩阵。

当父对象或子对象变换发生变化时,可以调用 `object.updateMatrixWorld()`, 触发子对象世界矩阵更新。

也可以通过 `applyMatrix4()` 对对象施加变换。注意:该方法底层依赖 `Matrix4.decompose()`,并非所有矩阵都能这样分解。 例如父对象存在非均匀缩放时,子对象世界矩阵可能无法正确分解, 此时该方法并不适用。

旋转与四元数

Three.js 提供两种 3D 旋转表示:欧拉角与四元数,并支持相互转换。 欧拉角会受到“万向节锁(gimbal lock)”问题影响, 在某些姿态下会丢失一个自由度(导致无法绕某一轴旋转)。 因此,对象旋转在内部始终存储为四元数。

旧版本库曾有 `useQuaternion` 属性,设为 false 时会用欧拉角计算对象矩阵。 这种做法已废弃。现在应使用 `object.setRotationFromEuler()`, 它会同步更新四元数。