使用 haskell 将矩阵分解为缩放、旋转和平移

Decomposing a matrix into scale, rotation, and translation with haskell

我正在尝试使用 haskell 将矩阵分解为 3x3 旋转矩阵、比例向量和平移向量。我正在使用 linear 包中的矩阵。不幸的是,该包仅导出用于从缩放、旋转和平移生成矩阵的函数,而不是从矩阵中提取这些函数。因此,我决定自己写一个函数来做。

但是,即使我使用的矩阵没有缩放,我的函数 returns 也是 V3 1.0 1.0 1.0 以外的缩放向量。

import qualified Linear.Matrix     as LA
import qualified Linear.V4         as LA
import qualified Linear.V3         as LA
import qualified Linear.Vector     as LA
import qualified Linear.Quaternion as LA

import Control.Lens hiding (deep)

...

decomposeMatrix :: LA.M44 Double -> (LA.M33 Double, LA.V3 Double, LA.V3 Double)
decomposeMatrix m = (rot, scale, trans)
    where trans = (m ^.LA.column LA._w ^. LA._xyz)
          scale = LA.V3 sx sy sz
          sx    = vecLength (m ^.(LA.column LA._x) ^. LA._xyz)
          sy    = vecLength (m ^.(LA.column LA._y) ^. LA._xyz)
          sz    = vecLength (m ^.(LA.column LA._z) ^. LA._xyz)
          rot   = LA.V3 ((m ^. (LA.column LA._x) ^.LA._xyz) LA.^/ sx)
                        ((m ^. (LA.column LA._y) ^.LA._xyz) LA.^/ sy)
                        ((m ^. (LA.column LA._z) ^.LA._xyz) LA.^/ sz)

vecLength :: LA.V3 Double -> Double
vecLength (LA.V3 a b c) = sqrt (a*a + b*b + c*c)

我是这样的 运行 这个函数在 ghci:

decomposeMatrix $ LA.mkTransformation (LA.Quaternion 1 (LA.V3 1 2 3)) $ LA.V3 1 2 3

这就是我得到的结果(经过格式化以便您更容易阅读):

(V3 (V3 (-0.9259259259259259) 0.37037037037037035 7.407407407407407e-2)
    (V3 (-8.444006618414981e-2) (-0.8021806287494233) 0.5910804632890487) 
    (V3 0.5965499862718936 0.5965499862718936 (-0.5368949876447042)),
V3 27.0 23.68543856465402 16.76305461424021,
V3 1.0 2.0 3.0)

提前致谢。

你的 decomposeMatrix 函数看起来不错(除了旋转矩阵是你想要的转置)。

最大的问题是您的测试用例:您使用的四元数 (LA.Quarternion 1 (LA.V3 1 2 3) 不是单位四元数,因此 LA.mkTransformation 没有构建纯旋转。它正在构建旋转和缩放的组合。试试这个例子:

decomposeMatrix $ LA.mkTransformation (LA.axisAngle (LA.V3 1 2 3) 1) 
                $ LA.V3 1 2 3

它使用 LA.axisAngle 来构建一个单位四元数,表示一个向量和角度的纯旋转,它会按预期工作。