矩阵乘法涉及位置、四元数和缩放组件

5
我的代码的一部分存储了一个4x3矩阵的等效值,通过存储一个xyz位置、一个xyz缩放和一个四元数。下面是代码片段:
class tTransform
{

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

};

我想将这两个对象相乘(就像矩阵相乘一样),不知道是否有比将每个对象转换成矩阵,进行乘法运算,然后再将结果的位置、旋转和缩放提取出来的更快或更好的方法?


谢谢回复 :) 我不禁想到,将矩阵转换为四元数,四元数转换为矩阵,再获取新比例矩阵的XYZ轴长度并不是最好的方法。不过我想我可以通过几个检查跳过比例部分。 - Hybrid
如果您知道更好的解决方案,可以在矩阵四元数上重载乘法运算符。 - ted
我认为缺乏答案表明我一开始就错误地解决了我的问题...我想重新开始! :) - Hybrid
@CharlesBeattie 有趣...我已经重新设计了我的实现方式,不需要解决这个问题,但我仍然很想听听解决方案? - Hybrid
就是这样。我不太信任这个比例尺,因为我只习惯了骨骼动画。 - Charles Beattie
3个回答

3

健康警告,以下内容是凭记忆编写且未经测试。您需要定义或替换tQuaterniontVector4的运算符。

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;
    }
};

1
我回答了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 =”方程时遇到了麻烦。 - Cyphall
我想我找到了:LS = LR^-1 * ((LR * WS) / PS),其中LS代表本地缩放,LR代表本地旋转,WS代表世界缩放,PS代表父级缩放。在此发布以备将来参考。 - Cyphall

0

能否解释一下为什么要点踩? 我真的很想确认哪个答案是正确的? - Tomas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接