.Net Matrix3D Transform()到底做什么/为什么我得到“-无穷大”;

本文关键字:无穷大 为什么 什么 Transform Matrix3D Net | 更新日期: 2023-09-27 18:26:06

我正在尝试对一些三维点进行透视变换。(如果有帮助的话,我会尝试应用这里描述的算法)。但基本上,我有一个Matrix3D,具有以下值:

 HasInverse = true
 IsAffine = false   
 IsIdentity = false     
 M11 = 1.000000000000000    
 M12 = 0.0  
 M13 = 0.0  
 M14 = 0.0  
 M21 = 0.0  
 M22 = 1.000000000000000    
 M23 = 0.0  
 M24 = 0.0  
 M31 = 0.0  
 M32 = 0.0  
 M33 = -1.0101010101010102  
 M34 = 0.0  
 M44 = 0.0  
 OffsetX = 100  
 OffsetY = -1.0101010101010102
 OffsetZ = 0.0  

当我使用此矩阵将变换应用于310120,0点时。

  Point3D p = new Point3D(310, 120, 0);
  Point3D pointResult = new Point3D();
  pointResult = (Point3D)TheMatrix.Transform(p);

我在结果中得到(无穷大,无穷大,-无穷大)。transform()方法到底做了什么?为什么我会得到这个结果?MSDN只是说这个方法。

将指定的Point3D转换为Matrix3D,并返回后果

.Net Matrix3D Transform()到底做什么/为什么我得到“-无穷大”;

首先通过添加1:将Point3D转换为齐次坐标中的矢量

p_h = (310, 120, 0, 1)

然后,将变换应用为乘法:

p_h* = p_h * M
     = (410, 119, 0, 0)

然后,执行w剪辑(这对于透视变换是必要的)。w片段将向量除以其w分量(最后一个维度)。既然这是零,你就会得到一个无穷大的结果。

问题是矩阵的M44。将此值设置为1,您应该会没事的。至少,矩阵的最后一列应该包含一些值。如果它们都为零,你总是会得到一个无穷大的结果。

遍历源代码有点痛苦,但以下是我可以收集到的。。。Transform内部调用一个名为MultiplyPoint的方法(两个源方法如下所示),该方法生成变量w,即x、y、z与相应值_m11、_m21、_m31的乘积之和。这些变量是通过一种称为NormalizedAffineInvert的方法乘以倒数和转置得到的。我不会发布所有的源代码,但这里有链接。

我所能想象的是w最终以某种方式等于0。既然你说的是IsAffine = false,那么你就进入除法逻辑,除以零就会得到Infinity。注意,调用公共方法Invert()将在内部调用NormalizedAffineInvert。你有没有调用过这个方法?

    #region Transformation Services
    /// <summary>
    ///  Transforms the given Point3D by this matrix, projecting the 
    ///  result back into the W=1 plane. 
    /// </summary>
    /// <param name="point">Point to transform. 
    /// <returns>Transformed point.</returns>
    public Point3D Transform(Point3D point)
    {
        MultiplyPoint(ref point); 
        return point;
    } 

MultiplyPoint:

    internal void MultiplyPoint(ref Point3D point)
    {
        if (IsDistinguishedIdentity) 
            return;
        double x = point.X; 
        double y = point.Y;
        double z = point.Z; 
        point.X = x*_m11 + y*_m21 + z*_m31 + _offsetX;
        point.Y = x*_m12 + y*_m22 + z*_m32 + _offsetY;
        point.Z = x*_m13 + y*_m23 + z*_m33 + _offsetZ; 
        if (!IsAffine) 
        { 
            double w = x*_m14 + y*_m24 + z*_m34 + _m44;
            point.X /= w;
            point.Y /= w;
            point.Z /= w;
        } 
    }