Pretiaのマップをplyに変換するエディタ拡張を作りたい
最近Pretiaの申請が通ってSDKが使えるようになったので
ちょっとずつ使い始めているんだけど、マップ作成が爆速ですごい
せっかく作ったマップを手元で確認したいので
plyに変換したいなぁと思っていた
PretiaはUnityからマップをDLすると
.map
という拡張子のjson形式の点群が降ってくる
このjsonをplyバイナリファイルに変換して、BlenderとかCloudCompareで読み込めると嬉しいよねって感じ
バイナリファイルの作成に関してはこちらを参考にすればよさげ
エディタ拡張のイメージとして、
Pretia>Convert map to plyみたいなメニューを選択すると
windowが起動して、.map
ファイルをSerialize Fieldにドラッグした後に
Convertボタンを押すと特定の場所にpyが出力されるシンプルなもの
TextAssetであれば普通にシリアライズフィールドにアタッチできるらしい
PretiaSDKの中身をのぞいてみてた
マップのDLに関しては、順を追って見ていくと、https://arc-map-public.pretiaar.com/maps/v1.1/platform-storage/map-content/{appKey}?path={mapKey}.json
って感じのエンドポイントにtokenとかをヘッダーにつけてリクエストしているらしい
次に点群データの取得について
最初は自力でシリアライズしようと思ってたけど、PretiaSDKの中にすでにシリアライズ用のコードを見つけたので、それが使えそう
具体的にはPcx/Editor/MapImporter.csの中にあるように、JsonSerializerでデシリアライズする
このシリアライザはUtf8Jsonというものを使っているらしい
シリアライズオブジェクトはPretiaPointClpudDataというもので、GetVerticesでList<Vector3>の点群データを返してくれるので使えそう
文字列をunicodeの文字コードに変換する
plyのヘッダは普通にasciiなのでこれする必要がある?
ユーザフローを考える
- メニューから変換ウィンドウを開く(Pretia>ply converter的な感じ?)
- .mapファイルをD&Dでアタッチ
- convertボタンを押すと
Asset/Pretia Map Converter/Maps/
以下に.plyファイルが生成される
だろうか
plyのバイナリフォーマットは、
データは単純にヘッダで指定された'エンディアン'かつ'property'レコードに与えられたデータタイプで、ぎっしり詰め込まれる。
らしい
ぎっしり詰め込むってどういう意味なんだろう、
調べてみて、もしかしたらfloat[]をBitConverterかなと思ったけど、
このstackoverflowにヒントになりそうなことがあった
var floatArray1 = new float[] { 123.45f, 123f, 45f, 1.2f, 34.5f };
// create a byte array and copy the floats into it...
var byteArray = new byte[floatArray1.Length * 4];
Buffer.BlockCopy(floatArray1, 0, byteArray, 0, byteArray.Length);
ところでBlockCopyはリトルエンディアンで解釈すしているらしい
バイナリの中身としては、
まずヘッダーをutf8エンコーダでGetBytesしたbyte[]と
float[]をBlockCopyしてできたbyte[]を
Linqでconcatする的な感じ?
遅い気がするけど、パフォーマンス重視しなくてよい場合にList<Vector3>をflattenなfloat[]にするLINQ
var floatArray = pointCloud.Aggregate(new List<float>(), (list, point) =>
{
list.Add(point.x);
list.Add(point.y);
list.Add(point.z);
return list;
}).ToArray();
dummyのデータ(0-1のキューブの中のランダムな1000個の点)を
binary little endianのplyバイナリとして出力できた
あとはこれをPretiaのマップデータに差し替える
本当はPointCloud.map
ファイルを読み込んで変換/出力って感じにしたかったんだけど、
MapファイルがPretiaの方でいい感じにPrefabにされてしまい点群データの取得がCoputeBufferからしかできなさそう
ComputeBuffer.GetDataではArray型のオブジェクトが返されるんだけど、
コイツの方がいまいちわかっていない
float[]なのかvector3[]なのかListなのか......
エディタの中だとファイルダイアログのユーティリティがあるらしい
これを使えば.mapファイルの読み込みも苦ではないし、出力先も指定できるかも
なんやかんやで手元では動くようになりました
良い感じにOSS公開できました