Search code examples
c++vectormatrixquaternions

Matrix multiply with position, quaternion and scale components


Part of my code stores the equivalent of a 4x3 matrix, by storing an xyz position, an xyz scale, and a quaternion. Code snippet below:

class tTransform
{

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

};

I want to multiply 2 of these objects together, (as though it were a matrix multiply), and am wondering if there is a faster/better way to do it than to convert each to a matrix, do the multiply that way, and then extract the resulting position, rotation and scale back out again?


Solution

  • Health warning as this is from memory and completely untested. You need to define or replace operators for tQuaternions and 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;
        }
    };