6.6 - A Matrix Library - GlMatrix4x4
¶
Fundamental to all 3D computer graphics is the 4x4 matrix transform. In the original OpenGL API, all basic transformations were implemented for you in the library’s code. All you had to do was call the correct function in the correct order. WebGL was implemented for low power mobile devices with limited CPU and GPU functionality. Transformation matrix functionality was not included in the WebGL API. Therefore, you have to implement your own matrix operations in JavaScript. But it doesn’t make sense for individual programmers to “re-invent the wheel”. This lesson presents you with a JavaScript matrix library and explains how to use it.
WebGL Transformation Matrices¶
A WebGL, 4x4, transformation matrix is a 1D array of type Float32Array
which contains 16 floating point values. The values represent a 2D array that
are stored in column-major order. (Back in the 1960’s, Fortran stored 2-dimensional
data in column-major order. That convention has propagated to various system still
in use today, including OpenGL. Most modern programming languages use row-major order.)
The 4x4 transformation matrix:
4
8
12
1
5
9
13
2
6
10
14
3
7
11
15
Eq1
would be created in JavaScript code like this:
var matrix = new Float32Array([0,4,8,12, 1,5,9,13, 2,6,10,14, 3,7,11,15]);
// Or
var m = new Float32Array(16);
m[0] = 0; m[4] = 1; m[ 8] = 2; m[12] = 3;
m[1] = 4; m[5] = 5; m[ 9] = 6; m[13] = 7;
m[2] = 8; m[6] = 9; m[10] = 10; m[14] = 11;
m[3] = 12; m[7] = 13; m[11] = 14; m[15] = 15;
In most cases the 2nd example above is used because it is easier to debug the code if you can visualize the data values as a 2D array.
Note: If you re-format the matrix library code you will lose the “multiple statements per line” formatting which helps to visualize the 4x4 matrices. It is recommended that you do not re-format this code file.
Design Decisions for a Matrix Library¶
A typical class definition defines a set of data and a set of functions that act on that data. One of the important ideas behind classes is the encapsulation and protection of a set of data values inside an instance of the class. We don’t really need data protection for our matrix library. What we need is encapsulation of the functionality of matrix operations so that we can minimize the creation and deletion of scratch arrays that are needed for matrix processing. Consider that an animation requires the rendering of a scene at least 30 times per second. If you are constantly creating new object instances every time you render, you will be creating a lot of objects. JavaScript does dynamic memory garbage collection, so many programmers simply ignore memory issues. But if you can minimize the creation of new objects for each rendering, your animations have the potential to run more smoothly.
The GlMatrix4x4
Class¶
A class called GlMatrix4x4
is defined in a file named
glmatrix4x4.js. It encapsulates the matrix functionality we
need to produce WebGL renderings. A GlMatrix4x4
object does
not store a matrix. It encapsulates matrix functionality and the scratch arrays
needed for that functionality. And, by separating matrix functionality from
matrix data, the syntax of the code is simplified.
You can typically create one instance of the library and use it for your entire program. The library contains functions that:
- create transforms,
- set the values of a specific type of transform, and
- perform matrix operations.
A matrix transform is stored as a Float32Array
. Four functions in an
GlMatrix4x4
object create and return new transforms and their
names all start with create
. These functions should not be called in your
rendering code for every animation frame. They should be called once in your
setup code to create any transforms you need during rendering. The four
functions that create a new matrix transform are:
create()
, which creates and returns a new 4x4 transformation matrix.createOrthographic()
, which creates a new orthographic projection transformation matrix.createPerspective()
, which creates a new perspective projection transformation matrix.createFrustum()
, which creates a new perspective projection transformation matrix.
Functions that set the values of a transformation matrix must send a transformation matrix as the first parameter. For example:
scale(M, sx, sy, sz)
setsM
to a scale transform.translate(M, tx, ty, tz)
setsM
to a translation transform.rotate(M, angle, x_axis, y_axis, z_axis)
setsM
to a rotation transform.
Functions that perform matrix calculations change the value of their first parameter, while leaving all of the other parameters unchanged. The parameters are ordered similar to assignment statements which always change their left-hand side variable, but leave all value on the right-hand-side of an assignment statement unchanged. For example:
multiply(R, A, B)
setsR
to the product of A times B. (R = A*B
)
The function multiplySeries()
will
multiply any number of matrices together to produce a single transformation
matrix. It uses variable arguments and will accept as many arguments as you send it.
For example, m.multiplySeries(R,A,B,C,D,E)
will calculate the matrix product
of A*B*C*D*E
and store the result in R
. In equation format, it performs
R = A*B*C*D*E;
. The order of the multiplications is critical. If the
transform R
is applied to a set of vertices, the effect of R
would be that
- transform
E
was applied to a vertex, - then transform
D
was applied to the transformed vertex, - then transform
C
was applied to the transformed vertex, - then transform
B
was applied to the transformed vertex, and - finally transform
A
was applied to the transformed vertex.
When you create a single transform from multiple transforms, you must always order the transformations from right to left.
The GlMatrix4x4 Code¶
The WebGL program below displays the GlMatrix4x4
class code.
Please study the GlMatrix4x4
class to get familiar with its matrix functionality.
(Hide the canvas to better review the code.)
The translate_scene.js
code demonstrates how to use the matrix functionality
in a WebGL program. Notice that the creation of all matrices is done once in the
scene’s constructor. The matrices are then used repeatedly in the scene’s
rendering function. Since there are no new objects created for each rendering,
garage collection is minimized.
An example of translating a model.
X translation 0.00 : -2.0 2.0
Y translation 0.00 : -2.0 2.0
Z translation 0.00 : -2.0 2.0
HTML Code To Use GlMatrix4x4¶
The GlMatrix4x4
class uses code from two other classes:
glpoint4.js
, which defines a class for(x,y,z,w)
points.glvector3.js
, which defines a class for<dx,dy,dz>
vectors.
These files must be loaded into your browser along with the matrix library.
To use the matrix library include <script>
directives in your HTML
file that look something like this:
<script src="../learn_webgl/glpoint4.js"></script>
<script src="../learn_webgl/glvector3.js"></script>
<script src="../learn_webgl/glmatrix4x4.js"></script>
Change the file paths based on the relative location of your JavaScript code files to your HTML file. If the HTML and JavaScript files are in the same folder on the server, you can omit a file path.
Glossary¶
- code library
- a set of common functionality gathered into a single place. It is standard practice to put the functionality into a single class, or a group of classes.
- column-major order
- values in a 2-dimensional array are store in a 1D array and organized by columns. (All computer memory is 1-dimensional; multi-dimensional arrays are always stored in computer memory as 1D arrays in some agreed upon order.)
Self Assessment¶
For all of these questions, assume that m
is an instance of the GlMatrix4x4
class.
-
Q-138: How many instances of the
- One
- Correct.
- Four
- Incorrect. Where did four come from?
- One for each 4x4 transform you need in a program.
- Incorrect. No, a GlMatrix4x4 contains functionality, not matrices.
- Two for each 4x4 transform you need in a program.
- Incorrect. No, a GlMatrix4x4 contains functionality, not matrices.
GlMatrix4x4
do you typically need to create for a WebGL program?
sam = m.create();
- Correct.
sam = new GlMatrix4x4().create();
-
Incorrect. (While this will work in theory, it creates an unnecessary
GlMatrix4x4
object.) sam = new GlMatrix4x4();
-
Incorrect. This creates an instance of the
GlMatrix4x4
class. m.create();
- Incorrect. It creates a new 4x4 transformation matrix but does not assign it to a variable so it can be used.
Q-139: You have created an instance of the GlMatrix4x4
class called m
and you
want to use it to create a 4x4 transformation matrix called sam
. Which of the following code examples
accomplish this?
- matrix q
- Correct. Only the first parameter is modified and contains the results of the matrix multiplications.
- matrix a
- Incorrect.
- matrix b
- Incorrect.
- matrix c
- Incorrect.
Q-140: You need to multiple 3 matrices together, a
times b
times c
, and
store the results in matrix q
. You can do this using the
multiplySeries()
function like this:
m.multiplySeries(q,a,b,c);
Which of the parameters to the multiplySeries()
function are modified by the function call?
(Select all that apply.)
-
Q-141: Which of the following statements set a matrix called
- m.scale(mary, 2, 1, 1);
- Correct. The x scale factor is 2, while the scale factors of 1 for the y and z components leaves them unchanged.
- m.scale(mary, 2, 2, 2);
- Incorrect. This doubles the x, y and z components of all vertices.
- m.scale(mary, 2);
- Incorrect. This does not provide the 3 scaling parameters required by the function call.
- m.scale(mary, 1, 1, 2);
- Incorrect. This doubles the z components, leaving the x and y components unchanged.
mary
to a
scaling transformation that doubles only the x coordinates of a model?
-
Q-142: Which of the following statements set a matrix called
- m.rotate(nice, 30, 0, 1, 0);
- Correct. The angle is 30 degrees and the axis of rotation is the y axis, <0,1,0>.
- m.rotate(nice, 30, 1, 0, 0)
- Incorrect. This rotates about the x axis, <1,0,0>.
- m.rotate(nice, 30, 0, 0, 1);
- Incorrect. This rotates about the z axis, <0,0,1>.
- m.rotate(nice, 30);
- Incorrect. This is missing the 3 parameters that define the axis of rotation.
nice
to a
rotation transformation that rotates a model 30 degrees about the y axis?
GlMatrix4x4
- A Robot Arm