swift 在RealityKit中启用手势

0mkxixxg  于 2023-02-15  发布在  Swift
关注(0)|答案(3)|浏览(177)

我有一个自定义的usdz文件(不是通过代码创建的,而是一把真实的的椅子!)我把它保存在Entity中。
一旦我有了它,这就是我的代码:

func updateUIView(_ uiView: ARView, context: Context) {
            
    if let modelEntity = model.modelEntity {
        
        print("\(model.modelName)")
        
        let anchorEntity = AnchorEntity(plane: .horizontal)
        
        anchorEntity.addChild(modelEntity.clone(recursive: true))
        
        uiView.scene.addAnchor(anchorEntity)
        
        // modelEntity.generateCollisionShapes(recursive: true) 
        // If we have multiple object, recursive true help to generate collision for all of them
        
        uiView.installGestures(.rotation, for: modelEntity as! Entity & HasCollision)
        
        uiView.debugOptions = .showPhysics
        
    } else {
        
        print("Unable to load modelEntity for \(model.modelName)")
        
    }
}

这里的问题是“参数类型'Entity'不符合预期的类型'HasCollision'”。所以我不能添加任何手势。
但是我找不到任何有用的资源来实现我的最终目标。有什么建议吗?

23c0lvtd

23c0lvtd1#

我还有别的情况:我需要从.usdz文件加载模型,它应该有一个动画。但我也需要有像平移和旋转这样的手势。研究指导我找到了正确答案的线程。我将在下面展示它的代码,主要思想是“将加载的实体嵌套在ModelEntity中,该实体具有动画,然后基于加载的模型的边界为该ModelEntity提供适当的CollisionComponent。”(c)

loadRequest = Entity.loadAsync(contentsOf: url)
    .sink(receiveCompletion: { status in
        print(status)
    }) { entity in
           
        // Scaling entity to a reasonable size
        entity.setScale(SIMD3(repeating: 0.01), relativeTo: nil)
           
        // Creating parent ModelEntity
        let parentEntity = ModelEntity()
        parentEntity.addChild(entity)
           
        // Anchoring the entity and adding it to the scene
        let anchor = AnchorEntity(.plane(.horizontal, classification: .any, minimumBounds: .zero))
        anchor.addChild(parentEntity)
        self.arView.scene.addAnchor(anchor)
           
        // Playing availableAnimations on repeat
        entity.availableAnimations.forEach { entity.playAnimation($0.repeat()) }
           
        // Add a collision component to the parentEntity with a rough shape and appropriate offset for the model that it contains
        let entityBounds = entity.visualBounds(relativeTo: parentEntity)
        parentEntity.collision = CollisionComponent(shapes: [ShapeResource.generateBox(size: entityBounds.extents).offsetBy(translation: entityBounds.center)])
                       
        // installing gestures for the parentEntity
        self.arView.installGestures(for: parentEntity)
    }
ljsrvy3e

ljsrvy3e2#

使用强制形式的向下转换(类型转换)as!Entity & HasCollision

arView.installGestures([.rotation], for: modelEntity as! Entity & HasCollision)

或者这样:

let entity = modelEntity as? Entity & HasCollision
arView.installGestures([.all], for: entity!)
  • source * 示例方法installGestures(_:for:)如下所示:
func installGestures(_ gestures: ARView.EntityGestures = .all,
                     for entity: HasCollision) -> [EntityGestureRecognizer]

Reality Composer中的初始设置

编译之前,在Reality Composer中为模型设置physics = participatesmotion type = fixedaccessibility = accessibility enabled

完整代码版本

import SwiftUI
import RealityKit

struct ARViewContainer: UIViewRepresentable {
    
    let boxAnchor = try! Experience.loadBox()
    
    func makeUIView(context: Context) -> ARView {
        
        let arView = ARView(frame: .zero)   
        arView.scene.anchors.append(boxAnchor)
        return arView
    }
    
    func updateUIView(_ uiView: ARView, context: Context) {
        
        if let modelEntity: Entity = boxAnchor.steelBox {    
            let anchorEntity = AnchorEntity(.plane(.vertical, 
                                             classification: .wall, 
                                             minimumBounds: [0.2, 0.2]))  
            anchorEntity.addChild(modelEntity.clone(recursive: true))    
            uiView.scene.addAnchor(anchorEntity)    
            modelEntity.generateCollisionShapes(recursive: true)    
            uiView.installGestures([.all], 
                               for: modelEntity as! Entity & HasCollision)    
            uiView.debugOptions = [.showPhysics]
        }
    }
}

附言。
此外,这篇文章将向您展示光线投射如何与RealityKit手势结合使用。

ar7v8xwq

ar7v8xwq3#

问题是您试图给予ModelEntity一个它不具备的能力(它没有冲突处理程序)。
您需要自己创建一个实体,它将符合HasCollision。
我会尝试这样的方法:

import RealityKit

class MyEntity: Entity, HasAnchoring, HasModel, HasCollision {

}

func updateUIView(_ uiView: ARView, context: Context) {
    // This is simply to create a dummy modelEntity
    let plane = MeshResource.generatePlane(width: 0.1, depth: 0.1)
    let texture = MaterialColorParameter.color(UIColor.red)
    var material = SimpleMaterial()
    material.baseColor = texture
    let modelEntity = ModelEntity(mesh: plane, materials: [material])
      
    // This is the class we have wrapping the model
    let myEntity = MyEntity()
    myEntity.addChild(modelEntity)
    
    // Now, we add the collision component
    let boxShape = ShapeResource.generateBox(width: 0.1, height: 0.1, depth: 0.1)
    let boxShapeCollisionComponent = CollisionComponent (
      shapes: [boxShape],
      mode: .trigger,
      filter: .default
    )
    myEntity.collision = boxShapeCollisionComponent
    // Or, you could of called myEntity.generateCollisionShapes(recursive: true)
    
    // Last thing, lets put this plane, with a box collision component,
    // right in front of us
    myEntity.transform = Transform.identity
    myEntity.transform.translation.z = myEntity.transform.translation.z - 0.3
    uiView.scene.addAnchor(myEntity)
    
    uiView.installGestures(.rotation, for: myEntity)
    
    uiView.debugOptions = .showPhysics
}

相关问题