Orrery
A GPU-accelerated N-body gravitational simulator
Loading...
Searching...
No Matches
matrix4.hpp File Reference

The 4-by-4 transforms a camera needs, and nothing else. More...

#include <array>
#include <cstddef>
#include "orrery/core/vec3.hpp"

Go to the source code of this file.

Classes

struct  orrery::viz::Vec4
 A point or direction in homogeneous coordinates. More...
struct  orrery::viz::Mat4
 A 4-by-4 transform in column-major order. More...

Functions

constexpr Mat4 orrery::viz::identity () noexcept
constexpr Mat4 orrery::viz::operator* (const Mat4 &a, const Mat4 &b) noexcept
 The transform that applies b and then a, as matrix products conventionally read.
constexpr Vec4 orrery::viz::operator* (const Mat4 &matrix, const Vec4 &vector) noexcept
constexpr Vec4 orrery::viz::homogeneous (core::Vec3 point) noexcept
 A point in world space, ready to be transformed.
Mat4 orrery::viz::look_at (core::Vec3 eye, core::Vec3 centre, core::Vec3 up) noexcept
 The view transform of a camera at eye looking at centre.
Mat4 orrery::viz::perspective (float vertical_field_of_view, float aspect_ratio, float near, float far) noexcept
 The perspective projection of a symmetric frustum.

Detailed Description

The 4-by-4 transforms a camera needs, and nothing else.

This is not a linear algebra library. It holds the three matrices a point renderer uses, a view, a projection and the product of the two, along with the operations needed to build and apply them. Anything a general matrix type would also offer, an inverse, a decomposition, an arbitrary-size template, would be code with one caller or none.

Why this is float when the rest of the project may be double

Every number here ends up in a uniform mat4 or a vertex attribute, and OpenGL's fixed-function pipeline works in single precision whatever is handed to it. A double-precision camera would be exact about a quantity that becomes a 24-bit depth value and a pixel on a screen. The simulation's own precision is a separate decision, made in core/types.hpp for reasons that are about the physics; this one is about the display.

The conversion happens at the boundary, where a position in the simulation's scalar type becomes a coordinate in the camera's. That is safe for the coordinates this project produces, which are of order tens in N-body units and so are represented to seven significant figures, far finer than a pixel.

Layout

Column-major, so element(row, column) is values[column * 4 + row]. That is the layout glUniformMatrix4fv expects with transposition off, which means a matrix built here can be handed to the driver without a copy or a flag. The cost is that the initialiser lists below read as the transpose of the matrix they represent, so each one is written a column at a time and says so.

Function Documentation

◆ look_at()

Mat4 orrery::viz::look_at ( core::Vec3 eye,
core::Vec3 centre,
core::Vec3 up )
nodiscardnoexcept

The view transform of a camera at eye looking at centre.

Right-handed, with the camera looking down its own negative z axis, which is the convention OpenGL's clip space is defined against.

up only has to be non-parallel to the direction of view; the component of it along that direction is removed. A camera looking straight down its own up vector has no defined orientation, and the caller is responsible for not asking for one. OrbitCamera does that by clamping its elevation.

◆ perspective()

Mat4 orrery::viz::perspective ( float vertical_field_of_view,
float aspect_ratio,
float near,
float far )
nodiscardnoexcept

The perspective projection of a symmetric frustum.

vertical_field_of_view is in radians and is the whole angle, not the half angle. near and far are positive distances in front of the camera, and both must be, since the transform divides by their difference and maps the near plane to a depth that is only meaningful for a frustum in front of the eye.