Scenekit - physicsWorld setup to prevent kinematic nodes to intersect

点点圈 提交于 2019-12-04 19:37:22

After a lot of days of headbanging and almost giving up, i re-re-reread the physicsWorld documentation and finally found what i was overlooking all the time - the contactTest method that can be manualy triggered at any time, independent of render loop. I use it in the renderer(_:willRenderScene:atTime:) in order to "fix" the overlap before the scene gets rendered.

My scene is bit more complicated than the example, but with few extra tweeks i almost got it working now. I'm not sure if this is the proper solution and how costy it will become performance wise, but for now i will settle down with this so i can move on with the development.

The relevant code in case somebody runs in similar situation:

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;
            }

        }

    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!