iOS 借助 ARKit 實現六自由度的 VR
效果展示
圖展示了『前后左右上下+頭部隨動』即六自由度的VR效果。
原理解析
涉及的庫
ARKit & SceneKit
原理
github上有Google CardBoard供大家使用,也有早期某好人開源后不更新的版本。
我接觸SceneKit發現可以便捷的實現VR效果,當然需要舍棄一部分內容。
個人以為,VR項目中核心組成有三:渲染引擎,九軸算法,反畸變算法。在此處我們可以基本舍棄反畸變算法與九軸算法,依靠SceneKit實現渲染部分。
層級關系
直接使用Xcode9beta在ARKit新建工程Demo的基礎上添加ARSCNView雙屏即可。
// retrieve the SCNView
SCNView scnViewLeft = [[SCNView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width0.5, self.view.frame.size.height)];
scnViewLeft.pointOfView = cameraNodeLeft;
scnViewLeft.scene = scene;
scnViewLeft.backgroundColor = [UIColor blackColor];
[self.sceneView addSubview:scnViewLeft];
SCNView scnViewRight = [[SCNView alloc]initWithFrame:CGRectMake(self.view.frame.size.width0.5, 0, 0.5*self.view.frame.size.width, self.view.frame.size.height)];
scnViewRight.pointOfView = cameraNodeRight;
scnViewRight.scene = scene;
scnViewRight.backgroundColor = [UIColor blackColor];
[self.sceneView addSubview:scnViewRight];</code></pre>
關于自由度
目前iPhone上可以下載到的VRAPP基本都是三自由度,即圍繞XYZ三軸心旋轉實現camera跟隨頭部轉動的效果。用戶無法自由移動從而接近或沿四周觀察物體。手機在不借助外接設備的情況下實現VR空間定位的產品目前基本沒有。但是借助ARKit,我們可以實現且誤差估計在十厘米左右。

六軸自由度
圖示為六自由度,三自由度為去除up/down,left/right,forward/back三軸的剩余部分。
Part3 VR部分的實現
Camera設置
在此Demo中需要注意的就是camera的設置。與一般游戲開發不同的是,我們這里需要2個camera,分別用于左右眼內容顯示。

因為左右眼內容實際是不一樣的,所以需要2個camera在增強視差實現立體效果。
考慮到后續需要2個眼睛隨著頭部轉動,會產生位移與旋轉,所以我們需要增加一個新的camera作為2個camera的容器。
// Containor Camera.
_cameraNode = [SCNNode node];
_cameraNode.camera = [SCNCamera camera];
[_cameraNode setPosition:SCNVector3Make(0, 0, 0)];
[scene.rootNode addChildNode:_cameraNode];
// Camera left
SCNNode *cameraNodeLeft = [SCNNode node];
cameraNodeLeft.camera = [SCNCamera camera];
[cameraNodeLeft setPosition:SCNVector3Make(-0.1, 0, 0)];
[_cameraNode addChildNode:cameraNodeLeft];
// Camera right
SCNNode *cameraNodeRight = [SCNNode node];
cameraNodeRight.camera = [SCNCamera camera];
[cameraNodeRight setPosition:SCNVector3Make(0.1, 0, 0)];
[_cameraNode addChildNode:cameraNodeRight];</code></pre>
之后針對攝像頭組的矩陣直接賦與containor camera即可。
關于攝像頭的空間坐標
借助WWDC2017發布的ARKit-ARCamera.transform實現頭部隨動與空間定位。
#pragma mark - ARSessionDelegate
- (void)session:(ARSession )session didUpdateFrame:(ARFrame )frame
{
// Retrive the matrix from ARKit - ARFrame - camera.
_transform = frame.camera.transform;
[_cameraNode setTransform:SCNMatrix4FromMat4(_transform)];
}</code></pre> 文檔提到過ARFrame提供的transform,這里的transform是六自由度的。
/**
The transformation matrix that defines the camera's rotation and translation in world coordinates.
*/
關于PBR材質
這篇博文很詳細,可供參考。
PBR,即Physically based rendering,可以實現很逼真的光影效果。
http://www.jianshu.com/p/b30785bb6c97
至此我們就可以實現文頭提供的Demo效果了。雖然誤差還是有的,但是畢竟是單目SLAM,是不是已經很厲害了呢。
使用注意點
因為這里空間定位基本依賴于ARKit提供的數據,所以ARKit的精確度直接影響到視覺效果。所以記得使用時記得遵守ARKit提到的運行條件,即 https://developer.apple.com/documentation/arkit 提到的
ARKit requires an iOS device with an A9 or later processor.
&
Understanding Augmented Reality:
Best Practices and Limitations段落中
However, it relies on details of the device’s physical environment that are
not always consistent or are difficult to measure in real time without some
degree of error. To build high-quality AR experiences, be aware of these
caveats and tips.
簡而言之:6S以上的設備,良好的光線環境,避免對著白墻(無法獲取特征點)。
這里我分享個沒有嚴謹驗證過的適用于ARKit快速穩定的技巧:
斜對著方形區域,水平環繞掃視矩形后繼續瞄準沿豎直方向觀測,基本就能保持穩定了。
如果您覺得有價值,請在github賞個star,不勝感激。
如果有什么想交流的,歡迎私信。
來自:http://www.jianshu.com/p/4f9809021142