Apple Engine

Apple, iPhone, iOS, その周辺のことについて

SceneKit アプリで使用しているシーンを Pixar USD として書き出す

f:id:x67x6fx74x6f:20190124184858j:plain

Model I/O framework は Metal で使用する一連をアセット操作するものがああり、ファイルを読み込んでアセットにしたり、アセットを別のファイル形式に書き出すことができる。

アセットの設定は Model I/O の MDLAsset を使用するのだが、MDLAsset では SceneKit のシーンファイル以外にも SCNScene 自体を読み込みアセットとして作成すること可能。

自分の場合 iOS でファイル操作をするのが面倒だったので macOS の NSOpenPanel で書き出すフォルダを調べてそこに書き出したが、 iOS の場合はアプリのドキュメントフォルダに保存するなどで書き出せると思われる。

 

注意点

SCNScene が正確に書き出されるわけではないの注意。
現状、基礎情報、ジオメトリ、カメラのみ書き出され、ライトなどは無視される。

 

ジオメトリはマテリアル、位置や回転や拡大縮小、アニメーション情報など付加されないので、この書き出しは Xcode のコマンドラインから USDZ に変換する用のものと考えてよいと思われる。

また、ワールド座標が Z 軸が上の Z up で書き出されるのでかなり罠。
USD の仕様に合わせていると思われ、xcrun usdz_converter では Y up かつ Physically Based のマテリアルが再設定される。

 

内容的には Xcode 上のデバッグの View UI Hierarchy で SCNScene を選択した際の「Export」から吐き出されるファイルに近い。  

f:id:x67x6fx74x6f:20190124185003p:plain
Debug 画面の View UI Hierarchy

 

コード

SceneKit は Model I/O を内包しているが、SceneKit の機能を参照する Model I/O の機能であるため、以下のインポートが必要。

import SceneKit.ModelIO

 

以下のコードで SCNScene と書き出し先のフォルダを設定する。

var assets = MDLAsset.init(scnScene: scene)

var fileURL = URL(string: "書き出しフォルダまでのパス")!
fileURL.appendPathComponent("export.usda")

if(MDLAsset.canExportFileExtension("usda")){
    do {
        try self.assets.export(to: fileURL)
    } catch let error {
        DispatchQueue.main.async {
            print(error.localizedDescription)
        }
    }
}else{
    print("This file format (extension) is not supported")
}

 

コードではアスキーファイルの USDA を設定しているが、バイナリ版の USDC も可能。
USDZ での書き出しはできない。

iOS の場合、USDC は USDZ 同様に QuickLook でプレビューできるため、USDC ファイルを直接もしくは Mac などの AirDrop でファイルアプリに保存すると AR のプレビューができる。
(ただし、そのままだとワールド座標が Z up になる)

 

まとめ

使い道はあまりないが、アプリで使用している SCNScene の USD 書き出しが簡単できることがわかった。