【Unity Reflect】プラグインが提供されていないその他CADからReflectに3Dデータを転送する
Unity Reflectに触れる機会があったのでちょっと個人的にプログラムを組んでみたのでメモ程度に。
RevitやSketchUpユーザーであればUnity公式がそのアプリ用のReflectプラグインを用意してくれているのですごい簡単なのですが、内製のCADとかになると自分でどうにかしなければなりません。具体的には用意されたPublisherAPIをいうライブラリを使用して、自力で頂点、マテリアル、テクスチャ、ライト、カメラ情報などを登録して送信する必要があります。
基本的にはCADが持つ頂点データを直接Reflect変換すればよいのですが、今回はCAD側にOBJ形式エクスポート機能があると仮定して、OBJ形式の建物をReflectデータに変換してみたいと思います。
やり方
Unity ReflectのPublisher APIが必要です。
実際にUnity Reflect上で見たいのであればトライアルか本契約が必要です。
Unity-Technologies / reflect.publisher.csharp – Github
あと今回はOBJ形式をReflect形式にしますので、OpenOBJライブラリを用意します。CADからダイレクトに転送する本番では不要です。
stefangordon / ObjParser – Github
OBJParserをビルドする
Visual Studioでreflect.publisher.csharp/Samples.slnを開いて、OBJParserプロジェクトを追加します。
一旦OBJPerserプロジェクトだけを普通にビルドしてしまうのがいいと思います。
OBJParser.dllが出力されます。
そしたらPublisherSample.vcxprojプロジェクト側で、[参照]をして、OBJParser.dllを設定します。
これでReflectのサンプルプロジェクトからOBJ形式が読み取れます
基本処理
3Dデータコンバータのプログラムに触れたことがある方は何も困ることはありません、ロジックは全く同じです。
こちらに公式リファレンスがあります。
Reflect Publisher API. Getting started – Unity Documentation
Publisher transactions & flows Transactions
Figure from Reflect Publisher API. Getting started
この1連の手続きをすることで、UnityのHierarchy上では1つのGameObjectとして表現されます。
OBJを開いてReflectに転送する
PerformExportTransaction()関数で形状の登録をします。
今回のOBJ形式の3Dデータではメッシュ数の分だけループして処理してあげれば良いわけです。
これでメッシュ数を取得して、for文で回します。
int num = meshData.obj.MeshList.Count;
これでi番目のメッシュデータが取得できます
ObjParser.Obj currentObj = meshData.obj.MeshList[i];
BuildMesh()関数でSyncMeshという構造体を作ります。
実験ベースだったため形状とマテリアルテクスチャがとりあえず見た目上うまくいけばいいやってレベルでしたのでFaceだけで判定してしまっていますが、
本来はindex数で判定します。
SyncSubMeshを生成しておいて、トライアングル情報をセットしていきます
syncMesh.SubMeshes.Addで登録します。
このsyncMeshをtransaction.Send()関数で登録します。
注意いただきたいのがテクスチャの登録をしている箇所です。SyncTexture。
これらはサンプルには登場せず、リファレンスにも特にTipsが無いので自力で試行錯誤してたどり着いた方法ですので、本来の方法とは少し違っているかもしれません。
次はBuildMaterial。
OBJ形式であれば、アルベドマップの存在はmat.map_Kd.Length > 0で確認ができます。
そんざいするならば BuildTexture()を呼びましょう。
テクスチャ画像を開いて、new Bitmapしてセットしてやります。
ちなみにUnity Reflectでは、テクスチャ画像の解像度が2のべき乗であることが必須ですので、念のためべき乗に解像度を丸める考慮を私のサンプルプログラムでは追加しています。
SyncTextureインスタンスを生成して、必要情報をセットしていきます。このあたりはSyncMaterialと対になっている感じなので、真似しながらやるとスムーズでしょう。
そしてBuildObject。
SyncObjectを生成して、メッシュとマテリアルを紐付けてやります。
parentObject.Metadata.Addをしていますが、これがいわゆる「BIMデータ」をセットする関数です。
今回は建築情報とかではなくてデバッグ用の情報をセットしています
ここで登録した文字列は、Unity Reflect上でパーツを選択した際に表示されます。
SyncObjectInstanceで、GameObjectとして登録されます。UnityスクリプトのInstantiate()と同じような意味合いです。
以後、必要なメッシュのぶんだけ繰り返しです。
それ以外の情報はこちらのリファレンスでわかります。かなり上辺だけの情報なので他のコンバーターの実装経験などがないとちょっときついかもしれません。(多少の妄想で補完が要る。)
Reflect Publisher API – Unity Reflect
ソースコード
こちらに公開してあります。
christinayan01/demo/unityreflect/publisherapi/ – github
参考サイト
- stefangordon / ObjParser – Github
- Installing the Industrial Hub and Reflect Plug-in – Unity Learning
- Unity-Technologies / reflect.publisher.csharp – Github
- Unity-Technologies / com.unity.reflect.viewer – Github
- UnityEngine.Reflect.PipelineDataProvider Class DataProvider – Unity Documentation
- Reflect Publisher API – Unity Reflect
- Unity Reflect documentation – Unity Documentation
- Reflect Publisher API. Getting started – Unity Documentation