Help us understand the problem. What is going on with this article?

SceneKitで扱える3Dモデルのフォーマット/アニメーションつき3DモデルをSceneKitで使う

More than 1 year has passed since last update.

やりたいこと:

  • 各種モデリングソフトからエクスポートされた3Dモデルを、SceneKit (on iOS)で使いたい
  • モデルに紐づくアニメーションとかボーン(Rigged Models)とかもそのまま使いたい

ちなみになぜUnityじゃないかというと、非ゲームな、基本的には2Dのアプリで、一部で「3D的表現」を行いたい、という要件からです。

扱えるフォーマット

結論からいうと、.dae(Digital Asset Exchange / COLLADA)の一択。(※追記: プロジェクトにリソースとして追加してあるdaeファイルは実際に使えますし、以下のコードで動作するのですが、「SceneKitが扱えるフォーマット」という点ではこの記述は語弊があります。詳しくはコメント欄をご参照ください)

こんな感じで使います。

let url = Bundle.main.url(forResource: "filename", withExtension: "dae")!
let sceneSource = SCNSceneSource(url: url, options: nil)!
guard let modelNode = sceneSource.entryWithIdentifier("modelId", withClass: SCNNode.self) else {
    fatalError()
}
scene.rootNode.addChildNode(modelNode)

if let animation = sceneSource.entryWithIdentifier("animationId", withClass
: CAAnimation.self) {
    modelNode.addAnimation(animation, forKey: "someKey")
}

他のフォーマットがNGだった理由は以下の通り。

  • .fbxは配布されているSDKを使うことでインポートできるが、頻繁にメンテされてるわけでもなさそうなので、そこに依存したくない
  • .objはSCNSceneSourceインポートできるが、そのファイル形式自体がアニメーションをサポートしていない
  • .3ds, .max はSceneKitにインポートできない(サードパーティ製ライブラリとかはあるかもしれない)

そしてこのCOLLADAの.daeファイルは大抵のモデリングツールでサポートされているらしい。

モデルの構造が複雑な場合

複雑というか、むしろ大抵のモデルは複数のオブジェクトやボーンから構成されている。

例えば、AppleのScene Kit Animationsという
フリーのこのモデルの.daeファイルをXcodeで見てみると、こんな感じでメッシュやらボーンやらでモデルが構築されています。

Screen Shot 2017-01-12 at 12.50.13.png

上でやったように、SCNSceneSourceでIDを指定してSCNNodeをつくってはaddChildする、という方法はこういうケースでは得策ではありません。

ではどうするかというと、非常にシンプルで、dae から SCNScene をつくるだけ。

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

このrootNodeを別のシーンにaddChildしようとしたら "removing the root node of a scene from its scene is not allowed" って怒られてしまったので、以下のように新しいノードに付け替えました。

let modelNode = SCNNode()
for childNode in modelScene.rootNode.childNodes {
    modelNode.addChildNode(childNode)
}

applemodel.gif

テクスチャが読み込めない?

Animated Army Pilotというモデルで同様の手法を試したところ、ジオメトリとアニメーションは再現されるものの、テクスチャが適用されませんでした。(※テクスチャはちゃんとプロジェクトに追加してありました)

実行時にこういうエラーが出ていました。

[SceneKit] Error: Failed loading : <C3DImage src:file:///Users/shuichi/Library/Developer/CoreSimulator/Devices/B2AF078C-BF73-429A-B9C0-182717D92859/data/Containers/Bundle/Application/55163269-393C-4F75-B729-5AF746CFDCA7/SceneKitModel.app/ [0.000000x0.000000]

ん?パスがちょっとおかしい。テクスチャが見つからないならこういうエラーが出るはず。

[SceneKit] Error: Failed loading : <C3DImage src:file:///Users/shuichi/Library/Developer/CoreSimulator/Devices/B2AF078C-BF73-429A-B9C0-182717D92859/data/Containers/Bundle/Application/55163269-393C-4F75-B729-5AF746CFDCA7/SceneKitModel.app/male_large_01.png

.daeの中身を見てみると(XMLファイルなので普通に見れる)、

  <library_images>
    <image id="head01-image" name="head01"><init_from>file://C:\Users\Nathan\Documents\New Project\Assets\Textures\soldier\head01.png</init_from></image>
    <image id="body01-image" name="body01"><init_from>file://C:\Users\Nathan\Documents\New Project\Assets\Textures\soldier\body01.png</init_from></image>
    <image id="m4tex-image" name="m4tex"><init_from>file://C:\Users\Nathan\Documents\New Project\Assets\Textures\soldier\m4tex.png</init_from></image>
  </library_images>

なんか制作環境の絶対パスが入っています。。

大丈夫なのか、と思いましたが、うまくいっているAppleの方のモデルの中身を見てみると、

  <library_images>
    <image id="male_large_01_png">
      <init_from>file:///Z:/art_depot/quest/characters/male_large_01/male_large_01.png</init_from>
    </image>
  </library_images>

こちらも絶対パスになっていました。

じゃあパスの指定方法が間違ってるのか、と思い、以下のように直してみました。

  <library_images>
    <image id="head01-image" name="head01"><init_from>file///C:/Users/Nathan/Documents/New Project/Assets/Textures/soldier/head01.png</init_from></image>
    <image id="body01-image" name="body01"><init_from>file///C:/Users/Nathan/Documents/New Project/Assets/Textures/soldier/body01.png</init_from></image>
    <image id="m4tex-image" name="m4tex"><init_from>file///C:/Users/Nathan/Documents/New Project/Assets/Textures/soldier/m4tex.png</init_from></image>
  </library_images>

:///// に、\/ に。

→ うまくいきました

army.gif

同じ仕様に則っているとはいえ、各社が別々にモデリングツールを開発していて、しかもメインとするプラットフォームが違ったりする(たとえば3DS MAXはWindows版しかない)中で、こういうエクスポートしたファイルフォーマットの微妙な違いによるトラブルというのは往々にしてあると思います。

上記のようなパスの違いが何によって生じたのか、よくあることなのかわかりませんが、ひとつの事例として。

.dae ファイルを .scn ファイルに変換する手順

  1. .daeファイルをXcodeプロジェクトに追加する
  2. 1で追加したファイルを選択する(SceneKitエディタでモデルが表示される)
  3. [Editor] > [Convert to scn file format] で変換される
shu223
フリーランスiOSエンジニア 著書:『iOS×BLE Core Bluetooth プログラミング』『Metal入門』『実践ARKit』『Depth in Depth』『iOSアプリ開発 達人のレシピ100』他 GitHubの累計スター数23,000超
http://shu223.hatenablog.com/
engineerlife
技術力をベースに人生を謳歌する人たちのコミュニティです。
https://community.camp-fire.jp/projects/view/280040
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした