3

Given a point in 3D space, how can I calculate a matrix in homogeneous coordinates which will project that point into the plane z == d, where the origin is the centre of projection.

Alnitak
  • 334,560
  • 70
  • 407
  • 495
Ricky Jones
  • 131
  • 3
  • 8
  • 1
    What form of projection do you want? Are you really talking about just `(X,Y,Z) => (X,Y,D)`, a matrix translation of D-Z on the Z axis? Are you trying to find the intersection of the segment between the origin and the point and an offset Z=D plane? Your question needs more details. – Phrogz Mar 11 '11 at 01:04
  • Would a matrix specific to that point do, or do you want one constant matrix that will project *any* point (other than the origin) onto the z=d plane, along the ray from the origin? – Beta Mar 11 '11 at 07:27
  • Did you check http://en.wikipedia.org/wiki/3D_projection ? I think it contains your answer, and explanations on the computation. – Alexandre C. Mar 11 '11 at 10:08
  • You're asking form a perspective projection transformation matrix, which is different from perspective transformation matrix. – Pui Ho Lam May 15 '18 at 05:28
  • I just answered this at length in https://stackoverflow.com/questions/24163987/projection-matrix-to-project-a-point-in-a-plane/52259013#52259013 – André Aichert Sep 10 '18 at 13:48

3 Answers3

4

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

Alnitak
  • 334,560
  • 70
  • 407
  • 495
1

the homogeneous transformation matrix is (Euler roll-pitch-yaw):

|r1 r2 r3 dx|
|r4 r5 r6 dy|
|r7 r8 r9 dz|
|px py pz sf|

r1-9 are the elements of the combined rotation matrix: Rx*Ry*Rz (work it out) dx dy and dz are displacement vector (d) elements px py and pz are the perspective vector (p) elements sf is the scaling factor

from here on, if you use the inverse of this, you get your projection as a perspective in any arbitrary plane by feeding rotations of your target plane, as well as it's position of origin wrt the reference one in (keep perspective vector at 0 0 0 and sf=1 for pure kinematics), you get T->T* = T1. Get T1^-1 (for kinematics, this is simply R' (transposed,), horizontal concatenated by -R'*d, then vertical concatenated simply by 0 0 0 1).

can have multiple planes e.g. a,b,c as a chain, in which case T1 = Ta*Tb*Tc*...

then, v(new) = (T1^-1)*v(old), job done.

1

I guess the projection you mean, as Beta says, consists in the intersection between:

  • the line formed by the origin O(0, 0, 0) and the point P(a, b, c) to be transformed
  • and the plane z=d

If I'm right, then let's have a look at the equation of this line, given by the vectorial product OP ^ OM = 0 (let's remind that the equation of a line between 2 given points A and B is given by AB ^ AM = 0, with M(x, y, z); this is a vectorial product, so all are vectors: 0 represents the null vector, AB is the vector AB, etc):

bz - cy = 0
cx - az = 0
cz - bx = 0

With z = d, we then have only 2 linearily independent equations:

bd = cy
cx = ad

So this projection converts a point P(a, b, c) into a point P'(ad/c, bd/c, d). For homogeneous coordinates that gives:

P'(ad/c, bd/c, d) = P'(ad/c, bd/c, cd/c)
                  = P'(ad/c: bd/c: cd/c: 1)
                  = P'(a: b: c: d/c)

EDIT : the matrix I 1st found was:

    1, 0, 0, 0
    0, 1, 0, 0
A = 0, 0, 1, 0
    0, 0, 0, d/c

but it uses c which is the a coordinate of the point P !! This is nonsense, I couldn't find an expression of A that does not use these coordinates. I may not be familiar enough with homogeneous coordinates.

Emmanuel
  • 13,935
  • 12
  • 50
  • 72
  • Your explanation is unclear - what is the point `M` and why is vector `OP` orthogonal to vector `OM`? – Alnitak Mar 11 '11 at 08:50
  • +1, but since you are scaling with d/c, I think the scaling element 1/s in the matrix should be c/d. – antonakos Mar 11 '11 at 09:16
  • @Alnitak: indeed, I tried to clarify this point. @antonakos: can you please develop ? The fact I could not find a correct matrix relies on the fact that I have `c` as a denominator... – Emmanuel Mar 11 '11 at 10:11
  • describing the line as a set of simultaneous equations makes it too complicated IMHO - it's actually simple geometry. – Alnitak Mar 11 '11 at 10:45
  • If you want to scale by s = d/c, then the element at position (4,4) in the matrix should be 1/s = c/d. See http://en.wikipedia.org/wiki/Scaling_%28geometry%29#Using_homogeneous_coordinates – antonakos Mar 11 '11 at 11:30
  • @antonakos that's not right, since it doesn't account for the fact that for each point the denominator depends on the original z coordinate. my answer does ;-) – Alnitak Mar 11 '11 at 11:44
  • @Alnitak It correct for the specific point (a, b, c), but I agree that your solution is probably what the OP was looking for. – antonakos Mar 11 '11 at 12:16
  • The point is that the transformation matrix should be _constant_ for any particular viewport for all points. Fixing the denominator is done by normalising the resulting homogenous vector. – Alnitak Mar 11 '11 at 12:31