CannonJS 3D世界向量转模型视图矩阵的转换问题
glMatrix与CannonJS四元数旋转转换异常问题
核心问题
使用glMatrix 3.4.0处理物体位置正常,但在四元数(QUAT)与轴角/旋转矩阵(mat4)的转换上存在异常:
- 明确glMatrix采用弧度制,能正常获取CannonJS物理体的四元数数据
- 尝试所有旋转转换方式(四元数转矩阵、轴角转矩阵等)均出现问题:玩家物理体推动立方体时,立方体的旋转不会立即固定,而是随推动次数逐渐趋于固定
- 经典
mat4.rotate调用存在角度误差:90°实际显示为96°,180°、270°也有明显偏差 - 直接用
mat4.fromQuat将CannonJS四元数转为旋转矩阵完全失效
相关代码
渲染逻辑代码
mat4.identity(object.mvMatrix); this.mvPushMatrix(object.mvMatrix, this.mvMatrixStack); mat4.translate(object.mvMatrix, object.mvMatrix, object.position.worldLocation); // 从CannonJS四元数获取旋转轴与角度:local.physics.currentBody.quaternion.toAxisAngle()[0]为轴,[1]为角度 // 【经典旋转方案 - 效果有误差】 // 存在角度偏差:90°显示为96°,180°、270°也有问题 var t = vec3.fromValues(object.rotation.axis.x, object.rotation.axis.z, object.rotation.axis.y); mat4.rotate(object.mvMatrix, object.mvMatrix, object.rotation.angle, t); // 【四元数转矩阵方案 - 完全失效】 var QP = object.physics.currentBody.quaternion; var QUAT = quat.fromValues(QP.x, QP.y, QP.z, QP.w); mat4.fromQuat(object.mvMatrix, QUAT);
重写的CannonJS四元数转轴角方法
尝试重写CannonJS原生toAxisAngle方法,但不同变体仅能修复特定角度问题,无法兼顾所有情况:
// 测试重写CannonJS四元数转轴角方法 CANNON.Quaternion.prototype.toAxisAngle = function(targetAxis){ targetAxis = targetAxis || new CANNON.Vec3(); if (this.w > 1) this.normalize(); // 若w>1,acos和sqrt会出错,归一化可避免该问题 var angle = 2 * Math.acos(this.w); var s = Math.sqrt(1 - this.w * this.w); // 假设四元数已归一化,w<1,因此值恒正 if (s < 0.001) { // 避免除零,此时轴方向理论上不影响结果 // 变体I:修复90°旋转问题,但180°会出现~30°偏差 targetAxis.x = 0; targetAxis.y = 0; targetAxis.z = 1; // 变体II:修复180°旋转问题,但90°会出错 // targetAxis.x = 1; // targetAxis.y = 0; // targetAxis.z = 0; // 原逻辑: // targetAxis.x = this.x; // targetAxis.y = this.y; // targetAxis.z = this.z; } else { targetAxis.x = this.x / s; // 归一化旋转轴 targetAxis.y = this.y / s; targetAxis.z = this.z / s; } return [targetAxis, angle]; };
问题效果截图
- 四元数转矩阵失效时的异常效果:

- 经典旋转方案的误差效果:

项目背景
项目基于matrix-engine,可通过FPSSHOOTER示例复现问题。
内容的提问来源于stack exchange,提问作者Nikola Lukic
相关产品推荐
相关产品推荐

