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

3x3矩阵变换链中非均匀缩放引发的旋转异常问题求助

问题根源:变换矩阵的乘法顺序完全错误

这绝对是变换矩阵的顺序搞反了导致的——不管是局部变换的内部顺序,还是和父变换的组合顺序,这就是非均匀缩放时出现异常的核心原因。我来给你拆解清楚:

1. 局部变换的顺序完全颠倒了

你当前的局部变换顺序是 Rotate → Scale → Translate,但正确的顺序应该是 Scale → Rotate → Translate(对应矩阵组合为 Translate * Rotate * Scale)。

为什么?因为矩阵乘法是右结合的:当你用变换矩阵乘以顶点时,v' = M * v,矩阵最右侧的变换会先被应用。你现在的代码实际执行的顺序是「先平移,再缩放,再旋转」,这完全不符合我们对局部变换的预期——尤其是旋转后再做非均匀缩放,会让物体的缩放方向跟着旋转后的轴走,导致后续子物体继承的坐标系被扭曲,最终出现不对齐、尺寸异常的问题。

2. 父变换与局部变换的组合顺序也错了

你现在是把局部变换结果乘以父的全局变换:output *= parent->getGlobalTransform(),这等价于 output = localTransform * parentTransform。但正确的逻辑应该是先应用父变换,再应用当前物体的局部变换,也就是 output = parentTransform * localTransform。

原因很简单:父变换定义了当前物体所在的坐标系,我们需要先把物体的局部坐标转换到父坐标系中,再应用自己的缩放、旋转、平移。

修正后的代码

把这两个顺序都改过来,你的问题应该就能解决:

maths::mat3 DisplayObject::getGlobalTransform() { 
    // 构建正确的局部变换:先缩放,再旋转,最后平移(矩阵组合为 Translate * Rotate * Scale)
    maths::mat3 local = maths::mat3::Translate(position);
    local *= maths::mat3::Rotate(rotation);
    local *= maths::mat3::Scale(scale);

    if(parent != nullptr){ 
        // 父变换在前,局部变换在后:先进入父坐标系,再应用自身变换
        return parent->getGlobalTransform() * local; 
    } 
    return local; 
}

额外说明

当父物体有非均匀缩放时,子物体的旋转会受到父坐标系扭曲的影响——这时候你用 GetRotation() 和 GetScale() 从组合矩阵中提取的数值可能会不准确,因为这些方法只适用于均匀缩放的场景。如果后续需要准确提取局部旋转/缩放,你可能需要单独存储每个物体的局部变换参数(而不是从组合矩阵中反推),这样在继承的时候可以基于父的参数重新计算,而不是依赖矩阵分解。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:04:10