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

如何修正满足A*C=B的4x4矩阵桥矩阵C的C++函数

修复满足A*C=B的矩阵求解函数符号错误问题

我需要实现一个C++函数,给定4x4矩阵A和B,生成满足A*C=B的矩阵C。目前写出的代码数值正确,但符号存在问题,输出结果不符合预期。

现有实现代码

Matrix Matrix::GetBridge(Matrix* theOther)
{
    Matrix aIMat=GetInvert();
    if (!theOther) return Identity();

    Matrix aResult=*theOther;
    aResult*=aIMat;
    return aResult;
}

输出结果

Matrix A: 1,0,0,0
          0,0.9063,0.4226,0
          0,-0.4226,0.9063,0
          0,0,0,1

Matrix B: 0,0,-1,0
          0,1,0,0
          1,0,0,0
          0,0,0,1

Matrix C: 0,-0.4226,-0.9063,0
          0,0.9063,-0.4226,0
          1,0,0,0
          0,0,0,1

Matrix B * C:  -1,-0,-0,0
               0,0.9063,-0.4226,0
               0,-0.4226,-0.9063,0
               0,0,0,1

可以看到B*C的数值与A一致,但符号不符,且不符合A*C=B的预期。

测试代码

Matrix aM1;aM1.RotateX(25);
Matrix aM2;aM2.RotateY(90);
Matrix aM3=aM1.GetBridge(&aM2);

aM1.Debug("$Matrix A:");
aM2.Debug("$Matrix B:");
aM3.Debug("$Matrix C:");

Matrix aM4=aM2;
aM4*=aM3;
aM4.Debug("!Matrix B * C:");

逆矩阵实现(供排查)

