6. DynamicStereoCamera Class

6.1. Specifying the Window

When you are using a static camera, you specify the frustum. But when you are using a dynamic camera, you need to specify the window. You must also specify the near and far planes.

6.1.1. Setting the Window From Its Size in Virtual Space

You can specify the window width and the depth at which it is placed from the center of the camera. The resulting window is centered on the z-axis of the camera, and its height is set to match the aspect ratio of the device's upper screen.

Note that the ratio of the window width and the window depth determines the FOV.

This method assumes that the resulting image will be displayed on the entire upper screen.

Code 6-1. SetWindowFromSize Function Definition
void SetWindowFromSize(const f32 windowWidth,
                       const f32 nearDepth,
                       const f32 windowDepth,
                       const f32 farDepth); 

6.1.2. Deriving the Window From the Base Camera Frustum

You can give left, right, bottom, and top tangent angles of the base camera frustum. The window is then defined as the intersection of this frustum and the plane at window depth. You can use this method to describe viewports that do not cover the entire screen. Compute the viewport border tangents from a standard viewing position in front of the center of the screen. It is assumed that the resulting image will be displayed on the largest area of the screen that matches the viewport description.

Code 6-2. SetWindowFromTangent Function Definition
void SetWindowFromTangent(const f32 tangentLeft,
                          const f32 tangentRight,
                          const f32 tangentBottom,
                          const f32 tangentTop,
                          const f32 nearDepth,
                          const f32 windowDepth,
                          const f32 farDepth); 

6.1.3. Setting the Window From the Viewport

To deal with a viewport that only covers a portion of the screen, you need to know the location of the viewport within the screen. The following member function is useful when you are using this kind of viewport and a realistic FOV.

Code 6-3. SetWindowFromViewport Function Definition
void SetWindowFromViewport(const f32 screenHorizontalHalfFOVTangent,
                           const f32 viewportLeftInUnitSceen,
                           const f32 viewportRightInUnitSceen,
                           const f32 viewportBottomInUnitSceen,
                           const f32 viewportTopInUnitSceen,
                           const f32 nearDepth,
                           const f32 windowDepth,
                           const f32 farDepth); 

6.1.4. Setting the Window Based on an Existing Projection Matrix

You can also set the window by specifying the window depth and the projection matrix of the base camera used to calculate the frustum.

However, this method can only be used for a projection matrix that targets the entire upper screen and assumes a symmetric frustum.

Code 6-4. SetWindowFromProjectionMatrix Function Definition
void SetWindowFromProjectionMatrix(const nn::math::Matrix44 *proj,
                                   const f32 windowDepth); 

6.2. Specifying the Base Camera’s View

Code 6-5. SetView Function Definition
void SetView(const nn::math::MTX34* viewMatrix);
void SetView(const nn::math::VEC3& position,
             const nn::math::VEC3& upDirection,
             const nn::math::VEC3& forwardDirection); 

Either specify the view matrix created by a function such as nn::math::MTX34LookAt, or directly specify the parameters for the base camera’s position. Make sure that you use the right-handed coordinate system adopted by the CTR graphics system when specifying the view matrix or the nn::math::Vector3 arguments.

6.3. Computing Left and Right Cameras

Code 6-6. ComputeViewsAndProjections Function Definition
f32 ComputeViewsAndProjections(
    nn::math::Matrix44* projL, nn::math::Matrix34* viewL,
    nn::math::Matrix44* projR, nn::math::Matrix34* viewR,
    const nn::math::VEC2* leftEyeTangent,
    const nn::math::VEC2* rightEyeTangent,
    const Setting& setting,
    const nn::math::PivotDirection pivot = nn::math::PIVOT_UPSIDE_TO_TOP
) const; 

This method is used to compute projection and view matrices to render left and right images for the left and right eyes.

This method assumes that the user is placed at the optimal distance from the surface of the LCD screen. It can provide a realistic stereoscopic view and other non-realistic (or artistic) views based on the setting parameter, explained below. This method can take into account the user's head position, and adjust the dynamic perspective accordingly.

The leftEyeTangent and rightEyeTangent parameters describe the position of the left and right eyes of the user relative to the screen. These values can be retrieved by a call to the nn::qtm::CTR::GetTrackingData() function.

When either leftEyeTangent or rightEyeTangent is NULL, this method produces the same behavior as a static stereoscopic camera. Set these parameters to NULL when developing for the CTR platform.

The upward direction of the camera in the generated projection matrix is the upward direction as determined by the pivot parameter. If pivot is set to nn::math::PIVOT_NONE, no rotation is applied. If an invalid value is specified for pivot, the function halts on an assertion. The default value is nn::math::PIVOT_UPSIDE_TO_TOP.

