Lab 094 – Visualize a Pivot Point
Using a Draw Component and System to visualize the position of a given entity’s pivot point in space.
Background
Michael Temper is teaching visionOS at the University of Applied Sciences Upper Austria. A couple of weeks ago he wrote about this work on LinkedIn. Michael graciously provided some of the labs/examples that he has been building so we can share them with you here. This is the first one of seven. The labs in this series focus on foundational 3D concepts.
Check out the post from Michael
Lab Code
You may want to check this commit to see the component, systems, and utilities added to support these labs. There is something to learn in each file. The Draw Component and Draw System are doing the heavy lifting here.
struct Lab094: View {
@Environment(\.realityKitScene) var scene
@State var root = Entity()
@State var showAxes = true
@State var sphere = Entity()
@State var xAxisLabel = Entity(components: [ViewAttachmentComponent(rootView: Text("X").font(.largeTitle)), BillboardComponent()])
@State var yAxisLabel = Entity(components: [ViewAttachmentComponent(rootView: Text("Y").font(.largeTitle)), BillboardComponent()])
@State var zAxisLabel = Entity(components: [ViewAttachmentComponent(rootView: Text("Z").font(.largeTitle)), BillboardComponent()])
init() {
registerComponentsAndSystems()
}
func registerComponentsAndSystems() {
DrawComponent.registerComponent()
DrawRuntimeComponent.registerComponent()
DrawSystem.registerSystem()
}
var body: some View {
RealityView { content in
setupRoot()
setupSphere()
root.addChild(sphere)
content.add(root)
}
.ornament(attachmentAnchor: .scene(.topBack)) {
ornamentUI
}
.onChange(of: showAxes) { oldValue, newValue in
xAxisLabel.isEnabled = newValue
yAxisLabel.isEnabled = newValue
zAxisLabel.isEnabled = newValue
scene?.performQuery(DrawSystem.query).forEach { entity in
entity.drawComponent?.showAxes = newValue
}
}
}
var ornamentUI: some View {
VStack {
Toggle(isOn: $showAxes.animation()) {
Text(showAxes ? "Hide Axes" : "Show Axes")
}
.toggleStyle(.button)
}
.padding()
.fixedSize()
.glassBackgroundEffect()
}
func setupRoot() {
root.components.set(DrawComponent(showAxes: showAxes))
root.components.set(DrawRuntimeComponent())
let axisLength: Float = 0.25
let offset: Float = 0.02
xAxisLabel.position.x = axisLength + offset
yAxisLabel.position.y = axisLength + offset
zAxisLabel.position.z = axisLength + offset
root.addChild(xAxisLabel)
root.addChild(yAxisLabel)
root.addChild(zAxisLabel)
}
func setupSphere() {
var material = UnlitMaterial(color: .cyan)
material.blending = .transparent(opacity: PhysicallyBasedMaterial.Opacity(floatLiteral: 0.5))
sphere = ModelEntity(
mesh: .generateSphere(radius: 0.015),
materials: [material])
sphere.name = "Sphere"
sphere.position = [0.1, 0.1, 0.1]
var manipulationComponent = ManipulationComponent()
manipulationComponent.releaseBehavior = .stay
manipulationComponent.dynamics.scalingBehavior = .none
manipulationComponent.dynamics.inertia = .zero
sphere.components.set(manipulationComponent)
sphere.generateCollisionShapes(recursive: true)
sphere.components.set(InputTargetComponent())
sphere.components.set(HoverEffectComponent())
sphere.components.set(DrawComponent(showAxes: showAxes))
sphere.components.set(DrawRuntimeComponent())
}
}Make sure to follow Michael to keep up with his work in visionOS. In addition to this course, he has created an innovative and whimsical game called Porta Nubi.
Support our work so we can continue to bring you new examples and articles.
Download the Xcode project with this and many more labs from Step Into Vision.

Follow Step Into Vision