在ARKit 2中更改场景

时间:2018-07-29 14:39:40

标签: ios swift scenekit arkit

我有一个检测到图像时显示的场景。理想情况下,我希望在检测到图像时加载两个场景,但一次只显示一个场景,并允许用户通过按钮操作进行切换。我该如何实现?谢谢。

case "qr-code":
                print("trackingWatch")
                activeScene = SCNScene(named: "art.scnassets/Apple_Watch/apple_watch.scn")!
                activeNode = activeScene?.rootNode.childNodes.first!
                activeNode?.position = SCNVector3Zero
                activeNode?.position.z = -0.15 
                planeNode.addChildNode(activeNode!)
                node.addChildNode(planeNode)

情况是加载活动场景的图像。我想要一个可以在两者之间旋转的活动场景。

2 个答案:

答案 0 :(得分:0)

您只需要一个场景,您可以做的是将scene2的rootNode附加到第一个场景。想法是将整个场景分成1个节点,可以一键隐藏。

let scene2root = scene2.rootnode
sceneView.scene.rootNode.addChildNode(scene2Root)

然后,当点击按钮时,隐藏scene2root。您甚至可以运行一个动作来平滑过渡。

答案 1 :(得分:0)

有很多方法可以解决这个问题,尽管无论如何它都没有得到优化,但我提供的答案很好用。它只是作为您的项目^ _________ ^的基础。

首先让我们创建一些variables并将其添加到我们的Class Declaration下:

//1. Variable To Store Our MainContentHolder
var activeNode = SCNNode()

//2. Variable To Determine Whether We Have Created Our Intial Content
var initialModelSet = false

//3. Our Dyanmic Scenes
var modelRootA: SCNNode!
var modelRootB: SCNNode!

然后我们将创建一个function来加载我们将在viewDidLoad中调用的场景,例如:

/// Loads Both Overlay Scenes
func setupScenes(){

    guard let activeSceneA = SCNScene(named: "art.scnassets/OverlayA.scn"),
          let modelRootA = activeSceneA.rootNode.childNode(withName: "Container", recursively: false)  else { return }

    self.modelRootA = modelRootA

    guard let activeSceneB = SCNScene(named: "art.scnassets/OverlayB.scn"),
          let modelRootB = activeSceneB.rootNode.childNode(withName: "Container", recursively: false)  else { return }

     self.modelRootB = modelRootB

}

然后,我们将使用ARSCNViewDelegate处理模型的初始设置:

//---------------------------
// MARK: -  ARSCNViewDelegate
//---------------------------

extension ViewController: ARSCNViewDelegate{

    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

        //1. Check We Have Detected An ARImageAnchor & Check It's The One We Want
        guard let validImageAnchor = anchor as? ARImageAnchor,
            let targetName = validImageAnchor.referenceImage.name else { return}

        //2. If Our ReferenceImage Is The QRCode & We Havent Set Our Initial Model Then Load It
        if targetName == "QRCode" && !initialModelSet{

            let width = CGFloat(validImageAnchor.referenceImage.physicalSize.width)
            let height = CGFloat(validImageAnchor.referenceImage.physicalSize.height)

            let planeGeometry = SCNPlane(width: width, height: height)

            activeNode.geometry = planeGeometry
            activeNode.transform = SCNMatrix4MakeRotation(-Float.pi / 2, 1, 0, 0)
            activeNode.addChildNode(modelRootA)
            node.addChildNode(activeNode)

            //3. Set Our Initial Model Set Variable To True
            initialModelSet = true
        }

    }
}

完成此操作后,我们需要为按钮创建IBAction,该按钮将在所需模型之间切换,例如:

/// Toggles The Scenes Shown On The ActiveNode
@IBAction func toggleScenes(){

    //1. If The 1st Model Is Displayed Then Remove It & Add The 2nd Model
    if activeNode.childNodes.contains(modelRootA){
        modelRootA.removeFromParentNode()
        activeNode.addChildNode(modelRootB)
        return
    }

    //2. If The 2nd Model Is Displayed Then Remove It & Add The 1st Modle
    if activeNode.childNodes.contains(modelRootB){
        modelRootB.removeFromParentNode()
        activeNode.addChildNode(modelRootA)
        return
    }
}

希望它会为您指明正确的方向...