iOS - SceneKit顯示與互動3D建模(一)

weixin_34082695發表於2017-05-18

最近公司要求在手機上顯示3D模型,並且要獲取點選的模型座標,找了很多相關資料,發現有兩種實現方式,一種是整合Unity3D,另一種是使用蘋果提供的SceneKit;由於使用Unity3D太麻煩,於是選擇使用SceneKit,而且這個是原生的,速度可想而知要比整合U3D後執行要來得快~

SceneKit建立在 OpenGL 的基礎上,包含了如光照、模型、材質、攝像機等高階引擎特性。SceneKit實現的內容為節點層次結構樹,也被稱為場景圖。一個場景由一個為場景世界定義一個座標空間的根節點,以及其他的可視節點組成。SceneKit會在一個檢視上展示場景,而這個場景在GPU上�進行有效地渲染每一幀之前,會處理場景�資料圖和執行動畫。

�接著來來了解下座標吧,查閱蘋果官方文件,可以看到如下這張圖片,SceneKit使用的是右手座標系,預設檢視的方向是沿負Z軸方向的。可以簡單的記住紅色為x軸,綠色為y軸,藍色為z軸。


2144614-c225659c0a60bd56.png
座標

初出茅廬

我們先來建立一個遊戲工程

2144614-4478211b50036553.png
遊戲工程

Game Technology選擇SceneKit


2144614-83c1de16b916efbf.png
Paste_Image.png

專案的目錄結構如下,比開發APP應用的專案多了一個scnassets資料夾,裡面有一個scn字尾的檔案,它是xcode能識別的�場景檔案。它支援一種字尾為dae的模型檔案,我們後續就會用到。


2144614-d2c44053381c11f2.png
目錄結構

執行後如圖所示,真是有夠炫的,圖的下方顯示的是當前渲染相關資料,方便我們開發者檢視。


2144614-f527fe3eb358dcf4.gif
�Game Demo

初窺門徑

程式碼從上至下的流程:

  1. 建立一個場景scene,場景本身並不可見,需要新增到sceneView的場景上
  2. 建立一個攝像機節點並設定擺放的位置,所處位置即視角所看的位置,可以聯想到眼睛視角
  3. 建立燈光節點設定擺放的位置,燈光可以讓需要呈現的物體變得更有質感。
  4. 獲取飛機模型,其中的【recursively:YES】意思為是否在子節點中查詢。
  5. 設定飛機模型繞著y軸旋轉,使用的是SCNAction,用法也很簡單。
  6. 獲取SCNView,並設定scnView。

牛刀小試

那接下來我們自己也搞一個工程來試試吧

2144614-67d7e8f915925d02.png
應用工程

在Link Binary With Libraries中引入SceneKit庫


2144614-107cd988f3ed8460.png
引入SceneKit庫

在ViewController中匯入SceneKit

#import <SceneKit/SceneKit.h>

接下來在桌面上新建一個art資料夾,並加上字尾【.scnassets】,將我們的素材Menchi.dae放進裡面,然後把art.scnassets拖進專案中,接下來程式碼獻上

// �初始化一個場景
SCNScene *scene = [SCNScene sceneNamed:@"art.scnassets/Menchi.dae"];

// 取出場景中根結點的第一個結點(目錄根結點也就一個子結點,就是我們素材中的Menchi)
SCNNode *node = scene.rootNode.childNodes.firstObject;
// 繞 y軸 一直旋轉
SCNAction *action = [SCNAction repeatActionForever:[SCNAction rotateByX:0 y:1 z:0 duration:1]];
[node runAction:action];
// 素材放大5倍(由於我們素材的尺寸太小了)
node.transform = SCNMatrix4MakeScale(5, 5, 5);

// �建立一個攝像機並放入場景中
SCNNode *cameraNode = [SCNNode node];
cameraNode.camera = [SCNCamera camera];
[scene.rootNode addChildNode:cameraNode];

// �擺放攝像機位置
cameraNode.position = SCNVector3Make(0, 5, 15);

// 建立�燈光並放入場景中
SCNNode *lightNode = [SCNNode node];
lightNode.light = [SCNLight light];
lightNode.light.type = SCNLightTypeOmni;
lightNode.position = SCNVector3Make(0, 10, 10);
[scene.rootNode addChildNode:lightNode];

// create and add an ambient light to the scene
SCNNode *ambientLightNode = [SCNNode node];
ambientLightNode.light = [SCNLight light];
ambientLightNode.light.type = SCNLightTypeAmbient;
ambientLightNode.light.color = [UIColor darkGrayColor];
[scene.rootNode addChildNode:ambientLightNode];

// 建立一個用來展示場景的SCNView
SCNView *scnView = [[SCNView alloc] initWithFrame:self.view.bounds];

[self.view addSubview:scnView];

// 設定場景
scnView.scene = scene;

// 設定背景
scnView.backgroundColor = [UIColor blackColor];

// 允許控制攝像機位置
scnView.allowsCameraControl = YES;

// 顯示資料控制檯
scnView.showsStatistics = YES;

好了,編輯執行。成功執行


2144614-9baf6468d874aa92.gif
小怪獸

** BUT **,在實際專案中往往需要我們從伺服器上將模型下載下來再來顯示,然而這種做法只能是事先把素材放入專案中才能正常顯示,【注意:我說的是正常顯示】,這是不符合我們的需求的。如果我們把素材從伺服器上下載到沙盒裡,程式再直接從沙盒讀取和初始化場景會出現為nil的問題。

iOS - SceneKit顯示與互動3D建模(�二)
最後附上DEMO LXF3DSceneDemo

相關文章