Reputation: 1
Image showing problematic collision
In an AR app using RealityKit, I am trying to create collisions between a set of objects, notably a "coin", which is a small disk, and a "table" which is a set of cube primitives.
The contact is functioning, however, the coin repeatedly bounces about 0.3 meters above the table, rather than directly on top of it.
In the image, the .showPhysics
debug option has been enabled so we can see the table contact shape highlighted in purple, and the coin in green.
The models have been created in Reality Composer Pro, and exported to .usdz
.
I have created the addPhysics
extension to Entity
which first generates a shape from the object mesh, then creates the collider and physics body.
The image indicates that the shapes have properly been assigned to the mesh.
I expect when I run, that the coin will bounce a few times before settling directly on top of the table.
In actuality, the coin settles 0.3 meters above the table.
import SwiftUI
import RealityKit
/// Note, ContentView is simplified as it is not critical to the question
struct ContentView : View {
var body: some View {
ARViewContainer()
}
}
struct ARViewContainer: UIViewRepresentable {
func makeUIView(context: Context) -> ARView {
let arView = ARView(frame: .zero)
arView.debugOptions = [.showFeaturePoints, .showWorldOrigin, .showAnchorOrigins, .showSceneUnderstanding, .showPhysics]
// Create horizontal plane anchor for the content
let anchor = AnchorEntity(.plane(.horizontal, classification: .any, minimumBounds: SIMD2<Float>(0.2, 0.2)))
// Load the La Rana scene
if let larana = try? Entity.load(named: "TableAndLaRana.usdz") {
// Append the loaded model to the anchor
anchor.addChild(larana)
// Add contact to the coin
if let coin = larana.findEntity(named: "Coin") {
// Set up the shape and physics for the coin
coin.addPhysics(material: Materials.metal, mode: .dynamic)
// TEMP: put the coin above the table so its visible and bounces a few times
coin.position = SIMD3<Float>(0.1, 5.0, 0.0)
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
print("coin position = \(coin.position)")
}
} else {
print("Coin entity not found.")
}
// Add contact to the turf sections
let turfEntities = ["TableMainFront", "TableMainBack", "TableMainLeft", "TableMainRight"]
addPhysics(to: turfEntities, in: larana, material: Materials.turf, mode: .static)
// Add contact to La Rana
let metalEntities = ["LaRanaFront", "LaRanaRear", "LaRanaLeft", "LaRanaRight"]
addPhysics(to: metalEntities, in: larana, material: Materials.metal, mode: .static)
}
// Add the horizontal plane anchor to the scene
arView.scene.anchors.append(anchor)
return arView
}
func updateUIView(_ uiView: ARView, context: Context) {}
// MARK: - Physics
func addPhysics(to listOfEntityNames: [String], in mainEntity: Entity, material: PhysicsMaterialResource, mode: PhysicsBodyMode) {
for name in listOfEntityNames {
if let entity = mainEntity.findEntity(named: name) {
entity.addPhysics(material: material, mode: mode)
} else {
print("Entity \(name) not found")
}
}
}
private struct Materials {
static let metal = PhysicsMaterialResource.generate(friction: 0.3, restitution: 0.99)
static let turf = PhysicsMaterialResource.generate(friction: 0.7, restitution: 0.5)
static let wood = PhysicsMaterialResource.generate(friction: 0.5, restitution: 0.7)
}
}
extension Entity {
func addPhysics(material: PhysicsMaterialResource, mode: PhysicsBodyMode) {
if let childWithModel = children.first(
where: { $0.components[ModelComponent.self] != nil }
) {
if let modelComponent = childWithModel.components[ModelComponent.self] as? ModelComponent {
// Generate collision shapes based on the model's mesh
let shape = ShapeResource.generateConvex(from: modelComponent.mesh)
let collisionComponent = CollisionComponent(shapes: [shape])
components[CollisionComponent.self] = collisionComponent
// Create and add a PhysicsBodyComponent
let physicsBody = PhysicsBodyComponent(
massProperties: .default,
material: material,
mode: mode
)
components[PhysicsBodyComponent.self] = physicsBody
print("Physics and collision components added to \(self)")
}
} else {
print("No child with a ModelComponent found")
}
}
}
Upvotes: 0
Views: 67