ARKitでは、hitTestの後にノードを挿入する2つの方法を見つけました
ARAnchorを挿入し、レンダラーにノードを作成します(_ renderer:SCNSceneRenderer、nodeFor anchor:ARAnchor)-> SCNNode?
let anchor = ARAnchor(transform:hit.worldTransform)
sceneView.session.add(anchor:anchor)
ノードを直接挿入する
node.position = SCNVector3(hit.worldTransform.columns.3.x, hit.worldTransform.columns.3.y, hit.worldTransform.columns.3.z)
sceneView.scene.rootNode.addChildNode(node)
どちらも私にとってはうまくいくように見えますが、なぜどちらか一方の方法ですか?
更新:iOS 11.3(別名「ARKit 1.5」)以降、の追加には違いがありますセッションへのARAnchor
(およびARSCNViewDelegate
コールバックを介したSceneKitコンテンツの関連付け)およびSceneKitスペースへのコンテンツの配置。
セッションにアンカーを追加すると、ARKitに、ワールド空間の特定のポイントがアプリに関連することを伝えています。その後、ARKitは、少なくともそのポイントの近くで、世界の座標空間が現実の世界と正確に一致するように、追加の作業を行うことができます。
そのため、仮想コンテンツを、テーブルや壁にオブジェクトを置くなど、現実世界の興味のあるポイントに「アタッチ」して見せようとする場合、ワールドトラッキングの不正確さによる「ドリフト」は少なくなります。そのオブジェクトは、SceneKitスペースに配置する場合よりもアンカーになります。そして、そのオブジェクトが静的な位置から別の位置に移動する場合、元のアンカーを削除し、後で新しい位置にアンカーを追加します。
さらに、iOS 11.3では opt in to "relocalization"ができます。これは、ARKitが(電話やアプリの切り替えなどによって)中断された後にセッションを再開するのに役立つプロセスです。以前の場所を現在の場所にマッピングする方法を見つけようとしている間もセッションは機能します。これにより、再ローカリゼーションが成功すると、アンカーのワールド空間の位置が変更される可能性があります。
(一方、空中に浮かぶスペースインベーダーを作成するだけの場合、完全に一致するワールドスペースはそれほど重要ではないため、アンカーベースと非アンカーベースの違いはあまり見られませんポジショニング。)
Appleの 拡張現実における3DインタラクションとUIコントロールの処理 記事/サンプルコードの「アンカーを使用して仮想オブジェクトの追跡品質を改善する」周辺のビットを参照してください。
この回答の残りの部分は歴史的にiOS 11.0-11.2.5に関連しており、いくつかのコンテキストを説明しているので、以下に残します...
まず、ARAnchor
withoutSceneKitの使用を検討してください。
ARSKView
を使用している場合、SpriteKitは3Dではないため、3D(現実の)空間で位置/方向を参照する方法が必要です。 3Dで位置を追跡して2Dにマッピングできるようにするには、ARAnchor
が必要です。
Metal(またはGL、何らかの奇妙な理由で)を使用して独自のエンジンを構築している場合、それは3Dシーン記述APIではなく、GPUプログラミングAPIです。したがって、実際にはワールドスペースの概念はありません。 ARAnchor
を使用して、ARKitのワールド空間の概念と構築するものの間の橋渡しをすることができます。
そのため、場合によってはARAnchor
が必要になります。これが3D位置を参照する唯一の賢明な方法だからです。 (そしてもちろん、飛行機の検出を使用している場合、ARKitは飛行機がどこにあるかの推定値を改良するときにシーン空間に対して実際にそれらを移動するため、ARPlaneAnchor
が必要です。)
ARSCNView
を使用すると、SceneKitにはすでに3Dワールド座標空間があり、ARKitはその空間をARKitがマップする実際の空間に一致させるためのすべての作業を行います。したがって、ワールド空間内の位置(および方向など)を記述する_float4x4
_変換を指定すると、次のいずれかを実行できます。
ARAnchor
を作成し、セッションに追加し、ARSCNViewDelegate
コールバックに応答して、アンカーごとにSceneKitコンテンツを提供します。これにより、ARKitはシーンに追加してシーン内に配置します。SCNNode
を作成し、そのsimdTransform
を設定して、シーンのrootNode
の子として追加します。実行中のARSession
がある限り、2つのアプローチに違いはありません。同じことを言うのは同等の方法です。したがって、SceneKitの方法で物事を行うのが好きなら、それは何も悪いことではありません。 (必要に応じて、SIMDタイプの代わりに_SCNVector3
_および_SCNMatrix4
_を使用することもできますが、ARKit APIからSIMDタイプも取得する場合は、前後に変換する必要があります。)
これらのアプローチが異なるのは、セッションがリセットされるときです。ワールドトラッキングが失敗した場合、中断されたセッションを再開するか、セッションをもう一度開始すると、「ワールドスペース」は、シーンにコンテンツを配置したときと同じように現実の世界と一致しなくなります。
この場合、ARKitにセッションからアンカーを削除させることができます— run(_:options:)
メソッドと _ARSession.RunOptions
_ を参照してください。 (はい、現時点ではそれらのいずれも有効であると信用できないためです。)アンカーとデリゲートコールバックを使用してシーンにコンテンツを配置すると、ARKitはすべてのコンテンツを破棄します。 (削除されるデリゲートコールバックを取得します。)SceneKit APIを使用してコンテンツを配置した場合、コンテンツはシーン内にとどまります(ほとんどの場合、間違った場所にあります)。
そのため、どちらを使用するかは、セッションの失敗と中断をどのように処理するかによって異なります(それ以外では、実質的な違いはありません)。
SCNVector3は、「3成分ベクトルの表現」です。 SCNVector3 docs 。
ARAnchorを使用すると、3コンポーネントベクトルにアクセスできますが、「カメラを基準にした実オブジェクトまたは仮想オブジェクトの位置と方向を追跡することもできます」 ARAnchor docs 。それが、シーンを使用する代わりにセッションを使用してアンカーを追加する理由です。
ドキュメントを参照すると、APIの点で違いがわかります:)
それが役に立てば幸い。