2017-07-18 48 views
14

在ARKit,我已發現了則hitTest使用ARAnchor插入節點並直接插入節點有什麼區別?

  1. 插入後插入節點的ARAnchor然後創建在渲染器的節點的2種方式(_渲染器:SCNSceneRenderer,nodeFor錨:ARAnchor) - > SCNNode?

    let anchor = ARAnchor(transform:hit.worldTransform) 
    sceneView.session.add(anchor:anchor) 
    
  2. 插入節點直接

    node.position = SCNVector3(hit.worldTransform.columns.3.x, hit.worldTransform.columns.3.y, hit.worldTransform.columns.3.z) 
    sceneView.scene.rootNode.addChildNode(node) 
    

看都爲我工作,但爲什麼一個方式或其他?

回答

20

更新:作爲在IOS 11.3的(又名「ARKit 1.5」),有添加ARAnchor到會話(然後關聯通過ARSCNViewDelegate回調SceneKit內容與它),只是把內容放在之間的差SceneKit空間。

當您爲會話添加錨點時,您告訴ARKit世界空間中的某個點與您的應用程序相關。然後,ARKit可以做一些額外的工作,以確保其世界座標空間與現實世界精確對齊,至少在該點附近。因此,如果您想讓虛擬內容顯示爲「附加」到某個真實世界的興趣點上,例如將對象放置在桌子或牆上,則由於跟蹤世界,您應該看到更少的「漂移」如果您給該對象一個定位點,而不是將其放置在SceneKit空間中,則該定位點不準確。如果該對象從一個靜態位置移動到另一個靜態位置,則需要刪除原始錨點並在之後的新位置添加一個錨點。

此外,在iOS 11.3中,您可以將opt in設置爲「relocalization」,這個過程可以幫助ARKit在中斷後恢復會話(通過電話,切換應用等)。會議仍然有效,但它試圖弄清楚如何映射你以前的位置到現在的位置,這可能會導致重定位成功後錨點的世界空間位置發生變化。 (另一方面,如果你只是讓空間入侵者漂浮在空中,那麼完美匹配的世界空間就不那麼重要,因此你不會真的看到基於錨和非錨的非常不同的區別 - 基於錨定的定位。)

請參閱Apple的Handling 3D Interaction and UI Controls in Augmented Reality文章/示例代碼中的「使用錨點提高虛擬對象周圍的跟蹤質量」。

該答案的其餘部分與iOS 11.0-11.2的歷史相關。5,並解釋某些方面,所以下面我將離開它...


首先使用ARAnchor考慮不 SceneKit。

  • 如果您使用ARSKView,你需要一種方法來參考位置/方位三維(真實世界)的空間,因爲SpriteKit不是3D。您需要ARAnchor來跟蹤3D中的位置,以便它們可以映射到2D中。

  • 如果你使用Metal(或GL,出於某種奇怪的原因)構建你自己的引擎......這不是一個3D場景描述API--它是一個GPU編程API--所以它並沒有一個概念的世界空間。您可以使用ARAnchor作爲ARKit的世界空間概念和您構建的任何東西之間的橋樑。

因此,在某些情況下,你需要ARAnchor因爲這是指3D位置的唯一方法。 (當然,如果你使用平面檢測,你需要ARPlaneAnchor因爲ARKit實際上搬完相對於場景的空間,因爲它改進了的地方平面是估計。)


隨着ARSCNView,SceneKit已經有一個三維世界座標空間,ARKit將所有的空間匹配到ARKit映射出來的實際空間。所以,對於一個float4x4變換描述了在世界空間中的位置(和方向等),您可以:

  • 創建ARAnchor,將其添加到會話,並ARSCNViewDelegate回調響應提供SceneKit內容ARKit將添加並定位在場景中的每個錨點。
  • 創建一個SCNNode,設置它的simdTransform,並將其添加爲場景的rootNode的子節點。

只要你有一個跑步ARSession,這兩種方法之間沒有區別 - 他們是等同的方式來說同樣的事情。所以如果你喜歡以SceneKit的方式做事,那沒什麼問題。 (你甚至可以使用SCNVector3SCNMatrix4,而不是SIMD類型,如果你想要的,但你必須來回轉換,如果你也ARKit的API獲得SIMD類型。)


的一次,這些方法不同的是會話重置。如果世界追蹤失敗,您將恢復中斷的會話,並且/或者您再次開始會話,則「世界空間」可能不再與現實世界一致,就像您將內容放入場景時一樣。

在這種情況下,您可以讓ARKit從會話中刪除錨點 - 請參閱run(_:options:)方法和ARSession.RunOptions。 (是的,所有這些,因爲在這一點上你不能相信他們中的任何一個是有效的。)如果你使用錨和委託回調在場景中放置了內容,ARKit將會把所有的內容都燒掉。 (您可以獲得代表回調,它將被刪除。)如果您使用SceneKit API放置了內容,它將停留在場景中(但很可能是錯誤的地方)。

那麼,使用哪種類型取決於你想如何處理會話失敗和中斷(並且在這之外沒有真正的區別)。

+0

所以原因:1)ARNode適用於非SceneKit引擎(SpriteKit,金屬等),對於SceneKit它是相同的(因爲ARKit派生自SceneKit並且具有相同的世界座標),2)如果跟蹤失敗,ARKit可以自動移除所有ARAnchor(並因此關聯的節點),但是SceneKit不會。正確? –

+0

@LimThyeChean Yup。 – rickster

+0

@rickster感謝您的解釋!這節省了我很多時間。 – Mencls

0

SCNVector3只是「三分量矢量的表示」。 SCNVector3 docs

使用ARAnchor時,您可以訪問三分量矢量,但也可以「跟蹤實際或虛擬對象相對於相機的位置和方向」ARAnchor docs。這就是爲什麼你使用會話來添加錨點而不是使用場景。

請參閱該文檔,你可以看到在API :)

希望它可以幫助方面的差異。

+0

這並不能解釋使用'SCNNode'與其''transform'屬性和'ARAnchor'與'transform'之間的區別。 – orangenkopf

+0

@orangenkopf你是對的,兩個作品。事實上,Apple似乎列出了這兩種方式是彼此替代的,但爲什麼我要爲每個節點添加一個額外的ARAnchor?節點似乎很好。蘋果文檔:https://developer.apple.com/documentation/arkit/arscnview/providing_3d_virtual_content_with_scenekit –

+0

一個錨在現實世界中佔有一席之地。你不能移動錨點。添加一個節點只是增加了一些視覺效果,你以後可以改變節點的位置。這是有道理的,API正在爲例如飛機,但我沒有看到你爲什麼應該手動添加一個原因 – orangenkopf