Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.9k views
in Technique[技术] by (71.8m points)

swift - ARKit – Adding box to anchor?

I wanted to create a simple object (box) and display it at a position, but everything I can find is about using the renderer() method.

Is there a simpler way to just use an anchor? And just add the anchor to my SCNBox object?

let rect = SCNBox(width: 10.0, height: 10.0, length: 10.0, chamferRadius: 0)
rect.firstMaterial?.diffuse.contents = UIImage(named: "test.png") 
let anchor = ARWorldAnchor( /* ... created with 4 columns */ )
// here how to add the rect object to the anchor ?
session.add(anchor: anchor)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

ARKit | SceneKit

As you suggested in your code, I created a custom anchor inside ARWorldAnchor class. To automatically track that anchor you need renderer(_:didAdd:for:) or session(_:didAdd:) instance methods telling the delegate that new AR anchor has been added to the session. That's why it's necessary to use renderer(_:didAdd:for:) and renderer(_:didUpdate:for:) in ARKit/SceneKit when you want your anchor/anchors to be tracked.

import ARKit

class ViewController: UIViewController {

    @IBOutlet weak var sceneView: ARSCNView!

    override func viewDidLoad() {
        super.viewDidLoad()
        sceneView.delegate = self

        let config = ARWorldTrackingConfiguration()
        sceneView.session.run(config)

        let worldAnchor = ARWorldAnchor(column3: [0, 0,-1, 1])
        sceneView.session.add(anchor: worldAnchor)
    }
}

extension ViewController: ARSCNViewDelegate {

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

        guard let worldAnchor = anchor as? ARWorldAnchor else { return }

        let myNode = SCNNode()
        myNode.geometry = SCNBox(width: 0.1, height: 0.1, 
                                length: 0.1, chamferRadius: 0)
        let path = "texture.jpg"
        myNode.geometry?.firstMaterial?.diffuse.contents = UIImage(named: path)
        node.addChildNode(myNode)
    }
}

class ARWorldAnchor: ARAnchor {

    init(column0: SIMD4<Float> = [1, 0, 0, 0],
         column1: SIMD4<Float> = [0, 1, 0, 0],
         column2: SIMD4<Float> = [0, 0, 1, 0],
         column3: SIMD4<Float> = [0, 0, 0, 1]) {

        let transform = simd_float4x4(columns: (column0,
                                                column1, 
                                                column2,
                                                column3))

        let worldAnchor = ARAnchor(name: "World Anchor",
                              transform: transform)

        super.init(anchor: worldAnchor)
    }

    required init(anchor: ARAnchor) {
        super.init(anchor: anchor)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        fatalError("Hasn't been implemented yet...")
    }
}

RealityKit

A simpler way, that you're talking about, is in RealityKit. When you tether a box with AnchorEntity it will be automatically tracked during running session. As you can see there's minimum boilerplate code in comparison with ARKit/SceneKit pair.

import UIKit
import RealityKit

class ViewController: UIViewController {
    
    @IBOutlet var arView: ARView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let box: MeshResource = .generateBox(size: 0.1)
        var material = SimpleMaterial()
        material.baseColor = try! .texture(.load(named: "texture.jpg"))
        let entity = ModelEntity(mesh: box, materials: [material])
        
        let anchor = AnchorEntity(world: [0, 0,-1])
        anchor.addChild(entity)
        arView.scene.anchors.append(anchor)
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...