空のシーンビューを画面に表示する
さて、ここでSwift Playgrounds上のプログラムに戻って、シーンを扱う方法を見ていきましょう。まず必要なのは、シーンを画面に表示できるようにするためのビューです。これは3次元、あるいは4次元の空間を2次元の平面に投影するための機能と考えることもできます。これは、一般的なビュー(UIView)のサブクラスとして、SceneKitに定義されているシーンビュー(SCNView)です。
今回のプログラムでは、まず通常のビューコントローラーを用意し、そのプロパティとしてシーンビューのオブジェクトsceneViewを作成し、それに背景色を設定してからビューコントローラーの元のビューに置き換えています。
ビューコントローラーのビューとして代入する前にフレームサイズをゼロに設定しているのは、以前に説明したSwift Playgrounds 2.1対策です。このプログラムを動作させると、薄いグレーの画面が表示されるだけです。ここまででは、一般的なビューとの違いはまったく見えてきません。
空のシーンを作成しその中に1つのノードを配置する
一般のビューと異なるシーンビューの最大の特徴は、sceneというプロパティを持っていることです。もちろんそこに表示したいシーンを設定すれば、画面に表示されます。
そこでまずSCNSceneクラスのオブジェクトとして空のシーンを作成し、そこに四角い箱(立方体)を配置して、シーンをまるごとシーンビューに張り付けてみましょう。
このプログラムはどこに書いてもいいのですが、viewDidLoadには初期設定を任せて、ここではviewWillAppearメソッドの中に書きました。四角い箱は、まずSCNBoxクラスのオブジェクトとしてジオメトリ(外形)を作り、それを指定してSCNNodeクラスのオブジェクト、つまりノードを作成します。このノードは、ARKitの回にも出てきました。とりあえず、シーンの中に配置する物体のことだと考えてください。その四角い箱のノードを、空のシーンにもともと含まれるルートノードの子ノードとして追加しています。
このプログラムを動かすと、最初に見たグレーの背景が、上下の細い水平領域を残して、白く塗りつぶされたように見える画面となります。
これだけでだと何が起こったのかわからないかもしれません。しかし、これはシーンの3次元空間の原点のあたりに箱を配置して、それをデフォルトのカメラの位置から見たものなのです。
シーンでは、何もカメラを設定しないと、配置したノードを見渡せる適当な位置にデフォルトのカメラが設置され、シーンビューには、そこから見た映像が表示されることになります。
カメラの位置を移動可能にして3D空間を飛び回る
カメラと箱の位置関係が頭ではわかっても、上の表示では、まだ何が起こっているのか体感するのは難しいでしょう。そこで、デフォルトのカメラの位置と向きを変更できるようにして画角を変えてみます。また、ついでにデフォルトの照明を加えて、箱に立体感を付けてみます。これもARKitの回に述べましたが、照明を何も指定していない状態では物体には全方向から一様の光が当てられているので、陰影がまったくない、立体感の欠如した映像となっています。
シーンビューのタッチ操作によってカメラを動かすには、シーンビューのプロパティであるallowsCameraControlをtrueに設定するだけです。また、適当な立体感の付くデフォルトの照明は、同様にautoenablesDefaultLightingのプロパティをtrueに設定します。
このプログラムを動かすと配置的には上とまったく同じ画面が表示されますが、白い壁のような領域の上下の部分にグラーデーションが付いたことに気付くでしょう。
ここで画面に触れて、2本指でのピンチイン/アウトや、ドラッグ、1本指での上下、左右方向へのドラッグを試してみると、目の前の壁のように見えたものが、実は四角い箱の1面を大きく見ているだけだったことがわかるでしょう。
ところで、タッチ操作によって、あたかも四角い箱の方を動かしたり、回転させたりしているように見えるでしょう。しかし実際は、箱は同じ場所に同じ大きさ、同じ向きでずっと固定されたままなのです。それを見ているカメラのほうが、箱の周りをぐるぐる周りながら、箱に近づいたり遠ざかったりしているのです。
1つのシーンの中に複数のノードを配置する
以上で、今回の目的はほとんど果たすことができたのですが、もう1つだけノードを追加して、それがどう見えるのか確かめておきましょう。ARKitの初回でも使いましたが「アスキー倶楽部」という文字列からSCNTextクラスを使って文字型のジオメトリを作り、それを指定してSCNNodeクラスのオブジェクト、つまりノードを作成します。フォントサイズは、ジオメトリの段階で指定しておきます。ノードの位置は、文字列の中央が箱の中央とだいたい揃い、四角い箱のちょっと上になるように、x軸とy軸の座標値を調整してノードのpositionプロパティを設定しています。
このプログラムを動かしてからタッチ操作でカメラを適当に動かすと、2つのノードの位置関係も把握しやすくなります。
これだけではモノクロームの世界で寂しい感じがするので、箱と文字列のノードに色を付けてみましょう。各ノードのfirstMaterialのdiffuseのcontentsプロパティにUIColorを指定することで、ノードの色を設定できます。UIColorのアルファ値を1.0より小さくすることで、半透明も表現できます。
次回の予定
今回は、前回までのARKitの中でも重要な役割を果たしている、SceneKitの基本を学びました。シーンの中に1つ、または2つノードを配置し、あとはデフォルトのカメラ、デフォルトの照明でシーンを撮影した状態を観察しました。これだけでも3Dグラフィックを非常に簡単に扱える、SceneKitのありがたみがよくわかったことと思います。次回は、配置するノードの種類を増やしたり、カメラや照明もデフォルトのものから脱却するなど、さらにSceneKitを探訪していく予定です。