three.js 數學方法之Matrix3

Vadim發表於2020-07-23

今天郭先生來說一說three.js的三維矩陣,這塊知識需要結合線性代數的一些知識,畢業時間有點長,線性代數的知識大部分都還給了老師。於是一起簡單的複習了一下。
所有的計算都是使用列優先順序進行的。然而,由於實際的排序在數學上沒有什麼不同, 而且大多數人習慣於以行優先順序考慮矩陣,所以three.js文件以行為主的順序顯示矩陣。 請記住,如果您正在閱讀原始碼,您必須對這裡列出的任何矩陣進行轉置transpose,以理解計算。例如:

var matrix3 = new THREE.Matrix3().set( 1,2,3,4,5,6,7,8,9); //而其內部elements則展示為: matrix3.elements = [1,4,7,2,5,8,3,6,9];

1. Matrix3的屬性

1. elements : Array

矩陣列優先column-major列表。

2. isMatrix3 : Boolean

用於判定此物件或者此類的派生物件是否是三維矩陣。預設值為 true。

2. Matrix3的方法

1. set(n11: number,n12: number,n13: number…): Matrix3

三維矩陣不能在建構函式中直接設定引數值,需要通過set()方法設定,set()方法引數採用行優先row-major, 而它們在內部是用列優先column-major順序儲存在陣列當中。程式碼如上面所示。

2. identity(): Matrix3

將此矩陣重置為3x3單位矩陣。

var matrix = new THREE.Matrix3(); 
matrix.identity();//返回elements: (9) [1, 0, 0, 0, 1, 0, 0, 0, 1]

3. clone(): this

建立一個新的矩陣,元素 elements 與該矩陣相同。不多說。

4. copy( m: Matrix3 ): this

將矩陣m的元素複製到當前矩陣中。不多說。

5. extractBasis( xAxis: Vector3, yAxis: Vector3, zAxis: Vector3 ): Matrix3

將此矩陣的基提取到提供的三個軸向量中。

var matrix = new THREE.Matrix3(); 
matrix.set( 1,2,3,4,5,6,7,8,9); 
var a = new THREE.Vector3(); 
var b = new THREE.Vector3(); 
var c = new THREE.Vector3(); 
matrix.extractBasis(a, b, c); 
console.log(a,b,c);//返回Vector3 {x: 1, y: 4, z: 7} Vector3 {x: 2, y: 5, z: 8} Vector3 {x: 3, y: 6, z: 9}

6. setFromMatrix4( m: Matrix4 ): Matrix3

將當前矩陣設定為4X4矩陣m左上3X3,

var matrix = new THREE.Matrix3(); 
var matrix4 = new THREE.Matrix4().makeScale(2,2,2); 
matrix.setFromMatrix4(matrix4)//elements: (9) [2, 0, 0, 0, 2, 0, 0, 0, 2]

7. multiplyScalar( s: number ): Matrix3

當前矩陣所有的元素乘以該縮放值s

var matrix = new THREE.Matrix3(); 
matrix.set( 1,2,3,4,5,6,7,8,9); 
matrix.multiplyScalar(2)//elements: (9) [2, 8, 14, 4, 10, 16, 6, 12, 18]

8. determinant(): number

計算並返回矩陣的行列式determinant 。

var matrix = new THREE.Matrix3(); 
matrix.set( 1,2,3,4,5,6,7,8,9); 
matrix.determinant()//返回0

計算方法a11 * a22 * a33 + a12 * a23 * a31 + a13 * a21 * a32 - a13 * a22 * a31 - a12 * a21 * a33 - a11 * a23 * a32 = 0;

9. getInverse( matrix: Matrix3, throwOnDegenerate?: boolean ): Matrix3

求傳入矩陣m的逆矩陣,使用解析法將該矩陣設定為傳遞矩陣m的逆矩陣。行列式為零的矩陣不能求逆。如果您嘗試這樣做,該方法將返回一個零矩陣。

var matrix1 = new THREE.Matrix3(); 
var matrix2 = new THREE.Matrix3(); 
matrix1.set(1,2,3,4,5,6,7,8,9); matrix2.set(1,1,0,0,1,1,0,0,1); 
new THREE.Matrix3().getInverse(matrix1)//因為行列式的值為0,所以返回零矩陣elements: (9) [0, 0, 0, 0, 0, 0, 0, 0, 0] 
new THREE.Matrix3().getInverse(matrix2)//因為行列式的值不為0,所以返回elements: (9) [1, 0, 0, -1, 1, 0, 1, -1, 1]

求逆矩陣的方法有很多,可以通過伴隨矩陣求逆矩陣,也可以行做差來構造逆矩陣。

