【问题标题】:What exactly does a .Net Matrix3D Transform() do / why am I getting "- infinity"?.Net Matrix3D Transform() 究竟做了什么/为什么我得到“-无穷大”?
【发布时间】:2015-12-08 17:39:41
【问题描述】:

我正在尝试对一些 3D 点进行透视变换。 (如果有帮助,我正在尝试应用here 描述的算法)。但基本上,我有一个具有以下值的 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  

当我使用此矩阵将 Transform 应用到 310,120,0 的点时。 . .

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

...我在结果中得到 (Infinity, Infinity, -Infinity)。 transform() 方法究竟做了什么?为什么我会得到这个结果? MSDN 只是说这种方法。 . .

通过 Matrix3D 转换指定的 Point3D 并返回 结果。

【问题讨论】:

    标签: c# wpf matrix 3d


    【解决方案1】:

    您的 Point3D 首先通过附加 1 转换为齐次坐标中的向量:

    p_h = (310, 120, 0, 1)
    

    然后,转换作为乘法应用:

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

    然后,执行 w 剪辑(这是透视变换所必需的)。 w 剪辑将向量除以其 w 分量(最后一维)。因为这是零,所以你得到一个无限的结果。

    问题是矩阵'M44。将此设置为1,您应该没问题。至少,矩阵的最后一列应该包含一些值。如果它们都为零,您将始终得到无限的结果。

    【讨论】:

      【解决方案2】:

      遍历源代码有点痛苦,但这是我能收集到的……Transform 内部调用了一个名为MultiplyPoint 的方法(两个源方法如下所示),它生成一个变量w,总和x, y, z 和对应值的乘积,_m11, _m21, _m31。这些变量是乘以倒数并在称为NormalizedAffineInvert 的方法中转置的结果。我不会发布所有源代码,而是here's the link

      我所能想象的只是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;
          } 
      

      乘点:

          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;
              } 
          }
      

      【讨论】:

        猜你喜欢
        • 2020-08-19
        • 2013-08-06
        • 1970-01-01
        • 2016-07-18
        • 2012-07-23
        • 2016-09-10
        • 2023-03-15
        • 2012-10-17
        • 2021-06-04
        相关资源
        最近更新 更多