Apple Engine

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

iOS で SceneKit を試す(Swift 3) その73 - 物理シミュレーションとパーティクルの空間に影響を与える PhysicsField について

重力、電磁気、乱気流などの外部から与えられる力を領域内に反映させるオブジェクト、PhysicsField (物理フィールド) について見ていこうと思う。

PhysicsField は物理アニメーションとパーティクルに適応でき、 コード上からカスタムの PhysicsField を作成することができる。

 

SceneKit で用意されている物理フィールド

f:id:x67x6fx74x6f:20170818163631p:plain

名称 機能
Drag 動きを減速させる流体摩擦や空気抵抗のフィールド
Vartex 指定した軸を中心に力が循環する渦のフィールド
Radial Gravity 中心に向かって加速する重力フィールド
Linner Gravity 特定の方向に加速する重力フィールド
Noise ランダムな力を適用するフィールド
Turbulance オブジェクトの速度に比例した大きさでランダムな力を適用するフィールド
Spring 中心に向かってバネのような力で引っ張るフィールド
Electoric 電荷によって中心から距離に基づいてオブジェクトを引き付けるか、または反発させるフィールド
Magnetic 電荷、速度、フィールド軸の距離に基づいて、オブジェクトを引き付けるか、または反発させるフィールド

 

共通のパラメーター

パラメーター Scene Editor 機能
strength PhysicsField が適応範囲に与える力の数値
falloffExponent 距離とともに strength の値がどのように減少するかを設定する数
minimumDistance 距離に基づく効果の最小値
isActive PhysicsField 効果の有効/無効を設定する
isExclusive PhysicsField が重なっている他のフィールドを無視するかどうかを指定する。デフォルト値は false。true にするとこれに重なる Field は無視される
halfExtent PhysicsField の適応範囲を設定する。デフォルト値は無限遠になっているため、Scene Editor で設定を変更する場合は infinite のチェックを外す
scope 適応範囲を指定している内側か外側かを決める。halfExtent がデフォルト値の場合は無限遠であるため変更しても変わらない
usesEllipsoidalExtent デフォルトでは適応範囲は立方体になっているが、こちらを true にすると球状に変更することができる
categoryBitMask × PhysicsField 用のカテゴリービットマスク。PhysicsBody と PhysicsField のビットマスクの AND 演算が 0 でなければ、PhysicsField を適応する

 

補足

halfExtent の設定

PhysicsField の中心である pivot から x, y, z 座標を指定するとそれに合わせた立方体が適応範囲となる。

PhysicsField を (x: 2.0, y:2.0, z:2.0) に配置した際、halfExtent を (x: 0.5, y:0.5, z:0.5) とした設定は、 x, y, z で 1.5 〜 2.5 が有効範囲となる。

 

Scene Editor での設定

f:id:x67x6fx74x6f:20170818163815p:plain

 

適応範囲を決めることでこのような効果を得られる。

f:id:x67x6fx74x6f:20170818163839g:plain

 

scope の outside

デフォルト値は内側の設定になっているので問題はないが、 outside にした場合、設定した適応範囲の外側すべてになるので注意。

 

フィールド効果の減衰

フィールド効果の減衰は pow(distance - minRadius, -falloff) で計算されている。

falloffExponent の数が 0 より大きい場合、フィールドの効果は近くの PhysicsBody が強くなる。 デフォルトの falloffExponent の値は、フィールドタイプによって異なる。

 

Scene Editor にだけあるパラメーター

Display - Field Scale でデフォルト値 1。

ガイドで表示されているポリライン(例えば Vartex の場合は渦状)の長さや大きさを変化させる。
Strength の値を増やしても見た目は変わるが、シーンが大きくて見えなかったりする場合などで確認するためのもの。

 

 

フイールド別の個別で設定できるパラメーター

 

Drag Field

f:id:x67x6fx74x6f:20170818171635p:plain

f:id:x67x6fx74x6f:20170818163948p:plain

 

Strength

適応範囲での抵抗の力。

 

個別のパラメーター

なし

 

Vartex Field

f:id:x67x6fx74x6f:20170818171551p:plain

f:id:x67x6fx74x6f:20170818164045p:plain

 

Strength

中心から渦状に外へ弾き出す力。

 

個別のパラメーター
パラメーター 説明
Direction SCNVector3 回転軸の方向。デフォルト値は (x:0, y:-1, z:0) で Y 軸方向に反時計回りで回る
Offset SCNVector3 回転軸の中央位置を変更する

 

