Xcode/ARKitで3Dモデルを読込み&表示

ARKitアプリを作る際には、Unityで作成すればfbxやobjといった3Dモデルを簡単にインポートして表示できます。
しかし、XcodeとSwiftでネイティブで作成しているアプリの一部分でだけ3Dモデルを使用したい、という要件があったので調査してみました。

調査する、とは言うものの、そのものズバリの投稿がQiitaにありました(すごい)

SceneKitで扱える3Dモデルのフォーマット/アニメーションつき3DモデルをSceneKitで使う - Qiita
やりたいこと: 各種モデリングソフトからエクスポートされた3Dモデルを、SceneKit (on iOS)で使いたい モデルに紐づくアニメーションとかボーン(Rigged Models)とかもそのまま使いたい ちなみになぜUnityじゃない...

ということで、Xcodeで使用するにはCollada(拡張子.dae)一択のようです。
[引用]

let url = Bundle.main.url(forResource: filename, withExtension: "dae")!
let modelScene: SCNScene
do {
    modelScene = try SCNScene(url: url, options: nil)
} catch {
    fatalError()
}

このように、シーン内でdaeを直接使用するのではなく、daeからSCNSceneオブジェクトを作成して使用します。

また、daeからSCNSceneファイル(拡張子.scn)をXcode内で予め作成しておく方法もあります。

daeファイルをプロジェクト内にインポートしてファイルを選択すると、dae内のノードがツリー状に表示されます。ノードを選択して、Editメニューの Convert Scenekit scene file format(.scn)… を選択します。

これでscnファイルが生成されます。

このとき、scnファイルを生成しているのは、scntoolという実行ファイルになります、
予め大量のdaeからscnを生成したい時などは、下記のようにコマンドラインで呼び出すこともできるそうです。

Batch convert dae to scn
Is there a way to batch convert Collada dae files to Scenekit scn files?My project uses approx 50 models created in sket...

生成したscnファイルを選択してインスペクタを切り替えると、位置・回転・スケールなどを編集できます。Unityのインスペクタっぽくってちょっと安心しますね(笑)

そして、scnファイルをARKitのシーンで表示するサンプルもありました(感謝)

【ARKit入門】平面にアイテムを配置する - Qiita
平面にオブジェクトを配置する こんな感じのです この記事ではARKitを用いて、検出された平面にアイテムを配置する実装を紹介します。 ARKitでの初期設定や、アイテムとして追加する3Dモデルのプロジェクトへの取り込みなどは以下をご参照くだ...

[引用]

let scene = SCNScene(named: "Models.scnassets/\(selectedItem).scn")

作成したscnファイルをxx.scnassetsフォルダから読み込んでいますが、ここにも重要な意味があります。

iOS で SceneKit を試す(Swift 3) その56 - SceneKit プロジェクトファイルの .scnassets フォルダとは? - Apple Engine
xcassets はプロジェクトの画像などのアセットを管理し最適化を行なっているが、 scnassets は SceneKit のファイルの管理をするフォルダ。 .scnassets にファイルを配置するとビルド時に内容を最適化してくれる。...

・オブジェクトファイルの座標を Y 軸を上方向に変換する
・画像ファイルを各デバイスの GPU に最適化されたものに変換する

また、xx.scnassetsフォルダの作り方ですが、Xcode上で「New Group」を選択してもうまくいきません。うまくいっていないときには、フォルダが黄色になります。

青いフォルダになっていれば正解です。

これは、Xcodeで「グループ」として認識されていて、「フォルダ参照」として認識されていない状態です。「フォルダ参照」として認識させるには、一旦XcodeでDelete→Remove Referencesを行って参照のみ消して、改めてFinderからフォルダをプロジェクトにドラッグ&ドロップします。

このとき「Create folder references」を選択してください。

上記で引用させてもらったコードから少し変更して実機で動かすことができました。
・scnファイルからノードを名前で取り出すところを簡素化してハードコード
・iPhone 6sだと遅いので、平面認識した部分でなく、推定平面に対してHitTest(estimatedHorizontalPlane)

ソースコードはGitHubにアップしました。

GitHub - torikasyu/ARKitNative: ARKit with Collada file
ARKit with Collada file. Contribute to torikasyu/ARKitNative development by creating an account on GitHub.

コメント

タイトルとURLをコピーしました