Created
August 7, 2024 03:51
-
-
Save pardeike/f353262a5c682d956f0a05caade08c4d to your computer and use it in GitHub Desktop.
Demo demonstrating physics joints breaking in RealityKit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// put the following code into a new VisionOS 2 beta project and run it | |
// inside a real device (hand tracking will fail in the simulator) | |
// interacting with the door on the hinge will separate it from the hinge | |
import SwiftUI | |
import RealityKit | |
import ARKit | |
let mat1 = UnlitMaterial(color: .blue) | |
let mat2 = UnlitMaterial(color: .yellow) | |
let mat3 = UnlitMaterial(color: .red) | |
let thickness = Float(0.005) | |
let width = Float(0.1) | |
let trackingProvider = HandTrackingProvider() | |
let arKitSession = ARKitSession() | |
@main | |
struct PhysicsTestApp: App { | |
var body: some SwiftUI.Scene { | |
ImmersiveSpace { ImmersiveView() } | |
.immersionStyle(selection: .constant(.mixed), in: .mixed) | |
} | |
} | |
struct ImmersiveView: View { | |
@State var handRoot = Entity() | |
@State var parts: [String: Entity] = [:] | |
var body: some View { | |
RealityView { content in | |
let hingeEntity = ModelEntity(mesh: .generateCylinder(height: width, radius: thickness / 1.5), materials: [mat2]) | |
hingeEntity.generateCollisionShapes(recursive: false) | |
hingeEntity.components.set(PhysicsBodyComponent(mode: .kinematic)) | |
hingeEntity.components.set(OpacityComponent(opacity: 0.5)) | |
hingeEntity.transform.rotation = .init(angle: .pi / 2, axis: [0, 0, 1]) | |
hingeEntity.position = [0, 1, -0.5 - width / 2] | |
content.add(hingeEntity) | |
let doorEntity = ModelEntity(mesh: .generateBox(size: [width, thickness, width]), materials: [mat1]) | |
doorEntity.generateCollisionShapes(recursive: false) | |
doorEntity.components.set(PhysicsBodyComponent(mode: .dynamic)) | |
doorEntity.components.set(OpacityComponent(opacity: 0.5)) | |
doorEntity.position = [0, 1, -0.5] | |
content.add(doorEntity) | |
let hingePin = hingeEntity.pins.set(named: "Hinge", orientation: .init(angle: .pi / 2, axis: [0, 0, 1])) | |
let doorPin = doorEntity.pins.set(named: "Door", position: [0, 0, width / -2]) | |
let doorHingeJoint = PhysicsRevoluteJoint(pin0: hingePin, pin1: doorPin) | |
try! doorHingeJoint.addToSimulation() | |
content.add(handRoot) | |
} | |
.task { | |
try! await arKitSession.run([trackingProvider]) | |
for await update in trackingProvider.anchorUpdates { | |
let anchor = update.anchor | |
guard anchor.isTracked else { continue } | |
guard let handSkeleton = update.anchor.handSkeleton else { continue } | |
for joint in handSkeleton.allJoints.filter({ $0.isTracked }) { | |
let partID = "\(joint.name)-\(anchor.chirality)" | |
var part = parts[partID] | |
if part == nil { | |
part = ModelEntity(mesh: .generateSphere(radius: 0.01), materials: [mat3]) | |
part!.generateCollisionShapes(recursive: false) | |
part!.components.set(PhysicsBodyComponent(mode: .kinematic)) | |
part!.components.set(OpacityComponent(opacity: 0.5)) | |
handRoot.addChild(part!) | |
parts[partID] = part | |
} | |
let transform = anchor.originFromAnchorTransform * joint.anchorFromJointTransform | |
part!.setTransformMatrix(transform, relativeTo: nil) | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment