THREE 矩陣優先原則和平移旋轉矩陣

undefined發表於2022-04-18

優先順序

行優先

[
    1,2,3,4
    5,6,7,8,
    9,10,11,12
]

如果是行優先,如上讀取順序為 1234, 5678, 9101112

列優先

[
    1,2,3,4
    5,6,7,8,
    9,10,11,12
]

如果是行優先,如上讀取順序為 159, 2610, 3711,4812

THREE優先規則

所有內部計算儲存的矩陣都是列優先, 但是行優先更適合人的閱讀順序, 所以 Matrix.set方法使用的是行優先讀入, 讀取的都是列優先.

const a = new THREE.Matrix3()
a.set(1,2,3,4,5,6,7,8,9)
console.log('矩陣: ====>', a.elements) // (9) [1, 4, 7, 2, 5, 8, 3, 6, 9]

為了閱讀,以下矩陣都是用行優先展示

行優先轉列優先

set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {

 const te = this.elements;

 te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
 te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
 te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
 te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;

 return this;

}

set方法 將行優先的矩陣轉換成了列優先矩陣, 矩陣計算全部都會經過set方法
轉換成列優先

ApplyMatrix4

    applyMatrix4( m ) {

        const x = this.x, y = this.y, z = this.z;
        const e = m.elements;

        const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );

        this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
        this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
        this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;

        return this;

    }
applyMatrix4的引數m是經過set方法轉換的列優先矩陣

根據上面的方法, 很容易得出平移矩陣:

const a = new THREE.Matrix4()
a.set(
  1, 0, 0, 1,
  0, 1, 0, 1,
  0, 0, 1, 1,
  0, 0, 0, 1
)

這是xyz分別平移1單位的矩陣。 所以得知平移矩陣的通用矩陣

1, 0, 0, dx,
0, 1, 0, dy,
0, 0, 1, dz,
0, 0, 0, 1

對於旋轉矩陣 難免和三角函式搭上關係。

對於旋轉都是以逆時針旋轉為正角度, 順時針為負角度。
關於X軸的旋轉矩陣根據上圖很容易寫出

[
    1, 0, 0, 0,
    0, cosN, -sinN, 0,
    0, sinN, cosN, 0,
    0, 0, 0, 1
]

關於任意軸旋轉的話, 可以直接看threejs的原始碼

makeRotationAxis( axis, angle ) {

 // Based on http://www.gamedev.net/reference/articles/article1199.asp

 const c = Math.cos( angle );
 const s = Math.sin( angle );
 const t = 1 - c;
 const x = axis.x, y = axis.y, z = axis.z;
 const tx = t * x, ty = t * y;

 this.set(

  tx * x + c, tx * y - s * z, tx * z + s * y, 0,
  tx * y + s * z, ty * y + c, ty * z - s * x, 0,
  tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
  0, 0, 0, 1

 );

 return this;

}

相關文章