如何从JavaScript的4x4相机变换矩阵提取x/y/z轴弧度制旋转值
从4x4相机变换矩阵提取弧度制欧拉角方案
你提到的world to obj矩阵即视图矩阵,作用是将世界坐标系下的坐标转换到相机局部坐标系,其左上角3×3子矩阵存储了旋转信息(无缩放前提下)。提取欧拉角前需要先确认两个前提:
- 矩阵的存储顺序(WebGL/Three.js等常用框架默认是列优先存储)
- 矩阵生成时使用的欧拉角旋转顺序,以下示例默认使用相机场景常用的
Y-X-Z(偏航-俯仰-滚转)顺序,如果你用的是其他顺序需要调整计算逻辑。
实现代码(JavaScript)
假设输入矩阵是长度为16的列优先数组,和gl-matrix、Three.js的Matrix4存储格式兼容:
function extractEulerFromViewMatrix(mat) { // 提取3x3旋转矩阵分量(列优先) const m11 = mat[0], m12 = mat[4], m13 = mat[8]; const m21 = mat[1], m22 = mat[5], m23 = mat[9]; const m31 = mat[2], m32 = mat[6], m33 = mat[10]; let x, y, z; // 计算俯仰角(X轴旋转) const sinX = -m23; if (Math.abs(sinX) >= 1) { // 处理万向锁特殊情况 x = sinX > 0 ? Math.PI / 2 : -Math.PI / 2; // 此时偏航和滚转耦合,默认将滚转设为0计算偏航 y = Math.atan2(-m31, m11); z = 0; } else { x = Math.asin(sinX); y = Math.atan2(m13, m33); z = Math.atan2(m21, m22); } // 返回弧度制欧拉角,顺序X、Y、Z return { x, y, z }; }
注意事项
- 如果你的矩阵存在缩放,需要先对3x3子矩阵的每一列做归一化处理,再代入上述公式计算,否则旋转值会有偏差
- 如果你的矩阵是行优先存储,需要把上述代码中分量的行列索引互换,例如m12对应
mat[1],m21对应mat[4]以此类推 - 欧拉角存在天然的万向锁缺陷,如果你需要无歧义的旋转表示,建议提取四元数代替欧拉角
参考效果
无旋转状态下的相机变换效果:
各轴施加1弧度旋转+轨道运动的效果:
内容的提问来源于stack exchange,提问作者c.hum
相关产品推荐
相关产品推荐

