Получить все ARAnchors сфокусированной камеры в ARKIT
Когда приложение запускается первым, на одной стене обнаруживается вертикальная поверхность, а не фокус камеры на вторую стену, во второй стене обнаруживается другая поверхность. Первая стена теперь больше не видна ARCamera, но этот код предоставляет мне якоря первой стены. но мне нужны анкеры второй стены, которая сейчас видна / сфокусирована в камере.
if let anchor = sceneView.session.currentFrame?.anchors.first {
let node = sceneView.node(for: anchor)
addNode(position: SCNVector3Zero, anchorNode: node)
} else {
debugPrint("anchor node is nil")
}
2 ответа
Чтобы получить узел, который в данный момент находится в точке зрения, вы можете сделать что-то вроде этого:
var targettedAnchorNode: SCNNode?
if let anchors = sceneView.session.currentFrame?.anchors {
for anchor in anchors {
if let anchorNode = sceneView.node(for: anchor), let pointOfView = sceneView.pointOfView, sceneView.isNode(anchorNode, insideFrustumOf: pointOfView) {
targettedAnchorNode = anchorNode
break
}
}
if let targettedAnchorNode = targettedAnchorNode {
addNode(position: SCNVector3Zero, anchorNode: targettedAnchorNode)
} else {
debugPrint("Targetted node not found")
}
} else {
debugPrint("Anchors not found")
}
Если вы хотите получить все сфокусированные узлы, соберите их в массив, удовлетворяющий заданному условию
Удачи!
Ключ к ответу находится в начале строки вашего if let
заявление.
Давайте разберемся с этим:
Когда ты сказал let anchor = sceneView.session.currentFrame?.anchors.first
, вы ссылаетесь на необязательный массив ARAnchor
который, естественно, может иметь более одного элемента.
Так как вы всегда звоните first
Например, индекс [0], вы всегда получите 1-й ARAnchor
который был добавлен в массив.
Поскольку теперь у вас есть 2 якоря, вам, естественно, понадобится последний (последний) элемент. Таким образом, вы можете попробовать это как стартер:
if let anchor = sceneView.session.currentFrame?.anchors.last {
let node = sceneView.node(for: anchor)
addNode(position: SCNVector3Zero, anchorNode: node)
} else {
debugPrint("anchor node is nil")
}
Обновление: так как другой автор интерпретировал вопрос по-другому, он полагает, что вопрос заключается в том, как я могу определить, находится ли ARPlaneAnchor в поле зрения? Давайте подойдем к этому по-другому.
Во-первых, мы должны принять во внимание, что у ARCamera есть Frostrum, в котором отображается наш контент:
Таким образом, нам нужно будет определить, был ли ARPlaneAnchor inViewOfFrostrum
,
Сначала мы создадим 2 переменные:
var planesDetected = [ARPlaneAnchor: SCNNode]()
var planeID: Int = 0
1-й хранить ARPlaneAnchor
и его связанный SCNNode
и 2-й, чтобы предоставить уникальный идентификатор для каждой плоскости.
в ARSCNViewDelegate
мы можем визуализировать ARPlaneAnchor и затем сохранить его информацию, например:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
//1. Get The Current ARPlaneAnchor
guard let anchor = anchor as? ARPlaneAnchor else { return }
//2. Create An SCNode & Geometry To Visualize The Plane
let planeNode = SCNNode()
let planeGeometry = SCNPlane(width: CGFloat(anchor.extent.x), height: CGFloat(anchor.extent.z))
planeGeometry.firstMaterial?.diffuse.contents = UIColor.cyan
planeNode.geometry = planeGeometry
//3. Set The Position Based On The Anchors Extent & Rotate It
planeNode.position = SCNVector3(anchor.center.x, anchor.center.y, anchor.center.z)
planeNode.eulerAngles.x = -.pi / 2
//4. Add The PlaneNode To The Node & Give It A Unique ID
node.addChildNode(planeNode)
planeNode.name = String(planeID)
//5. Store The Anchor & Node
planesDetected[anchor] = planeNode
//6. Increment The Plane ID
planeID += 1
}
Теперь мы сохранили обнаруженные плоскости, тогда нам, конечно, нужно определить, находится ли какая-либо из них в поле зрения ARCamera, например:
/// Detects If An Object Is In View Of The Camera Frostrum
func detectPlaneInFrostrumOfCamera(){
//1. Get The Current Point Of View
if let currentPointOfView = augmentedRealityView.pointOfView{
//2. Loop Through All The Detected Planes
for anchorKey in planesDetected{
let anchor = anchorKey.value
if augmentedRealityView.isNode(anchor, insideFrustumOf: currentPointOfView){
print("ARPlaneAnchor With ID \(anchor.name!) Is In View")
}else{
print("ARPlaneAnchor With ID \(anchor.name!) Is Not In View")
}
}
}
}
Наконец, нам нужно получить доступ к этой функции, которую мы могли бы сделать в следующем delegate
метод например renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval)
:
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
detectPlaneInFrostrumOfCamera()
}
Надеюсь, что оба из них будут указывать в правильном направлении...