BLOG

シンラボメンバーのあれこれ

  1. HOME
  2. ブログ
  3. 代表通信
  4. 代表技術通信~Unityで点群表示、Oculus Questで表示⑥ DMM点群をVFXでいじる

代表技術通信~Unityで点群表示、Oculus Questで表示⑥ DMM点群をVFXでいじる

こんばんは。代表の草場です。

前回の勉強である程度Visual Effect Graphの使い方がわかりました。いよいよDMMの点群で遊びます。
やり方は点群芸大の龍さんの「Visual Effect Graphで点群表示 | Point Cacheファイルの作り方」をもとに実施させてもらいました。
やることは以下です。
1.点群データをVFX Graph用のPoint Cacheファイルに変換する
2.VFX GraphでPoint Cacheを読み込み

そもそもPoint Cacheファイルとは、座標とそれに紐づく色情報等を持ったVFX Graph用のフォーマットです。拡張子は.pcacheです。座標 / 色 / ベクトル / 法線等が入っています。アスキーデータとバイナリデータと両方扱えますが、記事によると巨大なデータな場合はバイナリで作った方が読み込みも描画も軽快になるそうです。
記事ではアスキーデータの作り方が説明されているので、それを行います。

環境

OS:Windows 10 Pro
Unity:2019.4.10f1
点群データ:DMM.make AKIBA。約1億1千万点。約2GB。plyファイル。

パッケージ

Visual Effect Graph:7.3.1
High Definition RP:7.3.1

①点群データをVFX Graph用のPoint Cacheファイルに変換
点群データ編集にはCloudCompareを使用します。変換したい点群ファイルを読み込むと以下の画面がでます。

不要なデータを削除して軽くするために、NxNyNzのデータは不要なので、[None]に。Apply Allクリックします。以下の画面になります。

点群を選択し、左下のプロパティの[Box dimensions]と[Box center]を確認します。
Box dimensions:点群全体のサイズ(幅/奥行き/高さ)
Shifted box center:点群の中心の相対座標?(これは自信ないので別途調べます)
Global box center:点群の中心の絶対座標(たぶん、、、)

Box dimensionsのXの値は約43(Unityでは43m)で、スケールはあってそうなのでそのまま使います。Global box centerはUnityで16㎞遠方と、原点から大きく外れた位置になっているので、調整します。

編集>グローバル回転とスケールの編集をクリックすると、以下の画面が出ます。

このShiftの欄にGlobal box centerの値をそのまま入れます。スケールがおかしかった場合はここで調整するそうですが、おかしくないのでそのまま。入力したら「はい」をクリック。Global box centerのX, Y, Zが0となりました。

では保存です。ここがミソ。点群データを選択した状態で左上の保存アイコンをクリック。ASCII cloudを選択し、ファイル名に、この時点でPointCloud用の拡張子「.pcache」を付けてしまいます。

「保存」を押すと次の画面が表示されます。

coordinates precisionは小数点以下の桁数のデータの精度です。データ容量削減のため、記事の通り、4としました。
Save colors as float value(0-1)が必須項目です。Point CacheはRGBを0-255でなく0-1で扱うので、必ずここにチェック。そして「OK」クリック。保存したファイルが.txtで保存されているのはよくわかりませんが後ほど。

