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.
/**
* glmatrix4x4.js, By Wayne Brown, Fall 2017
*
* glmatrix4x4 is a set of functions that perform standard operations
* on 4x4 transformation matrices.
*
* The 4x4 matrices are stored in column-major order using an array of 32-bit
* floating point numbers, which is the format required by WebGL programs.
*
* The functions do not create new objects because in real-time graphics,
* creating new objects slows things down.
*
* Function parameters are ordered in the same order an equivalent
* assignment statements. For example, R = A*B, has parameters (R, A, B).
* All matrix parameters use capital letters.
*
* The functions are defined inside an object to prevent pollution of
* JavaScript's global address space. The functions contain no validation
* of parameters, which makes them more efficient at run-time.
*/
/**
* The MIT License (MIT)
*
* Copyright (c) 2017 C. Wayne Brown
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/**
* translate_scene.js, By Wayne Brown, Fall 2017
*/
/**
* The MIT License (MIT)
*
* Copyright (c) 2015 C. Wayne Brown
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
"use strict";
/** -----------------------------------------------------------------------
* Create a WebGL 3D scene, store its state, and render its models.
*
* @param id {string} The id of the webglinteractive directive
* @param download {SceneDownload} An instance of the SceneDownload class
* @param vshaders_dictionary {object} A dictionary of vertex shaders.
* @param fshaders_dictionary {object} A dictionary of fragment shaders.
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.
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.)
mary
to a
scaling transformation that doubles only the x coordinates of a model?
nice
to a
rotation transformation that rotates a model 30 degrees about the y axis?
GlMatrix4x4
- A Robot Arm