Realitykit - Stored Entities & Load The Scene Aynchronously from The Url

RealityKit – Asynchronous model loading doesn't work

Use the following macOS code version to find out how to load model asynchronously:

import AppKit
import RealityKit
import Combine

class GameViewController: NSViewController {

@IBOutlet var arView: ARView!
var model: ModelEntity? = nil
let anchor = AnchorEntity()
var cancellable: AnyCancellable? = nil

override func awakeFromNib() {

arView.environment.background = .color(.systemTeal)

cancellable = Entity.loadModelAsync(named: "Glasses.usdz")
.sink(receiveCompletion: { completion in
if case let .failure(error) = completion {
print("Unable to load a model due to error \(error)")
}
self.cancellable?.cancel()

}, receiveValue: { [self] (model: Entity) in
if let model = model as? ModelEntity {
self.model = model
cancellable?.cancel()
print("Congrats! Model is successfully loaded!")
anchor.addChild(model)
anchor.position = [0.4, 1.5, -1]
anchor.scale = [300, 300, 300] // set appropriate scale
arView.scene.anchors.append(anchor)
}
})
}
}

Sample Image

Loading anchor from url async doesnt work

You have to store subscriber somewhere in member

// somewhere above
private var subscribers: Set<AnyCancellable>()

...
if let url = url {
let loadRequest = Entity.loadAnchorAsync(contentsOf: url)
loadRequest.sink(receiveCompletion: { completion in
// handle completion
}, receiveValue: { anchor in
self.arView.scene.addAnchor(anchor)
}).store(in: &self.subscribers) // << keep it alive
} else {
fatalError("no url")
}

Error in displaying reality file from network

Uploading a .reality model from web works fine. You can easily check this in Xcode Simulator:

import UIKit
import RealityKit

class ViewController: UIViewController {

@IBOutlet var arView: ARView!

override func viewDidLoad() {
super.viewDidLoad()

let url = URL(string: "https://developer.apple.com/augmented-reality/quick-look/models/cosmonaut/CosmonautSuit_en.reality")
let documents = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let destination = documents.appendingPathComponent(url!.lastPathComponent)
let session = URLSession(configuration: .default,
delegate: nil,
delegateQueue: nil)

var request = URLRequest(url: url!)
request.httpMethod = "GET"

let downloadTask = session.downloadTask(with: request, completionHandler: { (location: URL?,
response: URLResponse?,
error: Error?) -> Void in

let fileManager = FileManager.default

if fileManager.fileExists(atPath: destination.path) {
try! fileManager.removeItem(atPath: destination.path)
}
try! fileManager.moveItem(atPath: location!.path,
toPath: destination.path)

DispatchQueue.main.async {
do {
let model = try Entity.loadAnchor(contentsOf: destination)
self.arView.scene.addAnchor(model)
} catch {
print("Fail loading entity.")
}
}
})
downloadTask.resume()
}
}

RealityKit – How to add motion to a loaded ModelEntity from USDZ file?

Add to your code .generateCollisionShapes(recursive:) instance method for every participant (entity) that not only creates collision's shapes but also allows you to simulate physics.

Sample Image

import SwiftUI
import RealityKit

struct ARViewContainer: UIViewRepresentable {

let boxx = ModelEntity(mesh: .generateBox(size: 0.5))
let ball = ModelEntity(mesh: .generateSphere(radius: 0.25))
let anchor = AnchorEntity()

func makeUIView(context: Context) -> ARView {
let arView = ARView(frame: .zero)
// BALL
ball.physicsBody = .init()
ball.physicsMotion = .init()
ball.physicsMotion?.linearVelocity = [10,0,0]
ball.position.x = -3
ball.generateCollisionShapes(recursive: true)
anchor.addChild(ball)
// BOX
boxx.physicsBody = .init()
boxx.physicsMotion = .init()
boxx.physicsMotion?.linearVelocity = [0,2,0]
boxx.generateCollisionShapes(recursive: true)
anchor.addChild(boxx)
// Anchor
anchor.position.z = -3
arView.scene.addAnchor(anchor)
return arView
}
func updateUIView(_ uiView: ARView, context: Context) { }
}

...

struct ContentView : View {
var body: some View {
return ARViewContainer().edgesIgnoringSafeArea(.all)
}
}

For more details, read THIS post.

Available animations collection is empty, while using .loadModelAsync()

Use ModelEntity.loadAsync. It loads full hierarchy including animation.

import RealityKit
import Combine

let anchor = AnchorEntity()
var cancellable: AnyCancellable? = nil

self.cancellable = ModelEntity.loadAsync(named: "biplane.usdz").sink(

receiveCompletion: { completion in

if case let .failure(error) = completion {
print("Unable to load a model \(error)")
}
self.cancellable?.cancel()
},

receiveValue: { [self] planeModel in

let animation = planeModel.availableAnimations[0]

anchor.addChild(planeModel)
anchor.position = [0, 0,-2]
anchor.scale = [0.1, 0.1, 0.1]
arView.scene.anchors.append(anchor)

planeModel.playAnimation(animation.repeat(count: .max))
}
)


Related Topics



Leave a reply



Submit