簡體   English   中英

如何使用 Swift 中的 ARKit、SceneKit 臨時凍結攝像機前的節點

[英]How to temporarily freeze a node in front of the camera using ARKit, SceneKit in Swift

我構建了一個完整的結構作為節點(及其子節點),用戶將使用 ARKit 遍歷它。 在某些時候,如果用戶由於現實世界中的一些真正障礙而無法繼續,我添加了一個“暫停”按鈕,該按鈕應該凍結用戶當前在相機前看到的任何內容,然后用戶可以自由移動到其他打開空間,當用戶釋放暫停按鈕時,他/她將能夠從他們離開的地方繼續(僅在現實世界中的其他地方)。

前段時間我在蘋果開發者論壇上問過,一位蘋果框架工程師給了如下回復:

為了“凍結”場景,您可以將錨點的 position(在世界坐標中)轉換為相機坐標,然后將您的內容錨定到相機。 這將為您提供場景“凍結”的效果,即不相對於相機移動。

我目前沒有使用錨,因為我不一定需要找到平坦的表面。 相反,我的節點相對於我們從 (0,0,0) 開始的位置放置在某個 position 處。

我的問題是,我該如何准確地執行 Apple 工程師告訴我的操作? 我有以下代碼,我仍然堅持。 當我將節點添加到相機(pointOfView,下面代碼的最后一行)時,它確實凍結到位,但我無法讓它凍結在與凍結之前相同的 position 和方向上。

    @IBAction func pauseButtonClicked(_ sender: UIButton) {

    let currentPosition = sceneView.pointOfView?.position
    let currentEulerAngles = sceneView.pointOfView?.eulerAngles
    
    var internalNodeTraversal = lastNodeRootPosition - currentPosition!     // for now, lastNodeRootPosition is (0,0,0)         
    internalNodeTraversal.y = lastNodeRootPosition.y + 20       // just so it’s positioned a little higher in front of the camera

    myNode?.removeFromParentNode()      // remove the node from the Real World view.  Looks like this line has no effect and just adding the node as a child to the camera (pointOfView) is enough, but it feels more right to do this anyway.
    
    myNode?.position = internalNodeTraversal        // the whole node is moved respectively in the opposite direction from the root to where I’m standing to reposition the camera in my current position inside the node
    
 //       myNode?.eulerAngles = (currentEulerAngles! * -1)      — this code put the whole node in weird positions so I removed it
        myNode?.eulerAngles.y = currentEulerAngles!.y * -1  // opposite orientation of the node so the camera will be oriented in the same direction
        myNode?.eulerAngles.x = 0.3     // just tilting it up a little bit to have a better view, more similar to the view as before it was locked to the camera
// I don’t think I need to change the eulerAngles.z
        

    myNode!.convertPosition(internalNodeTraversal, to: sceneView.pointOfView)       // I’m not sure I wrote this correctly.  Also, this line doesn’t seem tp change anything
    
    sceneView.pointOfView?.addChildNode(myNode!)        // attaching the node to the camera so it will remain stuck while the user moves around until the button is released
}

因此,我首先計算我當前站在節點中的位置,然后將節點的 position 朝相反方向更改,以便相機現在位於 position 中。 這似乎是正確的。 現在我需要改變節點的方向,使它指向正確的方向,這里的事情變得很奇怪。 這幾天我一直在嘗試很多事情。 我使用 eulerAngles 作為方向。 如果我設置整個向量乘以 -1,它會顯示奇怪的方向。 我最終只使用了 eulerAngles.y,它是左/右方向,我硬編碼了 x 方向(上/下)。

最終,我在上面的代碼中所擁有的是我能夠得到的最接近的。 如果我直指,凍結將是正確的。 如果我稍微轉動一下,凍結也會非常接近。 與用戶在凍結之前看到的幾乎相同。 但是我轉得越多,凍結的圖像就越關閉並且越傾斜。 在某些時候(比如我向一側轉了 50 或 60 度),整個節點都離開了相機並且看不到。

不知何故,我有一種感覺,必須有一種更簡單、更正確的方法來實現上述目標。 蘋果工程師寫道:“將錨的 position(在世界坐標中)轉換為相機坐標”。 出於這個原因,我在我的代碼中添加了“convertPosition”function,但是a)我不確定我是否正確使用它並且b)如果我有那行,它似乎不會改變我的代碼中的任何內容。

我究竟做錯了什么? 任何幫助將不勝感激。 謝謝!

實際上,我找到了解決方案。 我遇到的問題甚至沒有被描述,因為我認為它不相關。 我在原點前面 2 米處構建了 AR 節點(z 坐標為 -2),而我的節點的中心仍在原點,所以當我改變旋轉或 eulerAngles 時。 它圍繞原點旋轉,因此我的節點以大曲線移動,實際上也改變了它們的 position。

解決方案是使用 simdPivot。 我沒有更改 position 和節點本身的旋轉,而是創建了一個平移矩陣和一個位於相機點(用戶站立的位置)的旋轉矩陣,然后將兩個矩陣相乘。 現在,當我將節點添加為相機的子節點(pointOfView)時,這將凍結圖像,實際上顯示用戶在凍結之前看到的內容,因為 position 是相同的,並且旋轉正好圍繞用戶站立的 position .

暫無
暫無

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

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