Linear Algebra Upgraded
Eric Lengyel, Ph.D.
Terathon Software
About the speaker
● Working in game/graphics dev since 1994
● Previously at Sierra, Apple, Naughty Dog
● Current projects:
● Slug Library, Tombstone Engine, The 31st, FGED
2
About this talk
● Vector / matrix implementation in C++
● Vectors, points, planes, lines, antivectors
● Swizzling (like shading languages)
● Matrix manipulation
● 2D, 3D, 4D
3
About this talk
● Promoting mathematical correctness
● Providing zero-cost conveniences
● Vector swizzling: v1 = v2.zyx
● Row/column extraction: m.row1, m.col0
● Free transpose: v1 = m.transpose * v2
4
About this talk
● Many ways to implement math library
● Many ways equally correct
● Purpose of this talk is to share my
experiences with code I’ve developed and
refined over many years and give advice
● You are free to implement what you like
5
About this talk
● Skipping obvious stuff
● Like overloading operator + for two vectors
● Focusing on things that are not common
6
Class Names
● Vector2D, Vector3D, Vector4D, Point3D
● Matrix3D, Matrix4D, Transform4D
● Bivector3D (normals)
● Bivector4D (lines)
● Trivector4D (planes)
7
Grassmann Algebra
● Foundations of Game Engine
Development, Volume 1
● “Fundamentals of Grassmann
Algebra” (GDC 2012)
● “Grassmann Algebra in Game
Development” (GDC 2014)
8
Grassmann Algebra
● Thorough understanding not necessary
● Vector/antivector distinction most important
● Various facts stated throughout this talk
9
Basic Vector
class Vector2D class Vector3D class Vector4D
{ { {
public: public: public:
float x, y; float x, y, z; float x, y, z, w;
... ... ...
}; }; };
10
Constructors
Vector3D() = default;
Vector3D(float a, float b, float c)
{
x = a; y = b; z = c;
}
Vector3D(const Vector3D& v)
{
x = v.x; y = v.y; z = v.z;
}
11
Promotions
Vector3D(const Vector2D& v) Vector4D(const Vector3D& v)
{ {
x = v.x; x = v.x;
y = v.y; y = v.y;
z = 0.0F; z = v.z;
} w = 0.0F;
}
12
Overloaded Operators
● Obvious addition / subtraction
● Multiplication by scalar
● Division by scalar
● Multiplication of two vectors componentwise
● Consistent with shading languages
13
Division by Scalar
Vector3D& operator /=(float s)
{
float t = 1.0F / s;
x *= t;
y *= t;
z *= t;
return (*this);
}
14
Dot and Cross Product
● Recommend dot() and cross() functions
● Could overload * and % (or others)
● But this can get confusing
● Makes code hard to read
15
Wedge and Antiwedge Product
● Could use wedge() function
● I prefer overloading ^ operator
● Have to deal with low operator precedence
● Just means using parentheses a lot
● Used for both wedge and antiwedge product
16
Wedge Product
● Vector3D ^ Vector3D = Bivector3D
● Like cross product
● Vector3D ^ Bivector3D = scalar
● Like dot product
17
Points
● Same components as vector
● But behaves differently
● w = 1 when promoted to 4D
● Translation included when multiplied
by 4×4 matrix
18
Points
● Often, we just want point to be a vector
● Other times, we want to enforce point
used instead of vector
● Special case math for points
19
Points
● What works:
● Make point a subclass of vector
20
Point3D Class
class Point3D : public Vector3D
{
public:
Point3D() = default;
Point3D(float a, float b, float c) : Vector3D(a, b, c) {}
Point3D(const Point3D& p) : Vector3D(p) {}
};
21
Point3D Class
● Point type can always be implicitly converted
to vector type at no cost
● Can pass point to function accepting vector
● Can mix vectors and points in calculations
● Overload functions/operators where special
behavior is needed
22
Point as Subclass
● Point is specific type of vector
● Vector can’t be implicitly converted to point
● Function accepting a point must always have
a point passed to it
23
Point Operations
● Point + Point = Point
● Point − Point = Vector
● Point * Scalar = Point
24
Wedge Product
● Point3D ^ Point3D = Bivector4D
● Two points make a line
● Point3D ^ Point3D ^ Point3D = Trivector4D
● Three points make a plane
25
Conversion of Vector to Point
● Sometimes want a vector to be a point
● Rare for me, only 19 uses in 600K+ lines of code
● Create a “Zero” type to act as point at origin
● Add vector to origin to turn it into a point
● No casting, zero cost
26
Zero Type
class Zero3DType {};
extern const Zero3DType Zero3D;
const Point3D& operator +(const Zero3DType&, const Vector3D& v)
{
return (reinterpret_cast<const Point3D&>(v));
}
Point3D p = Zero3D + (expression producing 3D vector);
27
Promotion of Points
Vector4D(const Point2D& p) Vector4D(const Point3D& p)
{ {
x = p.x; x = p.x;
y = p.y; y = p.y;
z = 0.0F; z = p.z;
w = 1.0F; w = 1.0F;
} }
28
Basic Matrix
class Matrix3D class Matrix4D
{ {
public: public:
float n[3][3]; float n[4][4];
... ...
}; };
29
Matrices
● Think of matrix as array of vectors
● We want this storage order
● Column vectors → matrix is array of columns
● Row vectors → matrix is array of rows
30
Vector Array
● Object-to-world
transform is
array of vectors
● World x = 1st vector z
● World y = 2nd vector y
● World z = 3rd vector
x
31
Operator []
Vector3D& operator [](int index)
{
return (*reinterpret_cast<Vector3D *>(n[index]);
}
const Vector3D& operator [](int index) const
{
return (*reinterpret_cast<const Vector3D *>(n[index]);
}
32
Row or Column Vectors
● Vectors can be thought of as
1×n row matrices
● Or vectors can be thought of as
n×1 column matrices
● Neither is more mathematically
correct than the other
33
Row or Column Vectors
● Consistency is what matters
● Pick one convention and stick to it
● Everything works out the same
● But matrix-vector products will have
operands in opposite orders
34
Matrix Storage
● Row vectors → matrix is array of rows
● “Row-major” storage order
● Column vectors → matrix is array of columns
● “Column-major” storage order
35
Operand Order
● Row vectors transformed by matrix on right
vx vy vz v x v y v z M
● Column vectors transformed by matrix on left
vx vx
v M v
y
y
vz v z
36
Column Vectors
● I use column vectors
● Remainder of this talk uses column vectors
● Convention used by scientists and engineers
● Matrix composition and quaternion
composition have same ordering
● Consistency is king
37
Vectors and Antivectors
● Vectors are n×1 column matrices
● Antivectors are 1×n row matrices
● (Whichever you choose for vectors,
it’s the opposite for antivectors.)
38
Vectors and Antivectors
● Vectors are ordinary directions
● Tangent, bitangent, velocity, force, etc.
● Antivectors are formed by cross products
● Normal, angular velocity, torque, etc.
● Bivectors in 3D, with planar orientation
39
Planes
● Planes are 4D antivectors
● Wedge product of 3 homogeneous points
40
Transformation
● Vector (column) is transformed as
v Mv
● Antivector (row) is transformed as
n n adj M n det M M 1
41
Transformation
● Can enforce transformation rules by using
different types for vectors / antivectors
● Implement operators only for valid products
● Can’t accidentally multiply normal or plane
with matrix on the left
42
Transformation
Vector3D operator *(const Matrix3D& m, const Vector3D& v);
Vector4D operator *(const Matrix4D& m, const Vector4D& v);
Bivector3D operator *(const Bivector3D& b, const Matrix3D& m);
Trivector4D operator *(const Trivector4D& t, const Matrix4D& m);
43
Normal Transformation
● If 3×3 matrix M is orthogonal, = M−1 MT
● So don’t need inverse to transform normal:
n nM nM
1 T
● In this case, can treat normal like vector:
n Mn
T T
44
Plane Transformation
● Can’t do same thing for plane f
● 4×4 matrix H generally not orthogonal
● Always need adjugate for correct transform:
f f adj H f det H H 1
45
Swizzling
● Shading languages have swizzles
● Can rearrange components
● Can extract subvectors
● All we can do in C++ with our basic vector
class is .x, .y, .z, etc.
46
Swizzling Examples
Vector3D v;
v.xyz
v.zyx
v.xy
v.zx
...
47
Swizzling
● Making this work requires some abstraction
● And some C++ templates
● But it can be done cleanly
● And it’s worth it, IMO
48
Type Structures
● One for each mathematical entity
● Vector2D, Vector3D, Bivector3D, Matrix3D, etc.
● Holds type info about components
and subparts
● Used by templates
49
Type Structures
struct TypeVector3D
{
typedef float component_type;
typedef Vector2D vector2D_type;
typedef Vector3D vector3D_type;
};
50
Component Template
● Abstraction of vector component
● Type struct is a template parameter
● Important part is that the component
index is a template parameter
51
Component Template
template <typename type_struct, int index>
class Component
{
public:
typedef typename type_struct::component_type component_type;
component_type data[1];
operator component_type&(void) { return (data[index]); }
operator const component_type&(void) const { return (data[index]); }
...
52
2D Subvector Template
● Abstraction of two components of n-D vector
● Type struct is again a template parameter
● New parameter: boolean value indicating
whether subvector is an antivector
53
2D Subvector Template
template <typename type_struct, bool anti, int index_x, int index_y>
class Subvec2D
{
public:
typedef typename type_struct::component_type component_type;
typedef typename type_struct::vector2D_type vector2D_type;
component_type data[2];
...
54
3D and 4D Subvectors
● Similar to 2D subvector
● Just have more index template parameters
55
Conversion to Vector
● Subvectors are generic set of components
● Need to be able to implicitly convert to
vectors of same dimension
● When components are consecutive in
memory, don’t want any copying
56
Converter Templates
● Turns an n-D subvector into an n-D vector
● Used by conversion operators in subvector
class templates
● Explicit specializations handle cases when
components are consecutive
57
ConverterVector2D Template
template <typename type_struct, int index_x, int index_y>
struct ConverterVector2D
{
typedef typename type_struct::component_type component_type;
typedef typename type_struct::vector2D_type vector2D_type;
typedef typename type_struct::vector2D_type const_vector2D_type;
static vector2D_type Convert(component_type *data)
{
return (vector2D_type(data[index_x], data[index_y]));
}
};
58
Explicit Specializations
template <typename type_struct>
struct ConverterVector2D<type_struct, 0, 1>
{
typedef typename type_struct::component_type component_type;
typedef typename type_struct::vector2D_type& vector2D_type;
typedef const typename type_struct::vector2D_type& const_vector2D_type;
static vector2D_type Convert(component_type *data)
{
return (reinterpret_cast<vector2D_type>(data[0]));
}
};
59
Explicit Specializations
template <typename type_struct>
struct ConverterVector2D<type_struct, 1, 2>
{
typedef typename type_struct::component_type component_type;
typedef typename type_struct::vector2D_type& vector2D_type;
typedef const typename type_struct::vector2D_type& const_vector2D_type;
static vector2D_type Convert(component_type *data)
{
return (reinterpret_cast<vector2D_type>(data[1]));
}
};
60
Explicit Specializations
template <typename type_struct>
struct ConverterVector2D<type_struct, 2, 3>
{
typedef typename type_struct::component_type component_type;
typedef typename type_struct::vector2D_type& vector2D_type;
typedef const typename type_struct::vector2D_type& const_vector2D_type;
static vector2D_type Convert(component_type *data)
{
return (reinterpret_cast<vector2D_type>(data[2]));
}
};
61
Conversion to Vector
● Notice that generic converter constructs
a new object
● But explicit specializations return references
● Difference captured in typedefs inside
converter
● Used by conversion operator
62
Conversion of Subvec2D
template <typename type_struct, bool anti, int index_x, int index_y>
class Subvec2D
{
...
operator typename
ConverterVector2D<type_struct, index_x, index_y>::vector2D_type(void)
{
return (ConverterVector2D<type_struct, index_x, index_y>
::Convert(data));
}
63
Overloaded Operators
● Arithmetic done with Subvec2D, Subvec3D,
Subvec4D
● Allows general swizzling of both operands
● Compiler automatically generates code for
all combinations actually used
64
Assignment Operator
template <typename type_struct, bool anti, int index_x, int index_y>
class Subvec2D
{
...
template <typename type, int ind_x, int ind_y>
Subvec2D& operator =(const Subvec2D<type, anti, ind_x, ind_y>& value)
{
data[index_x] = value.data[ind_x];
data[index_y] = value.data[ind_y];
return (*this);
}
65
Vector / Antivector Safeguard
● Notice that anti template parameter must
be same for both operands
● Can’t accidentally mix vectors and
antivectors
66
Operators for Full Vectors
● Also overload operators with full vector
operands
● Subvectors will be result of swizzles
● Otherwise, would have to write swizzles all
the time, even if components not reordered
67
Assignment of Full Vector
template <typename type_struct, bool anti, int index_x, int index_y>
class Subvec2D
{
...
Subvec2D& operator =(const vector2D_type& value)
{
data[index_x] = value.x;
data[index_y] = value.y;
return (*this);
}
68
Overloaded Operators
● Componentwise +, −, * work similarly
● Scalar *, / affect components identified by
index template parameters
● Nothing fancy going on
69
Unions
● Swizzle members implemented with union
● Holds all individual components
● Holds all possible subvectors
● May choose to exclude subvectors
with repeated components
70
Vec2D Class Template
template <typename type_struct, bool anti = false>
class Vec2D
{
public:
union
{
Component<type_struct, 0> x;
Component<type_struct, 1> y;
Subvec2D<type_struct, anti, 0, 1> xy;
Subvec2D<type_struct, anti, 1, 0> yx;
};
71
Vec3D Union (15 members)
Component<type_struct, 0> x;
Component<type_struct, 1> y;
Component<type_struct, 2> z;
Subvec2D<type_struct, anti, 0, 1> xy;
Subvec2D<type_struct, anti, 0, 2> xz;
Subvec2D<type_struct, anti, 1, 0> yx;
Subvec2D<type_struct, anti, 1, 2> yz;
Subvec2D<type_struct, anti, 2, 0> zx;
Subvec2D<type_struct, anti, 2, 1> zy;
Subvec3D<type_struct, anti, 0, 1, 2> xyz;
Subvec3D<type_struct, anti, 0, 2, 1> xzy;
Subvec3D<type_struct, anti, 1, 0, 2> yxz;
Subvec3D<type_struct, anti, 1, 2, 0> yzx;
Subvec3D<type_struct, anti, 2, 0, 1> zxy;
Subvec3D<type_struct, anti, 2, 1, 0> zyx;
72
Vec4D Union (64 members)
Component<type_struct, 0> x; Subvec3D<type_struct, anti, 1, 0, 3> yxw; Subvec4D<type_struct, anti, 1, 2, 0, 3> yzxw;
Component<type_struct, 1> y; Subvec3D<type_struct, anti, 1, 3, 0> ywx; Subvec4D<type_struct, anti, 1, 2, 3, 0> yzwx;
Component<type_struct, 2> z; Subvec3D<type_struct, anti, 1, 2, 3> yzw; Subvec4D<type_struct, anti, 1, 3, 0, 2> ywxz;
Component<type_struct, 3> w; Subvec3D<type_struct, anti, 1, 3, 2> ywz; Subvec4D<type_struct, anti, 1, 3, 2, 0> ywzx;
Subvec2D<type_struct, anti, 0, 1> xy; Subvec3D<type_struct, anti, 2, 0, 1> zxy; Subvec4D<type_struct, anti, 2, 0, 1, 3> zxyw;
Subvec2D<type_struct, anti, 0, 2> xz; Subvec3D<type_struct, anti, 2, 1, 0> zyx; Subvec4D<type_struct, anti, 2, 0, 3, 1> zxwy;
Subvec2D<type_struct, anti, 0, 3> xw; Subvec3D<type_struct, anti, 2, 0, 3> zxw; Subvec4D<type_struct, anti, 2, 1, 0, 3> zyxw;
Subvec2D<type_struct, anti, 1, 0> yx; Subvec3D<type_struct, anti, 2, 3, 0> zwx; Subvec4D<type_struct, anti, 2, 1, 3, 0> zywx;
Subvec2D<type_struct, anti, 1, 2> yz; Subvec3D<type_struct, anti, 2, 1, 3> zyw; Subvec4D<type_struct, anti, 2, 3, 0, 1> zwxy;
Subvec2D<type_struct, anti, 1, 3> yw; Subvec3D<type_struct, anti, 2, 3, 1> zwy; Subvec4D<type_struct, anti, 2, 3, 1, 0> zwyx;
Subvec2D<type_struct, anti, 2, 0> zx; Subvec3D<type_struct, anti, 3, 0, 1> wxy; Subvec4D<type_struct, anti, 3, 0, 1, 2> wxyz;
Subvec2D<type_struct, anti, 2, 1> zy; Subvec3D<type_struct, anti, 3, 1, 0> wyx; Subvec4D<type_struct, anti, 3, 0, 2, 1> wxzy;
Subvec2D<type_struct, anti, 2, 3> zw; Subvec3D<type_struct, anti, 3, 0, 2> wxz; Subvec4D<type_struct, anti, 3, 1, 0, 2> wyxz;
Subvec2D<type_struct, anti, 3, 0> wx; Subvec3D<type_struct, anti, 3, 2, 0> wzx; Subvec4D<type_struct, anti, 3, 1, 2, 0> wyzx;
Subvec2D<type_struct, anti, 3, 1> wy; Subvec3D<type_struct, anti, 3, 1, 2> wyz; Subvec4D<type_struct, anti, 3, 2, 0, 1> wzxy;
Subvec2D<type_struct, anti, 3, 2> wz; Subvec3D<type_struct, anti, 3, 2, 1> wzy; Subvec4D<type_struct, anti, 3, 2, 1, 0> wzyx;
Subvec3D<type_struct, anti, 0, 1, 2> xyz; Subvec4D<type_struct, anti, 0, 1, 2, 3> xyzw;
Subvec3D<type_struct, anti, 0, 2, 1> xzy; Subvec4D<type_struct, anti, 0, 1, 3, 2> xywz;
Subvec3D<type_struct, anti, 0, 1, 3> xyw; Subvec4D<type_struct, anti, 0, 2, 1, 3> xzyw;
Subvec3D<type_struct, anti, 0, 3, 1> xwy; Subvec4D<type_struct, anti, 0, 2, 3, 1> xzwy;
Subvec3D<type_struct, anti, 0, 2, 3> xzw; Subvec4D<type_struct, anti, 0, 3, 1, 2> xwyz;
Subvec3D<type_struct, anti, 0, 3, 2> xwz; Subvec4D<type_struct, anti, 0, 3, 2, 1> xwzy;
Subvec3D<type_struct, anti, 1, 0, 2> yxz; Subvec4D<type_struct, anti, 1, 0, 2, 3> yxzw;
Subvec3D<type_struct, anti, 1, 2, 0> yzx; Subvec4D<type_struct, anti, 1, 0, 3, 2> yxwz;
73
Repeated Components
● Rarely useful (I’ve never needed them)
● Adds a lot more members to union
● Don’t want them to be assignable
● Declare them const in the union
74
Final Types
● Components and subvectors are generally
internal implementation
● Rest of code doesn’t need to know
about them
● Use high-level classes for specific
mathematical types
75
Final Types
class Vector2D : public Vec2D<TypeVector2D>
class Vector3D : public Vec3D<TypeVector3D>
class Vector4D : public Vec4D<TypeVector4D>
class Bivector3D : public Vec3D<TypeBivector3D, true>
class Trivector4D : public Vec4D<TypeTrivector4D, true>
class Point3D : public Vector3D
class Integer2D : public Vec2D<TypeInteger2D>
class Integer3D : public Vec2D<TypeInteger3D>
76
Antivector Type Structure Example
struct TypeTrivector4D
{
typedef float component_type;
typedef Vector2D vector2D_type;
typedef Bivector3D vector3D_type;
typedef Trivector4D vector4D_type;
};
77
Matrices
● We can extend same concepts to matrices
● Subvectors can be used to extract
rows and columns
● Then they can be used in expressions without any
copying going on
● Compiler generates new functions to access
components in the right places
78
Matrices
● Submatrices of lower dimension
can be extracted
● Only one I’ve ever used is 3×3 upper-left part
of a 4×4 matrix
● Submatrix just indexes components inside
larger matrix, so no copying
79
Matrices
● We can “swizzle” a matrix to turn it
into its transpose
● Again, no copying
● And compiler generates new functions to perform
operations on transposed matrix
80
3D Submatrix Template
● Abstraction of 3×3 submatrix
● Type struct is one template parameter
● Entry locations defined by 9 more
template parameters
81
Submat3D Template
template <typename type_struct, int index_00, int index_01, int index_02,
int index_10, int index_11, int index_12,
int index_20, int index_21, int index_22>
class Submat3D
{
public:
typedef typename type_struct::component_type component_type;
typedef typename type_struct::matrix3D_type matrix3D_type;
component_type data[9];
...
82
Submat4D Template
template <typename type_struct, int index_00, int index_01, int index_02, int index_03,
int index_10, int index_11, int index_12, int index_13,
int index_20, int index_21, int index_22, int index_23,
int index_30, int index_31, int index_32, int index_33>
class Submat4D
{
public:
typedef typename type_struct::component_type component_type;
typedef typename type_struct::matrix4D_type matrix4D_type;
component_type data[16];
...
83
Unions
● Same concept as with vectors
● Holds all individual entries
● Holds set of columns and rows
● Holds submatrices, if needed
● Holds transpose
84
Columns and Rows
● Columns are vectors
● Rows are antivectors
● This is reflected in subvector types
85
Matrix Rows
● Noncontiguous components
● Still behaves like ordinary antivectors
to code doing operations with them
● Rows of 4×4 matrix are planes
86
Mat3D Union
Component<type_struct, 0> m00;
Component<type_struct, 1> m10;
Component<type_struct, 2> m20;
Component<type_struct, 3> m01;
Component<type_struct, 4> m11;
Component<type_struct, 5> m21;
Component<type_struct, 6> m02;
Component<type_struct, 7> m12;
Component<type_struct, 8> m22;
Subvec3D<column_type_struct, false, 0, 1, 2> col0;
Subvec3D<column_type_struct, false, 3, 4, 5> col1;
Subvec3D<column_type_struct, false, 6, 7, 8> col2;
Subvec3D<row_type_struct, true, 0, 3, 6> row0;
Subvec3D<row_type_struct, true, 1, 4, 7> row1;
Subvec3D<row_type_struct, true, 2, 5, 8> row2;
Submat3D<type_struct, 0, 3, 6, 1, 4, 7, 2, 5, 8> matrix;
Submat3D<type_struct, 0, 1, 2, 3, 4, 5, 6, 7, 8> transpose;
87
Mat4D Union
Component<type_struct, 0> m00; Subvec4D<column_type_struct, false, 0, 1, 2, 3> col0;
Component<type_struct, 1> m10; Subvec4D<column_type_struct, false, 4, 5, 6, 7> col1;
Component<type_struct, 2> m20; Subvec4D<column_type_struct, false, 8, 9, 10, 11> col2;
Component<type_struct, 3> m30; Subvec4D<column_type_struct, false, 12, 13, 14, 15> col3;
Component<type_struct, 4> m01; Subvec4D<row_type_struct, true, 0, 4, 8, 12> row0;
Component<type_struct, 5> m11; Subvec4D<row_type_struct, true, 1, 5, 9, 13> row1;
Component<type_struct, 6> m21; Subvec4D<row_type_struct, true, 2, 6, 10, 14> row2;
Component<type_struct, 7> m31; Subvec4D<row_type_struct, true, 3, 7, 11, 15> row3;
Component<type_struct, 8> m02; Submat3D<type_struct, 0, 4, 8, 1, 5, 9, 2, 6, 10> matrix3D;
Component<type_struct, 9> m12; Submat3D<type_struct, 0, 1, 2, 4, 5, 6, 8, 9, 10> transpose3D;
Component<type_struct, 10> m22;
Component<type_struct, 11> m32; Submat4D<type_struct, 0, 4, 8, 12, 1, 5, 9, 13,
Component<type_struct, 12> m03; 2, 6, 10, 14, 3, 7, 11, 15> matrix;
Component<type_struct, 13> m13; Submat4D<type_struct, 0, 1, 2, 3, 4, 5, 6, 7,
Component<type_struct, 14> m23; 8, 9, 10, 11, 12, 13, 14, 15> transpose;
Component<type_struct, 15> m33;
88
Final Types
● As with vectors, details of submatrices and
subvectors are internal
● Application works with high-level classes
89
Final Types
class Matrix3D : public Mat3D<TypeMatrix3D>
class Matrix4D : public Mat4D<TypeMatrix4D>
class Transform4D : public Matrix4D
90
Matrix Type Struct
● Contains component type
● Contains high-level matrix type
for conversions
● Contains type structs for columns and rows
● Used by subvector representations
91
Matrix Type Structs
struct TypeMatrix3D
{
typedef float component_type;
typedef Matrix3D matrix3D_type;
typedef TypeVector3D column_type_struct;
typedef TypeBivector3D row_type_struct;
};
92
Matrix Type Structs
struct TypeMatrix4D
{
typedef float component_type;
typedef Matrix3D matrix3D_type;
typedef Matrix4D matrix4D_type;
typedef TypeVector4D column_type_struct;
typedef TypeTrivector4D row_type_struct;
};
93
Matrix Operations
● Matrix-matrix products and matrix-vector
products defined in terms of submatrices
and subvectors
● Compiler can generate specialized functions
for any swizzled combinations
94
Normal Transformation
● Remember when M is orthogonal
n nM nM
1 T
● We can do this without making copy:
n2 = n1 * m.transpose;
95
Matrix Operations
● Could just declare matrix-matrix product
in header file
● 34 template parameters!
● Then define product in .cpp file
● Explicitly instantiate for unswizzled
matrices and transposes
96
Contact
● lengyel@terathon.com
● @EricLengyel on Twitter
● Expo floor, booth #2204
● Slides posted here after conference:
http://terathon.com/lengyel/
97