Projection matrix to project a point in a plane

2019-07-18 12:01发布

问题:

How to determinate the 4x4 S matrix so that the P gets projected into Q, on the XZ (Y=0) plane?

Q = S P

回答1:

I will give the general solution for central projection from a point C to a plane E (assuming that L is not contained in E).

I will use Octave/MATLAB notation for convenience.

Let L be given in homogeneous coordinates

L=[lx ly lz 1]'

And E be given in Hessian normal form (also homogeneous coordinates)

E=[nx, ny, ,nz, d]'

where [nx, ny, nz] is the normal to the plane and d is its signed distance to the origin.

Then the matrix S which projects any point P (also in homogeneous coordinates) to the plane E through the center of projection L is

S=eye(4)*(L'*E)-L*E'

The central projection is

Q=S*P

As an Octave/MATLAB function

% A matrix S describing central projection to a plane E
% L a point in homogeneous coordinates of projective 3-space
% E a plane in homogeneous coordinates of projective 3-space
% Requirement: scalar product of L and E is non-zero (i.e. L is not contained in E)
function S = central_projection_to_plane(L, E)
    S = [
     + L(2)*E(2) + L(3)*E(3) + L(4)*E(4), - L(1)*E(2)                         , - L(1)*E(3)                         , - L(1)*E(4)                        ;
     - L(2)*E(1)                        , + L(1)*E(1) + L(3)*E(3) + L(4)*E(4) , - L(2)*E(3)                         , - L(2)*E(4)                        ;
     - L(3)*E(1)                        , - L(3)*E(2)                         , + L(1)*E(1) + L(4)*E(4) + L(2)*E(2) , - L(3)*E(4)                        ;
     - L(4)*E(1)                        , - L(4)*E(2)                         , - L(4)*E(3)                         , + L(1)*E(1) + L(2)*E(2) + L(3)*E(3)
];
end % function

P.S.: To derive this, note that the line through L and P can be written as a 4x4 Plücker matrix

Rx=L*P'-P*L'.

The intersection of the line Rx and the plane E is simply

Q=Rx*E
 =(L*P'-P*L')*E
 =(eye(4)*(L'*E)-L*E')*P
 =S*P

See also: https://en.wikipedia.org/wiki/Plücker_matrix



回答2:

The ray has coordinates r(t) = L + t * (P-L). That is in component form:

r_x = L_x + t*(P_x-L_x)
r_y = L_y + t*(P_y-L_y)
r_z = L_z + t*(P_z-L_z)

Now you need to find Q = r(t) such that r_y = 0. That is done when t = -L_y/(P_y-L_y) or

Q_x = L_x - L_y/(P_y-L_y)*(P_x-L_x)
Q_y = 0
Q_z = L_z - L_y/(P_y-L_y)*(P_z-L_z)

In general, the projection plane is defined by a unit normal vector n=(n_x,n_y,n_z) and the distance of the plane to the origin d. A point r(t) lies on the plane if r(tn=d where · is the vector dot product.

The solution for point Q in general is

t = (d - n·L)/(n·(P-L))

Q = L + t *( P-L )

In pseudo C style code the above is:

// L : Light Source 
// P : Point to be projected
// n : Plane _unit_ normal vector
// d : Distance of plane to the origin
// returns: The point Q along the ray that intersects the plane.
Vector3 HitPlaneWithRay(Vector3 L, Vector3 P, Vector3 n, double d)
{
    double t = (d-Dot(L,n))/Dot(P-L,n);
    return L + t*(P-L);
}
// Intersect ray with floor (Normal=[0,1,0], Distance=0)
Vector3 HitFloorWithRay(Vector3 L, Vector3 P)
{
    return HitPlaneWithRay(L, P, Vector3.J, 0);
}