Apple Engine

Apple, iPhone, iOS, その周辺のことについて

ARKit や SceneKit で使用している simd について - 行列での関数編 -

今回は行列で用意されている関数について

 

用意されている関数

以下のものが用意されている。

  • simd_add()
  • simd_sub()
  • simd_mul()
  • simd_equal()
  • simd_almost_equal_elements()
  • simd_almost_equal_elements_relative()
  • simd_linear_combination()
  • simd_determinant()
  • simd_inverse()
  • simd_transpose()

 

simd_determinant、simd_inverse、simd_transpose は行列で用意されているプロパティと同じなので割愛。

 

各関数の説明

simd_add()

2つの行列の成分(要素)を足したものを返す。

let f4_1 = simd_float4x4(1)
let f4_2 = simd_float4x4(
    float4(1, 0, 0, 0),
    float4(0, 1, 0, 0),
    float4(0, 0, 1, 0),
    float4(3, 2, 1, 1)
)

simd_add(f4_1, f4_2)
/*
simd_float4x4([
    [2.0, 0.0, 0.0, 0.0)],
    [0.0, 2.0, 0.0, 0.0)],
    [0.0, 0.0, 2.0, 0.0)],
    [3.0, 2.0, 1.0, 2.0)]
])
*/

 

simd_sub()

2つの行列の成分(要素)を引いたものを返す。

let f4_1 = simd_float4x4(2)
let f4_2 = simd_float4x4(
    float4(1, 0, 0, 0),
    float4(0, 1, 0, 0),
    float4(0, 0, 1, 0),
    float4(3, 2, 1, 1)
)

simd_add(f4_1, f4_2)
/*
simd_float4x4([
    [1.0, 0.0, 0.0, 0.0)],
    [0.0, 1.0, 0.0, 0.0)],
    [0.0, 0.0, 1.0, 0.0)],
    [-3.0, -2.0, -1.0, 1.0)]
])
*/

 

simd_mul()

1つの値(スカラー)と行列、 または2つの行列の成分(要素)をかけたものを返す。

let f4_1 = simd_float4x4(2)
let f4_2 = simd_float4x4(
    float4(1, 0, 0, 0),
    float4(0, 1, 0, 0),
    float4(0, 0, 1, 0),
    float4(3, 2, 1, 1)
)

simd_mul(4.0, f4_2)
/*
simd_float4x4([
    [4.0, 0.0, 0.0, 0.0)],
    [0.0, 4.0, 0.0, 0.0)],
    [0.0, 0.0, 4.0, 0.0)],
    [12.0, 8.0, 4.0, 4.0)]
])
*/

simd_mul(f4_1, f4_2)
/*
simd_float4x4([
    [2.0, 0.0, 0.0, 0.0)],
    [0.0, 2.0, 0.0, 0.0)],
    [0.0, 0.0, 2.0, 0.0)],
    [6.0, 4.0, 2.0, 2.0)]
])
*/

 

simd_equal()

2つの行列を比較して同じなら true を返す。

let f4_1 = simd_float4x4(
    float4(1, 0, 0, 0),
    float4(0, 1, 0, 0),
    float4(0, 0, 1, 0),
    float4(0, 0, 0, 1)
)

let f4_2 = simd_float4x4(
    float4(1, 0, 0, 0),
    float4(0, 1, 0, 0),
    float4(0, 0, 1, 0),
    float4(0, 0, 0, 1)
)

simd_equal(f4_1, f4_2) // true

 

simd_almost_equal_elements()

2つの行列を比較して、3番めの引数で許容範囲を設定、その範囲にあるの場合なら true を返す。

許容範囲の値はマイナスも許容するため、2.5 にした場合は -2.0 も許容する。

let f4_1 = simd_float4x4(
    float4(1, 0, 0, 0),
    float4(0, 1, 0, 0),
    float4(0, 0, 1, 0),
    float4(0, 0, 0, 1)
)

let f4_2 = simd_float4x4(
    float4(  1,    0,   0, 0),
    float4(  0,    1,   0, 0),
    float4(  0,    0,   1, 0),
    float4(1.2, -2.0, 2.5, 1)
)

simd_almost_equal_elements(f4_1, f4_2, 2.5)
// true

simd_almost_equal_elements(f4_1, f4_2, 2.0)
// false

 

simd_almost_equal_elements_relative()

2つの行列を比較して、3番めの引数で許容範囲を設定、その範囲にあるの場合なら true を返す。

行列1 - 行列2 の値を比較するためマイナス値が許容されない。
例えば、最初の行列1に 0 があり、行列2の数値がある場合はマイナスになるため false になるので注意。

let f4_1 = simd_float4x4(
    float4(1, 0, 0, 0),
    float4(0, 1, 0, 0),
    float4(0, 0, 1, 0),
    float4(1, 1, 1, 1)
)

let f4_2 = simd_float4x4(
    float4(  1,   0,   0, 0),
    float4(  0,   1,   0, 0),
    float4(  0,   0,   1, 0),
    float4(2.0, 1.5, 3.0, 1)
)

simd_almost_equal_elements_relative(f4_1, f4_2, 3.0)
// true

simd_almost_equal_elements_relative(f4_1, f4_2, 1.0)
// false

 

simd_linear_combination()

値(スカラー)と行列の行の2セットを引数として設定し、 値と行をかけたものを足して行に設定した線型結合を返す。

simd_linear_combination(a, x, b, y) -> float4x4 の中身は

    x.columns[0] = a * x.columns[0] + b * y.columns[0]
    x.columns[1] = a * x.columns[1] + b * y.columns[1]
    x.columns[2] = a * x.columns[2] + b * y.columns[2]
    x.columns[3] = a * x.columns[3] + b * y.columns[3]
    return x;

  

let f4_1 = simd_float4x4(1)
let f4_2 = simd_float4x4(
    float4(1, 0, 0, 0),
    float4(0, 1, 0, 0),
    float4(0, 0, 1, 0),
    float4(3, 2, 1, 1)
)

simd_linear_combination(2, f4_1, 4, f4_2)
/*
simd_float4x4([
    [6.0, 0.0, 0.0, 0.0)],
    [0.0, 6.0, 0.0, 0.0)],
    [0.0, 0.0, 6.0, 0.0)],
    [12.0, 8.0, 4.0, 6.0)]
])
*/

 

まとめ

行列の方は関数が少ないが、比較や線型結合はそれなりに使う可能性があるので簡単に使えるのはよいかと。

残りは新しく追加されたクォータニオンの型があるが、説明が面倒なのでちょいと先になるかも。