Matrix& Matrix::Invert()
{
    float aInv[16];

    aInv[0]=mData.mm[5]*mData.mm[10]*mData.mm[15]-mData.mm[5]*mData.mm[11]*mData.mm[14]-mData.mm[9]*mData.mm[6]*mData.mm[15]+mData.mm[9]*mData.mm[7]*mData.mm[14]+mData.mm[13]*mData.mm[6]*mData.mm[11]-mData.mm[13]*mData.mm[7]*mData.mm[10];
    aInv[4]=-mData.mm[4]*mData.mm[10]*mData.mm[15]+mData.mm[4]*mData.mm[11]*mData.mm[14]+mData.mm[8]*mData.mm[6]*mData.mm[15]-mData.mm[8]*mData.mm[7]*mData.mm[14]-mData.mm[12]*mData.mm[6]*mData.mm[11]+mData.mm[12]*mData.mm[7]*mData.mm[10];
    aInv[8]=mData.mm[4]*mData.mm[9]*mData.mm[15]-mData.mm[4]*mData.mm[11]*mData.mm[13]-mData.mm[8]*mData.mm[5]*mData.mm[15]+mData.mm[8]*mData.mm[7]*mData.mm[13]+mData.mm[12]*mData.mm[5]*mData.mm[11]-mData.mm[12]*mData.mm[7]*mData.mm[9];
    aInv[12]=-mData.mm[4]*mData.mm[9]*mData.mm[14]+mData.mm[4]*mData.mm[10]*mData.mm[13]+mData.mm[8]*mData.mm[5]*mData.mm[14]-mData.mm[8]*mData.mm[6]*mData.mm[13]-mData.mm[12]*mData.mm[5]*mData.mm[10]+mData.mm[12]*mData.mm[6]*mData.mm[9];
    aInv[1]=-mData.mm[1]*mData.mm[10]*mData.mm[15]+mData.mm[1]*mData.mm[11]*mData.mm[14]+mData.mm[9]*mData.mm[2]*mData.mm[15]-mData.mm[9]*mData.mm[3]*mData.mm[14]-mData.mm[13]*mData.mm[2]*mData.mm[11]+mData.mm[13]*mData.mm[3]*mData.mm[10];
    aInv[5]=mData.mm[0]*mData.mm[10]*mData.mm[15]-mData.mm[0]*mData.mm[11]*mData.mm[14]-mData.mm[8]*mData.mm[2]*mData.mm[15]+mData.mm[8]*mData.mm[3]*mData.mm[14]+mData.mm[12]*mData.mm[2]*mData.mm[11]-mData.mm[12]*mData.mm[3]*mData.mm[10];
    aInv[9]=-mData.mm[0]*mData.mm[9]*mData.mm[15]+mData.mm[0]*mData.mm[11]*mData.mm[13]+mData.mm[8]*mData.mm[1]*mData.mm[15]-mData.mm[8]*mData.mm[3]*mData.mm[13]-mData.mm[12]*mData.mm[1]*mData.mm[11]+mData.mm[12]*mData.mm[3]*mData.mm[9];
    aInv[13]=mData.mm[0]*mData.mm[9]*mData.mm[14]-mData.mm[0]*mData.mm[10]*mData.mm[13]-mData.mm[8]*mData.mm[1]*mData.mm[14]+mData.mm[8]*mData.mm[2]*mData.mm[13]+mData.mm[12]*mData.mm[1]*mData.mm[10]-mData.mm[12]*mData.mm[2]*mData.mm[9];
    aInv[2]=mData.mm[1]*mData.mm[6]*mData.mm[15]-mData.mm[1]*mData.mm[7]*mData.mm[14]-mData.mm[5]*mData.mm[2]*mData.mm[15]+mData.mm[5]*mData.mm[3]*mData.mm[14]+mData.mm[13]*mData.mm[2]*mData.mm[7]-mData.mm[13]*mData.mm[3]*mData.mm[6];
    aInv[6]=-mData.mm[0]*mData.mm[6]*mData.mm[15]+mData.mm[0]*mData.mm[7]*mData.mm[14]+mData.mm[4]*mData.mm[2]*mData.mm[15]-mData.mm[4]*mData.mm[3]*mData.mm[14]-mData.mm[12]*mData.mm[2]*mData.mm[7]+mData.mm[12]*mData.mm[3]*mData.mm[6];
    aInv[10]=mData.mm[0]*mData.mm[5]*mData.mm[15]-mData.mm[0]*mData.mm[7]*mData.mm[13]-mData.mm[4]*mData.mm[1]*mData.mm[15]+mData.mm[4]*mData.mm[3]*mData.mm[13]+mData.mm[12]*mData.mm[1]*mData.mm[7]-mData.mm[12]*mData.mm[3]*mData.mm[5];
    aInv[14]=-mData.mm[0]*mData.mm[5]*mData.mm[14]+mData.mm[0]*mData.mm[6]*mData.mm[13]+mData.mm[4]*mData.mm[1]*mData.mm[14]-mData.mm[4]*mData.mm[2]*mData.mm[13]-mData.mm[12]*mData.mm[1]*mData.mm[6]+mData.mm[12]*mData.mm[2]*mData.mm[5];
    aInv[3]=-mData.mm[1]*mData.mm[6]*mData.mm[11]+mData.mm[1]*mData.mm[7]*mData.mm[10]+mData.mm[5]*mData.mm[2]*mData.mm[11]-mData.mm[5]*mData.mm[3]*mData.mm[10]-mData.mm[9]*mData.mm[2]*mData.mm[7]+mData.mm[9]*mData.mm[3]*mData.mm[6];
    aInv[7]=mData.mm[0]*mData.mm[6]*mData.mm[11]-mData.mm[0]*mData.mm[7]*mData.mm[10]-mData.mm[4]*mData.mm[2]*mData.mm[11]+mData.mm[4]*mData.mm[3]*mData.mm[10]+mData.mm[8]*mData.mm[2]*mData.mm[7]-mData.mm[8]*mData.mm[3]*mData.mm[6];
    aInv[11]=-mData.mm[0]*mData.mm[5]*mData.mm[11]+mData.mm[0]*mData.mm[7]*mData.mm[9]+mData.mm[4]*mData.mm[1]*mData.mm[11]-mData.mm[4]*mData.mm[3]*mData.mm[9]-mData.mm[8]*mData.mm[1]*mData.mm[7]+mData.mm[8]*mData.mm[3]*mData.mm[5];
    aInv[15]=mData.mm[0]*mData.mm[5]*mData.mm[10]-mData.mm[0]*mData.mm[6]*mData.mm[9]-mData.mm[4]*mData.mm[1]*mData.mm[10]+mData.mm[4]*mData.mm[2]*mData.mm[9]+mData.mm[8]*mData.mm[1]*mData.mm[6]-mData.mm[8]*mData.mm[2]*mData.mm[5];
    float aDet=mData.mm[0]*aInv[0]+mData.mm[1]*aInv[4]+mData.mm[2]*aInv[8]+ mData.mm[3]*aInv[12];
    if (aDet!=0) {aDet=1.0f/aDet;for (int aCount=0;aCount<16;aCount++) mData.mm[aCount]=aInv[aCount]*aDet;}

    return *this;
}
inline Matrix   GetInvert() {Matrix aMat=*this;aMat.Invert();return aMat;}

注:该逆矩阵函数在其他场景(如坐标转换到局部空间)可正常工作,错误不在此。


修复方案

核心问题是矩阵乘法顺序错误:
要满足A*C=B,正确的推导是在等式两边左乘A⁻¹,得到C = A⁻¹ * B。而原代码计算的是C = B * A⁻¹,这是错误的顺序,导致符号和结果不符合预期。

修改后的GetBridge函数:

Matrix Matrix::GetBridge(Matrix* theOther)
{
    Matrix aIMat = GetInvert();
    if (!theOther) return Identity();

    Matrix aResult = aIMat;
    aResult *= *theOther;
    return aResult;
}

验证说明

修改后,应测试A*C是否等于B,即把测试代码中的aM4 = aM2; aM4 *= aM3;改为aM4 = aM1; aM4 *= aM3;,此时输出的aM4应与aM2一致,满足A*C=B的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 03:21:00