PTSをVTFで利用する(DDSを使った16bitイメージの保存)


どたばたして書けてなかったTipsを順次上げていきたいと思います。
githubにサンプルも上げたのですがgithubサーバがおかしいのでリンクは後程・・・。

渋谷駅のポイントクラウドデータをリアルタイム表示したい

少し前ですが、渋谷駅のポイントクラウドデータが公開されました。
Unityユーザが反応し、すぐにリアルタイム表示をしていたのでTouchDesignerでもできないかな、と試してみました。
結果、DDS形式に変換することでうまく行ったのでそのプロセスを公開します。

PTS形式とは

渋谷駅のデータはPTS形式で保存されています。
ちゃんとした規格のページが見つかりませんでしたが、フォーラムを見る限りPTS形式は要するにスペース区切りのUTF8のテーブルデータのようです。
LiDAR(測域センサ)のデータの保存によく使われているようです。
そしてどうやら最初の3列がXYZで、最後の3列がRGBのようです。
『なるほど、ようするにテキストデータか』ということでatomで開いたところ、かなり時間がかかる上にエラーが・・・。
よく見るとファイルサイズが2GB近くあります。
行数=頂点数として200万オーバー。確実に普通のモデルとしては読み込めないサイズです。
が、テクスチャに焼いてVTFとして表示すればリアルタイム表示は不可能ではないサイズでした。
また、上記の仕様以外に一番上の行に総行数=総頂点数を書くというルールがあるようでした。

DDS形式とは

VTFで利用する場合、16bitのfloatのフルカラー画像で保存することが大前提になります。そして色々人に聞いてみたところ、DDSを利用することにしました。
DirectDraw SurfaceとはDirectXで利用可能な画像フォーマットです。
TouchDesignerではJPGやPNGと同様に簡単にMovie File Out TOP、 Movie File In TOPから保存、読み込みが可能です。

chan形式とは

PTSを直接TouchDesignerで読み込めれば楽なのですがTouchDesignerはPTS形式に対応していません。
なので変換が必要になります。
TouchDesignerで簡単にテキストベースのデータを読み込む形、それはchan形式です。
chanはスペース区切りのUTF8のテーブルデータです。
つまり、PTSとの違いは一番上の行の総頂点数ファイル形式名称だけです。
試しにフォーラムに上がっていたStanford BunnyのPTSデータを

  • 一番上の行を削除し、
  • ファイル形式名称を.chanにリネーム

したところ、File In CHOPで.chanファイルとして値が読み込めました。

PTSからchan形式に変換

ここまで来たらもう一息です。2GBのテキストデータはTouchDesignerではまともに読めなかったため、X、Y、Z、R、G、Bの各チャンネルのデータに分離して保存しなおすPythonを書きました。
一番最初の行の削除だけAtomで行って再度保存し、PythonのPandasを使って配列を分割しました。

split.py

import pandas as pd

df = pd.read_csv('ShibuyaUnderground.chan', header=None, sep=' ')
df.to_csv('shibuya_x.chan', header=False, index=False, columns=[0], sep = ' ')
df.to_csv('shibuya_y.chan', header=False, index=False, columns=[1], sep = ' ')
df.to_csv('shibuya_z.chan', header=False, index=False, columns=[2], sep = ' ')
df.to_csv('shibuya_r.chan', header=False, index=False, columns=[4], sep = ' ')
df.to_csv('shibuya_g.chan', header=False, index=False, columns=[5], sep = ' ')
df.to_csv('shibuya_b.chan', header=False, index=False, columns=[6], sep = ' ')

この6つの.chanファイルをTouchDesignerを使って2枚のDDSにします。

chan形式をDDS形式に変換

短ければパッチのみでTOP化することが可能だと思うんですが、200万行のデータはCHOP上で少しいじるだけでTouchDesignerがフリーズしてしまいます。
そこで直接CHOPをTOPに変換するShaderを書きました。

image.frag
uniform samplerBuffer buffer_r, buffer_g, buffer_b;
uniform vec2 uBufferSize;
out vec4 fragColor;

void main()
{
    int count = int(vUV.x * uBufferSize.x) + int(int(uBufferSize.y * vUV.y) * uBufferSize.x);
    vec4 color = vec4(texelFetch(buffer_r, count).r,texelFetch(buffer_g, count).r, texelFetch(buffer_b, count).r,  1.0);
    fragColor = TDOutputSwizzle(color);
}

そして出来上がった画像をMovie File Out TOPを使ってDDSで保存します。

ビジュアライズ

あとはこれをVTFで画像表示するだけ!