Authors:

- Alen Ladavac, Lead Programmer, Croteam

Targeted audience:

- Croteam programmers
- licencee programmers
- public programmers

Required reading:

Required knowledge:

- C++ programming,
- familiarity with geometry and linear algebra

Explains:

- Description of the most relevant classes and functions in the 'Math' part of the Engine dll.

Vector<> is templated by scalar type contained in the vector and its dimension.

Following vector types are used:

typedef Vector<PIX, 2> PIX2D;

typedef Vector<MEX, 2> MEX2D;

typedef Vector<ANGLE, 3> ANGLE3D; // Euclidean angles (h,p,b)

typedef Vector<FLOAT, 2> FLOAT2D;

typedef Vector<FLOAT, 3> FLOAT3D;

typedef Vector<DOUBLE, 2> DOUBLE2D;

typedef Vector<DOUBLE, 3> DOUBLE3D;

Vector<> has standard operators overloaded:

- sign flipping (unary-)
- addition and substraction of two vectors (+, -, +=, -=)
- multiplication and division with scalar (*, /, *=, /=)
- cross (outer) product (*) (3D only)
- scalar (inner) product (%)

Three norms are defined: Euclidean (Length()), Manhattan (ManhattanNorm()) and Max-norm (MaxNorm).

Normalization works on the vector object itself, and returns its reference (quite like +=).

Elements of the vector are accessed using overloaded operator(), and one-based indices. This is similar to mathematical notations, unlike C-styled arrays. Constructors from elements are given for up to 4 dimensions.

Example:

FLOAT3D v(10, 20, 30);

FLOAT x = v(1);

FLOAT y = v(2);

FLOAT z = v(3);

Matrix<> is templated by the scalar type contained in the matrix and its two dimensions.

Following matrix types are used:

typedef Matrix<FLOAT, 3, 3> FLOATmatrix3D;

typedef Matrix<DOUBLE, 3, 3> DOUBLEmatrix3D;

Elements of the matrix are accessed using overloaded operator(), and one-based indices. First index denotes row and the second one column. This is similar to mathematical notations, unlike C-styled arrays. There are no constructors except default one (which trashes the contents in debug version) and constructor for clearing entire matrix to one given value.

Diagonal matrix can be made with diagonal set to a scalar value or filled with a vector using two overloaded versions of Diagonal().

Multiplication/division with scalar is defined by *, /, *= and /=. Matrix is transposed in-place using ! and from another matrix using !=.

Matrix addition substraction is done by +, -, +=, -=. Matrix multiplication is * or *=.

Quaternion<> is templated by the scalar type contained. It defines construction from 4 scalars, conversion from euler angles (FromEuler()) and into a rotation matrix (ToMatrix()).

Standar operations are defined: flipping (-), congjugation (~), inversion (Inv()), multiplication and division by a scalar (*, *=, /, /=), addition and substraction (+, -, +=, -=), multiplication (*, *=) and dot product (%).

Norm() gives Euclidean lenght of the quaternion. For interpolation, Exp(), Log(), Slerp(), and Squad() are defined.

AABBox<> is templated by contained scalar type and dimension.

Following box types are used:

typedef AABBox<MEX, 2> MEXaabbox2D;

typedef AABBox<PIX, 2> PIXaabbox2D;

typedef AABBox<FLOAT, 2> FLOATaabbox2D;

typedef AABBox<FLOAT, 3> FLOATaabbox3D;

typedef AABBox<DOUBLE, 2> DOUBLEaabbox2D;

typedef AABBox<DOUBLE, 3> DOUBLEaabbox3D;

By default, and aabbox is initialized to a normalized empty bounding box. That is a box whose min vector has maximum values and max vector has minimum values allowed for the type.

It can be constructed to contain only one point, a sphere, or two points (for diagonal construction).

Defined operations are: union (|=), intersection (&, &=), translation by a vector (+=, -=), stretching and expanding (Expand(), StretchByFactor(), StretchByVector()).

Bounding box checking is done with == and != for (in)equality, >= and <= for containment, HasContactWith() and TouchesSphere() for adjacency/contact checking.

To get properties of bounding box, you can use: Size(), Center(), Min(), Max() and IsEmpty().

OBBox<> is templated by the contained scalar type and is always a 3D box.

Following box types are used:

typedef OBBox<FLOAT> FLOATobbox3D;

typedef OBBox<DOUBLE> DOUBLEobbox3D;

