Глядя на ваш код, я вижу несколько проблем (не говоря уже о соглашениях по присвоению имен для ваших переменных и методов).
Во-первых, вы создаете Global Variable
, который вы объявили следующим образом:
var cake_1_PlaneNode : SCNNode? = nil
Однако вы используете Local
и Global Variable
для вашего cake_1_PlaneNode
в вашем Delegate Callback
:
let cake_1_PlaneNode = SCNNode(geometry: cake_1_Plane)
self.cake_1_PlaneNode = cake_1_PlaneNode
Который должен просто читаться так:
self.cake_1_PlaneNode = SCNNode(geometry: cake_1_Plane)
Во-вторых, вы добавляете cake_1_PlaneNode
к rootNode
вашего ARSCNView
, а не к обнаруженному ARImageAnchor
, что, вероятно, вам не нужно делать, поскольку при обнаружении ARAnchor
:
Вы можете предоставить визуальный контент для якоря, добавив геометрию
(или другие функции SceneKit) к этому узлу или путем добавления дочерних узлов.
Таким образом, этот метод (если вы на самом деле не хотите делать это так) не нужен.
Остальные проблемы заключаются в самой функции cake_1
.
Во-первых, вы на самом деле не добавляете свой planeNodee
к своему sceneHierachy
.
Поскольку вы не указали, следует ли добавить только что инициализированный planeNode
непосредственно к вашему ARSCNView
или как childNode
вашего cake_1_planeNode
, ваш function
должен включать одно из следующих:
self.sceneView.scene.rootNode.addChildNode(planeNodee)
self.cake_1_planeNode.addChildNode(planeNodee)
Кроме того, вероятно, нет необходимости поворачивать planeNodee
, поскольку по умолчанию SCNPlane
отображается вертикально.
Поскольку вы не указали, где будете размещать свой контент, возможно, использование -.pi / 2
не нужно, поскольку это может сделать его практически невидимым для невооруженного глаза.
Еще одна проблема, которая может также объяснить, что вы не видите свой узел, когда вы фактически добавляете его, это позиция Z.
Если вы установите 2 узла в одной позиции, вы, скорее всего, столкнетесь с проблемой, известной как Z-fighting
(подробнее о здесь вы можете прочитать ). Таким образом, вы, вероятно, должны немного переместить добавленный узел вперед, например, добавив его. SCNVector3 (0,0,0.001)
чтобы учесть это.
Основываясь на всех этих пунктах, я привел полностью рабочий и прокомментированный пример ниже:
import UIKit
import ARKit
//-------------------------
//MARK: - ARSCNViewDelegate
//-------------------------
extension ViewController: ARSCNViewDelegate {
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
//1. Check We Have An ARImageAnchor, Then Get It's Reference Image & Name
guard let imageAnchor = anchor as? ARImageAnchor else { return }
let detectedTarget = imageAnchor.referenceImage
guard let detectedTargetName = detectedTarget.name else { return }
//2. If We Have Detected Our Virtual Menu Then Add The CakeOnePlane
if detectedTargetName == "cakeMenu" {
let cakeOnePlaneGeometry = SCNPlane(width: 0.045, height: 0.045)
cakeOnePlaneGeometry.firstMaterial?.diffuse.contents = UIColor.cyan
cakeOnePlaneGeometry.cornerRadius = 0.01
let cakeOnPlaneNode = SCNNode(geometry: cakeOnePlaneGeometry)
cakeOnPlaneNode.eulerAngles.x = -.pi/2
//3. To Allow Us To Easily Keep Track Our Our Currently Added Node We Will Assign It A Unique Name
cakeOnPlaneNode.name = "Strawberry Cake"
node.addChildNode(cakeOnPlaneNode)
cakeOnPlaneNode.runAction(SCNAction.moveBy(x: 0.15, y: 0, z: 0, duration: 0.75))
}
}
}
class ViewController: UIViewController {
@IBOutlet var augmentedRealityView: ARSCNView!
let augmentedRealitySession = ARSession()
let configuration = ARWorldTrackingConfiguration()
//------------------
//MARK: - Life Cycle
//------------------
override func viewDidLoad() {
super.viewDidLoad()
setupARSession()
}
//-----------------
//MARK: - ARSession
//-----------------
/// Runs The ARSession
func setupARSession(){
//1. Load Our Detection Images
guard let detectionImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil) else { return }
//2. Configure & Run Our ARSession
augmentedRealityView.session = augmentedRealitySession
augmentedRealityView.delegate = self
configuration.detectionImages = detectionImages
augmentedRealitySession.run(configuration, options: [.resetTracking, .removeExistingAnchors])
}
//--------------------
//MARK: - Interaction
//--------------------
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
//1. Get The Current Touch Location & Perform An ARSCNHitTest To Check For Any Hit SCNNode's
guard let currentTouchLocation = touches.first?.location(in: self.augmentedRealityView),
let hitTestNode = self.augmentedRealityView.hitTest(currentTouchLocation, options: nil).first?.node else { return }
//2. If We Have Hit Our Strawberry Cake Then We Call Our makeCakeOnNode Function
if let cakeID = hitTestNode.name, cakeID == "Strawberry Cake"{
makeCakeOnNode(hitTestNode)
}
}
/// Adds An SCNPlane To A Detected Cake Target
///
/// - Parameter node: SCNNode
func makeCakeOnNode(_ node: SCNNode){
let planeGeometry = SCNPlane(width: 0.15 , height: 0.15)
planeGeometry.firstMaterial?.diffuse.contents = UIColor.black.withAlphaComponent(0.75)
let planeNode = SCNNode(geometry: planeGeometry)
planeNode.position = SCNVector3(0, 0, 0.001)
planeNode.runAction(SCNAction.moveBy(x: 0.21, y: 0, z: 0, duration: 0))
node.addChildNode(planeNode)
}
}
Что дает на моем устройстве следующее:
![enter image description here](https://i.stack.imgur.com/JSxGy.png)
Для вашей информации, это, кажется, показывает, что ваши расчеты по размещению вашего контента отключены (если, конечно, это не желаемый результат).
Как видите, весь контент отображается правильно, однако расстояние между ними было довольно большим, и поэтому вам, скорее всего, придется немного панорамировать ваше устройство, чтобы увидеть все это при тестировании и дальнейшей разработке.
Надеюсь, это поможет ...