簡體   English   中英

Scenekit-PhysicsWorld設置可防止運動學節點相交

[英]Scenekit - physicsWorld setup to prevent kinematic nodes to intersect

我的場景中有幾個節點可以旋轉和拖動。 我已經建立了physicsWorld委托,將kinematic類型的PhysicsBody添加到我的節點,並檢查physicsWorld didBeginContact-至此,一切正常,當我移動節點時,聯系人開始/結束觸發。

我嘗試處理此問題的方法是將布爾變量設置為在接觸開始后就更改為true以防止進一步移動,但是我遇到了一些情況(尤其是如果我將節點拖動得太快),則該節點會在另一個對象的內部。

我應該使用其他方法嗎? 我真的不想要碰撞,只是另一個節點表現為“實體”,即使在高速接觸時也不允許相交。

編輯:

一些示例圖像可以進一步闡明問題:

為簡單起見,我僅添加了2個節點來演示該問題。 第一張圖片是初始位置,第二張和第三張(側視圖)在向右快速平移之后。 僅在節點已相交后才觸發接觸檢測。

我嘗試的一種方法是在觸發接觸之前抓取最后一個位置,並在檢測到接觸后重置節點位置,但是結果非常不穩定且不穩定,您有時可以看到物體在相交之前相交,然后跳轉到最后的“好”位置。 我覺得必須有一些更簡單的方法來實現這一目標,但是在花了幾個小時瀏覽可用資源后,我無法弄清楚。

編輯2

進一步的研究指出了掃掠測試的路線,從技術上講,如果我可以在移動節點之前檢測到可能發生的碰撞,那么我應該能夠限制移動在發生交集之前停止

更新: Xcode指出了另一個死胡同

Error: convexSweep only works with convex shapes

經過數天的猛烈抨擊並幾乎放棄了,我重新閱讀了PhysicsWorld文檔,終於找到了我一直無視的東西-contactTest方法,可以隨時手動觸發,而與渲染循環無關。 我在renderer(_:willRenderScene:atTime :)中使用它,以便在渲染場景之前“修復”重疊。

我的場景比示例中要復雜一些,但是經過幾個星期的時間,我幾乎可以正常工作了。 我不確定這是否是正確的解決方案,以及它在性能方面的成本有多高,但現在我將對此付諸實踐,以便繼續進行開發。

萬一有人在類似情況下運行時的相關代碼:

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

        }

    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM