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

C++自定义四元数实现Y/Z轴旋转正常 加入X轴后模型异常拉伸

四元数旋转拉伸问题修复方案

核心问题点

  • 旋转轴未归一化:生成旋转四元数的前提是输入的旋转轴为单位向量,你传入的(1,1,0)、(1,0,1)这类组合轴的模长为√2≠1,生成的四元数模长不等于1,不是单位四元数,最终转换得到的矩阵不是正交矩阵,会引入非预期的缩放效果,也就是你看到的拉伸。你之前测试的单轴、(0,1,1)组合轴能正常工作只是巧合,要么是测试角度过小误差不明显,要么是测试时无意中传入了归一化后的轴参数。
  • 四元数更新后未主动归一化:你仅在四元数模长偏离1超过阈值时才做归一化,且乘法运算后没有主动触发归一化,浮点误差加上非单位四元数的初始偏差会持续累积,加重拉伸问题。
  • 额外优化提示:你rotate函数的第一个参数名用w容易和四元数的实部w混淆,建议改名为angle提升代码可读性。

修复代码

1. 修正rotate函数,增加轴归一化逻辑

Quaternion rotate(float angle, float x, float y, float z) {
    Quaternion n;
    // 先对旋转轴做归一化
    float axis_len = sqrtf(x*x + y*y + z*z);
    // 避免轴长度为0导致的除零异常
    if (axis_len < 1e-6f) {
        n.w = 1.0f;
        n.x = n.y = n.z = 0.0f;
        return n;
    }
    x /= axis_len;
    y /= axis_len;
    z /= axis_len;

    float half_angle = angle / 2.0f;
    float sin_half = sinf(half_angle);
    n.w = cosf(half_angle);
    n.x = x * sin_half;
    n.y = y * sin_half;
    n.z = z * sin_half; 

    return n;
}

2. 优化归一化函数,每次更新主动调用

Quaternion normalize(Quaternion n) {
    double total = (double)n.w*n.w + (double)n.x*n.x + (double)n.y*n.y + (double)n.z*n.z;
    // 模长接近0时返回单位四元数避免异常
    if (total < 1e-12) {
        Quaternion unit = {1.0f, 0, 0, 0};
        return unit;
    }
    float inv_len = (float)(1.0 / sqrt(total));
    n.w *= inv_len;
    n.x *= inv_len;
    n.y *= inv_len;
    n.z *= inv_len;
    return n;
}

3. 修正旋转更新逻辑

obj.rotation = normalize(rotate(angle, x_axis, y_axis, z_axis) * obj.rotation);

你现有的四元数乘法、四元数转矩阵的公式逻辑是正确的,无需修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 16:24:02