SCNCamera 在 SceneKit 和 ARKit 中有什麼不一樣?

在 ARKit 和 SceneKit 開發中,相機位置都是用 SCNView 對象的 pointOfView 結點來表示的,相機的具體參數則在scnView.pointOfView.camera中。code

咱們先來看看 SCNCamera 中幾個不太好理解的參數,而後再來看看它在 SceneKit 和 ARKit 中有什麼不一樣。cdn

SCNCamera 重要參數

這是蘋果官網上的說明圖片,表示了相機一些參數的含義,可是這張圖已通過時了,如今蘋果已經廢棄了 xFOVyFOV 這種表示顯示範圍的方法,統一用 fieldOfView 來表示了。 對象

  • projectionDirection:默認值SCNCameraProjectionDirectionVertical
    這個參數是決定下面 fieldOfView 方向的,二者配合使用。共有水平和豎直兩種選擇,默認是按豎直方向計算 fieldOfView。好比,視圖寬高比爲 4:3,豎直方向的 fieldOfView 爲 60 度,那麼水平天然就是 80 度;視圖寬高比爲 16:9,豎直方向的 fieldOfView 爲 60 度,那麼水平天然就是 106 度。blog

  • fieldOfView:默認 60 度
    之前的 xFOVyFOV 能夠本身隨意調整,如今不行了。如今你只有經過 fieldOfView 決定其中一個(哪個由projectionDirection的值決定,默認是豎直),另外一個方向會根據視圖比例自動計算。蘋果舉例說明:當手機屏幕是16:9並豎屏,SCNView 全屏鋪滿時寬高比9:16,projectionDirection 默認豎直,而 fieldOfView 是 60 度時,水平視角度數是 33.75 度。這個角度就是保持豎起方向 60 度的狀況,根據 16:9 的比例,換算出的水平視角。圖片

  • sensorHeight:默認值和手機鏡頭有關,常見是 24mm
    這個值通常不去調整,保持默認就行了。若是非要調整的話,會致使 fieldOfView 發生變化,sensorHeight 變大則 fieldOfView 變小,畫面顯示的物體則會變大。開發

  • focalLength:默認值和手機有關,常見是 20.784610748291016mm
    這個值,其實一開始是根據 sensorHeightfieldOfView 的默認值計算出來的。調整這個參數,會改變 fieldOfView 的值。it

  • zNear:ARKit 默認 0.001m,SceneKit 默認 1.0m
    能看到的最近距離io

  • zFar:ARKit 默認 1000m,SceneKit 默認 100m
    能看到的最遠距離class

從上面能夠看出:fieldOfViewsensorHeightfocalLength 這三個參數是密切相關的,調整任意一個可能會影響其餘的。那通常咱們須要時應該怎麼調整呢?答案是調整 fieldOfViewlazyload

fieldOfView 是最終決定顯示效果的參數,也是人理解起來最直觀的參數,因此咱們只須要調整它,就能達到咱們想要的效果。但實際上,從本質來講,若是隻調整 fieldOfView,那最終會致使 focalLength 發生變化,從而影響投影矩陣和顯示效果。

三者的關係以下圖:

SceneKit 與 ARKit 中的不一樣

通過實踐,我發現 SceneKit 與 ARKit 中 Camera 的不一樣,除了 zNearzFar外,最主要是對projectionDirection的認定不一樣。

SceneKit 中的視圖方向是跟隨手機旋轉方向的,當手機方向變化時,永遠保持豎直方向的視角爲 60 度,即便視圖變寬了,也不會改變顯示的大小。
而 ARKit 比較複雜,當視圖的高度佔滿屏幕時,只縮小寬度沒什麼變化,這和 SceneKit 是同樣的。當寬度高度都改變時,表現也和 SceneKit 相同。而當高度較小時 ARKit 視圖的寬度變大,看到的物體也會變大!!!

這究竟是什麼意思?咱們來看幾張對比圖就知道了。下圖的 demo 中一個有背景的是 ARSCNView,另外一個黑色背景的是 SCNView。二者的 3D 模型位置、大小相同,相機參數包括位置也是相同的。先看豎屏時的狀況:

再看橫屏時的狀況:

能夠看到的是:SceneKit 中的fieldOfView嚴格遵照了約定的角度和方向,始終嚴格按照豎直方向來計算,當手機橫屏切換時,會按照新的豎直方向來計算;
而 ARKit 就複雜了不少,寬度和高度彷佛都會影響。

通過個人觀察,發現:ARKit 彷佛會按照最長的那個邊進行計算,若是最長的那條邊沒有改變,畫面就會保持原先的大小;而最長的那條邊變短時,畫面就會按比例縮小。

可能你們會問,爲何不打印一下 ARKit 中 SCNCamera 的參數呢?其實我試過了,無論畫面如何變化,ARKit 中 SCNCamera 的參數永遠也不會變,根本看不出來具體是多少。。。。。

總結

SCNCamera 的參數在 ARKit 和 SceneKit 中表現並不相同,產生的效果也有一點差別。最主要差別是:SceneKit 會遵照設置的方向和角度來設置 FOV,並會根據手機屏幕旋轉來更新;而 ARKit 無視手機屏幕旋轉,也不遵照projectionDirection的設置,彷佛會按視圖最長邊來設置 FOV。

相關文章
相關標籤/搜索