8
\$\begingroup\$

I'm working on a game with a 2D view in a 3D world. It's a kind of shoot'em up. I've a spaceship at the center of the screen and i want that ennemies appear at the borders of my window. Now i don't know how to determine positions of the borders of the window.

For example, my camera is at (0,0,0) and looking forward (0,0,1). I set my spaceship at (0,0,50). I also know the near plane (1) and the far plane(1000). I think i'd have to find the 4 corners of the plane in the frustum whose z position is 50, and with these corner i can determine borders. But i don't know how to determine x and y.

\$\endgroup\$

3 Answers 3

6
\$\begingroup\$

Disclaimer: This solution really is simplified for your particular problem, because your camera is looking straight down the Z axis of the world's coordinate system. Also, the center point at 50 units away is already given as (0, 0, 50). If your camera's viewing direction was an arbitrary vector, there would be more multiplications involving the distance with a cross product of the viewing vector and the camera's Up vector.

Determining the borders of a plane at a given distance is dependent on the FOV angle in which the view is projected. Usually, the FOV angle is measured in the Y axis for rectangular viewports.

For any given distance Z from the camera, the shortest distance D from the center point of a plane perpendicular to the viewing vector at Z to one of its borders above or below the center (really, the intersection of the plane and frustum) is D = tan(FOV / 2) * Z . Add and subtract D from the center point's Y component to get the maximum and minimum Y extents.

To get the minimum and maximum X extents, add and subtract D * aspect_ratio.

Now getting the location of the plane's corners is simply plugging in the mix/max X and Y in its four possible combinations along with the Z distance.

\$\endgroup\$
6
  • \$\begingroup\$ When i compute tan(FOV/2) * Z, FOV has to be in radian or degrees? \$\endgroup\$ Nov 15, 2011 at 23:07
  • 2
    \$\begingroup\$ In standard math libraries (libm, etc), angles must always be expressed in radians. If you're using some other custom third-party math library, check the library's documentation for what units it uses for angles. But unless it says otherwise, it's usually safe to assume radians. \$\endgroup\$ Nov 15, 2011 at 23:54
  • \$\begingroup\$ It works fine since my camera z position is at 0. But does it works if set my camera elsewhere? For exemple if my camera is at (0,0, -50) and the plane i'm looking for is at (0,0, 50). In this exemple, the Z component in tan(FOV/2) * Z has to be 50 (origin to plane) or 100 (camera z-position to plane)? \$\endgroup\$ Nov 21, 2011 at 8:58
  • 1
    \$\begingroup\$ In this case the Z component is 100 because it's the distance from the camera to the plane. This formula works for any view direction parallel to the Z axis (any multiple of [0, 0, 1]). \$\endgroup\$
    – ChrisC
    Nov 21, 2011 at 17:03
  • \$\begingroup\$ Thanks, it works. One last thing, now i'm curious to know how to do the same with a camera looking anywhere. \$\endgroup\$ Nov 22, 2011 at 13:39
15
+25
\$\begingroup\$

This is a more general solution

To start you will need some data.

The Camera's position represented by P (this is a point)

The normalized viewing vector represented by v

The Camera's up vector represented by up

The Camera's right vector represented by w (this is the cross product of v X up)

The near distance represented by nDis

The far distance represented by fDis

The field of view represented by fov (this usually in radians)

The aspect ratio represented by ar (this is the width of the screen divided by the height)


First we will get the width and height of the near plane

Hnear = 2 * tan(fov / 2) * nDis

Wnear = Hnear * ar


Then we do the same for the far plane

Hfar = 2 * tan(fov / 2) * fDis

Wfar = Hfar * ar


Now we get the center of the planes

Cnear = P + v * nDis

Cfar = P + v * fDis


And now we get our points

Near Top Left = Cnear + (up * (Hnear / 2)) - (w * (Wnear / 2))

Near Top Right = Cnear + (up * (Hnear / 2)) + (w * (Wnear / 2))

Near Bottom Left = Cnear - (up * (Hnear / 2)) - (w * (Wnear /2))

Near Bottom Right = Cnear + (up * (Hnear / 2)) + (w * (Wnear / 2))

Far Top Left = Cfar + (up * (Hfar / 2)) - (w * Wfar / 2))

Far Top Right = Cfar + (up * (Hfar / 2)) + (w * Wfar / 2))

Far Bottom Left = Cfar - (up * (Hfar / 2)) - (w * Wfar / 2))

Far Bottom Right = Cfar - (up * (Hfar / 2)) + (w * Wfar / 2))


Common assumptions that might be useful:

  • Most games have their field of view set at 110 degrees as this is close to the human field of view
  • The camera is most often set at the origin (0,0,0)
  • The view vector is usually along the negative Z axis (0,0,-1)
  • The up vector is usually along the Y axis (0,1,0)
  • The right vector is usually along the X axis (1,0,0)
\$\endgroup\$
4
  • \$\begingroup\$ I don't think this answers the question. Near and far planes should be irrelevant, as the problem is about intersection of view frustum and a plane perpendicular to the view direction and where an object is located. \$\endgroup\$
    – msell
    May 10, 2013 at 5:03
  • \$\begingroup\$ I'm sorry, but as @msell said, it does not answer the question. Your answer explain how to determine corners of a frustum. I (we) need to determine corners of a plane into the frustum. I have made this picture to make it clearer. Anyway, thanks for your current work, have an upvote :) \$\endgroup\$ May 11, 2013 at 9:51
  • \$\begingroup\$ So if I understand you clearly, there is a plane inside the frustum that runs parallel to the near and far planes, and perpendicular to the view vector. The formula you are looking for, takes a distance from the camera's position, and calculates the corners of the plane, that lie on the plane, and intersect with the edges of the frustum. \$\endgroup\$
    – Lucas C.
    May 14, 2013 at 20:12
  • 1
    \$\begingroup\$ Near Bottom Right = Cnear + (up * (Hnear / 2)) + (w * (Wnear / 2)) should be Near Bottom Right = Cnear - (up * (Hnear / 2)) + (w * (Wnear / 2)) \$\endgroup\$
    – scones
    Sep 3, 2015 at 14:49
0
\$\begingroup\$

Conisdering you translate your "camera" by writing something like: gltranslatef(1, 3, 0). Make values such as posX and posY, and whenever you translate your camera, add to those values. Then when you add your enemy set it's X value to posX and it's Y value to posY for the enemy to appear where it would if the camera was at the origin.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .