Scenekit – physicsWorld设置,以防止运动节点相交

我的场景中有几个节点,我可以旋转和拖动。 我build立了一个physicsWorld委托,在我的节点中添加了types为kinematic的physicsBody,并检查了PhysicsWorld的didBeginContact – 到目前为止,一切正常,当我移动节点时,联系开始/结束触发。

我试图解决这个问题的方式是设置一个布尔variables,一旦联系开始,以防止进一步的运动,但变成案件(特别是如果我拖动节点太快),更改为真,节点获取一点点在另一个对象的内部。

我应该用不同的方法呢? 我不是真的要碰撞,只是另一个节点行事“坚实”,即使在更高的速度接触,也不允许交集。

编辑:

一些示例图像来进一步澄清问题:

为了简单起见,我只添加了2个节点来演示这个问题。 第一个图像是初始位置,第二个和第三个(侧视图)是在一个非常快的平底锅之后。 接触检测仅在节点已经相交后才被触发。

我尝试的一种方法是在联系被触发之前抓住最后一个位置,并在检测到接触后重新设置节点的位置,但结果是非常不稳定和不稳定,并且在一秒钟之内,有时可以看到物体相交,然后跳到最后“好”的位置。 我觉得必须有一些更简单的方法来实现这一点,但花费数小时后,通过可用的资源,我无法弄清楚。

编辑2

进一步的研究指出了扫描testing的线,技术上,如果我能检测到可能的碰撞之前,我移动节点,我应该能够限制运动停止之前发生交叉点

更新: Xcode指出另一个死胡同

Error: convexSweep only works with convex shapes 

在经历了很多日子的头痛,几乎放弃之后,我重新阅读了physicsWorld文档,最终发现了我一直忽略的东西 – contactTest方法,可以在任何时候手动触发,独立于render循环。 我在渲染器(_:willRenderScene:atTime :)中使用它,以便在场景呈现之前“修复”重叠。

我的场景比这个例子稍微复杂一点,但是现在我几乎没有多余的镊子了。 我不确定这是否是正确的解决scheme,以及如何高成本地performance出明智的performance,但是现在我会安定下来,这样我就可以继续发展了。

如果有人在类似的情况下运行的相关代码:

 func renderer(_ renderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: TimeInterval) { // make sure we have active node and pan direction if(selectedBrickNode != nil && self.panDirection != nil){ // contactTest let pw = scnScene.physicsWorld let node = selectedBrickNode.node! let contacts = pw.contactTest(with: node.physicsBody!, options: nil) var axisVector:SCNVector3 // specify which axis we want to correct switch self.panDirection!{ case "right","left": axisVector = SCNVector3Make(1,0,0) default: axisVector = SCNVector3Make(0,1,0); } for contact in contacts { // round contact normal to get a unit vector let cn = SCNVector3( round(contact.contactNormal.x), round(contact.contactNormal.y), round(contact.contactNormal.z)) // fix only for pan direction axis if abs(cn.x) == axisVector.x && abs(cn.y)==axisVector.y { let normal = contact.contactNormal let transform = SCNMatrix4MakeTranslation( round(normal.x) * -Float(contact.penetrationDistance), round(normal.y) * -Float(contact.penetrationDistance), round(normal.z) * -Float(contact.penetrationDistance)) node.transform = SCNMatrix4Mult(node.transform, transform) // break to prevent repeated contacts break; } } } }