わふうの人が書いてます。

iOSアプリケーション開発、BLEのファームウェアとハードウェア試作のフリーランスエンジニア。

SceneKitで遊んでみる

SceneKitで遊んでみる

iOS8にはいった、3Dの何かを簡単に作れるSceneKitで遊んでみた。

キャラクタが画面中央に表示されて、5秒に1回ジャンプのアニメを実行する。BananasAsimpleSceneKitplatforminggame と https://github.com/shu223/iOS8-Sampler のSceneKitのサンプルをコピペでつなぎあわせたようなもの。

感じ的には、three.js で3Dしている方の説明とおんなじ感じだなと思った。せっかくだから、ミクさんのアプリを作ればいいのに、3Dデータ変換方法がわからなくて、断念。

Githubのサンプルアプリ。
https://github.com/reinforce-lab/ObjC_Codes/tree/master/SceneKitDaeExample

https://developer.apple.com/library/mac/documentation/3DDrawing/Conceptual/SceneKit_PG/Introduction/Introduction.html

SceneKit Framework Reference
https://developer.apple.com/library/ios/documentation/SceneKit/Reference/SceneKit_Framework/

3Dデータの変換

https://github.com/ark-project/ark-project にオープンなデータがあったので、サンプルに使わせてもらった。
cheetah3dというMacのアプリで読み込んで、dae形式に書き出して、テクスチャの設定をする感じ。

モデルが最初真っ白だったから、まず左のペインのMマークのマテリアルで、diffuseにテクスチャの画像ファイルを指定。光の放出を意味するEmissionが白だと、やっぱり白いままなので、これを黒に変更、とかすると3Dモデル+テクスチャが表示される。

lapisの3Dモデルは、上腕部がXcodeでプレビュ表示されない。またビルド時にdae形式のアイルを変換するっぽくて、その時にエラーが出てた。なので、モデルファイルはプロジェクトからは削除してある。

ツールによって、ファイルフォーマットの相性とか、データの作り方や命名方法など、実際にやっていくと、いろいろあるんかもね。

SceneKitの使いどころ

3Dのモデルを読み込み、それを表示させたり、アニメーションをさせたり、物理シミュレーションで動かしたりするのが簡単にできるのが、SceneKit。昨年iOS7で導入された2Dテームを手軽に作れる SpriteKit の3D版といった感じ。

3Dゲームを作る環境には、Unity等がある。それに比べて何か利点があるかというと、多分ない。開発環境を見ても、3Dのモデルはプレビューはできるけど編集能力はないし、物理シミュレーションやアニメーションができるけど、現在のところはインタラクティブに確認する機能もないから、ビルドして振る舞いを見るしかない。プラットフォームもiOSかMacOS縛りになる。

Unityを使うほどではないとか、Unityのラインセスをとって学ぶのが大変だとか、Unityを使った人がいないときに、アプリにちょっと3Dを入れたい場合には便利だと思う。3Dのシーンを見せるのに、レンダリングした動画を入れちゃうと、見るだけになるけど、例えばカメラアングルをぐりぐり動かしたいとか、アプリ側から演出したいとか、そういうときに3Dモデル+アプリ的ななにか、をちょっと入れる場面も、使えると思う。

イメージ的には、アイカツ!ミュージックビデオメーカーみたいな。http://app.famitsu.com/20140806_420069/

あるいは、月齢表示とかのアプリなら、月の3Dモデルに太陽と地球の放射光があたっているさまを、表示するとか。

SceneKitのなかみ

プロジェクトのサンプルコードを見たら、そのままだけど。

表示は、UIViewを継承する SCNView 。これのsceneプロパティに、SCNScene のオブジェクトを入れる。ゲームだと、3D画面の上に操作用画面をいれるけど、それはSCNScene のoverlayなんとかに、SpriteKitの画面を入れられるので、それを使うといいっぽい。

SCNScene は、3Dモデルやアニメーションといったデータを保持するクラス。内部のデータ構造は、SCNNode をノードにする木構造。ノードを作っては、そこにカメラとかオブジェクトとかを張り付けていく。木構造の根は、SCNScene の rootNode プロパティ。

3Dモデルのテクスチャには、リソースの画像ファイルや、文字列やら、CALayerやSpriteKitの画面が貼り付けられる。だから、カメラのプレビュ画面がCALayerから派生しているけど、そういうカメラ動画を貼り付けるとか、そんなのも簡単にできる。

OpenGLのレンダラを生で叩くとか、低レベルなところもありっぽい。OpenGLで別で自分で書いたのと融合とか、面白い事が出来る人には、使いこなせるんあろうと思う。

面白いのは、アニメーションの指定がCoreAnimation。ノードに貼り付けた3Dオブジェクトやライトやカメラの、位置や速度や質量や加速度やらをCoreAnimationでアニメできる。また、アニメのデータは dae 形式のファイルに入れたアニメのデータをCoreAnimationとして読みだすことができるので、別にコードで書かなくてもいい。

2次元のUIのアニメだと思っていたCoreAnimationのスキルが、3Dなところでもそのまま使えるのは、汎用的で面白い。

あとはパッと見たところで:

SCNProgram

OpenGL Shading Language (GLSL)で記述したシーエだープログラムを使ってカスタムなレンダリングを実行する。
バーテックスシェーダー、フラグメントシェーダー

