在RealityKit中启用手势

时间:2020-10-03 09:37:48

标签: swift swiftui augmented-reality arkit realitykit

我有一个自定义的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'不符”。所以我无法添加任何手势。

但是我找不到任何有用的资源来实现我的最终目标。有什么建议吗?

3 个答案:

答案 0 :(得分:2)

使用as!Entity & HasCollision强制转换(类型转换)arView.installGestures([.rotation], for: modelEntity as! Entity & HasCollision)

let entity = modelEntity as? Entity & HasCollision
arView.installGestures([.all], for: entity!)

或这种方式:

installGestures(_:for:)


source 实例方法@discardableResult func installGestures(_ gestures: ARView.EntityGestures = .all, for entity: HasCollision) -> [EntityGestureRecognizer] 看起来像这样:

physics = participates


Reality Composer中的初始设置

在编译之前,在Reality Composer中为模型设置motion type = fixedaccessibility = accessibility enabledimport 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] } } }

完整代码版本

import pandas as pd
import numpy as np

# These are the first 30 rows of the csv file 
'Budget Code,Level 02,Level 03,2015-07-31,2015-08-31,2015-09-30,2015-10-31,2015-11-30,2015-12-31,2016-01-31,2016-02-29,2016-03-31,2016-04-30,2016-05-31,2016-06-30,2016-07-31,2016-08-31,2016-09-30,2016-10-31,2016-11-30,2016-12-31,2017-01-31,2017-02-28,2017-03-31,2017-04-30,2017-05-31,2017-06-30,2017-07-31,2017-08-31,2017-09-30,2017-10-31,2017-11-30,2017-12-31,2018-01-31,2018-02-28,2018-03-31,2018-04-30,2018-05-31,2018-06-30,2018-07-31,2018-08-31,2018-09-30,2018-10-31,2018-11-30,2018-12-31,2019-01-31,2019-02-28,2019-03-31,2019-04-30,2019-05-31,2019-06-30,2019-07-31,2019-08-31,2019-09-30,2019-10-31,2019-11-30,2019-12-31,2020-01-31,2020-02-29,2020-03-31,2020-04-30,2020-05-31,2020-06-30,2020-07-31,2020-08-31,2020-09-30,2020-10-31,2020-11-30,2020-12-31,2021-01-31,2021-02-28,2021-03-31,2021-04-30,2021-05-31,2021-06-30'
data = pd.read_csv(r'example_data.csv', index_col=[0,1,2]
data = data.fillna(0)
data.groupby('Budget Code').plot()

答案 1 :(得分:1)

问题是您试图赋予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
}

答案 2 :(得分:0)

我还有其他情况:我需要从.usdz文件中加载模型,它应该具有动画。但是我还需要像平移和旋转这样的手势。研究将我引向正确答案的thread。我将在下面显示的代码的主要思想是“将具有动画的加载实体嵌套在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)
           
        }