前回の記事では、SceneKitで3Dオブジェクトに重力を付与しました。
 
 
今回は、ARKitで現実世界に描写した3Dオブジェクトに、物理シュミレーションを設定し重力を持ち込みます。
 

実装する内容

実装する内容はいたってシンプル。

  • 平面検出し、床となる3Dオブジェクトを追加する
  • 球体の3Dオブジェクトを床の上に落とす

の2点のみです。

平面検出や、ARSCNViewDelegateのデリゲートメソッドなど基本的なARKitの機能の説明は本記事では省略します。

床となるPlaneNodeクラスを作成

床となるPlaneNode(SCNNode)クラスを作成する際に、physicsBodyプロパティに物理情報を追加する事で、物理シュミレーションが可能となります。

このPlaneNodeは球体を受け止める床となりますので、PhysicsBodyのTypeは固定の.staticとします。

PhysicsBodyのType

  • Static :  静止物
  • Dynamic : 動く
  • Kinematic : 単体だと動かないけど、他の物体の影響で動く

ARSCNViewDelegateのデリゲートメソッドであるrenderer(_:didUpdate:for:)で更新された、より正確なARアンカー(ここでは平面情報)を取得した際に、geometryやpositionを更新できる様にupdate(anchor: ARPlaneAnchor)も用意します。

落下させる球体となるBallNodeクラスを作成

球体となるBallNode(SCNNode)クラスにも、物理情報を追加します。

球体は落下させるので、Typeは.dynamicとします。

タップしたARアンカー上の3D座標に球体を落とす機能を実装

まずタップした位置を取得する為に、viewDidLoad()にUITapGestureRecognizerを設定します。

hitTest(_:types:)

次にタップした位置に存在するARアンカーの座標を取得する、ARSCNViewのhitTestメソッドを実装します。
 
 

  • パラメータ
    • 第1引数はCGPoint(2D座標軸)
    • 第2引数はARHitTestResult.ResultType(検出タイプ)
  • 戻り値:
    • ARHitTestResult型の配列。※カメラから近い順にソートされる
      • .worldTransform: simd_float4x4型 (4×4の変換行列)

※参考
https://developer.apple.com/documentation/arkit/arscnview/2875544-hittest

ARHitTestResult.ResultType

ARHitTestResult.ResultTypeの種類は下記

  • featurePoint (特徴点)
  • estimatedHorizontalPlane (推定の平面)
  • estimatedVerticalPlane (推定の垂直の平面)
  • existingPlane (検出した平面 + 平面サイズを考慮しない)
  • existingPlaneUsingExtent (検出した平面 + 平面サイズを考慮する)
  • existingPlaneUsingGeometry (検出したジオメトリ + 平面サイズとカタチを考慮する)

今回は、平面のサイズを考慮するので、existingPlaneUsingExtentを使用します。

※参考
https://developer.apple.com/documentation/arkit/arhittestresult/resulttype

実行

 

特徴量が少ないテーブルで平面検出した為か、テーブルの縁の認識が少し甘いですが、ARKitの世界に重力を持ち込む事が出来ました。