UnityでPoint Cloudを表示する方法

3次元点群を3Dビューアでグリグリとただ表示するだけならPoint Cloud Libraryを使ってすぐにできるんだけど、インタラクティブなコンテンツとして点群を利用したい場合にはPoint Cloud Libraryだけだとちょっと味気ない。Point Cloud Libraryだと視点を動かす時は点群の更新が止まっちゃうし。

何でUnityで点群を扱いたいかというと、お察しの通り、Kinectで取得した点群をカッコよく表示したいのです。Kinect V2になってからMicrosoftが公式にUnityプラグインを配布し始めたし、せっかくだから自前でOpenCVとかPoint Cloud Libraryでゴリゴリ頑張るよりも、Unityで他のAssetと組み合わせてサクッとリッチなコンテンツに仕上げたいのだ。

Microsoft公式のKinect v2 for Unityプラグインには、サンプルとしてKinectのColorとDepthをMesh化して表示するScriptコードが付属しているんだけど、無理やりMesh化して表示してるからちょっと汚らしい。
Microsoft公式のUnityプラグインおよびサンプルプロジェクトは以下のページの”Unity Pro packages“のリンクから。↓
https://www.microsoft.com/en-us/download/details.aspx?id=44561

こちらの公式サンプルでは、Kinect V2から取得した点群を4分の1の量にダウンサンプリングしてから、それらを頂点としたポリゴンメッシュ化してリアルタイム表示している。
Kinect V2で取得可能な点群(つまりDepth画像の解像度)は
512 × 424 = 217,088
だけど、Unityには「1つのMeshオブジェクトが持つ三角形の数は最大65,535まで」という制限があるため、ダウンサンプリングで頂点の数を減らしてMesh化してるんだと思う。
このサンプルでは解像度をダウンサンプリングする代わりに、Depth値を近傍ピクセルの平均から求めたりもしてるんだけど、結果として表示されるMeshがあんまりきれいじゃない。

2017年12月 追記:Meshオブジェクトのポリゴン数制限はUnity 2017.3から解消されたようです。

ということで、Unityで「面」ではなく「点」の描画を実現する方法を調べてみた。


スポンサーリンク


ちょっと調べてみると、どうやら点群ファイルを表示するための有料のAssetでPoint Cloud Viewer and Toolsというものがすでにあるようだ。以下サポートページに詳細が載っている。↓


スポンサーリンク

Point Cloud Viewer & Tools for Unity

Point Cloud Viewer and Tools

このツールはファイル読み込み用なので、どうやら動的にKinectの情報を表示はできなさそう。読み込みをサポートしているフォーマットはXYZ, XYZRGB, CGO, ASC, CATIA ASC, PLY (ASC)。読み込んだファイルを自動でUnityのポリゴン制限数で分割して表示と、バイナリデータへの保存ができるようだ。

Kinectの点群をリアルタイムで表示するにはやっぱり自分でScriptを書くしかなさそうなので点の描画方法を調べてみたら、ドンピシャなブログ記事を見つけた。↓

Rendering a Point Cloud inside Unity

Here is a short example of how to render a point cloud using MeshRenderer inside Unity, have in mind that you have a limit of 65k points per mesh, so if you want to render more points, you need to split them.

ソースコードも全部載せてくれている。OpenGLのAPIコマンドを有効にしてPoint SizeとSmooth PointをEnableにして、Shader側で受け取ってやるってことね。

上記の記事だけだとShaderへのパラメータ渡しの記述が欠けてるけど、以下のフォーラムの記事に全部載っている。↓

How do I use PSIZE in a Unity 4.5.4 shader?

このフォーラム記事では、DirectX環境ではPoint Sizeの指定が描画に反映されないことについて話題になっている。要するに、残念ながらOpenGL環境でしか動かない仕様っぽい。


こちらが描画用のPoint Cloudをランダムに生成するC# Scriptのサンプルコード。↓


点を受け取って描画するShaderのコード。↓


そしてUnityでOpenGLのPoint Sizeコマンドを有効にするC# Scriptコード。(これはMain Cameraとかにアタッチする)↓

初めて知ったけど、UnityのMeshってMeshTopologyを指定すれば三角形じゃなくてもいけるのね。

リアルタイムで動く点群をグリグリできると、スターウォーズに出てくる立体映像みたいでカッコイイね。


スポンサーリンク

関連記事

3Dオブジェクトの確認・変換に便利なフリーウェア『MeshLab』
インターフェイスは世界を規定する
AndroidもopenGLも初心者さ (でもJavaは知ってるよ)
粘土をこねるようなスカルプトモデリング
Arduinoで作るダンボーみたいなロボット『ピッコロボ』
Unityで使える数値計算ライブラリ『Math.NET Numerics』
ラクガキの立体化 1年半ぶりの続き
SIGGRAPH ASIA 2009で学生ボランティア募集してるみたい
Google Chromecast
WordPressプラグインの作り方
マルコフ連鎖モンテカルロ法
Windows Server 2008にAutodesk Maya 2009をインストール
オープンソースのネットワーク可視化ソフトウェアプラットフォーム『Cytoscape』
オープンソースの物理ベースGIレンダラ『appleseed』
ハリウッド版「GAIKING」パイロット映像
トランスフォーマー :リベンジのメイキング (デジタルドメイン)
UnityのGameObjectの向きをScriptで制御する
pythonの機械学習ライブラリ『scikit-learn』
スマホのカメラで3Dスキャンできるアプリ『Qlone』
3D映画のポストプロダクション 2D-3D変換
書籍『データビジュアライゼーションのデザインパターン20』読了
『PIXARのひみつ展』に行ってきた
Amazon EC2ログイン用の秘密鍵を無くした場合の対処方法
FacebookがDeep learningツールの一部をオープンソース化
書籍『3次元コンピュータビジョン計算ハンドブック』を購入
サンプルコードにも間違いはある?
Konashiを買った
UnityからROSを利用できる『ROS#』
PythonでMayaのShapeノードプラグインを作る
このブログのデザインに飽きてきた
Raspberry Pi 2のGPIOピン配置
Unityで強化学習できる『Unity ML-Agents』
機械学習手法『Random Forest』
ZBrushで仮面ライダー3号を造る 仮面編 横顔のシルエットをリファレンスに合わせる
映画から想像するVR・AR時代のGUIデザイン
Mayaのレンダリング アトリビュート
CGAN (Conditional GAN):条件付き敵対的生成ネットワーク
ゴジラ(2014)のメイキング
PolyPaint
クラスの基本
SONY製のニューラルネットワークライブラリ『NNabla』
iPadをハンディ3Dスキャナにするガジェット『iSense 3D Scanner』

コメント

  1. kusano より:

    参考にさせていただきました。ありがとうございます。
    そのままでは動かなかったのですが、
    struct VertexOutput {
    float4 pos : SV_POSITION;
    float4 col : COLOR;
    float4 size : PSIZE;
    };

    struct VertexOutput {
    float4 pos : SV_POSITION;
    float4 col : COLOR;
    float size : PSIZE;
    };
    に書き換えたところ動きました。

    • NegativeMind より:

      すみません、書き間違えてました。
      確かに、sizeはベクトルじゃなくてスカラー値ですよね。本文のコードも修正しました。