OK, let's try to sort this out, expanding on Emmanuel's answer.
Assuming that your view vector is directly along the Z axis, all dimensions must be scaled by the ratio of the view plane distance d
to the original z
coordinate. That ratio is trivially d / z
, giving:
x' = x * (d / z)
y' = y * (d / z)
z' = z * (d / z) ( = d)
In homogenous coordinates, it's usual to start with P = [x, y, z, w]
where w == 1
and the transformation is done thus:
P' = M * P
The result will have w != 1
, and to get the real 3D coordinates we normalise the homogenous vector by dividing the whole thing by its w
component.
So, all we need is a matrix that given [x, y, z, 1
] gives us [x * d, y * d, z * d, z]
, i.e.
| x' | = | d 0 0 0 | * | x |
| y' | = | 0 d 0 0 | * | y |
| z' | = | 0 0 d 0 | * | z |
| w' | = | 0 0 1 0 | * | 1 |
which once normalised (by dividing by w' == z
) gives you:
[ x * d / z, y * d / z, d, 1 ]
per the first set of equations above
You need to convert your plane to a different representation. One where N is the normal, and O is any point on the plane. The normal you already know, it's your (xyz). A point on the plane is also easy, it's your normal N times your distance d.
Transform O by the 4x4 matrix in the normal way, this becomes your new O. You will need a Vector4 to multiply with a 4x4 matrix, set the W component to 1 (x, y, z, 1).
Also transform N by the 4x4 matrix, but set the W component to 0 (x, y, z, 0). Setting the W component to 0 means that your normals won't get translated. If your matrix is composed of more that just translating and rotating, then this step isn't so simple. Instead of multiplying by your transformation matrix, you have to multiply by the transpose of the inverse of the matrix i.e. Matrix4.Transpose(Matrix4.Invert(Transform))
, there's a good explanation on why here.
You now have a new normal vector N and a new position vector O. However I suppose you want it in xyzd form again? No problem. As before, xyz is your normal N all that's left is to calculate d. d is the distance of the plane from the origin, along the normal vector. Hence, it is simply the dot product of O and N.
There you have it! If you tell me what language you're doing this in, I'd happily type it up in code as well.
EDIT, In pseudocode:
The plane is vector3 xyz
and number d
, the matrix is a matrix4x4 M
vector4 O = (xyz * d, 1)
vector4 N = (xyz, 0)
O = M * O
N = transpose(invert(M)) * N
xyz = N.xyz
d = dot(O.xyz, N.xyz)
xyz
and d
represent the new plane
Best Answer
I know this is only a workaround, but you can deduce the near plane point by only using the far point and the viewing position.
As for you real problem. First, don't forget to divide by W! Also, depending on your projection matrix, have you tried (x,y,0,1) as opposed to z=-1.