Oriented bounding box is defined by its center, 3 axis direction vectors and box size along each of the axes.

It can be constructed as empty, from its components, or from an aabbox and given position and orientation in 3D.

It can be tested only against a 3D plane for now.

Plane<> is templated by the contained scalar type and dimension. Currently, only 3D planes are supported.

Following box types are used:

typedef Plane<FLOAT, 3> FLOATplane3D;

typedef Plane<DOUBLE, 3> DOUBLEplane3D;

A plane is defined by the plane normal vector (always normalized) and distance from the origin along the normal vector.

It can be constructed from its components, from normal vector and a point on the plane, and from 3 points on the plane (in ccw order).

You can access the distance parameter by Distance(), and take advantage of the fact that Plane<> inherites from Vector<> to access its normal vector.

Plane can be flipped (-), translated by a vector (+, -, +=, -=), rotated by multiplication with a matrix (*) and offset forward (Offset()).

PointDistance() finds distance of a point from the plane, GetCoordinate() fills in a missing coordinate of a point on the plane, PlaneDistance() finds distance of a plane from the plane (assuming they are parallel or anti-parallel).

ProjectPoint() and ProjectDirection() project a point or a direction vector to the plane.

DeprojectPoint() and DeprojectDirection() project a point or a direction vector to the plane, but not along this planes normal, but rather along another plane's normal (used in projected mapping).

Euler angles (ANGLE3D) used in Serious Engine are Heading, Pitch and Banking (HPB). Heading is rotation around Y axis, Pitch around X axis and Banking around Z axis. All rotations are mathematically positive (counter-clockwise if viewed from the tip of the imaginary plus vector of the rotation axis, along the axis down towards negative direction).

Simplified: increasing Heading rotates left, increasing Pitch rotates up, increasing Banking tilts to the left. Order of rotations is Banking-Pitch-Heading making Heading most influencing one.

To convert between Euler angles and rotation matrices, use following functions:

MakeRotationMatrix()

MakeInverseRotationMatrix()

DecomposeRotationMatrix()

or

MakeRotationMatrixFast()

MakeInverseRotationMatrixFast()

DecomposeRotationMatrixNoSnap()

The first versions perform snapping, while the latter are faster and smooth.

CPlacement3D is a class consisting simply of a 3D vector (FLOAT3D) and a set of 3 Euler angles (ANGLE3D).

It defines position and orientation of an object in a reference system. The reference can be the absolute coordinate system, or some relative system, depending on the meaning in any given context. The class itself does not retain that information.

For various rotations and translations of a placement use:

Rotate_TrackBall()

Rotate_Airplane()

Rotate_HPB()

Translate_OwnSystem()

Translate_AbsoluteSystem()

To transform between different reference systems use:

AbsoluteToRelative()

RelativeToAbsolute()

RelativeToRelative()

or

AbsoluteToRelativeSmooth()

RelativeToAbsoluteSmooth()

RelativeToRelativeSmooth()

The base function (non-'Smooth') snap the coordinates of the placement after transformation, and are useful only in GUI editing, or CSG operations. Use 'Smooth' variants if snapping is not required.

CProjection3D is an abstract base class for all projections. Projections are generally used for transforming coordinates from one 3D space to another 3D or 2D space.

CSimpleProjection3D implements simple transformation from 3D to 3D, including translation, rotation, uniform stretch and mirroring.

CIsometricProjection3D implements 3D to 2D orthografic projection along an axis parallel to the viewing plane.

CPerspectiveProjection3D implements 3D to 2D perspective projection.

CParallelProjection3D implements 3D to 2D orthografic projection along an axis that is generally not parallel to the viewing plane.

They are mostly used inside engine when rendering or performing some other calculations. From the outside, you will only need to set them up by adjusting viewer placement and viewing parameters (FOV, zoom etc.). You will seldom need to manually project points using projections.

You can transform Euclidean angles to direction vectors and vice versa using:

AnglesToDirectionVector()

DirectionVectorToAngles()

UpVectorToAngles()

To mirror a vector or rotation matrix by a give plane use:

ReflectPositionVectorByPlane()

ReflectDirectionVectorByPlane()

ReflectRotationMatrixByPlane_cols()

ReflectRotationMatrixByPlane_rows()

Misc. management with vectors and matrices (useful in AI and physics):

GetParallelComponent()

GetNormalComponent()

GetParallelAndNormalComponents()

OrthonormalizeRotationMatrix()