10. transpose(): Matrix3

將該矩陣轉置。

var matrix = new THREE.Matrix3(); 
matrix.set(1,1,0,0,1,1,0,0,1);//返回elements: (9) [1, 0, 0, 1, 1, 0, 0, 1, 1]; matrix.transpose(); 
console.log(matrix);//返回elements: (9) [1, 1, 0, 0, 1, 1, 0, 0, 1];

11. getNormalMatrix( matrix4: Matrix4 ): Matrix3

將這個矩陣設定為給定矩陣的正規矩陣normal matrix(左上角的3x3)。 正規矩陣是矩陣m的逆矩陣inverse 的轉置transpose。

this.setFromMatrix4( matrix4 ).getInverse( this ).transpose();

上面試three.js的原始碼,從原始碼可以看出這是setFromMatrix4,getInverse和transpose的組合用法。

var matrix = new THREE.Matrix3(); 
var matrix4 = new THREE.Matrix4().makeScale(2,2,2); 
matrix.getNormalMatrix(matrix4);//返回elements: (9) [0.5, 0, 0, 0, 0.5, 0, 0, 0, 0.5]

12. transposeIntoArray( r: number[] ): Matrix3

將當前矩陣的轉置Transposes存入給定的陣列array : Array但不改變當前矩陣, 並返回當前矩陣。

var matrix = new THREE.Matrix3(); 
matrix.set(1,1,0,0,1,1,0,0,1); 
var array = []; matrix.transposeIntoArray(array); 
console.log(array);//返回[1, 1, 0, 0, 1, 1, 0, 0, 1]

13. setUvTransform( tx: number, ty: number, sx: number, sy: number, rotation: number, cx: number, cy: number ): Matrix3

tx - x偏移量
ty - y偏移量
sx - x方向的重複比例
sy - y方向的重複比例
rotation - 旋轉(弧度)
cx - 旋轉中心x
cy - 旋轉中心y
使用偏移,重複,旋轉和中心點位置設定UV變換矩陣。

var matrix = new THREE.Matrix3(); 
matrix.setUvTransform(0,0,0,0,0,0.5,0.5); 
console.log(matrix);//返回elements: (9) [0, -0, 0, 0, 0, 0, 0.5, 0.5, 1]

14. equals( matrix: Matrix3 ): boolean

如果矩陣m 與當前矩陣所有對應元素相同則返回true。

15. fromArray( array: number[], offset?: number ): Matrix3

使用基於列優先格式column-major的陣列來設定該矩陣。

var matrix = new THREE.Matrix3(); 
matrix.fromArray([1,4,7,2,5,8,3,6,9]);//因為是基於列優先原則,所以設定的陣列和elements屬性相同,不需轉置。

16. toArray( array?: number[], offset?: number ): number[]

使用列優先column-major格式將此矩陣的元素寫入陣列中。這是fromArray的逆運算。

var matrix = new THREE.Matrix3(); 
matrix.set(1,2,3,4,5,6,7,8,9); 
matrix.toArray(array); 
console.log(array);//返回[1, 4, 7, 2, 5, 8, 3, 6, 9]

17. multiply( m: Matrix3 ): Matrix3

將當前矩陣乘以矩陣m。

var matrix1 = new THREE.Matrix3(); 
var matrix2 = new THREE.Matrix3(); 
matrix1.set(1,2,3,4,5,6,7,8,9); 
matrix2.setFromMatrix4(new THREE.Matrix4().makeScale(0.5, 0.5, 0.5));//通過4維矩陣,得到三維矩陣 
matrix1.multiply(matrix2);//返回elements: (9) [0.5, 2, 3.5, 1, 2.5, 4, 1.5, 3, 4.5]

18. premultiply( m: Matrix3 ): Matrix3

將矩陣m乘以當前矩陣。和上面相比這是左乘和右乘的問題,不多說。

19. multiplyMatrices( a: Matrix3, b: Matrix3 ): Matrix3

設定當前矩陣為矩陣a x 矩陣b。和上面的方法差不多,不多說。

20. multiplyVector3( vector: Vector3 ): any

和Vector3.applyMatrix3一樣

var matrix1 = new THREE.Matrix3(); 
matrix1.set(1,2,3,4,5,6,7,8,9); 
var vector3 = new THREE.Vector3(1,2,3); 
matrix1.multiplyVector3(vector3);//返回Vector3 {x: 14, y: 32, z: 50}

這就是Matrix3的一些屬性和方法,Matrix3理解起來比Vector3確實更困難,同時功能更強大。它讓three更靈活強大。

 

轉載請註明地址:郭先生的部落格

相關文章