ARKitによって追跡される水平面および垂直面を使用して、オブジェクトを壁の後ろ/実際のオブジェクトの後ろに隠すにはどうすればよいですか?現在、3Dで追加されたオブジェクトは、部屋を出るとき、および/または背後にあるべきオブジェクトの前に、壁を通して見ることができます。 ARKitが提供するデータを使用して、壁を通してオブジェクトが表示されずに、より自然なARエクスペリエンスを提供することは可能ですか?
ここには2つの問題があります。
(そして、あなたも 正規表現を使用 !
SceneKitマテリアルの colorBufferWriteMask
を空の値([]
(Swift)では、そのマテリアルを使用するオブジェクトはビューに表示されませんが、レンダリング中は引き続きzバッファーに書き込まれ、他のオブジェクトのレンダリングに影響します。実際には、オブジェクトのような形の「穴」ができます。この穴を通して、背景(ARSCNView
の場合はカメラフィード)が表示されますが、他のSceneKitオブジェクトを隠すことができます。
また、隠されている他のノードの前に、オクルードされたものがレンダリングされることを確認する必要があります。これは、ノード階層を使用して行うことができます(親ノードが子の前にレンダリングされるか、またはその逆にレンダリングされるかを覚えていませんが、テストするのは簡単です)。階層内のピアであるノードには確定的な順序はありませんが、 renderingOrder
プロパティを使用すると、階層に関係なく順序を強制できます。このプロパティはデフォルトでゼロに設定されているため、-1に設定するとすべての前にレンダリングされます。 (またはより細かく制御するには、いくつかのノードのrenderingOrder
sを値のシーケンスに設定します。)
IOS 11.3以降(別名「ARKit 1.5」)では、 vertical
プレーン検出をオンにできます。 (注: vertical
から平面アンカーが戻ると、それらは自動的に回転します。したがって、アンカーにモデルをアタッチすると、ローカルの「上」方向はまた、iOS 11.3の新機能では、方向に関係なく、検出された各平面のより詳細な形状推定を取得できます( ARSCNPlaneGeometry を参照)。
ただし、水平および垂直がある場合でも、平面の外側の限界は時間とともに変化する推定値にすぎません。つまり、ARKitは壁の一部がどこにあるかをすばやく検出できますが、ユーザーがデバイスを振って空間をマップするために時間を費やすことなく、壁の端がどこにあるかを知りません。その場合でも、マッピングされたエッジは実際の壁のエッジと正確に一致しない場合があります。
したがって...検出された垂直面を使用して仮想ジオメトリをオクルードすると、壁の端に隠れていないか、場所を通して見えることにより、隠されるはずの仮想オブジェクトが見える場所を見つけることができますここで、ARKitは実際の壁全体をマッピングしていません。 (後者の問題は、ARKitよりも大きな範囲を想定することで解決できる場合があります。)
オクルージョンマテリアルを作成するのは本当に簡単です
let boxGeometry = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)
// Define a occlusion material
let occlusionMaterial = SCNMaterial()
occlusionMaterial.colorBufferWriteMask = []
boxGeometry.materials = [occlusionMaterial]
self.box = SCNNode(geometry: boxGeometry)
// Set rendering order to present this box in front of the other models
self.box.renderingOrder = -1
優れたソリューション:
私のために働いた。
しかし、私の場合、コードで壁を設定したかったのです。したがって、ユーザーが壁を設定したくない場合->平面検出を使用して壁を検出し、コードで壁を設定します。
または、4メートルの範囲でiphone dephtセンサーが機能し、 ARHitTest で障害物を検出できます。
ホールドアウト操作(別名ブラックホールまたはブロッキングマテリアル)では、iOS 11およびmacOS 13で.colorBufferWriteMask
と呼ばれるインスタンスプロパティを使用できます。このプロパティは、マテリアルをレンダリングするときに深度チャネル情報を書き込みます。この方法で使用できます:
torus.geometry?.firstMaterial?.colorBufferWriteMask = .alpha
またはこの方法:
func blockingMaterial() -> SCNMaterial {
let holdout = SCNMaterial()
holdout.isDoubleSided = true
holdout.diffuse.contents = CIColor.black
holdout.colorBufferWriteMask = SCNColorMask(rawValue: 0)
return holdout
}
torus.geometry?.firstMaterial = blockingMaterial()
目に見えない仮想壁をシェーディングするために、このプロパティを簡単に使用できます。これらの見えない仮想壁を適切な場所に配置するには、ARWorldMap
クラス(iOS 12で動作します)およびARAnchors
を支援します。
session.getCurrentWorldMap { worldMap, error in
guard let worldMap = worldMap else {
showAlert(error)
return
}
}
let configuration = ARWorldTrackingConfiguration()
configuration.initialWorldMap = worldMap
session.run(configuration)
ARWorldMap
は、スペースマッピング状態と、世界追跡ARセッションからの一連のARAnchorsです。それについて読む こちら 。