https://developer.apple.com/library/ios/documentation/SceneKit/Reference/SCNProgram_Class/index.html#//apple_ref/occ/cl/SCNProgram

SCRenderer

https://developer.apple.com/library/ios/documentation/SceneKit/Reference/SCNRenderer_Class/index.html#//apple_ref/occ/cl/SCNRenderer

すでにレンダラのコンテキストが指定されているアプリに、別のコンテキストを指定できる。EAGLContext object 。

SCNView。カメラグリグリ動かせる、フレームレート(最大60、デフォルト60)、スナップショット。

https://developer.apple.com/library/ios/documentation/SceneKit/Reference/SCNView_Class/

SCNScene。Vihicleのサンプル、オーバーレイが継承している。

SKSpriteNode。2次元の画像。

SpriteKit(2次元ゲームを作るやる)のシーンをオーバレイ。速度メータとか。

1
2
SKScene *scene = self.overlaySKScene
//self はSCNView

SCAAnimationEvent。足音とか、アニメに同期した音

MacとiOSで同じ名前空間

SceneKitとSpriteKitは、MacとiOSで同じ3Dなものを同時開発するのに、便利だと思う。iOSとMacで、名前空間が同じでAPIも同じように振る舞うから、画面サイズが違うだけのなにか、として開発できる。

色を扱うとき、MacだとNSColor、iOSだとUIColorだけど、こういう些細な差分は SpriteKit の SKColor を使えば吸収できるようになっている。SKColor は ifdef で、NSColor と UIColor を切り替えているだけのものだけど、標準のSDKで名前の些細な違いを吸収する仕組みが入っているのが、いい感じ。

色以外にも、いろんな違いがあるんだろうけど、そこまで詳しくないからしらない。

PlayGroundで使えるの?

PlayGroundは、Swiftで簡単なコードを作り、その場で実行して結果を確認できるXcode6の新機能。3Dモデルの読み込み結果及び簡単な動作確認やパラメータの調整に使えると便利だろうと思ったけど、2014年10月3日に、Maverickでの、Xcode6.0.1およびXcode6.1beta(2014年9月30日時点)の2つの環境では無理っぽい。

何が無理っぽかったかというと:
2つの環境で、 MyPlayground.playground を実行してみる。これはiOSをターゲットにしたPlayGroundでの、SceneKitのサンプルコード。

アシスタントエディタを表示(View->Assistant Editor->Show Assistant EditorをON)にすると、実行画面が確認できるけど、

2014-10-03 12:37:51.185 MyPlayground[11251:1205362] Error sending deferral props: 0x10000003

こんなエラーが出る。iOS dev forumをみても、同じようなエラーが報告されているけど、対処はわからない。

iOSターゲットがだめなら、Macターゲットならどうだと思って、そんなPlaygroundをつくろうとすると、Xcode6.0.1はMacのPlaygroundにまだ対応していない。仕方ないので、Xcode6.1beta を入れてMacターゲットで実行しても、エラーはでないけど、なんか表示画面が真っ黒のままで表示されない。

よくわかんない。ツールの問題ということにしておきたい。そのうち動くんじゃないかしらと思う。

リソースの管理

3Dのテクスチャやモデルを管理するなら、アセットにしておくと便利。フォルダを適当に作って、そのフォルダ名に”.scnassets”という拡張子っぽい名前をつけて、Xcodeに放り込めば、アセットとして扱ってくれる。

リソースファイルを追加したいときは、そのフォルダにファイルを放り込めば、自動でXcodeに反映される。

モデルとアニメのファイルはフォルダ構成で区別してやればいい。
例えばサンプルプロジェクトは art.scnassets/characters/explorer/run みたいにして、冒険者のキャラクタの走る場面のアニメーションファイルを入れている。

3Dモデルデータ

Xcode6は、Colladaファイル(.dae)という形式で3Dモデルを読み込める。”Import COLLADA 3D objects and build scenes composed by cameras, lights, and meshes. “ だそうだ。

Colladaファイルは、非営利技術コンソーシアムのクロノス・グループが管理していて、”COLLAborative Design Activity” の略。対話型3Dコンピュータ・グラフィックス・アプリケーション間の、交換用のファイル・フォーマットで、その中身はXMLファイル。バージョン? 1.4で物理学(Physics)、摩擦係数とかが追加されているらしい。カメラとかアニメーションデータとかも1つのファイルで扱えるので便利。

ミクミクダンスとかのファイルをdaeに変換して読み込むフローがつくれると、iOSアプリでお手軽ミクさんフローが作れていいなとおもったけど、MMDの形式をdaeに変換する方法がわからないから、断念。

daeファイルを動的に読み込む方法

ゲームとかだと、データファイルを後からダウンロードさせたいときがある。そのとき、daeファイルが読み込めないとエラーになることがある。

Mac OSだとdaeファイル自体を読み込めるが、iOSのSceneKitは、前処理されたdaeファイルしか読み込めない。http://www.the-nerd.be/2014/11/07/dynamically-load-collada-files-in-scenekit-at-runtime/ ここに詳しく書いてあるように、xscassetsの前処理を自分でコマンド実行して、その結果ファイルを使わないといけない。

/Applications/Xcode.app/Contents/Developer/usr/bin/copySceneKitAssets product-1.scnassets/ -o product-1-optimized.scnassets

ここ、結構引っかかるので、めも。