Swift Playgroundsで学ぶiOSプログラミング

SceneKitの基礎シーンビュー、シーン、ノードを理解する

文●柴田文彦 編集●吉田ヒロ

2018年07月25日 17時00分

空のシーンビューを画面に表示する

 さて、ここでSwift Playgrounds上のプログラムに戻って、シーンを扱う方法を見ていきましょう。まず必要なのは、シーンを画面に表示できるようにするためのビューです。これは3次元、あるいは4次元の空間を2次元の平面に投影するための機能と考えることもできます。これは、一般的なビュー(UIView)のサブクラスとして、SceneKitに定義されているシーンビュー(SCNView)です。

 今回のプログラムでは、まず通常のビューコントローラーを用意し、そのプロパティとしてシーンビューのオブジェクトsceneViewを作成し、それに背景色を設定してからビューコントローラーの元のビューに置き換えています。

一般的なビューコントローラーのビューを、空のシーンビュー(SCNView)に置き換えて表示してみました。シーンビューの背景色を薄いグレーに設定しているのは、あとで白い3Dオブジェクトを配置したときに、とりあえず見えるようにするためです

 ビューコントローラーのビューとして代入する前にフレームサイズをゼロに設定しているのは、以前に説明したSwift Playgrounds 2.1対策です。このプログラムを動作させると、薄いグレーの画面が表示されるだけです。ここまででは、一般的なビューとの違いはまったく見えてきません。

空のシーンを作成しその中に1つのノードを配置する

 一般のビューと異なるシーンビューの最大の特徴は、sceneというプロパティを持っていることです。もちろんそこに表示したいシーンを設定すれば、画面に表示されます。

 そこでまずSCNSceneクラスのオブジェクトとして空のシーンを作成し、そこに四角い箱(立方体)を配置して、シーンをまるごとシーンビューに張り付けてみましょう。

上で作った空のシーンの中に、とりあえず四角い箱を1つだけ配置します。SCNBoxとして箱のジオメトリを作成し、そこからSCNNodeのオブジェクトを作成して、シーンの子のノードとして配置しています

 このプログラムはどこに書いてもいいのですが、viewDidLoadには初期設定を任せて、ここではviewWillAppearメソッドの中に書きました。四角い箱は、まずSCNBoxクラスのオブジェクトとしてジオメトリ(外形)を作り、それを指定してSCNNodeクラスのオブジェクト、つまりノードを作成します。このノードは、ARKitの回にも出てきました。とりあえず、シーンの中に配置する物体のことだと考えてください。その四角い箱のノードを、空のシーンにもともと含まれるルートノードの子ノードとして追加しています。

 このプログラムを動かすと、最初に見たグレーの背景が、上下の細い水平領域を残して、白く塗りつぶされたように見える画面となります。

グレーの背景だけだったシーンに、真っ白な壁のようなものが現れました。あとでわかりますが、これは上で配置した四角い箱の1つの面を大きく見ているのです

 これだけでだと何が起こったのかわからないかもしれません。しかし、これはシーンの3次元空間の原点のあたりに箱を配置して、それをデフォルトのカメラの位置から見たものなのです。

シーンキットのアップルのドキュメントのうち、シーンとノードの関係のページを見ると、シーンの座標系とノード、デフォルトのカメラの位置関係がわかるような図があります。上のプログラムで見えているのは、ちょうどこの図のような状態です

 シーンでは、何もカメラを設定しないと、配置したノードを見渡せる適当な位置にデフォルトのカメラが設置され、シーンビューには、そこから見た映像が表示されることになります。

カメラの位置を移動可能にして3D空間を飛び回る

 カメラと箱の位置関係が頭ではわかっても、上の表示では、まだ何が起こっているのか体感するのは難しいでしょう。そこで、デフォルトのカメラの位置と向きを変更できるようにして画角を変えてみます。また、ついでにデフォルトの照明を加えて、箱に立体感を付けてみます。これもARKitの回に述べましたが、照明を何も指定していない状態では物体には全方向から一様の光が当てられているので、陰影がまったくない、立体感の欠如した映像となっています。

 シーンビューのタッチ操作によってカメラを動かすには、シーンビューのプロパティであるallowsCameraControlをtrueに設定するだけです。また、適当な立体感の付くデフォルトの照明は、同様にautoenablesDefaultLightingのプロパティをtrueに設定します。

シーンビューのallowsCameraContorolプロパティをtrueに設定して、タッチ操作でカメラを動かせるようにしています。ついでに、autoenablesDefaultLightingもtrueに設定してデフォルトの照明を当てて、箱が立体的に見えるようにしました

 このプログラムを動かすと配置的には上とまったく同じ画面が表示されますが、白い壁のような領域の上下の部分にグラーデーションが付いたことに気付くでしょう。

 ここで画面に触れて、2本指でのピンチイン/アウトや、ドラッグ、1本指での上下、左右方向へのドラッグを試してみると、目の前の壁のように見えたものが、実は四角い箱の1面を大きく見ているだけだったことがわかるでしょう。

画面にタッチして、ピンチイン/アウトしたりドラッグしたりすることで、壁のように見えたものが、四角い箱の1つの面だったことがはっきりするでしょう。操作によって箱が動いているように見えますが、実は動いているのはカメラのほうです

 ところで、タッチ操作によって、あたかも四角い箱の方を動かしたり、回転させたりしているように見えるでしょう。しかし実際は、箱は同じ場所に同じ大きさ、同じ向きでずっと固定されたままなのです。それを見ているカメラのほうが、箱の周りをぐるぐる周りながら、箱に近づいたり遠ざかったりしているのです。

1つのシーンの中に複数のノードを配置する

 以上で、今回の目的はほとんど果たすことができたのですが、もう1つだけノードを追加して、それがどう見えるのか確かめておきましょう。ARKitの初回でも使いましたが「アスキー倶楽部」という文字列からSCNTextクラスを使って文字型のジオメトリを作り、それを指定してSCNNodeクラスのオブジェクト、つまりノードを作成します。フォントサイズは、ジオメトリの段階で指定しておきます。ノードの位置は、文字列の中央が箱の中央とだいたい揃い、四角い箱のちょっと上になるように、x軸とy軸の座標値を調整してノードのpositionプロパティを設定しています。

四角い箱に加えて、その上方に「アスキー倶楽部」という文字列から作ったノードを配置しています。これはARKitの初回に使ったものとほとんど同じですが、大きさや位置の指定は変えています

 このプログラムを動かしてからタッチ操作でカメラを適当に動かすと、2つのノードの位置関係も把握しやすくなります。

1714494

 これだけではモノクロームの世界で寂しい感じがするので、箱と文字列のノードに色を付けてみましょう。各ノードのfirstMaterialのdiffuseのcontentsプロパティにUIColorを指定することで、ノードの色を設定できます。UIColorのアルファ値を1.0より小さくすることで、半透明も表現できます。

四角い箱には、半透明の青緑、文字列には不透明のオレンジの色を指定してみました。カメラの位置を動かすと、半透明の箱の向こう側に文字列が透けて見えるような画角も容易に実現できます

次回の予定

 今回は、前回までのARKitの中でも重要な役割を果たしている、SceneKitの基本を学びました。シーンの中に1つ、または2つノードを配置し、あとはデフォルトのカメラ、デフォルトの照明でシーンを撮影した状態を観察しました。これだけでも3Dグラフィックを非常に簡単に扱える、SceneKitのありがたみがよくわかったことと思います。次回は、配置するノードの種類を増やしたり、カメラや照明もデフォルトのものから脱却するなど、さらにSceneKitを探訪していく予定です。

mobileASCII.jp TOPページへ