Reputation: 8281
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
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
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