2017-10-20 94 views
0

我的場景中有幾個節點,我可以旋轉和拖動。我建立了一個physicsWorld委託,爲我的節點添加了類型爲kinematic的physicsBody並檢查了PhysicsWorld didBeginContact - 到目前爲止,一切正常,當我移動節點時,聯繫開始/結束觸發。Scenekit-physicsWorld設置防止運動節點相交

我試圖解決這個問題的方法是設置一個布爾變量,一旦聯繫開始,以防止進一步移動,但我遇到案件(特別是如果我拖動節點太快),更改爲真,該節點在另一個對象內稍微有一點點。

我應該對此採用不同的方法嗎?我不是真的想要碰撞,只是另一個節點表現「堅實」,即使在更高速的接觸下也不允許相交。

編輯:

一些樣本圖像以進一步澄清該問題:

爲了簡單起見我已經添加僅2個節點來證明的問題。第一張圖像是初始位置,第二張和第三張(側面圖)在非常快速的平移之後。只有在節點已經相交後才觸發聯繫檢測。

我嘗試的一種方法是在聯繫人被觸發前抓住最後一個位置,並在檢測到接觸後重新設置節點位置,但結果非常不穩定並且不穩定,並且瞬間可以看到物體相交然後跳到最後的「好」位置。我覺得必須有一些更簡單的方法來實現這一點,但花費數小時後,通過可用資源,我無法弄清楚。

EDIT 2

進一步研究朝下掃描試驗線,technicaly如果我能發現可能的碰撞之前我移動節點,我應該能夠限制運動停止intersetion發生

UPDATE:另一個死衚衕,因爲Xcode中指出

Error: convexSweep only works with convex shapes 

回答

1

很多撞頭和人的天之後大多數放棄了,我重新閱讀了physicsWorld文檔,並最終找到了我一直忽略的東西 - contactTest方法,可以在任何時候手動觸發,獨立於渲染循環。我在渲染器(_:willRenderScene:atTime :)中使用它,以便在場景呈現之前「修復」重疊。

我的場景比示例稍微複雜一點,但是幾乎沒有多餘的tweeks,現在我幾乎可以使用它了。我不確定這是否是合適的解決方案,以及如何高性價比才能成爲明智的選擇,但現在我會安頓下來,這樣我可以繼續開發。

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

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

     } 

    } 
}