-- | note: this will only work if no column c in turn is mapped to -c in turn' !
mat4SmoothTurn :: Turn -> Turn -> Float -> Mat4
mat4SmoothTurn turn turn' alpha =
    let Turn x0 x1 x2 
             y0 y1 y2
             z0 z1 z2 = turn
        Turn x0' x1' x2'
             y0' y1' y2'
             z0' z1' z2' = turn'
        a = (1 - alpha)
        a' = alpha
        x0'' = a * (fromIntegral x0) + a' * (fromIntegral x0')
        x1'' = a * (fromIntegral x1) + a' * (fromIntegral x1')
        x2'' = a * (fromIntegral x2) + a' * (fromIntegral x2')
        y0'' = a * (fromIntegral y0) + a' * (fromIntegral y0')
        y1'' = a * (fromIntegral y1) + a' * (fromIntegral y1')
        y2'' = a * (fromIntegral y2) + a' * (fromIntegral y2')
        z0'' = a * (fromIntegral z0) + a' * (fromIntegral z0')
        z1'' = a * (fromIntegral z1) + a' * (fromIntegral z1')
        z2'' = a * (fromIntegral z2) + a' * (fromIntegral z2')
        xscale = scale x0'' x1'' x2''
        yscale = scale y0'' y1'' y2''
        zscale = scale z0'' z1'' z2''
 
    in
        Mat4 (xscale * x0'') (xscale * x1'') (xscale * x2'') 0
             (yscale * y0'') (yscale * y1'') (yscale * y2'') 0
             (zscale * z0'') (zscale * z1'') (zscale * z2'') 0
             0    0    0    1

    where
        scale a0 a1 a2 =
            1 / (sqrt $ a0 * a0 + a1 * a1 + a2 * a2) -- note: fails if zero
mat4SmoothTurn :: Turn -> Turn -> Float -> Mat4
mat4SmoothTurn turn turn' alpha =
    let Turn x0 x1 x2 
             y0 y1 y2
             z0 z1 z2 = turn
        Turn x0' x1' x2'
             y0' y1' y2'
             z0' z1' z2' = turn'
        a = (1 - alpha)
        a' = alpha
        x0'' = a * (fromIntegral x0) + a' * (fromIntegral x0')
        x1'' = a * (fromIntegral x1) + a' * (fromIntegral x1')
        x2'' = a * (fromIntegral x2) + a' * (fromIntegral x2')
        y0'' = a * (fromIntegral y0) + a' * (fromIntegral y0')
        y1'' = a * (fromIntegral y1) + a' * (fromIntegral y1')
        y2'' = a * (fromIntegral y2) + a' * (fromIntegral y2')
        z0'' = a * (fromIntegral z0) + a' * (fromIntegral z0')
        z1'' = a * (fromIntegral z1) + a' * (fromIntegral z1')
        z2'' = a * (fromIntegral z2) + a' * (fromIntegral z2')
        xscale = scale x0'' x1'' x2''
        yscale = scale y0'' y1'' y2''
        zscale = scale z0'' z1'' z2''
 
    in
        Mat4 (xscale * x0'') (xscale * x1'') (xscale * x2'') 0
             (yscale * y0'') (yscale * y1'') (yscale * y2'') 0
             (zscale * z0'') (zscale * z1'') (zscale * z2'') 0
             0    0    0    1

    where
        scale a0 a1 a2 =
            1 / (sqrt $ a0 * a0 + a1 * a1 + a2 * a2) -- note: fails if zero
mat4SmoothTurn turn turn' alpha =
    let Turn x0 x1 x2 
             y0 y1 y2
             z0 z1 z2 = turn
        Turn x0' x1' x2'
             y0' y1' y2'
             z0' z1' z2' = turn'
        a = (1 - alpha)
        a' = alpha
        x0'' = a * (fromIntegral x0) + a' * (fromIntegral x0')
        x1'' = a * (fromIntegral x1) + a' * (fromIntegral x1')
        x2'' = a * (fromIntegral x2) + a' * (fromIntegral x2')
        y0'' = a * (fromIntegral y0) + a' * (fromIntegral y0')
        y1'' = a * (fromIntegral y1) + a' * (fromIntegral y1')
        y2'' = a * (fromIntegral y2) + a' * (fromIntegral y2')
        z0'' = a * (fromIntegral z0) + a' * (fromIntegral z0')
        z1'' = a * (fromIntegral z1) + a' * (fromIntegral z1')
        z2'' = a * (fromIntegral z2) + a' * (fromIntegral z2')
        xscale = scale x0'' x1'' x2''
        yscale = scale y0'' y1'' y2''
        zscale = scale z0'' z1'' z2''
 
    in
        Mat4 (xscale * x0'') (xscale * x1'') (xscale * x2'') 0
             (yscale * y0'') (yscale * y1'') (yscale * y2'') 0
             (zscale * z0'') (zscale * z1'') (zscale * z2'') 0
             0    0    0    1

    where
        scale a0 a1 a2 =
            1 / (sqrt $ a0 * a0 + a1 * a1 + a2 * a2) -- note: fails if zero