图形学中的常见数学各种矩阵各种变换数学

172 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第15天,点击查看活动详情

已知向量 a\vec{a}b\vec{b} 和旋转轴 m\vec{m},求 a\vec{a}b\vec{b} 的旋转角度

  1. 单位化

    a\vec{a}

    单位化:Normalize(a\vec{a})

    b\vec{b}

    单位化:Normalize(b\vec{b})

  2. 求点积

    dDot=ab=abcosθ=cosθdDot = \vec{a} \cdot \vec{b} = \left\|\vec{a} \right\| \left\|\vec{b} \right\| \cos\theta =\cos\theta

   if (::fabs(::fabs(dDot) - 1) < Config<T>::GetAbs())
   {
       return dDot > 0 ? 0 : Config<T>::GetPI();
       //分别对应0度多一点点和180度的旋转角,画cos即可
   }
参数(x)返回值
acos[-1,1][0,π\pi]
(x, y)atan2(y,x)atan(y/x)
(+, +)(0, π/2\pi/2 )(0, π/2\pi/2 )
(+, -)(π/2\pi/2, π\pi )(π/2-\pi/2, 0 )
(-, -)(π-\pi, π/2-\pi/2 )(0, π/2\pi/2 )
(-, +)(π/2-\pi/2, 0 )(π/2-\pi/2, 0 )

所以到底是(0,π\pi)还是 (π\pi,2π2\pi)的数值还需要判断一下

这里使用叉乘 n=a×b\vec{n} = \vec{a} \times \vec{b} 这个结果对应于旋转角度在(0,π\pi)之间

二者同向二者反向
旋转轴 n\vec{n} 与真实旋转轴 m\vec{m}点乘cos0=1\cos 0 = 1 ,点乘的值为 > 0cos180=1\cos180 = -1 ,点乘的值为 < 0
旋转角度acos(dDot) acos(dDot)2πacos(dDot)2\pi - acos(dDot)
T GetRotateAngle(const Vec3 &cToVec, const Vec3 &cAxis) const
{
    Vec3 cVec1 = Vec3::Normalize(*this);
    Vec3 cVec2 = Vec3::Normalize(cToVec);
    T dDot = cVec1 % cVec2;
    if (::fabs(::fabs(dDot) - 1) < Config<T>::GetAbs())
    {
            return dDot > 0 ? 0 : Config<T>::GetPI();
    }

    T dCurAngle = ::acos(dDot);
    Vec3 cVec3 = cVec1 * cVec2;

    return cVec3 % cAxis > 0 ? dCurAngle : (2 * Config<T>::GetPI() - dCurAngle);
}

会使用到的图形库

glm::dot(cVec1.m_cVec, cVec2.m_cVec);
glm::cross(cVec1.m_cVec, cVec2.m_cVec); 

三维变换矩阵

  • 求平移量,GetTranslationVec

    Vec3<T> GetTranslationVec() const
    {
            return std::move(Vec3<T>(m_cMat[3][0], m_cMat[3][1], m_cMat[3][2]));
    }
    
  • 求缩放量,GetScalingVec

    Vec3<T> GetScalingVec() const
    {
            return std::move(Vec3<T>(glm::length(m_cMat[0]), glm::length(m_cMat[1]), glm::length(m_cMat[2])));
    }
    
  • 求旋转矩阵

    Mat3<T> GetRotateMat3() const
    {
            Vec3<T> cScaleVec = GetScalingVec();
            Vec3<T> cVec = (T)1.0 / GetScalingVec();
    
            Mat3<T> cMat3;
            cMat3[0][0] = m_cMat[0][0] * cVec.x;
            cMat3[0][1] = m_cMat[0][1] * cVec.x;
            cMat3[0][2] = m_cMat[0][2] * cVec.x;
            cMat3[1][0] = m_cMat[1][0] * cVec.y;
            cMat3[1][1] = m_cMat[1][1] * cVec.y;
            cMat3[1][2] = m_cMat[1][2] * cVec.y;
            cMat3[2][0] = m_cMat[2][0] * cVec.z;
            cMat3[2][1] = m_cMat[2][1] * cVec.z;
            cMat3[2][2] = m_cMat[2][2] * cVec.z;
    
            return std::move(cMat3);
    }
    
  • 求是否是对称的

     bool IsReflect() const
     {
             double dNormalLen = (1.0 - m_cMat[0][0]) * 0.5 + (1.0 - m_cMat[1][1]) * 0.5 + (1.0 - m_cMat[2][2]) * 0.5;
             if (::fabs(dNormalLen - 1.0) > Config<T>::GetAbs())
             {
                     return false;
             }
    
             const T  *pData = GetData();
             if (::fabs(pData[4] - pData[1]) > Config<T>::GetAbs())
             {
                     return false;
             }
             if (::fabs(pData[8] - pData[2]) > Config<T>::GetAbs())
             {
                     return false;
             }
             if (::fabs(pData[9] - pData[6]) > Config<T>::GetAbs())
             {
                     return false;
             }
    
             return true;
     }