【问题标题】:Matrix multiply with position, quaternion and scale components矩阵乘以位置、四元数和比例分量
【发布时间】:2011-12-21 17:50:08
【问题描述】:

我的部分代码通过存储 xyz 位置、xyz 比例和四元数来存储相当于 4x3 矩阵的内容。代码如下:sn-p:

class tTransform
{

    // data
    tVector4f    m_Position;
    tQuaternion  m_Rotation;
    tVector4f    m_Scale;

};

我想将这些对象中的 2 个相乘,(就好像它是矩阵相乘一样),我想知道是否有比将每个对象转换为矩阵更快/更好的方法,以这种方式进行相乘,然后再次提取结果位置、旋转和缩小?

【问题讨论】:

  • 感谢您的回复 :) 我不禁想到做矩阵到四元、四元到矩阵,以及获取新尺度的结果矩阵的 XYZ 轴的长度不是最好的方法。我想我可以通过几次检查来跳过比例部分。
  • 如果您知道更好的解决方案,您可以重载矩阵四元数上的乘法运算符
  • 我认为缺乏答案表明我一开始就以完全错误的方式解决我的问题......我想回到绘图板! :)
  • @CharlesBeattie 有趣...我已经重新设计了我的实现,不再需要解决方案,但我仍然很想听到解决方案?
  • 你去。我不太相信比例尺,因为我只用过骨骼动画。

标签: c++ vector matrix quaternions


【解决方案1】:

健康警告,因为这是来自记忆并且完全未经测试。 您需要为tQuaternions 和tVector4s 定义或替换运算符。

class tTransform
{

    // data
    tVector4f    m_Position;
    tQuaternion  m_Rotation;
    tVector4f    m_Scale;

public:
    // World = Parent * Local (*this == parent)
    tTransform operator * (const tTransform& localSpace)
    {
        tTransform worldSpace;
        worldSpace.m_Position = m_Position + 
                                m_Rotation * (localSpace.m_Position * m_Scale);
        worldSpace.m_Rotation = m_Rotation * localSpace.m_Rotation;
        worldSpace.m_Scale = m_Scale * (m_Rotation * localSpace.m_Scale);
        return worldSpace;
    }

    // Local = World / Parent (*this = World)
    tTransform operator / (const tTransform& parentSpace)
    {
        tTransform localSpace;
        tQuaternion parentSpaceConjugate = parentSpace.m_Rotation.conjugate(); 
        localSpace.m_Position = (parentSpaceConjugate * 
                                (m_Position - parentSpace.m_Position)) /
                                parentSpace.m_Scale;

        localSpace.m_Rotation = parentSpaceConjugate * m_Rotation;

        localSpace.m_Scale = parentSpaceConjugate *
                             (m_Scale / parentSpace.m_Scale);
        return localSpace;
    }
};

【讨论】:

    【解决方案2】:

    我回答了 Tomas 的问题,我也将在此处复制,因为它也回答了您的问题。答案几乎是伪代码,因此您应该能够将其应用到您的课程中。您没有指定使用哪个顺序构建矩阵(TRS 或 SRT),所以我假设为 TRS。 (你的向量是列)

    transform transform::operator * (const transform &other) const
    {
        // mat1 = T1 * R1 * S1; mat2 = T2 * R2 * S2
        // mat = mat1 * mat2; mat*v = mat1 * mat2 * v
        // assuming "this" is mat1, and other is mat2
        // alternatively "this" can be considered parent, and other child in a node hierarchy
        transform r;
        // R = R1 * R2
        r.orientation = orientation * other.orientation;
        // Note: I don't know how to implement inverse of quat in your lib
        // S = R2^-1 * (S1 * (R2 * S2))
        r.scale = inverse(other.orientation) * (scale * (other.orientation * other.scale));
        // T = T1 * (R1 * (S1 * T2))
        r.position = position + (orientation * (scale * other.position));
        return r;
    }
    

    您可以在此处了解如何通过四元数旋转矢量: https://gamedev.stackexchange.com/questions/28395/rotating-vector3-by-a-quaternion

    【讨论】:

    • 您知道如何将比例从世界空间反转到本地空间吗?我无法解决 S2 = 的方程式。
    • 我想我找到了:LS = LR^-1 * ((LR * WS) / PS),LS=LocalScale、LR=LocalRotation、WS=WorldScale 和 PS=ParentScale。在这里发布以供将来参考。
    【解决方案3】:

    我被告知在一般情况下这是不可能的。 见https://gamedev.stackexchange.com/questions/167287/combine-two-translation-rotation-scale-triplets-without-matrices

    问题是结构不能表示剪切,在结合旋转和非均匀缩放后可能需要。

    如果我错了,请纠正我。

    【讨论】:

    • 想解释一下否决票?我真的很想确认哪个答案是正确的?
    猜你喜欢
    • 1970-01-01
    • 2013-07-25
    • 1970-01-01
    • 1970-01-01
    • 2011-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多