Tim Langner
Tim Langner

Reputation: 417

How to place a 3D model on top of a reference image with RealityKit?

I want to place a 3D Model from the local device on top of the reference image when it's recognized. To achieve this I have tried the following:

  1. Adding the reference image to the session configuration:
override func viewDidLoad() {
    super.viewDidLoad()
        
    arView.session.delegate = self
        
    // Check if the device supports the AR experience
    if (!ARConfiguration.isSupported) {
        TLogger.shared.error_objc("Device does not support Augmented Reality")
        return
    }
        
    guard let qrCodeReferenceImage = UIImage(named: "QRCode") else { return }
    let detectionImages: Set<ARReferenceImage> = convertToReferenceImages([qrCodeReferenceImage])
        
    let configuration = ARWorldTrackingConfiguration()
    configuration.detectionImages = detectionImages
        
    arView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
}
  1. Using the ARSessionDelegate to get notified when the reference image was detected and placing the 3D model at the same position as his ARImageAnchor:
func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {
    for anchor in anchors {
        guard let imageAnchor = anchor as? ARImageAnchor else { return }
        let position = imageAnchor.transform

        addEntity(self.localModelPath!, position)
    }
}
func addEntity(_ modelPath: URL, _ position: float4x4) {
    // Load 3D Object as Entity
    let entity = try! Entity.load(contentsOf: modelPath)
        
    // Create the Anchor which gets added to the AR Scene
    let anchor = AnchorEntity(world: position)
    anchor.addChild(entity)
    anchor.transform.matrix = position
    arView.scene.addAnchor(anchor)
}

However, whenever I try to place the anchor including my 3D model (the entity) at a specific position, it doesn't appear in the arView. It seems like the model is getting loaded though since a few frames are getting lost when executing the addEntity function. When I don't specifically set the anchors position the model appears in front of the camera.

Can anyone lead me in the right direction here?

Upvotes: 2

Views: 1625

Answers (1)

Andy Jazz
Andy Jazz

Reputation: 58553

Solution I

To make your code work properly, remove this line:

anchor.transform.matrix = position

enter image description here

@TimLangner – "...But I want to make the model appear on top of the reference image and not at any other location..."

As you can see, my test sphere has appeared on top of the reference image. When changing its position, remember that the Y-axis of the image anchor is directed towards the camera if the QR is vertical, and is directed up if the QR code is on a horizontal surface.

Make sure, a pivot point is located where it should.

In my case (you can see that I'm using AppClipCode), to move sphere 30 cm up, I have to move along negative Z direction.

entity.position.z = anchor.position.z - 0.3

Solution II

In my opinion, the most simple and productive solution would be to use the RealityKit's native AnchorEntity(.image(...)), without the need of implementing ARImageAnchor in delegate's method.

AnchorEntity(.image(group: "GroupName", name: "forModel"))

Here's a code:

import UIKit
import RealityKit

class ViewController: UIViewController {
    
    @IBOutlet var arView: ARView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let entity = ModelEntity(mesh: .generateSphere(radius: 0.1))
        let anchor = AnchorEntity(.image(group: "AR Resources", 
                                          name: "appClipCode"))
        anchor.addChild(entity)
        
        entity.position.z = anchor.position.z - 0.3
        arView.scene.anchors.append(anchor)
    }
}

Upvotes: 2

Related Questions