1. 概述
three.js中自帶了矩陣運算庫,不過在使用的過程中總是容易混淆。不知道是行主序還是列主序,前乘和后乘也很容易弄反。就在這里辨析一下。
2. 詳論
2.1. 行主序與列主序列
很早就知道OpenGL中使用的矩陣是列主序,而Direct3D中使用的是行主序,但是沒什么具體的體會,還直接弄混淆了。應該來說,無論Direct3D還是OpenGL,使用的矩陣應該都能線性代數中描述的矩陣是等價的,只不過存儲方式不同。矩陣在編程實現中一般會表示成數組的形式,以線性代數中描述的矩陣為標准,行主序就是依次按行存儲,而列主序就是依次按列存儲。
在threeJS中:
var A = new THREE.Matrix4();
A.set(1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16);
console.log(A);
var B = new THREE.Matrix4();
B.set(16, 15, 14, 13,
12, 11, 10, 9,
8, 7, 6, 5,
4, 3, 2, 1);
console.log(B);
var C = new THREE.Matrix4();
C.multiplyMatrices (A, B);
console.log(C);
其運行結果為:
在網上找一個在線矩陣計算器,相對應的計算結果如下:
因此可以認為,threejs矩陣內部儲存形式為列主序,表達和描述的仍然是線性代數中行主序,set()函數就是以行主序接受矩陣參數的。
2.2. 矩陣乘法
前面用到的矩陣乘法是新建了一個矩陣,調用multiplyMatrices。threejs矩陣還有前乘和后乘的區別,也很容易混淆。
在threeJS中矩陣的后乘方法為multiply():
var A = new THREE.Matrix4();
A.set(1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16);
var B = new THREE.Matrix4();
B.set(16, 15, 14, 13,
12, 11, 10, 9,
8, 7, 6, 5,
4, 3, 2, 1);
A.multiply(B);
console.log(A);
console.log(B);
其運行結果為:
表明后乘方法multiply()的結果就是\(A * B\)。
反過來,使用前乘方法premultiply():
var A = new THREE.Matrix4();
A.set(1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16);
var B = new THREE.Matrix4();
B.set(16, 15, 14, 13,
12, 11, 10, 9,
8, 7, 6, 5,
4, 3, 2, 1);
A.premultiply(B);
console.log(A);
console.log(B);
其運行結果為:
對比在線矩陣計算器中的計算結果:
表明前乘方法premultiply()的結果是\(B * A\)。