pret / pokeplatinum

Decompilation of Pokémon Platinum
188 stars 62 forks source link

Document 3D Camera #228

Closed Fexty12573 closed 3 months ago

Fexty12573 commented 3 months ago

Documents the 3D Camera used by the game.

Below is a quick write-up of how the camera works. (Sorry for wall of text 😛)

Camera Tracking

Using the Camera_TrackTarget function, a pointer to a VecFx32 can be passed, which will be tracked by the camera. The main update function of the camera is Camera_ComputeViewMatrix which, as the name implies, calculates the cameras view matrix based on its position, target position, and angle.

It's important to note that by default the camera does not support rotation around the Z axis (i.e. "roll"). Z axis rotation is only taken into account when using Camera_ComputeViewMatrixWithRoll. By default, this function is only used when the player is in the distortion world. (It can however be enabled by setting unk_20 in FieldSystem to 1. Also notable is that sprites don't get rotated (regardless of rotation axis).

Tracking can also be limited to only one or two axes using the trackTarget[XYZ] fields in the camera.

Camera Position History

The camera has a "history" built in (has to be explicitly enabled using Camera_InitHistory) which allows following a target with a delay. It uses a circular buffer to store a history of camera position deltas, which are applied with a delay of any number of frames. The size of the history buffer is dependent on how many frames of delay are requested. Just like the normal tracking, the delay can also only be applied to one or more axes.

Free Move

The camera can also act on its own without being locked to a target. In this mode all camera operations must be manually performed, as opposed to tracking mode where the camera automatically moves relative to the target. Z axis rotation also requires using the dedicated function.

Angles

Camera angles are specified as pitch, yaw, and roll. Typically held in a CameraAngle struct, each component represents an index into the Sin/Cos table. This means that a value of 0 is 0°, and a value of 65535 is 360°. This can lead to some confusion because passing FX32_CONST(3.14159265358 / 2) as an angle does not equate to 90°, it would instead have to be FX_RAD_TO_IDX(FX32_CONST(3.14159265358 / 2)).

Depending on which mode the camera is in, there are 2 different functions used for setting the camera angle:

Projection

The Camera_ComputeProjectionMatrix function takes a projection parameter, which can be either CAMERA_PROJECTION_PERSPECTIVE or CAMERA_PROJECTION_ORTHOGRAPHIC, for perspective or orthographic projection respectively.

Active Camera

For a camera to be used for rendering it must first be set as the active camera using Camera_SetAsActive, because Camera_ComputeViewMatrix[WithRoll] does not take any parameter. The camera can also be disabled using Camera_ReleaseActive.