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)
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…