1

I have a 3D scene with an infinite horizontal plane (parallel to the xz coordinates) at a height H along the Y vertical axis.

I would like to know how to determine the intersection between the axis of my camera and this plane.

The camera is defined by a view-matrix and a projection-matrix.

BDL
  • 21,052
  • 22
  • 49
  • 55
toto_tata
  • 14,526
  • 27
  • 108
  • 198

2 Answers2

1

For a general line-plane intersection there are lot of answers and tutorials.

Your case is simple due to the plane is horizontal.

I suppose the camera is at C(cx, cy, cz) and it looks at T(tx, ty,tz).
Then the line camera-target can be defined by:

cx - x     cy - y     cz - z
------  =  ------  =  ------        /// These are two independant equations
tx - cx    ty - cy    tz - cz

For a horizontal plane, only a equation is needed: y = H. Substitute this value in the line equations and you get

(cx-x)/(tx-cx) = (cy-H)/(ty-cy)
(cz-z)/(tz-cz) = (cy-H)/(ty-cy)

So

x = cx - (tx-cx)*(cy-H)/(ty-cy)
y = H
z = cz - (tz-cz)*(cy-H)/(ty-cy)

Of course if your camera looks in an also horizontal line then ty=cy and there is not solution.

Ripi2
  • 7,031
  • 1
  • 17
  • 33
  • Thanks for your help. There is something I don't understand in your equations. The vector XC is colinear to the vector T. So I think it should be (cx - x) / tx = (cy - y) / ty = (cz - z) / tz Am I correct ? – toto_tata Mar 14 '18 at 21:39
  • No, no correct. `cx, tx, cy, ty,...` are coordinates, not vectors components. Your equations are wrong. – Ripi2 Mar 15 '18 at 01:10
1

There are two sub-problems here: 1) Extracting the position and view-direction from the camera matrix. 2) Calculating the intersection between the view-ray and the plane.

Extracting position and view-direction

The view matrix describes how points are transformed from world-space to view space. The view-space in OpenGL is usually defined such that the camera is in the origin and looks into the -z direction.

To get the position of the camera, we have to transform the origin [0,0,0] of the view-space back into world-space. Mathematically speaking, we have to calculate:

camera_pos_ws = inverse(view_matrix) * [0,0,0,1]

but when looking at the equation we'll see that we are only interrested in the 4th column of the inverse matrix which will contain 1

camera_pos_ws = [-view_matrix[12], -view_matrix[13], -view_matrix[14]]

The orientation of the camera can be found by a similar calculation. We know that the camera looks in -z direction in view-space thus the world space direction is given by

camera_dir_ws = inverse(view_matrix) * [0,0,-1,0];

Again, when looking at the equation, we'll see that this only takes the third row of the inverse matrix into account which is given by2

camera_dir_ws = [-view_matrix[2], -view_matrix[6], -view_matrix[10]]

Calculating the intersection

We now know the camera position P and the view direction D, thus we have to find the x,z value along the ray R(x,y,z) = P + l * D where y equals H. Since there is only one unknown, l, we can calculate that from

y = Py + l * Dy
H = Py + l * Dy
l = (H - Py) / Dy

The intersection point is then given by pasting l back into the ray equation.

Notes

1 The indices assume that the matrix is stored in a column-major linear array.

2 Note, that the inverse of a matrix of the form

M = [  R T ]
       0 1

, where R is a orthogonal 3x3 matrix, is given by

inv(M) = [ transpose(R)  -T ]
                0         1
BDL
  • 21,052
  • 22
  • 49
  • 55
  • Thanks for this details answer. Are you sure that camera_pos_ws = [-view_matrix[13], -view_matrix[14], -view_matrix[15]] ? Isn't it : camera_pos_ws = [-view_matrix[12], -view_matrix[13], -view_matrix[14]] ? – toto_tata Mar 14 '18 at 21:52
  • 1
    You are absolutely right. Thanks for the feedback, I corrected the mistake. If you have any other comments or find more errors just let me know :) – BDL Mar 14 '18 at 21:55
  • "where y equals 0" Did you mean "where y equals H" ? (H = elevation of the plane along the Y axis) – toto_tata Mar 14 '18 at 22:02
  • 1
    Ups, completely overread the "at height H" part. Also corrected now. – BDL Mar 14 '18 at 22:09
  • Consider an alternative way of writing the matrix transform `y = Mx = R * x + T`; invert this and one obtains `x = inv(M) * y = transpose(R) * (y - T)`. So the last column of `inv(M)` is not quite `-T`, but **`-transpose(R) * T`**. – meowgoesthedog Mar 15 '18 at 01:21