iOS で SceneKit を試す(Swift 3) その73 - 物理シミュレーションとパーティクルの空間に影響を与える PhysicsField について
重力、電磁気、乱気流などの外部から与えられる力を領域内に反映させるオブジェクト、PhysicsField (物理フィールド) について見ていこうと思う。
PhysicsField は物理アニメーションとパーティクルに適応でき、 コード上からカスタムの PhysicsField を作成することができる。
SceneKit で用意されている物理フィールド
名称 | 機能 |
---|---|
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 での設定
適応範囲を決めることでこのような効果を得られる。
scope の outside
デフォルト値は内側の設定になっているので問題はないが、 outside にした場合、設定した適応範囲の外側すべてになるので注意。
フィールド効果の減衰
フィールド効果の減衰は pow(distance - minRadius, -falloff) で計算されている。
falloffExponent の数が 0 より大きい場合、フィールドの効果は近くの PhysicsBody が強くなる。 デフォルトの falloffExponent の値は、フィールドタイプによって異なる。
Scene Editor にだけあるパラメーター
Display - Field Scale でデフォルト値 1。
ガイドで表示されているポリライン(例えば Vartex の場合は渦状)の長さや大きさを変化させる。
Strength の値を増やしても見た目は変わるが、シーンが大きくて見えなかったりする場合などで確認するためのもの。
フイールド別の個別で設定できるパラメーター
Drag Field
Strength
適応範囲での抵抗の力。
個別のパラメーター
なし
Vartex Field
Strength
中心から渦状に外へ弾き出す力。
個別のパラメーター
パラメーター | 型 | 説明 |
---|---|---|
Direction | SCNVector3 | 回転軸の方向。デフォルト値は (x:0, y:-1, z:0) で Y 軸方向に反時計回りで回る |
Offset | SCNVector3 | 回転軸の中央位置を変更する |
Radial Gravity Field
Strength
メートル/秒でフィールドの中心へ加速させる力。
マイナスの場合は押し出す。
重力のフィールドあるため質量が考慮される。
個別のパラメーター
パラメーター | 型 | 説明 |
---|---|---|
Offset | SCNVector3 | 効果が発生する中心の位置を変更する |
Linner Gravity Field
Strength
指定した方向にメートル/秒で加速させる。
重力のフィールドあるため質量が考慮される。
個別のパラメーター
パラメーター | 型 | 説明 |
---|---|---|
Direction | SCNVector3 | 重力が発生する方向。デフォルト値は (x:0, y:-1, z:0) で Y 軸方向に下向きに |
Noise Field
Strength
Simplex noise のアルゴリズムを使用したノイズの大きさ。
個別のパラメーター
以下、コードでイニシャライズ時に使用できる。
パラメーター | 型 | 説明 |
---|---|---|
smoothness | CGFloat | ノイズの滑らかさ。0.0 が最大で、1.0 でなくなる |
speed | CGFloat | 時間でのノイズの変化。0.0 で変化しなくなる |
Turbulance Field
Strength
Noise と同じような乱気流効果の大きさ。
Noise より速く激しく揺れるように振る舞う。
個別のパラメーター
以下、コードでイニシャライズ時に使用できる。
パラメーター | 型 | 説明 |
---|---|---|
smoothness | CGFloat | ノイズの滑らかさ。0.0 が最大で、1.0 でなくなる |
speed | CGFloat | 時間でのノイズの変化。0.0 で変化しなくなる |
Spring Field
Strength
バネの堅さ。
値を高くすると速く中央に戻る。
個別のパラメーター
パラメーター | 型 | 説明 |
---|---|---|
Offset | SCNVector3 | 効果が発生する中心の位置を変更する |
Electoric Field
Strength
電荷によって引き付ける(遠ざける)力。
こちらは中央に引き付ける。
個別のパラメーター
パラメーター | 型 | 説明 |
---|---|---|
Offset | SCNVector3 | 磁界の中央位置を変更する |
Magnetic Field
Strength
Electoric Field 同様。
こちらは直線電流の磁場のようなフィールドであるため、プラス値で半時計回り、マイナス値で時計周りになる。
(PhysicsBody が 負の電荷を持つ場合は逆)
個別のパラメーター
パラメーター | 型 | 説明 |
---|---|---|
Direction | SCNVector3 | 力の方向。デフォルト値は (x:0, y:-1, z:0) で Y 軸方向に下方向 |
Offset | SCNVector3 | 中央位置を変更する |
パーティクルを物理フィールドでも動くようにする
デフォルトではオフになっている。
コードから isAffectedByPhysicsFields を true にするか、
SceneEditor の Attributes Inspector から Affected by physics field のチェックを入れる。
コードから設定する
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
今回はここまで。