【问题标题】:ARKit: two objects are not contacting with each other, but didBegin() function is calledARKit:两个对象没有相互接触,但调用了 didBegin() 函数
【发布时间】:2018-01-14 05:38:20
【问题描述】:

在场景中,两个 3d 对象没有相互接触,而是调用了函数func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {}

我使用addItem()在场景中添加节点

func addItem(hitTestResult: ARHitTestResult) {
        if let selectedItem = self.selectedItem {
            let scene = SCNScene(named: "art.scnassets/\(selectedItem).scn")
            let node = (scene?.rootNode.childNode(withName: selectedItem, recursively: false))!

            let transform = hitTestResult.worldTransform
            let thirdColumn = transform.columns.3
            node.position = SCNVector3(thirdColumn.x, thirdColumn.y, thirdColumn.z)


             node.physicsBody = SCNPhysicsBody(type:.dynamic, shape: SCNPhysicsShape(node: node, options: nil))


            node.physicsBody?.isAffectedByGravity = false


            node.physicsBody?.categoryBitMask = BitMaskCategory(rawValue: selectedItem)!.maskValue


            node.physicsBody?.contactTestBitMask = BitMaskCategory.mug.maskValue


            self.sceneView.scene.rootNode.addChildNode(node)
        }
    }


enum BitMaskCategory: String {

    case mug, banana, cup, vase

    var maskValue : Int {
        switch self {
        case .mug: return 1
        case .banana: return 2
        case .cup: return 3
        case .vase: return 4

        }
    }
}

当我点击屏幕并在场景中添加两个节点(杯子和马克杯)时,这两个节点开始相互远离。他们互相排斥,即使他们没有互相接触。

谢谢。

【问题讨论】:

  • 要调试碰撞或接触,您需要使用调试功能。 sceneView.debugOptions = .showPhysicsShapes 这将显示物理形状是否大于可见的渲染节点。这通常发生在您在导入 dae 后让 SceneKit 近似形状时。

标签: objective-c 3d arkit


【解决方案1】:

调试physicsBodies的碰撞和接触的最佳方法是使用:

 sceneView.debugOptions = .showPhysicsShapes

在上面的代码中,您选择 nil 作为物理形状:

 node.physicsBody = SCNPhysicsBody(type:.dynamic, shape: SCNPhysicsShape(node: node, options: nil))

此选项允许 scenekit 近似形状...在使用第三方 3d 建模软件中创建的导入 dae 模型时通常效果不佳。

我通常将基本的原始物理形状(例如球体或盒子)应用于复杂的 dae 模型,而不是使用 nil 选项。

额外了解

如果您的模型有凹形部件,比如管子......并且它不需要是动态的。您可以使用以下代码来确保管子可以允许物体通过内管段。

tubeNode.physicsBody = SCNPhysicsBody(type: .static, shape: SCNPhysicsShape(geometry: geometry, options: [SCNPhysicsShape.Option.type: SCNPhysicsShape.ShapeType.concavePolyhedron]))

这就是结果...你可以看到绿线代表physicsBody。像球这样的物体现在可以从管子的中心落下。

如果物体需要动态,凹面不可用...下面的代码可以将选项设置为动态体上的convexHull。

 tubeNode.physicsBody = SCNPhysicsBody(type: .dynamic, shape: SCNPhysicsShape(geometry: geometry, options: [SCNPhysicsShape.Option.type: SCNPhysicsShape.ShapeType.convexHull]))

所以掉在上面的球会落在管子的顶部,不会穿过管子的中心。

【讨论】:

  • 感谢您的建议。我试过self.sceneView.debugOptions = .showPhysicsShapesnode.physicsBody = SCNPhysicsBody(type:.dynamic, shape: SCNPhysicsShape(node: node, options:[SCNPhysicsShape.Option.type: SCNPhysicsShape.ShapeType.concavePolyhedron]))。在场景中,节点的实际物理形状比场景中的节点大得多。我该如何解决?谢谢
  • 你可以创建你想要的基本形状类型,如 SCNBox,然后将它应用到physicsBody(type.dynamic, shape: Box)。您还可以缩放physicsBody形状update scnphysicsbody when scaling scnnode
猜你喜欢
  • 1970-01-01
  • 2021-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多