Closed19

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が出力されるシンプルなもの

にー兄さんにー兄さん

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>の点群データを返してくれるので使えそう

にー兄さんにー兄さん

ユーザフローを考える

  1. メニューから変換ウィンドウを開く(Pretia>ply converter的な感じ?)
  2. .mapファイルをD&Dでアタッチ
  3. convertボタンを押すとAsset/Pretia Map Converter/Maps/以下に.plyファイルが生成される

だろうか

にー兄さんにー兄さん

ぎっしり詰め込むってどういう意味なんだろう、
調べてみて、もしかしたらfloat[]をBitConverterかなと思ったけど、
このstackoverflowにヒントになりそうなことがあった
https://stackoverflow.com/a/4636735/10142918

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);
にー兄さんにー兄さん

バイナリの中身としては、
まずヘッダーを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なのか......

このスクラップは2022/03/21にクローズされました