Calculating 3D camera position based on a 2D camera

404 views Asked by At

I have a 2D sidescrolling game engine and want to be able to add 3D objects. So I need a 3D camera. To make the 2D objects look exactly like before, I need to calculate a 3D camera position, but somehow my calculations are off: it's zoomed in too far. The situation:

  • All my 2D objects are at Z = 0.
  • My 2D camera is defined as position (X,Y) and width.
  • The aspect ratio of the view automatically determines the camera's height.
  • For the 3D camera the user sets FOVx.

So I guess the question really is: how do I calculate the camera's Z position based on width and FOVx?

I figured I could just use tan. Looking at this image:

camera
(source: proun-game.com)

I figured I could calculate camera Z like this:

cameraPos.z = width / 2 / tan(FOVx / 2)

The result however is incorrect: the camera is zoomed in too far. How much too far varies with the FOVx I set, so it isn't even consistent.

This is the total code used for this:

float cameraZ = -cameraWidth / 2 / tan(FOVx.valueRadians() / 2);
D3DXMATRIX viewMatrix;
D3DXMatrixLookAtLH(&viewMatrix,
                   &D3DXVECTOR3(cameraPos.x, cameraPos.y, cameraZ), // the eye point
                   &D3DXVECTOR3(cameraPos.x, cameraPos.y, 0),       // the camera look-at target
                   &D3DXVECTOR3(0.0f, 1.0f, 0.0f));                 // the current world's up direction

D3DXMATRIX projectionMatrix;
D3DXMatrixPerspectiveFovLH(&projectionMatrix,
                           FOVx.valueRadians() / aspectRatio,   // Field of view in the y direction, in radians
                           aspectRatio,                         // Aspect ratio, defined as view space width divided by height
                           0.01f,                               // Z-value of the near view-plane
                           100.0f);                             // Z-value of the far view-plane

DXMatrix multiplied = worldMatrix * viewMatrix * projectionMatrix;
D3DXMatrixTranspose(&totalMatrixForCurrentObject, &multiplied);

What am I doing wrong here?

(I found this similar question and borrowed their image, but unfortunately the answer there is too general to be of help.)

2

There are 2 answers

1
AudioBubble On

The documentation for D3DXMatrixLookAtLH says that the FOV is specified in the y direction, so you probably want to do your calculation based on the height, not the width.

https://msdn.microsoft.com/en-us/library/windows/desktop/bb205350(v=vs.85).aspx

0
Oogst On

In the meanwhile I've finally solved my problem. :) The mistake turns out to have been that going from fovX to fovY is not simply a matter of dividing by aspect ratio. So this line was the problem:

fovX.valueRadians() / aspectRatio

Going from fovX to fovY can be done in several ways depending on which parameters you use. Here's one way to do it:

fovY = 2 * atan((cameraHeight / 2) / ((cameraWidth / 2) / tan(fovX / 2)))

The camera's Z position I was calculating was already correct! :)