Radial Gravity Field

f:id:x67x6fx74x6f:20170818171745p:plain

f:id:x67x6fx74x6f:20170818165427p:plain

 

Strength

メートル/秒でフィールドの中心へ加速させる力。
マイナスの場合は押し出す。

重力のフィールドあるため質量が考慮される。

 

個別のパラメーター
パラメーター 説明
Offset SCNVector3 効果が発生する中心の位置を変更する

 

Linner Gravity Field

f:id:x67x6fx74x6f:20170818171801p:plain

f:id:x67x6fx74x6f:20170818165449p:plain

 

Strength

指定した方向にメートル/秒で加速させる。

重力のフィールドあるため質量が考慮される。

 

個別のパラメーター
パラメーター 説明
Direction SCNVector3 重力が発生する方向。デフォルト値は (x:0, y:-1, z:0) で Y 軸方向に下向きに

 

Noise Field

f:id:x67x6fx74x6f:20170818171825p:plain

f:id:x67x6fx74x6f:20170818165526p:plain

 

Strength

Simplex noise のアルゴリズムを使用したノイズの大きさ。

 

個別のパラメーター

以下、コードでイニシャライズ時に使用できる。

パラメーター 説明
smoothness CGFloat ノイズの滑らかさ。0.0 が最大で、1.0 でなくなる
speed CGFloat 時間でのノイズの変化。0.0 で変化しなくなる

 

Turbulance Field

f:id:x67x6fx74x6f:20170818171635p:plain

f:id:x67x6fx74x6f:20170818165541p:plain

 

Strength

Noise と同じような乱気流効果の大きさ。
Noise より速く激しく揺れるように振る舞う。

 

個別のパラメーター

以下、コードでイニシャライズ時に使用できる。

パラメーター 説明
smoothness CGFloat ノイズの滑らかさ。0.0 が最大で、1.0 でなくなる
speed CGFloat 時間でのノイズの変化。0.0 で変化しなくなる

 

Spring Field

f:id:x67x6fx74x6f:20170818171905p:plain

f:id:x67x6fx74x6f:20170818165600p:plain

 

Strength

バネの堅さ。
値を高くすると速く中央に戻る。

 

個別のパラメーター
パラメーター 説明
Offset SCNVector3 効果が発生する中心の位置を変更する

 

Electoric Field

f:id:x67x6fx74x6f:20170818171925p:plain

f:id:x67x6fx74x6f:20170818165620p:plain

 

Strength

電荷によって引き付ける(遠ざける)力。
こちらは中央に引き付ける。

 

個別のパラメーター
パラメーター 説明
Offset SCNVector3 磁界の中央位置を変更する

 

Magnetic Field

f:id:x67x6fx74x6f:20170818171937p:plain

f:id:x67x6fx74x6f:20170818165636p:plain

 

Strength

Electoric Field 同様。 こちらは直線電流の磁場のようなフィールドであるため、プラス値で半時計回り、マイナス値で時計周りになる。
(PhysicsBody が 負の電荷を持つ場合は逆)

 

個別のパラメーター
パラメーター 説明
Direction SCNVector3 力の方向。デフォルト値は (x:0, y:-1, z:0) で Y 軸方向に下方向
Offset SCNVector3 中央位置を変更する

 

パーティクルを物理フィールドでも動くようにする

デフォルトではオフになっている。

コードから isAffectedByPhysicsFields を true にするか、
SceneEditor の Attributes Inspector から Affected by physics field のチェックを入れる。

f:id:x67x6fx74x6f:20170818172729p:plain

 

コードから設定する

SCNPhysicsField をイニシャライズして SCNNode の physicsField に渡す。

let field = SCNPhysicsField.vortex()

field.isActive = true
field.isExclusive = false

field.strength = 1
field.falloffExponent = 0
field.minimumDistance = 0

field.halfExtent = SCNVector3(10,10,10)
field.usesEllipsoidalExtent = false
field.scope = .insideExtent

field.direction = SCNVector3(0,0,0)
field.offset = SCNVector3(0,0,0)

field.categoryBitMask = -1

let fieldNode = SCNNode()
fieldNode.physicsField = field

scene.rootNode.addChildNode(fieldNode)

 

イニシャライズの命令はこちらを参照。

SCNPhysicsField - SceneKit | Apple Developer Documentation

 

今回はここまで。