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:

0
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) sets M to a scale transform.
  • translate(M, tx, ty, tz) sets M to a translation transform.
  • rotate(M, angle, x_axis, y_axis, z_axis) sets M 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) sets R 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

  1. transform E was applied to a vertex,
  2. then transform D was applied to the transformed vertex,
  3. then transform C was applied to the transformed vertex,
  4. then transform B was applied to the transformed vertex, and
  5. 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.

Show: Code   Canvas   Run Info
x
 
1
/**
2
 * glmatrix4x4.js, By Wayne Brown, Fall 2017
3
 *
4
 * glmatrix4x4 is a set of functions that perform standard operations
5
 * on 4x4 transformation matrices.
6
 *
7
 * The 4x4 matrices are stored in column-major order using an array of 32-bit
8
 * floating point numbers, which is the format required by WebGL programs.
9
 *
10
 * The functions do not create new objects because in real-time graphics,
11
 * creating new objects slows things down.
12
 *
13
 * Function parameters are ordered in the same order an equivalent
14
 * assignment statements. For example, R = A*B, has parameters (R, A, B).
15
 * All matrix parameters use capital letters.
16
 *
17
 * The functions are defined inside an object to prevent pollution of
18
 * JavaScript's global address space. The functions contain no validation
19
 * of parameters, which makes them more efficient at run-time.
20
 */
21
22
/**
23
 * The MIT License (MIT)
24
 *
25
 * Copyright (c) 2017 C. Wayne Brown
26
 *
27
 * Permission is hereby granted, free of charge, to any person obtaining a copy
28
 * of this software and associated documentation files (the "Software"), to deal
29
 * in the Software without restriction, including without limitation the rights
30
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
31
 * copies of the Software, and to permit persons to whom the Software is
32
 * furnished to do so, subject to the following conditions:
33
 *
34
 * The above copyright notice and this permission notice shall be included in all
35
 * copies or substantial portions of the Software.
36
37
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
200
 
1
/**
2
 * translate_scene.js, By Wayne Brown, Fall 2017
3
 */
4
5
/**
6
 * The MIT License (MIT)
7
 *
8
 * Copyright (c) 2015 C. Wayne Brown
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to deal
12
 * in the Software without restriction, including without limitation the rights
13
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
 * copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * The above copyright notice and this permission notice shall be included in all
18
 * copies or substantial portions of the Software.
19
20
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
 * SOFTWARE.
27
 */
28
29
"use strict";
30
31
/** -----------------------------------------------------------------------
32
 * Create a WebGL 3D scene, store its state, and render its models.
33
 *
34
 * @param id {string} The id of the webglinteractive directive
35
 * @param download {SceneDownload} An instance of the SceneDownload class
36
 * @param vshaders_dictionary {object} A dictionary of vertex shaders.
37
 * @param fshaders_dictionary {object} A dictionary of fragment shaders.
../_static/06_example05/translate.html

An example of translating a model.

Please use a browser that supports "canvas"
Animate
X translation 0.00 : -2.0 2.0
Y translation 0.00 : -2.0 2.0
Z translation 0.00 : -2.0 2.0

Open this webgl program in a new tab or window

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 GlMatrix4x4 do you typically need to create for a WebGL program?





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?






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 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 nice to a rotation transformation that rotates a model 30 degrees about the y axis?





Next Section - 6.7 - Using GlMatrix4x4 - A Robot Arm