You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

3D四元数旋转不符合预期的实现问题咨询

三维旋转与四元数实践(基于GLM/Vulkan)

核心结论:用单个四元数维护对象最终旋转状态

不需要拆分多个四元数分别管理旋转,单个四元数完全可以承载对象的最终朝向。你当前的核心问题是没有区分旋转的空间(世界空间/对象局部空间),而非四元数的存储方式。

你的代码问题分析

先看你现有的rn_object_rotate方法:

void rn_object_rotate(void* o, float x, float y, float z, float degrees) {
    Object object = (Object) o;
    versor q;
    glm_quat(q, glm_rad(degrees), x, y, z);
    glm_quat_mul(object->node->rotation, q, object->node->rotation);
}

GLM的glm_quat_mul(a, b, c)等价于c = a * b,四元数乘法顺序代表变换的执行顺序:

  • 左乘(new_q = q * current_q):新旋转是世界空间下的变换
  • 右乘(new_q = current_q * q):新旋转是对象局部空间下的变换

你当前的代码用了左乘,当你传入世界Y轴[0,1,0]时,实际是让对象在世界空间下绕Y轴旋转——但如果对象已经有局部旋转,你误以为的"世界Y轴旋转"会和原有旋转叠加,导致看起来像绕倾斜轴转动。

另外,你的rn_object_set_rotation方法可以简化:先设单位四元数再乘q,等价于直接赋值q,没必要多做一次乘法。

修正后的旋转实现

设置旋转(直接覆盖当前状态,轴为世界空间)

void rn_object_set_rotation(void* o, float x, float y, float z, float degrees) {
    Object object = (Object) o;
    versor q;
    // 直接构造目标四元数并覆盖当前旋转
    glm_quat(q, glm_rad(degrees), x, y, z);
    glm_quat_copy(object->node->rotation, q);
}

叠加世界空间旋转

用于绕固定的世界轴旋转(比如鼠标左右拖动时绕世界Y轴转):

void rn_object_rotate_world(void* o, float x, float y, float z, float degrees) {
    Object object = (Object) o;
    versor q, temp;
    glm_quat(q, glm_rad(degrees), x, y, z);
    // 左乘:先应用对象原有旋转,再叠加世界空间的新旋转
    glm_quat_mul(temp, q, object->node->rotation);
    glm_quat_copy(object->node->rotation, temp);
}

叠加局部空间旋转

用于绕随对象转动的局部轴旋转(比如鼠标上下拖动时绕对象自身X轴转):

void rn_object_rotate_local(void* o, float x, float y, float z, float degrees) {
    Object object = (Object) o;
    versor q, temp;
    glm_quat(q, glm_rad(degrees), x, y, z);
    // 右乘:先应用对象原有旋转,再叠加局部空间的新旋转
    glm_quat_mul(temp, object->node->rotation, q);
    glm_quat_copy(object->node->rotation, temp);
}

针对你的需求的使用方式

  • 鼠标左右拖动:调用rn_object_rotate_world(o, 0.0f, 1.0f, 0.0f, delta_deg),实现绕世界Y轴旋转
  • 鼠标上下拖动:调用rn_object_rotate_local(o, 1.0f, 0.0f, 0.0f, delta_deg),实现绕对象局部X轴旋转(该轴会随对象绕世界Y轴的旋转同步转动,且始终垂直于世界Y轴)

额外注意事项

  • 确保传入的旋转轴是归一化的单位向量,GLM的glm_quat要求轴向量单位化,否则会导致旋转异常
  • 多次四元数乘法后可能出现精度损失,可定期调用glm_quat_normalize(object->node->rotation, object->node->rotation)做归一化处理

内容的提问来源于stack exchange,提问作者Plegeus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 22:37:49