The function returns the factor for the distance between cameras, ƒI. This factor is described in the appendix.

6.4. Setting Class

Code 6-7. Setting Class Definition
struct Setting
{
    f32 StereoFactor;
    f32 ParallaxDistanceLimit;
    f32 DynamicPerspectiveAmplitudeX;
    f32 DynamicPerspectiveAmplitudeY;
    f32 DynamicPerspectiveClampingLeft;
    f32 DynamicPerspectiveClampingRight;
    f32 DynamicPerspectiveClampingBottom;
    f32 DynamicPerspectiveClampingTop;
    f32 RealisticFovFactor;
    f32 WideFovMotionFactor;
    bool TiltEnabled;
} 

You can use the Setting class passed as an argument to the ComputeViewsAndProjections() function to adjust the behavior of the stereoscopic camera.

  • StereoFactor adjusts the stereoscopic effect, as described in 4.7 3D Slider and Stereo Factor.
  • ParallaxDistanceLimit specifies the parallax distance limit, in millimeters. This limit is the maximum distance between the object in the image for the left eye and the object in the image for the right eye. For more information, see 4.6 Parallax Distance Limit.
  • DynamicPerspectiveAmplitudeX and DynamicPerspectiveAmplitudeY are multiplication factors for the user position. They amplify or reduce the dynamic perspective effect for a head movement.
  • DynamicPerspectiveClampingLeft, DynamicPerspectiveClampingRight, DynamicPerspectiveClampingBottom, and DynamicPerspectiveClampingTop are used to clamp the user’s position horizontally and vertically. They take values in the range from 0 through 1. When set to 1, the position is clamped to the limit value obtained using GetTrackingData. If set to a value in the middle of the range, the position is clamped to the corresponding fraction of the limit value. If set to 0, the camera stops moving in that direction. Note that the position is clamped before the amplitude set by DynamicPerspectiveAmplitude is applied.
  • RealisticFovFactor is used to interpolate the camera position between the realistic camera and the base camera, as described in 4.2 Realistic FOV Factor.
  • WideFovMotionFactor adjusts how the camera moves in response to movements by the user when a wide FOV is being used, as described in 4.1 Wide FOV.
  • TiltEnabled indicates whether tilt is enabled or disabled. For more information, see 4.5. Tilt and Improved Static Stereoscopic Camera.

6.5. Occupancy Volume

Code 6-8. OccupancyVolume Structure Definition
struct OccupancyVolume
(
    math::VEC3 CameraCenter;
    math::VEC3 ForwardDirection;
    math::VEC3 OrthoUpDirection;
    math::VEC3 RightDirection;
    f32 NearPlaneDepth;
    f32 NearLeft;
    f32 NearRight;
    f32 NearBottom;
    f32 NearTop;
    f32 CameraLeft;
    f32 CameraRight;
    f32 CameraBottom;
    f32 CameraTop;
}; 

Use the OccupancyVolume structure to express the occupancy volume of the camera. To guarantee that artifacts do not appear unnatural due to the camera crossing paths with objects, make sure that no objects are located inside this volume.

  • CameraCenter is the camera position when dynamic perspective is disabled. If RealisticFovFactor is set to 0, this position is the same as that specified by the SetView member function. For any value greater than 0, the camera position is adjusted along the axis in the forward direction, approaching the realistic FOV. The plane on which the camera moves for dynamic perspective is called the camera plane.

  • ForwardDirection is the unit vector in the forward direction. The value is the same as that set by the SetView member function.
  • OrthoUpDirection is the unit vector in the upward direction. It bisects at right angles with ForwardDirection.
  • RightDirection is the unit vector in the rightward direction. Because it bisects at right angles with ForwardDirection and OrthoUpDirection, you can calculate the rightward vector from their cross product.

RightDirection = ForwardDirection × OrthoUpDirection

  • NearPlaneDepth is the distance from the camera position to the near plane.
  • NearLeft and NearRight define the range of the occupancy volume in the horizontal direction (in the direction of the rightward vector) in the near plane.
  • NearBottom and NearTop define the range of the occupancy volume in the vertical direction (in the direction of the upward vector) in the near plane.
  • CameraLeft and CameraRight define the range of the occupancy volume in the horizontal direction in the camera plane.
  • CameraBottom and CameraTop define the range of the occupancy volume in the vertical direction in the camera plane.
Figure 6-1. Occupancy Volume Parameters

Occupancy Volume pancy Volume


CONFIDENTIAL