Please send suggestions or corrections for this page to the author at sbuss@ucsd.edu.
This page gives basic documentation for using the GlLinearMath functions. The GlLinearMath routines are a collection of routines for working with vectors in R2, R3, and R4. They were developed for joint use on a number of projects, including the author's ray tracing software and OpenGL code examples.
PAGE UNDER DEVELOPMENT
The most commonly used vector and matrix types in GlLinearMath are:
VectorR2
VectorR3
VectorR4
LinearMapR2
LinearMapR3
LinearMapR4
Remark: The matrix classes are built on type of subclasses called
Matrix2x2
, Matrix3x3
and Matrix4x4
. These
classes are not really intended to be used directly. Earlier
versions of the code also contained classes called
RotationMapR2
,
RotationMapR3
,
AffineMapR3
,
RigidMapR2
and
RotationMapR4
; these have been removed from GlLinearMath,
but are still available in VrMath.
To work with 2-vectors and 2x2 matrices, you need the files
LinearR2.h, LinearR2.cpp,
and mathMisc.h. And, you must use
#include <LinearR2.h>
.
To work with 3-vectors and 3x3 matrices, you need the files
LinearR3.h, LinearR3.cpp,
and mathMisc.h. And, you must use
#include <LinearR3.h>
.
To work with 4-vectors and 4x4 matrices, you need the files
LinearR3.h, LinearR4.h,
LinearR3.cpp, LinearR4.cpp,
and mathMisc.h. And, you must use
#include <LinearR4.h>
.
We discuss mostly VectorR3
below. But
the vector classes VectorR2
and VectorR4
work similarly. (The main exception
is for crossproduct, which is exclusive to VectorR3
.)
You can allocate and set a VectorR3
by
any of the following methods:
this code sets vec1
through vec6
all
equal to the vector <1,2,3>.
VectorR3 vec1(1.0, 2.0, 3.0);
VectorR3 vec2 = VectorR3(1.0, 2.0, 3.0);
VectorR3 vec3;
vec3.Set(1.0, 2.0, 3.0);
VectorR3 vec4;
vec4.x = 1.0;
vec4.y = 2.0;
vec4.z = 3.0;
VectorR3 vec5 = vec4;
double values[3] = {1.0, 2.0, 3.0};
VectorR3 vec6;
vec6.Load(&values[0]);
The command vec7.SetZero();
sets a vector equal to zero.
The analogous methods work for VectorR2
and VectorR4
's. A VectorR2
has only the members x
and y
(no z
).
A VectorR4
has the four members x
, y
,
z
and w
.
The vector classes support the usual operations of
addition (+
and +=
) and
subtraction (-
and -=
) of
two vectors, multiplication
(*
and *=
)
of a vector and a scalar,
and division of a vector by a scalar
(/
and /=
). There is also
a special AddScaled
command that adds
on a scalar multiple of another vector.
As examples, here are four different ways of
setting the vector vecA
equal to
2*vecB+vecC
:
vecA = 2.0 * vecB + vecC;
vecA = vecB;
vecA *= 2.0;
vecA += vecC;
vecA = vecB;
vecA /= 0.5;
vecA += vecC;
vecA = vecC;
vecA.AddScaled(vecB, 2.0);
The dot product (^
), cross product (*
),
and the component-wise products can be computed by
the following commands. For each command, u
, v
and
w
are VectorR3
objects, and dotp
is a
scalar (a double
).
dotp = u^v;
// Computes the dot product of u
and v
.
dotp = InnerProduct(u,v);
// Another way to compute the dot product of u
and v
.
u = v*w;
// Computes the cross product of v
and w
.
u *= w;
// Sets u
equal to the cross product of u
and w
.
u.CrossProductLeft(w);
// Sets u
equal to the cross product of w
and u
. (Note
order of the product.)
u = ArrayProd(v,w);
// Component-wise products: Sets the components of u
equal to the products of the corresponding components of
v
and w
. (This is not a common mathematical construction,
but can often be useful in computer graphics applications.)
The same commands (except for cross product!) can be used
with VectorR2
and VectorR4
objects.
The following functions compute the norm (magnitude) of a vector, or the distances
between two vectors. The "Sq" versions return the square of the
value: these can be used when possible to avoid a square root. All these functions
return a double
.
x = u.Norm();
// Computes the norm (magnitude) of u
.
x = u.NormSq();
// Computes the square of the norm of u
.
x = Dist(u, v);
// Computes the Euclidean distance between u
and v
.
x = DistSq(u, v);
// Computes the square of the Euclidean distance between u
and v
.
The following method normalize of vector u
; namely,
it replaces a u
with a unit vector
in the direction of u
. Of course, u
should
not be the zero vector.
u.Normalize();
// Divides u
by its magnitude, to make it a unit vector.
For specialized use only: If u
is extremely close to being a unit,
a more computationally efficient way to normalize it is to
call u.ReNormalize();
. This can be
useful in animation where roundoff errors can accumulate as vectors
are rotated.
We discuss mostly how to use LinearMapR3
objects
for linear maps on R3, namely for 3x3 matrices.
Only the most commonly useful methods are covered: for a full description
of all the methods and functions, see
the header file definitions for the classes
Matrix3x3
and LinearMapR3
.
Similar methods work for LinearMapR2
's
and LinearMapR4
's.
You can explicitly set the entries in either column-order or row-order; however, in keeping with the usual conventions in computer graphics, column-order is preferred. The following lines of code show different ways to load matrices with the entries 1-9, in column order (so that, for instance, the first column contains 1,2,3):
LinearMapR3 mat1(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0);
LinearMapR3 mat2;
mat2.Set(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0);
VectorR3 column1(1.0, 2.0, 3.0), column2(4.0, 5.0, 6.0), column3(7.0, 8.0, 9.0);
LinearMapR3 mat3(column1, column2, column3);
LinearMapR3 mat4;
mat4.Set(column1, column2, column3);
If you want to set a matrix in row order, this can be done with
the SetByRows
methods; namely,
LinearMapR3 mat5;
mat5.SetByRows(1.0, 4.0, 7.0, 2.0, 5.0, 8.0, 3.0, 6.0, 9.0);
VectorR3 row1(1.0, 4.0, 7.0), row2(2.0, 5.0, 8.0), row3(3.0, 6.0, 9.0);
LinearMapR3 mat6;
mat6.SetByRows(row1, row2, roy3);
There are convenience commands for setting a matrix to the zero matrix, or the identity matrix:
mat7.SetZero(); // Set mat7 to the zero matrix
mat8.SetIdentity(); // Set mat8 to the identity matrix
There are methods SetColumn1
, SetColumn2
,
SetColumn3
, SetRow1
, SetRow2
and SetRow3
to set a single column or row. There are also
that functions to access a single column or row. For instance,
mat1.Column1()
will return the first column of mat1
as a VectorR3
object.
The matrix classes support the usual operations of
addition (+
and +=
) and
subtraction (-
and -=
) of
two matrices, of multiplication
(*
and *=
)
of a matrix and a scalar,
and division of a matrix by a scalar
(/
and /=
)
These use the usual C++ syntax; as shown above in the section
"Calculating with vectors".
To multiply a matrix and vector, use M * x
. For example,
with x
a VectorR3
and M
a
LinearMapR3
,
VectorR3 y = M * x; // Sets y := M*x.
The following functions allow you to transpose and invert matrices.
In the examples, M
and N
are matrices.
MT
and M-1
denote the transpose
and the inverse of M
:
M = N.Transpose(); // Sets M := NT.
M.MakeTranspose(); // Sets M := MT.
M = N.Inverse(); // Sets M := N-1.
M.Invert(); // Sets M := M-1.
If you do not need to invert a matrix, but just want to solve an equation z = M x, where z is a known vector, you can use:
VectorR3 x = M.Solve(z); // Sets x := M-1(z)
There are also some specialized functions for multiplying by matrices on the right, and for multiplying by a transposed matrix.
M *= N; // Sets M := M * N.
M.LeftMultiplyBy(N); // Sets M := N * M.
M.RightMultiplyByTranspose(N); // Sets M := M * (NT).
M.LeftMultiplyByTranspose(N); // Sets M := (NT) * M.
LinearMapR4
's).
The LinearMapR4
contains functions for reproducing the
functionality of legacy OpenGL commands for projection and modelview
matrices. These include the following commands for setting a matrix
M
(that is, a LinearMapR4
M
).
For more details on these see the author's textbook on
3D Computer Graphics (second edition) or other
OpenGL documentation.
The rotation functions in LinearMapR4 take angles in radians (unlike OpenGL, not degrees!)
M.Set_glScale(alpha); // Same as M.Set_glScale( alpha, alpha, alpha) -- Uniform scaling.
M.Set_glScale(x, y ,z); // Set M to nonuniform scaling matrix.
M.Set_glTranslate(x, y, z); // Set M to matrix for translation by <x,y,z>.
M.Set_glTranslate(vec); // Set M to matrix for translation by VectorR3 vec.
M.Set_glRotate(angle, x, y, z); // Set M to matrix that rotates angle radians around <x,y,z>.
M.Set_glRotate(angle, vec); // Set M to matrix that rotates angle radians around VectorR3 vec.
M.Set_glFrustum(left, right, bottom, top, near, far); // Set M to OpenGL glFrustum matrix.
M.Set_glOrtho(left, right, bottom, top, near, far); // Set M to OpenGL glOrtho matrix.
M.Set_gluPerspective(fov_y_radians, aspectRatio, zNear, zFar); // Set M to OpenGL gluPerspective matrix.
M.Set_gluLookAt(eyePos, lookAtPos, upDir); // Set M to OpenGL gluLookAt matrix
// - eyePos, lookAtPos, upDir are VectorR3's
The first block of functions have corresponding functions which multiply M
on the right by the indicated matrix (similar to legacy OpenGL functions):
M.Mult_glScale(alpha); // Same as M.Mult_glScale( alpha, alpha, alpha) -- Uniformly scale.
M.Mult_glScale(x, y ,z); // Multiply M by nonuniform scaling matrix.
M.Mult_glTranslate(x, y, z); // Multiply M by matrix for translation by <x,y,z>.
M.Mult_glTranslate(vec); // Multiply M by matrix for translation by VectorR3 vec.
M.Mult_glRotate(angle, x, y, z); // Multiply M by matrix that rotates angle radians around <x,y,z>.
M.Mult_glRotate(angle, vec); // Multiply M by matrix that rotates angle radians around VectorR3 vec.
LinearMapR3
's
There are also some useful functions for manipulating linear transformations in
R3. These include the following, where u
and w
are
VectorR3
's; and M
is a LinearMapR3
.
M.SetCrossProductMatrix( const VectorR3& u ); // Set M equal to the crossproduct matrix Mu×.
// Then M*w will equal u*w (vector crossproduct).
M = LinearMapR3 VectorProjectMap( u ); // Set M equal to the linear map that projects onto the vector u.
// Important: u must be a unit vector.
M = LinearMapR3 PlaneProjectMap ( w ); // Set M equal to the linear map that projects onto the plane P
// that is perpendicular to w and contains the origin.
// Important: w must be a unit vector.
There are other special VectorR3
and LinearMapR3
functions available; for these, see
the header file declarations.
The "Dump" functions work oppositely to the "Load" functions mentioned above. They allow
writing the entries of a vector or a matrix into an array of floats or doubles. We illustrate
the dump function for a LinearMapR4
object M
:
float valuesf[16]; // Allocate space for all 16 entries
M.DumpByColumns(&valuesf[0]); // Store entries in column order in the array.
The function DumpByColumns
with float
's is helpful to extract a matrix's entries
for use with OpenGL.