【问题标题】:Placing SCNScene on the other SCNScenePlacing SCNScene on the other SCNScene
【发布时间】:2022-12-01 21:51:23
【问题描述】:

I am trying to built an app where you can place dices at the table, that spawns automatically if the app detects horizontal plane. I will explain the problem after the code:

import UIKit
import SceneKit
import ARKit

class ViewController: UIViewController, ARSCNViewDelegate {

    @IBOutlet var sceneView: ARSCNView!
    
    var isTableAdded = false
    
    var diceArray = [SCNNode]()
        
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Set the view's delegate
        sceneView.delegate = self
        
        self.sceneView.debugOptions = [ARSCNDebugOptions.showFeaturePoints]
        
        sceneView.autoenablesDefaultLighting = true
        
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        // Create a session configuration
        let configuration = ARWorldTrackingConfiguration()
        
        configuration.planeDetection = .horizontal
        
        // Run the view's session
        sceneView.session.run(configuration)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        // Pause the view's session
        sceneView.session.pause()
    }
     
// MARK: - ADDS DICE
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        
        print("Tapped")

        if let touch = touches.first {
            let touchLocation = touch.location(in: sceneView)
            
            let results = sceneView.hitTest(touchLocation, types: .existingPlaneUsingExtent)
            
            if let hitResults = results.first {
                
                // Create a new scene
                let diceScene = SCNScene(named: "art.scnassets/diceCollada.scn")!
                
                if let diceNode = diceScene.rootNode.childNode(withName: "Dice", recursively: true) {
                    
                    diceNode.position = SCNVector3(
                        x: hitResults.worldTransform.columns.3.x,
                        y: hitResults.worldTransform.columns.3.y,
                        z: hitResults.worldTransform.columns.3.z)
                    
                    diceArray.append(diceNode)
                    
                    sceneView.scene.rootNode.addChildNode(diceNode)
                    
                }
            }
        }
    } 

// MARK: - RENDERS TABLE AT THE HORIZONTAL PLANE

    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        print("plane detected")

        if isTableAdded == false {
            let planeAnchor = anchor
            // let planeNode = SCNNode()
            let x = planeAnchor.transform.columns.3.x
            let y = planeAnchor.transform.columns.3.y
            let z = planeAnchor.transform.columns.3.z
            //planeNode!.position = SCNVector3(x: x, y: y, z: z)
            
            let idleScene = SCNScene(named: "art.scnassets/Table.scn")!
            let node = SCNNode()
            for child in idleScene.rootNode.childNodes{
                node.addChildNode(child)
            }
            node.position = SCNVector3(x,y,z)
            node.scale = SCNVector3(0.001,0.001,0.001)
            
            sceneView.scene.rootNode.addChildNode(node)
            
            isTableAdded = true
        }
        print("Model placed")
    }
    
    func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
        guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
        
        print("plane updated")
    }
}

The problem is here. (Video at Imgur). As you can see table is placed, but I don't quite understand how to place SCNScene directly at the other one. The only thing I have achieved is creating a model at the tap and it's placed only at the horizontal plane.

How can I spawn model on the other model?

【问题讨论】:

    标签: swift uikit scenekit arkit scnscene


    【解决方案1】:

    You could probably use this tiny little extension to achive what you want. It basically is a helper function that allows you to grab all the geometry objects from any scene-file (.scn) and you can place them wherever you want. I use this function to compose/build one single scene (the default) from out of plenty of other scene-files, which hold individual geometries. It will return a SCNNode instead of a new SCNScene. Let me know, if you need more information, or if I missunderstand you.

    extension SCNNode {
        convenience init(named name: String) {
            self.init()
            guard let scene = SCNScene(named: name) else {return}
            for childNode in scene.rootNode.childNodes {addChildNode(childNode)}
        }
    }
    

    (place this code-sn-p somewhere outside your ViewController)

    Keep in mind to add a static physicsBody to the Table (and probably the floor) and dynamic physicsBodies to your dices, if you want to keep them on the top of the table and prevent them to fall trough the ground (floor).

    【讨论】:

      猜你喜欢
      • 2021-04-23
      • 1970-01-01
      • 2017-03-29
      • 1970-01-01
      • 1970-01-01
      • 2016-04-04
      • 1970-01-01
      • 2017-01-05
      • 2021-06-30
      相关资源
      最近更新 更多