Getting Started with RealityKit: Models

Importing and generating models with RealityKit

Importing from USDZ

One of the more popular and exciting methods of importing a model to RealityKit would be importing it from a USD file. There are several ways to do this, and not knowing the subtle differences can lead you to miss parts of the imported models such as animations.

Retaining Entity Hierarchy

To maintain information bundled in the USD file such as animations, the best import methods are Entity.load and Entity.loadAsync. The difference between these two is that load will block the thread it is called on until the file has been imported, while loadAsync will use a LoadRequest (where the Output is an Entity) to get the model imported while allowing you to continue on the current thread.

guard let entity = try? Entity.load(
named: "toy_robot_vintage"
) else {
// failed to load entity
return
}
// do something with entity
_ = Entity.loadAsync(named: "toy_robot_vintage").sink(
receiveCompletion: { loadCompletion in
// Added this switch just as an example
switch loadCompletion {
case .failure(let loadErr):
print(loadErr)
case .finished:
print("entity loaded without errors")
}
}, receiveValue: { entity in
// do something with entity
}
)
_ = Entity.loadAsync(named: "toy_robot_vintage")
.append(Entity.loadAsync(named: "gramophone"))
.append(Entity.loadAsync(named: "fender_stratocaster"))
.collect()
.sink(receiveCompletion: { loadCompletion in
// Add switch case for loadCompletion
}, receiveValue: { entities in
// Do something with returned entities array.
}
)

Load an AnchorEntity

In a very similar way to load and loadAsync, you can load your USD file in as an AnchorEntity, letting you place it in your scene directly, without needing to make a separate anchor for it. Any animations in your USDZ file will also be available, as with load and loadAsync.

guard let entity = try? Entity.loadAnchor(
named: "toy_robot_vintage"
) else {
// failed to load entity
return
}
entity.anchoring = AnchoringComponent(
.plane(
.horizontal, classification: .floor, minimumBounds: [1, 1]
)
)
arview.scene.addAnchor(entity)

Loading a BodyTrackedEntity

When you want to import a model that is rigged up to be animated by a real person, you instead want to use loadBodyTracked or loadBodyTrackedAsync to import a BodyTrackedEntity.

guard let entity = try? Entity.loadBodyTracked(
named: "robot"
) else {
// failed to load entity
return
}
// do something with body tracked entity

Loading a Flattened Model

When you just want to import a Model from a USDZ file, removing entity hierarchy as well as animations, you can import using loadModel or loadModelAsync. This will turn your 3d model of what would be various levels of nodes and children into a single Entity containing meshes and an array of all the materials.

Loading a Remote USDZ File

Currently there is no straightforward or builtin way to import USDZ files from remote URLs, but thankfully there are a few solutions, here’s one from StackOverflow:

The above method does not handle all possible exceptions, use with caution.

Generating Shapes

In its current state, the provided generators include Box (cuboid), Plane, Sphere or Text. Ironically, out of the three shapes in the RealityKit logo, only one of those (a sphere) can be produced without importing USDZ files.

let newModel = ModelEntity(mesh: .generateBox(size: 1))
Cube without a material in RealityKit

Customising Models

Once you bring a USDZ file in your scene there may be some customisation you want to do to it, such as changing a material, or actually moving around one part of the model.

With Hierarchy

If you import your model with anything other than loadModel or loadModelAsync you can replace the material of your choosing with ease.

if let gramRecord1 = gramophoneModel.findEntity(
named: "GramophoneRecord1"
) as! HasModel {
gramRecord1.materials = SimpleMaterial(
color: .green, isMetallic: true
)
}
Original on the left, altered material on the right

Without Hierarchy

If you imported your model using loadModel or loadModelAsync, then as discussed earlier there is no hierarchy of entities, just the one ModelEntity consisting of a ModelComponent with a single mesh and a collection of materials. Take this file, fender_stratocaster.usdz:

modelAdjusted.model?.materials[1] = SimpleMaterial(
color: .blue, isMetallic: true
)
Original on the left, altered material on the right

Excited about all things Augmented Reality! Developer Evangelist at Agora.io.