UnityのPointCacheはファイルサイズが1,048,576KBを超えると読み込めないそうで、保存したファイルサイズを確認します。保存したファイルが4GBでオーバーしているので、ファイルを分割するか点群を間引きします。
今回はCloud Compareの編集>再サンプリングで、min. space between を0.1に設定しました。
同じ手続きで保存。4MBになりました。間引きすぎ?とりあえずこれで行きます。
別の方法で、ファイル分割を分割する方法もあるそうです(ファイルの分割と結合 – EmEditor (テキストエディタ)

よくわからないですが、この時点で、保存したtxtファイルのプロパティにいって、拡張子 .pcache.txtを.pcacheに変更しておきます。

さて、データが用意できたら、pcache用のヘッダーを追加します。EmEditorで編集します。記事によると、巨大なファイルを扱う場合はEmEditorがおすすめだそうです。

Point Cacheのヘッダーのフォーマットは以下の通り。

pcache
format ascii 1.0

comment Exported from CloudCompare

elements 20000000
property float position.x

property float position.y

property float position.z

property float color.x

property float color.y

property float color.z

end_header

elementsは点の総数(行数)なので、ヘッダーを抜いた行数を記載します。EmEditorの右下に行数が記載されています。
property float positionがミソ。Unity用にyとzを入れ替えておく必要があります。CloudCompareからはZアップで書き出されているので以下の様にYアップにします(もしくはCloudCompareで点群を読み込む時点で、ZとYを入れ替えておいても良いですそうです)。ここはよくわからないので後ほど勉強。

これでPoint Cacheファイルができた、はず!!!

②VFX Graphでpcacheを読み込む
よし、ということで、前回の記事をもとに点群いじります。前回の記事「代表技術通信~Unityで点群表示、Oculus Questで表示⑤ Visual Effect Graphについて」をもとに、
まずはUnityでプロジェクト作成。
作成したプロジェクトのUnity画面から、Windows > Package Managerを選択、パッケージマネージャーからVisual Effect Graph。で、自分の記事の通りやったら点群が表示されず。。

ということで、かめくめさんの「UnityのVFXのPoint Cacheを使ったサンプル」を発見したので、こちらで試してみました。

まずはVFXのテンプレートファイルとゲームオブジェクトを作成します。Assetsエリア内で右クリックからCreate>Visual Effects>Visual Effect Graphを選択し。ファイル名をDMMVFXとします。

DMMVFXファイルをヒエラルキー上にドラッグ&ドロップ。VFXのゲームオブジェクトが作成されるので、それを選択してInspectorのVisual EffectのEditボタンを押します。

VFXのグラフウインドウが開きます。一からコンテキストの流れを作成していくので、すべていったん削除。これで準備完了。

Spawnコンテキストの作成

VFXのウインドウを開き何もない場所で右クリック、「Create Node」クリック、検索までで「Spawn」と入れて、を選択しSpawnコンテキストを作成します。

Spawnコンテキストはパーティクルを生成するコンテキストなので、ここで生成する為のブロックを設定します。Spawnコンテキストを選択した状態で右クリック、検索窓で「Single Burst」検索、選択します。

とりあえず、記事の通り、Single BurstのCountを5000にして、パーティクルを5000個生成するようにします。

Initializeコンテキストの作成

次は、VFXの何もないところで右クリック、Create Node>Contextで、「Initialize」と検索、Initialize Particle(Context)を選択します。

Initializeコンテキストは、個々のパーティクルの初期化をするコンテキストです。SpawnコンテキストのSpawn EventとInitialize Particleのコンテキストをつなぎます。Initialize ParticleのCapacityは、記事の通り、5000にします。Capacityはパーティクルの最大量のことです。

Initializeのコンテキストを選択し、右クリックで「Create Block」をクリック、検索窓で「Set Position from Map」と検索、選択します。Set Position from MapはMapから位置をセットするブロックです。

Point Cacheノードの作成

VFXの何もないところで、右クリック、「Create Node」、検索窓で「Point Cache」、Point Cacheを選択します。

Point Cacheの⦿をクリック、先ほど作成したDMMのpcacheファイルを選択します。

Point CacheのAttributeMap : Positionと、Initialize ParticleのSet Position from MapのAttribute Mapを接続します。

Set Position from MapはMapから位置をセットするブロックなので、Point Cacheに設定したDMMのpcacheファイルのポイントから位置情報を設定します。

Updateコンテキストの作成

VFXの何もない所で右クリック、Create Node、検索窓でUpdateと入力、Update Particleを選択します。

Updateコンテキストは、パーティクル情報の更新をするコンテキストです。Initialize ParticleコンテキストのParticleと、Update Particleコンテキストを接続します。

パーティクルの角度を変更するブロックの作成

Update Particleコンテキストを選択した状態で右クリック、Create Blockクリック、Set Angleを検索、Set Angle Randomを選択します。B(おそらく最大値)のXYZにそれぞれ360を入力します。Set Angle.XYZ RandomはXYZの角度をAからBの間でランダムに決定します。

パーティクルのスケールを変更するブロックの作成

Update Particleコンテキストを選択した状態で右クリック、Create Blockクリック、Set Scaleを検索、Set Scale Randomを選択します。Set Scale.XYZ Randomというブロック名に変わるので、AのXYZに-0.2、BのXYZに0.2を入力します。

パーティクルの色を変更するブロックの作成

UUpdate Particleコンテキストを選択した状態で右クリック、Create Blockクリック、Set Colorを検索、Set Color Randomを選択します。Set Color  Randomというブロック名に変わるので、BのXYZを0にして、黒色にします。

ここまでの全体像は以下です。

パーティクルのレンダリングブロックの作成

パーティクルの生成と更新が出来たので、最後にレンダリングブロックを作成します。VFXウインドウの何もない所で右クリック、Create Node、検索窓でOutput Particle Cubeと入力、選択します。Update ParticleコンテキストのParticleと、Output Particle Quadコンテキストを接続します。

なんかぽつぽつ出てきました!いけそう。

続きは明日。

関連記事