使用 RealityKit 对对象施加向下的力

问题描述 投票:0回答:1

这是我之前关于“一般对 AR 对象的某个点施加力”的问题,它有一个完美的答案。 我已经成功地通过一点点修改对给定点施加力量,以达到对我来说完美的效果。让我也展示一些代码。 我从

Experience

获取 AR 对象,例如:

if let skateAnchor = try? Experience.loadSkateboard(), 
   let skateEntity = skateAnchor.skateboard {

    guard let entity = skateEntity as? HasPhysicsBody else { return }
    skateAnchor.generateCollisionShapes(recursive: true)
    entity.collision?.filter.mask = [.sceneUnderstanding]
    skateboard = entity
}

之后,我设置了飞机和激光雷达扫描仪,并向其添加一些手势,例如:

let arViewTap = UITapGestureRecognizer(target: self, action: #selector(tapped(sender:))) arView.addGestureRecognizer(arViewTap) let arViewLongPress = UILongPressGestureRecognizer(target: self, action: #selector(longPressed(sender:))) arView.addGestureRecognizer(arViewLongPress)

到目前为止一切顺利,在点击手势时,我应用了之前链接的答案中的逻辑并应用了力脉冲,例如:

if let sk8 = skateboard as? HasPhysics { sk8.applyImpulse(direction, at: position, relativeTo: nil) }

我的问题来自于我的“捕捉”逻辑,我确实想使用长按,并对我的滑板 AR 对象施加向下的力

,如下所示: @objc func longPressed(sender: UILongPressGestureRecognizer) { if sender.state == .began || sender.state == .changed { let location = sender.location(in:arView) if arView.entity(at: location) is HasPhysics { if let ray = arView.ray(through: location) { let results = arView.scene.raycast(origin: ray.origin, direction: ray.direction, length: 100.0, query: .nearest, mask: .all, relativeTo: nil) if let _ = results.first, let position = results.first?.position, let normal = results.first?.normal { // test different kind of forces let direction = SIMD3<Float>(0, -20, 0) if let sk8 = skateboard as? HasPhysics { sk8.addForce(direction, at: position, relativeTo: nil) } } } } } }

现在我知道我忽略了光线投射结果,但这是纯粹的开发状态,我的问题是当我应用正/负
x/z

时,对象响应良好,它要么前后滑动,要么左右滑动,正

y
也可以通过在空中拖动板来工作,唯一容易出错的力方向是我努力实现的方向是朝下的负值
y
。该物体只是坐在那里,没有任何效果。
让我们也分享一下我的对象是如何在 Reality Composer 中定义的:

skateboard inside the Reality Composer

swift augmented-reality arkit realitykit reality-composer
1个回答
2
投票

在现实生活中,如果您将整个身体的重量转移到滑板板的前端(就像做奥利动作),滑板的质心就会从中间转移到受力点。在 RealityKit 中,如果需要将滑板的后(前)轮从地板上撕下来,请将模型的质心移向斜坡。

enter image description here 质心的重新定位发生在局部坐标系中。

import SwiftUI import RealityKit struct ContentView : View { var body: some View { ARViewContainer().ignoresSafeArea() } } struct ARViewContainer: UIViewRepresentable { func makeUIView(context: Context) -> ARView { let arView = ARView(frame: .zero) arView.debugOptions = .showPhysics // shape visualization let scene = try! Experience.loadScene() let name = "skateboard_01_base_stylized_lod0" typealias ModelPack = ModelEntity & HasPhysicsBody & HasCollision let model = scene.findEntity(named: name) as! ModelPack model.physicsBody = .init() model.generateCollisionShapes(recursive: true) model.physicsBody?.massProperties.centerOfMass.position = [0, 0,-27] arView.scene.anchors.append(scene) return arView } func updateUIView(_ uiView: ARView, context: Context) { } }

物理形状

您需要解决的第二个问题是替换模型的物理身体的盒子形状(RealityKit和Reality Composer默认生成这种类型的形状)。它的形状不能是整体盒子的形式,这是很明显的,因为盒子形状不允许适当地施加力。您需要一个与模型轮廓相似的形状。

enter image description here 因此,您可以使用以下代码来创建自定义形状:

(四个球体用于轮子,盒子用于甲板)

let shapes: [ShapeResource] = [ .generateBox(size: [ 20, 4, 78]) .offsetBy(translation: [ 0.0, 11, 0.0]), .generateSphere(radius: 3.1) .offsetBy(translation: [ 7.5, 3, 21.4]), .generateSphere(radius: 3.1) .offsetBy(translation: [ 7.5, 3,-21.4]), .generateSphere(radius: 3.1) .offsetBy(translation: [-7.5, 3, 21.4]), .generateSphere(radius: 3.1) .offsetBy(translation: [-7.5, 3,-21.4]) ] // model.physicsBody = PhysicsBodyComponent(shapes: shapes, mass: 4.5) model.collision = CollisionComponent(shapes: shapes)

enter image description here

enter image description here

enter image description here 重要:

您还应该知道,您可以使用

generateConvex(from:)

创建自定义非立方体碰撞形状。 附注

Reality Composer 模型的设置(

我使用 Xcode 14.0 RC 1

)。

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.