RealityKit Basics: Visual Bounds

We can use visual bounds to get the center, extent, and other properties of a bounding box for a given entity.

Overview

Each entity in RealityKit has a bounding box. We can access this by reading data from entity.visualBounds.

let earthBounds = earth.visualBounds(relativeTo: nil)
let earthSize = earthBounds.extents
let earthCenter = earthBounds.center
// also: min, max, and boundingRadius

These values can be useful when positioning entities, or when fitting content to a volume. See how we used extents in this article: Using onGeometryChange3D to scale RealityView content when a Volume is resized.

Let’s draw a box around the Earth model in this scene.

guard let earth = scene.findEntity(named: "Earth") else { return }
let earthBounds = earth.visualBounds(relativeTo: nil)
let earthSize = earthBounds.extents
let earthCenter = earthBounds.center
let earthBox = ModelEntity(mesh: .generateBox(size: earthSize), materials: [boundsMat])
earthBox.position = scene.position + earthCenter
content.add(earthBox)

We can also draw a box around multiple entities or children of a parent entity.

guard let earth = scene.findEntity(named: "Earth") else { return }
let earthBounds = earth.visualBounds(relativeTo: nil)
let earthSize = earthBounds.extents
let earthCenter = earthBounds.center
let earthBox = ModelEntity(mesh: .generateBox(size: earthSize), materials: [boundsMat])
earthBox.position = scene.position + earthCenter
content.add(earthBox)

RealityKit seems to add a bit of padding to visual bounds so it may not line up with the edges of a collision shape or model.

Example Code

struct Example135: View {

    var boundsMat: PhysicallyBasedMaterial {
        var boundsMat = PhysicallyBasedMaterial()
        boundsMat.baseColor = .init(tint: .stepRed)
        boundsMat.blending = .transparent(opacity: .init(floatLiteral:0.2))
        return boundsMat
    }

    var body: some View {
        RealityView { content in

            guard let scene = try? await Entity(named: "VisualBounds", in: realityKitContentBundle) else { return }
            content.add(scene)

            // Draw bounds around a single entity
            guard let earth = scene.findEntity(named: "Earth") else { return }
            let earthBounds = earth.visualBounds(relativeTo: nil)
            let earthSize = earthBounds.extents
            let earthCenter = earthBounds.center
            let earthBox = ModelEntity(mesh: .generateBox(size: earthSize), materials: [boundsMat])
            earthBox.position = scene.position + earthCenter
            content.add(earthBox)

            // Draw bounds around all entites in the scene
            let sceneBounds = scene.visualBounds(recursive: true, relativeTo: scene)
            let sceneSize = sceneBounds.extents
            let sceneCenter = sceneBounds.center
            let sceneBox = ModelEntity(mesh: .generateBox(size: sceneSize), materials: [boundsMat])
            sceneBox.position = scene.position + sceneCenter
            content.add(sceneBox)

        }
    }
}

Support our work so we can continue to bring you new examples and articles.

Download the Xcode project with this and many more examples from Step Into Vision.
Some examples are provided as standalone Xcode projects. You can find those here.

Questions or feedback?