Search code examples
swiftswiftuiaugmented-realityscenekitarkit

Adding multiple SCNNode(s) at the same time


I have this function named addShapes. I want it to create 3 shapes

import ARKit
import SwiftUI
struct SceneKitView: UIViewRepresentable {
    
    let arView = ARSCNView(frame: .zero)
    let config = ARWorldTrackingConfiguration()
    @Binding var addBox: Int
    @Binding var reset: Bool
    @Binding var node: SCNNode
    
    fileprivate func addShapes() {
        let letBall1Geo = SCNSphere(radius: 0.05)
        letBall1Geo.firstMaterial?.diffuse.contents = UIColor.red
        letBall1Geo.firstMaterial?.specular.contents = UIColor.white
        let ball1 = SCNNode(geometry: letBall1Geo)
        ball1.position = SCNVector3(0, 0, 0)
        self.arView.scene.rootNode.addChildNode(ball1)
                
        let letBall2Geo = SCNSphere(radius: 0.05)
        letBall2Geo.firstMaterial?.diffuse.contents = UIColor.white
        letBall2Geo.firstMaterial?.specular.contents = UIColor.white
        let ball2 = SCNNode(geometry: letBall2Geo)
        ball1.position = SCNVector3(1, 1, 1)
        self.arView.scene.rootNode.addChildNode(ball2)
        
        let stickGeo = SCNCapsule(capRadius: 0.05, height: 0.1)
        stickGeo.firstMaterial?.diffuse.contents = UIColor.blue
        stickGeo.firstMaterial?.specular.contents = UIColor.white
        let stick = SCNNode(geometry: stickGeo)
        stick.position = SCNVector3(2, 2, 2)
        self.arView.scene.rootNode.addChildNode(stick)
        
    }
    
    fileprivate func removeCube() {
        /////
    }
    
    func makeUIView(context: Context) -> ARSCNView {
        arView.scene = SCNScene()
        arView.autoenablesDefaultLighting = true
        arView.debugOptions = [ARSCNDebugOptions.showFeaturePoints, ARSCNDebugOptions.showWorldOrigin]
        arView.session.run(self.config)
        return arView
    }
    
    func updateUIView(_ uiView: ARSCNView,
                       context: Context) {
        if addBox > 0 {
            self.addShapes()
        }
        if reset {
            self.removeCube()
        }
    }
}

The problem is that it's only adding the first shape (ball1) and not all of them. Do you know why? Thanks in advance!


Solution

  • Your code works fine (a position was a problem):

    import SwiftUI
    import ARKit
    
    struct ContentView : View {
        
        @State var addBox: Int = 3
        @State var reset: Bool = false
        @State var node: SCNNode = SCNNode()
        
        var body: some View {
            return SceneKitView(addBox: $addBox,
                                 reset: $reset,
                                  node: $node).edgesIgnoringSafeArea(.all)
        }
    }
    

    ...

    struct SceneKitView: UIViewRepresentable {
        
        let arView = ARSCNView(frame: .zero)
        let config = ARWorldTrackingConfiguration()
        @Binding var addBox: Int
        @Binding var reset: Bool
        @Binding var node: SCNNode
        
        fileprivate func addShapes() {
            let letBall1Geo = SCNSphere(radius: 0.05)
            letBall1Geo.firstMaterial?.diffuse.contents = UIColor.red
            letBall1Geo.firstMaterial?.specular.contents = UIColor.white
            let ball1 = SCNNode(geometry: letBall1Geo)
            ball1.position = SCNVector3(0, 0, -1)
            self.arView.scene.rootNode.addChildNode(ball1)
                    
            let letBall2Geo = SCNSphere(radius: 0.05)
            letBall2Geo.firstMaterial?.diffuse.contents = UIColor.green
            letBall2Geo.firstMaterial?.specular.contents = UIColor.white
            let ball2 = SCNNode(geometry: letBall2Geo)
            ball1.position = SCNVector3(0, 0.2, -1)
            self.arView.scene.rootNode.addChildNode(ball2)
            
            let stickGeo = SCNCapsule(capRadius: 0.05, height: 0.1)
            stickGeo.firstMaterial?.diffuse.contents = UIColor.blue
            stickGeo.firstMaterial?.specular.contents = UIColor.white
            let stick = SCNNode(geometry: stickGeo)
            stick.position = SCNVector3(0, 0.4, -1)
            self.arView.scene.rootNode.addChildNode(stick)            
        }
    
        func makeUIView(context: Context) -> ARSCNView {
            arView.scene = SCNScene()
            arView.autoenablesDefaultLighting = true
            arView.debugOptions = [.showFeaturePoints, .showWorldOrigin]
            arView.session.run(self.config)
            return arView
        }
        
        func updateUIView(_ uiView: ARSCNView, context: Context) {
            if addBox > 0 {
                self.addShapes()
            }
        }
    }
    

    enter image description here