nngn
|
Abstract orthographic/perspective camera. More...
#include <camera.h>
Public Types | |
enum | Flag : u8 { UPDATED = 1u << 0 , SCREEN_UPDATED = 1u << 1 , DASH = 1u << 2 , PERSPECTIVE = 1u << 3 , IGNORE_LIMITS = 1u << 4 } |
State flags and configuration. More... | |
Public Member Functions | |
bool | dash (void) const |
bool | perspective (void) const |
void | set_dash (bool b) |
void | set_perspective (bool b) |
void | set_ignore_limits (bool b) |
vec3 | center (void) const |
p added to a unit vector in the view direction. | |
vec3 | up (void) const |
The "up" vector for the view direction. | |
vec3 | world_to_view (vec3 p) const |
Projects a point from world to view space. | |
vec3 | view_to_clip (vec3 p) const |
Projects a point from view to clip space. | |
vec2 | clip_to_screen (vec3 p) |
Projects a point from clip to screen space. | |
vec3 | screen_to_clip (vec2 p) |
Projects a point from screen to clip space. | |
vec3 | clip_to_view (vec3 p) const |
Projects a point from clip to view space. | |
vec3 | view_to_world (vec3 p) const |
Projects a point from view to world space. | |
float | z_for_fov (void) const |
Derives Z coordinate from the camera's screen size and field of view. | |
float | scale_for_fov (void) const |
Derives orthographic scaling factor from camera parameters. | |
void | set_pos (vec3 p) |
void | set_rot (vec3 r) |
void | set_zoom (float z) |
void | set_fov_y (float f) |
void | set_fov_z (float z) |
void | set_screen (uvec2 s) |
void | set_limits (vec3 bl, vec3 tr) |
void | look_at (vec3 center, vec3 pos, vec3 up) |
bool | update (const Timing &t) |
Static Public Member Functions | |
static constexpr float | fov (float z, float w) |
Calculates field of view based on screen size and distance. | |
Public Attributes | |
vec3 | p = {} |
Position. | |
vec3 | v = {} |
Velocity. | |
vec3 | a = {} |
Acceleration. | |
vec3 | rot = {} |
Rotational Euler angles (ZYX). | |
vec3 | rot_v = {} |
Rotational velocity. | |
vec3 | rot_a = {} |
Rotational acceleration. | |
vec3 | bl_limit = {-INFINITY, -INFINITY, -INFINITY} |
Bottom left point of the limit for p. | |
vec3 | tr_limit = {+INFINITY, +INFINITY, +INFINITY} |
Top right point of the limit for p. | |
float | zoom = 1 |
Scaling factor. | |
float | zoom_v = {} |
Scaling factor velocity. | |
float | zoom_a = {} |
Scaling factor acceleration. | |
float | max_v = INFINITY |
Maximum value for v. | |
float | max_rot_v = INFINITY |
Maximum value for rot_v. | |
float | max_zoom_v = INFINITY |
Maximum value for zoom_v. | |
float | fov_y = FOVY |
Field of view in perspective mode. | |
float | fov_z = {} |
Enable auto-adjustment of the field-of-view angle. | |
float | damp = {} |
Damping factor when not accelerating. | |
uvec2 | screen = {} |
Screen size. | |
mat4 | proj = mat4{1} |
Projection matrix (orthographic/perspective). | |
mat4 | screen_proj = mat4{1} |
Projection matrix for screen coordinates. | |
mat4 | view = mat4{1} |
View matrix. | |
mat4 | inv_proj = mat4{1} |
Inverse matrix of proj. | |
mat4 | inv_view = mat4{1} |
Inverse matrix of view. | |
Flags< Flag > | flags = {} |
Static Public Attributes | |
static constexpr float | NEAR = 0.01f |
Perspective projection near plane. | |
static constexpr float | FAR = 2048 |
Perspective projection far plane. | |
static constexpr float | FOVY = static_cast<float>(Math::pi() / 3) |
Perspective projection field of view along the Y axis (default). | |
Abstract orthographic/perspective camera.
Two complementary projection modes are supported: orthographic and perspective. Some facilities are provided to make them as close to each other as possible.
In orthographic mode, objects ocupy the XY plane. The projection matrix is set up so that objects are displayed in their natural size, scaled by the zoom parameter. Their Z position is expected to be set such that they can be rendered in any order, using a depth buffer to sort overlaps.
The z
value of the position is also used as a scaling factor. This preserves the size of objects on the XY plane when transitioning from ortographic to perspective mode, as long as the camera remains parallel to the Z axis. The scaling factor is the ratio of z_for_fov to the z
position.
In perspective mode, objects maintain their position in the XY plane but have a third dimension in the Z direction. A standing sprite thus has the same XY position but is rotated 90° at its base around the X axis. Although counter-intuitive, having the "up" vector parallel to the Z axis (as opposed to the Y axis, as is commonly done) allows sprites to occupy the same XY position in both projection modes.
This mode tries to be as close to the orthographic mode as possible, by adjusting the camera's projection matrix and Z position so that the position and relative scale of objects is maintained as long as the camera view vector is parallel to the Z axis. With the regular camera orientation facing the direction of the -Z axis, toggling between the two projection modes leaves objects in the XY plane (such as the map) unchanged.
Calculations of dimensions, field-of-view, etc. are based on a 14"/35.5cm, 16:9 laptop monitor at a distance of 60cm from the camera/eye:
x/y ----- x = 31cm \z| / y = 17.4cm \|/ z = 60cm fov fov = 2 * atan(31/60) ~= 60° = π/3
The initial size of the window is taken to be the full screen size and assigned a vertical field-of-view angle of 60° (π/3). This angle can be automatically adjusted when the window is resized (see set_fov_z): this ensures the image is not distorted — i.e. objects retain their size and proportion — in perspective mode.
enum nngn::Camera::Flag : u8 |
State flags and configuration.
Enumerator | |
---|---|
UPDATED | Parameters of the camera have changed. This indicates the matrices need to be recalculated (via update). |
SCREEN_UPDATED | The screen size has changed. Not used internally, but can be used by external code mid-frame to determine whether values dependent on the screen size need to be updated. |
DASH | Increases the speed of displacement/rotation/etc. |
PERSPECTIVE | Chooses between orthographic/perspective mode. |
IGNORE_LIMITS | The camera limits do not restrict movement when set. |
vec3 nngn::Camera::center | ( | void | ) | const |
Projects a point from clip to screen space.
Projects a point from clip to view space.
|
inline |
Calculates field of view based on screen size and distance.
w ----- a = fov / 2, op = w / 2, adj = z \z| / tan(a) = op / adj \|/ tan(fov/2) = w / 2 / z fov
z | Distance from the camera to the projection plane. |
w | Width of the projection plane. |
z
has width w
.
|
inline |
|
inline |
Derives orthographic scaling factor from camera parameters.
When an orthographic projection is used (i.e. when the camera's Z position does not alter the apparent size of objects), this factor can be used to preserve the size of objects directly on the XY plane as if a perspective projection were used (with the same constraints as z_for_fov).
y' --------- y = screen.y \ z'| / z = z_for_fov(), z' = p.z y\-----/ y' / z' = y / z \z| / s = y / y' \|/ s = z / z' fov
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
vec3 nngn::Camera::up | ( | void | ) | const |
The "up" vector for the view direction.
Projects a point from view to clip space.
Projects a point from view to world space.
Projects a point from world to view space.
|
inline |
Derives Z coordinate from the camera's screen size and field of view.
When changing the camera's projection matrix from perspective to orthographic, using this Z coordinate will preserve the size of objects directly on the XY plane (provided the camera's view vector is perpendicular to it, i.e. parallel to the Z axis).
y ----- a = fov / 2, op = y / 2, adj = z \z| / tan(a) = op / adj \|/ tan(fov / 2) = y / 2 / z fov z = y / 2 / tan(fov / 2)
vec3 nngn::Camera::a = {} |
Acceleration.
vec3 nngn::Camera::bl_limit = {-INFINITY, -INFINITY, -INFINITY} |
Bottom left point of the limit for p.
float nngn::Camera::damp = {} |
Damping factor when not accelerating.
|
staticconstexpr |
Perspective projection far plane.
float nngn::Camera::fov_z = {} |
Enable auto-adjustment of the field-of-view angle.
In perspective mode, this makes the image retain its size when the window is resized. The value should be z_for_fov. A value of zero disables auto-adjustment.
Perspective projection field of view along the Y axis (default).
vec3 nngn::Camera::p = {} |
Position.
vec3 nngn::Camera::rot = {} |
Rotational Euler angles (ZYX).
vec3 nngn::Camera::rot_a = {} |
Rotational acceleration.
vec3 nngn::Camera::rot_v = {} |
Rotational velocity.
uvec2 nngn::Camera::screen = {} |
Screen size.
vec3 nngn::Camera::v = {} |
Velocity.
float nngn::Camera::zoom = 1 |
Scaling factor.
float nngn::Camera::zoom_a = {} |
Scaling factor acceleration.
float nngn::Camera::zoom_v = {} |
Scaling factor velocity.