user316117
user316117

Reputation: 8281

What exactly does a .Net Matrix3D Transform() do / why am I getting "- infinity"?

I'm trying to do a perspective transform on some 3D points. (if it helps, I'm trying to apply the algorithm described here). But basically, I have a Matrix3D with the following values:

 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  

When I apply a Transform using this matrix to a point of 310,120,0 . . .

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

... I get (Infinity, Infinity, -Infinity) in the result. What exactly does the transform() method do and why do I get that result? The MSDN just says that method . . .

Transforms the specified Point3D by the Matrix3D and returns the result.

Upvotes: 1

Views: 1233

Answers (2)

Nico Schertler
Nico Schertler

Reputation: 32607

Your Point3D is first converted to a vector in homogeneous coordinates by appending a 1:

p_h = (310, 120, 0, 1)

Then, the transformation is applied as a multiplication:

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

Then, a w-clip is performed (which is necessary for perspective transforms). The w-clip divides the vector by its w-component (the last dimension). Since this is zero, you get an infinite result.

The problem is the matrix' M44. Set this to 1 and you should be fine. At least, the last column of the matrix should contain some values. If they are all zero, you will always get an infinite result.

Upvotes: 2

TayTay
TayTay

Reputation: 7170

Traversing the source code is slightly painful, but here's what I can glean... Transform internally calls a method called MultiplyPoint (both source methods shown below), which generates a variable w, the sum of the products of x, y, z and corresponding values, _m11, _m21, _m31. These variables result from being multiplied by the reciprocal and transpose in a method called NormalizedAffineInvert. I won't post all the source code, but here's the link.

All I can imagine is happening is that w ends up equalling 0 somehow. Since you say IsAffine = false, you enter the division logic and dividing by zero thus causes Infinity. Note that calling the public method Invert() will interally call NormalizedAffineInvert. Are you ever calling this method?

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

Upvotes: 1

Related Questions